From e25a9a8bef0857829b2dfc5e9851725d750f1651 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 16:43:45 +1200 Subject: [PATCH 001/222] Bug 592941. Fix performance regression by ensuring we create a ThebesLayerInvalidRegionProperty for frames with new container layers. r=tnikkel,a=blocking --- layout/base/FrameLayerBuilder.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 5dffc807b803..6effcdb88d4b 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -472,6 +472,8 @@ FrameLayerBuilder::UpdateDisplayItemDataForFrame(nsPtrHashKey* aEntry, if (newDisplayItems->HasContainerLayer()) { // Reset or create the invalid region now so we can start collecting // new dirty areas. + // Note that the NS_FRAME_HAS_CONTAINER_LAYER bit is set in + // BuildContainerLayerFor, so we don't need to set it here. nsRegion* invalidRegion = static_cast (props.Get(ThebesLayerInvalidRegionProperty())); if (invalidRegion) { @@ -505,11 +507,12 @@ FrameLayerBuilder::StoreNewDisplayItemData(DisplayItemDataEntry* aEntry, { LayerManagerData* data = static_cast(aUserArg); nsIFrame* f = aEntry->GetKey(); + FrameProperties props = f->Properties(); // Remember that this frame has display items in retained layers NS_ASSERTION(!data->mFramesWithLayers.GetEntry(f), "We shouldn't get here if we're already in mFramesWithLayers"); data->mFramesWithLayers.PutEntry(f); - NS_ASSERTION(!f->Properties().Get(DisplayItemDataProperty()), + NS_ASSERTION(!props.Get(DisplayItemDataProperty()), "mFramesWithLayers out of sync"); void* propValue; @@ -518,8 +521,11 @@ FrameLayerBuilder::StoreNewDisplayItemData(DisplayItemDataEntry* aEntry, // Steal the list of display item layers array->SwapElements(aEntry->mData); // Save it - f->Properties().Set(DisplayItemDataProperty(), propValue); + props.Set(DisplayItemDataProperty(), propValue); + if (f->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER) { + props.Set(ThebesLayerInvalidRegionProperty(), new nsRegion()); + } return PL_DHASH_REMOVE; } From 43c2fbb41796bc9fe4b0725c6a88c7389306a9a5 Mon Sep 17 00:00:00 2001 From: "timeless@mozdev.org" Date: Thu, 2 Sep 2010 16:46:53 +1200 Subject: [PATCH 002/222] Bug 587483 warning: comparison between signed and unsigned integer expressions in FrameLayerBuilder. r=roc,a=roc --- layout/base/FrameLayerBuilder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 6effcdb88d4b..01c9797f776b 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -657,7 +657,7 @@ ContainerState::CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot) * have a frame because only nsDisplayClip items don't have a frame, * and those items are flattened away by ProcessDisplayItems. */ -static PRUint32 +static PRInt32 AppUnitsPerDevPixel(nsDisplayItem* aItem) { // The underlying frame for zoom items is the root frame of the subdocument. @@ -1425,7 +1425,7 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer, nsIntPoint offset(PRInt32(transform.x0), PRInt32(transform.y0)); nsPresContext* presContext = containerLayerFrame->PresContext(); - nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); + PRInt32 appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); nsRect r = (aRegionToInvalidate.GetBounds() + offset). ToAppUnits(appUnitsPerDevPixel); containerLayerFrame->InvalidateWithFlags(r, From 5eeb4518f0ebb2bc2e29f9b62f9598569902a2c3 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 16:47:12 +1200 Subject: [PATCH 003/222] Bug 580410. Hide reftest window title bar so the reftest window fits on our Mac test machines. test-only change, a=me. --- layout/tools/reftest/reftest.xul | 1 + 1 file changed, 1 insertion(+) diff --git a/layout/tools/reftest/reftest.xul b/layout/tools/reftest/reftest.xul index 2e8a09ebcc04..66604f1030df 100644 --- a/layout/tools/reftest/reftest.xul +++ b/layout/tools/reftest/reftest.xul @@ -44,6 +44,7 @@ Date: Thu, 2 Sep 2010 15:23:52 +0800 Subject: [PATCH 004/222] Bug 591216 Fix Gtk-WARNING gtk_window_set_wmclass: shouldn't set wmclass after window is realized r=roc a=roc --- widget/src/gtk2/nsWindow.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/widget/src/gtk2/nsWindow.cpp b/widget/src/gtk2/nsWindow.cpp index 6d3bf5387aef..9ce6d5f7c8e9 100644 --- a/widget/src/gtk2/nsWindow.cpp +++ b/widget/src/gtk2/nsWindow.cpp @@ -3777,11 +3777,12 @@ nsWindow::Create(nsIWidget *aParent, // GTK_WINDOW_POPUP, which will use a Window with the // override-redirect attribute (for temporary windows). mShell = gtk_window_new(GTK_WINDOW_POPUP); + gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup", cBrand.get()); } else { // For long-lived windows, their stacking order is managed by // the window manager, as indicated by GTK_WINDOW_TOPLEVEL ... mShell = gtk_window_new(GTK_WINDOW_TOPLEVEL); - GtkWindow* gtkWin = GTK_WINDOW(mShell); + gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup", cBrand.get()); // ... but the window manager does not decorate this window, // nor provide a separate taskbar icon. if (mBorderStyle == eBorderStyle_default) { @@ -3794,11 +3795,11 @@ nsWindow::Create(nsIWidget *aParent, gtk_window_set_deletable(GTK_WINDOW(mShell), mBorderStyle & eBorderStyle_close); } } - gtk_window_set_skip_taskbar_hint(gtkWin, TRUE); + gtk_window_set_skip_taskbar_hint(GTK_WINDOW(mShell), TRUE); // Element focus is managed by the parent window so the // WM_HINTS input field is set to False to tell the window // manager not to set input focus to this window ... - gtk_window_set_accept_focus(gtkWin, FALSE); + gtk_window_set_accept_focus(GTK_WINDOW(mShell), FALSE); #ifdef MOZ_X11 // ... but when the window manager offers focus through // WM_TAKE_FOCUS, focus is requested on the parent window. @@ -3808,8 +3809,6 @@ nsWindow::Create(nsIWidget *aParent, #endif } - gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup", cBrand.get()); - GdkWindowTypeHint gtkTypeHint; switch (aInitData->mPopupHint) { case ePopupTypeMenu: From bc14460ac4c69087b21a4d433aacf813545c53b5 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 21:18:39 +1200 Subject: [PATCH 005/222] Bug 579276. Part 1: Change layer/layermanager user data API to use keys and values. r=cjones,sr=vlad --- content/canvas/src/WebGLContext.cpp | 4 +- .../canvas/src/nsCanvasRenderingContext2D.cpp | 4 +- gfx/layers/Layers.h | 113 ++++++++++++++++-- layout/base/FrameLayerBuilder.cpp | 59 +++++---- 4 files changed, 140 insertions(+), 40 deletions(-) diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index 5b4f9dfbc177..9ac05fa7c7f6 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -508,7 +508,7 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer, LayerManager *aManager) { if (!mResetLayer && aOldLayer && - aOldLayer->GetUserData() == &gWebGLLayerUserData) { + aOldLayer->HasUserData(&gWebGLLayerUserData)) { NS_ADDREF(aOldLayer); if (mInvalidated) { aOldLayer->Updated(nsIntRect(0, 0, mWidth, mHeight)); @@ -522,7 +522,7 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer, NS_WARNING("CreateCanvasLayer returned null!"); return nsnull; } - canvasLayer->SetUserData(&gWebGLLayerUserData); + canvasLayer->SetUserData(&gWebGLLayerUserData, nsnull); CanvasLayer::Data data; diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index c0a9f753d196..d76eee6f82e8 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -4154,7 +4154,7 @@ nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer, return nsnull; if (!mResetLayer && aOldLayer && - aOldLayer->GetUserData() == &g2DContextLayerUserData) { + aOldLayer->HasUserData(&g2DContextLayerUserData)) { NS_ADDREF(aOldLayer); // XXX Need to just update the changed area here aOldLayer->Updated(nsIntRect(0, 0, mWidth, mHeight)); @@ -4166,7 +4166,7 @@ nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer, NS_WARNING("CreateCanvasLayer returned null!"); return nsnull; } - canvasLayer->SetUserData(&g2DContextLayerUserData); + canvasLayer->SetUserData(&g2DContextLayerUserData, nsnull); CanvasLayer::Data data; diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 47a9baab9b75..6643d60f0062 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -83,6 +83,14 @@ class SpecificLayerAttributes; virtual const char* Name() const { return n; } \ virtual LayerType GetType() const { return e; } +/** + * Base class for userdata objects attached to layers and layer managers. + */ +class THEBES_API LayerUserData { +public: + virtual ~LayerUserData() {} +}; + /* * Motivation: For truly smooth animation and video playback, we need to * be able to compose frames and render them on a dedicated thread (i.e. @@ -109,6 +117,52 @@ class SpecificLayerAttributes; * BasicLayerManager for such an implementation. */ +/** + * Helper class to manage user data for layers and LayerManagers. + */ +class THEBES_API LayerUserDataSet { +public: + LayerUserDataSet() : mKey(nsnull) {} + + void Set(void* aKey, LayerUserData* aValue) + { + NS_ASSERTION(!mKey || mKey == aKey, + "Multiple LayerUserData objects not supported"); + mKey = aKey; + mValue = aValue; + } + /** + * This can be used anytime. Ownership passes to the caller! + */ + LayerUserData* Remove(void* aKey) + { + if (mKey == aKey) { + mKey = nsnull; + LayerUserData* d = mValue.forget(); + return d; + } + return nsnull; + } + /** + * This getter can be used anytime. + */ + PRBool Has(void* aKey) + { + return mKey == aKey; + } + /** + * This getter can be used anytime. Ownership is retained by this object. + */ + LayerUserData* Get(void* aKey) + { + return mKey == aKey ? mValue.get() : nsnull; + } + +private: + void* mKey; + nsAutoPtr mValue; +}; + /** * A LayerManager controls a tree of layers. All layers in the tree * must use the same LayerManager. @@ -142,7 +196,7 @@ public: LAYERS_D3D9 }; - LayerManager() : mUserData(nsnull), mDestroyed(PR_FALSE) + LayerManager() : mDestroyed(PR_FALSE) { InitLog(); } @@ -267,10 +321,28 @@ public: */ virtual LayersBackend GetBackendType() = 0; - // This setter and getter can be used anytime. The user data is initially - // null. - void SetUserData(void* aData) { mUserData = aData; } - void* GetUserData() { return mUserData; } + /** + * This setter can be used anytime. The user data for all keys is + * initially null. Ownership pases to the layer manager. + */ + void SetUserData(void* aKey, LayerUserData* aData) + { mUserData.Set(aKey, aData); } + /** + * This can be used anytime. Ownership passes to the caller! + */ + nsAutoPtr RemoveUserData(void* aKey) + { nsAutoPtr d(mUserData.Remove(aKey)); return d; } + /** + * This getter can be used anytime. + */ + PRBool HasUserData(void* aKey) + { return mUserData.Has(aKey); } + /** + * This getter can be used anytime. Ownership is retained by the layer + * manager. + */ + LayerUserData* GetUserData(void* aKey) + { return mUserData.Get(aKey); } // We always declare the following logging symbols, because it's // extremely tricky to conditionally declare them. However, for @@ -305,7 +377,7 @@ public: protected: nsRefPtr mRoot; - void* mUserData; + LayerUserDataSet mUserData; PRPackedBool mDestroyed; // Print interesting information about this into aTo. Internally @@ -460,10 +532,28 @@ public: // quality. PRBool CanUseOpaqueSurface(); - // This setter and getter can be used anytime. The user data is initially - // null. - void SetUserData(void* aData) { mUserData = aData; } - void* GetUserData() { return mUserData; } + /** + * This setter can be used anytime. The user data for all keys is + * initially null. Ownership pases to the layer manager. + */ + void SetUserData(void* aKey, LayerUserData* aData) + { mUserData.Set(aKey, aData); } + /** + * This can be used anytime. Ownership passes to the caller! + */ + nsAutoPtr RemoveUserData(void* aKey) + { nsAutoPtr d(mUserData.Remove(aKey)); return d; } + /** + * This getter can be used anytime. + */ + PRBool HasUserData(void* aKey) + { return mUserData.Has(aKey); } + /** + * This getter can be used anytime. Ownership is retained by the layer + * manager. + */ + LayerUserData* GetUserData(void* aKey) + { return mUserData.Get(aKey); } /** * Dynamic downcast to a Thebes layer. Returns null if this is not @@ -519,7 +609,6 @@ protected: mNextSibling(nsnull), mPrevSibling(nsnull), mImplData(aImplData), - mUserData(nsnull), mOpacity(1.0), mUseClipRect(PR_FALSE), mIsOpaqueContent(PR_FALSE) @@ -539,7 +628,7 @@ protected: Layer* mNextSibling; Layer* mPrevSibling; void* mImplData; - void* mUserData; + LayerUserDataSet mUserData; nsIntRegion mVisibleRegion; gfx3DMatrix mTransform; float mOpacity; diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 01c9797f776b..df505c492ba5 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -57,14 +57,19 @@ namespace { /** * This is the userdata we associate with a layer manager. */ -class LayerManagerData { +class LayerManagerData : public LayerUserData { public: LayerManagerData() : mInvalidateAllThebesContent(PR_FALSE), mInvalidateAllLayers(PR_FALSE) { + MOZ_COUNT_CTOR(LayerManagerData); + mFramesWithLayers.Init(); } + ~LayerManagerData() { + MOZ_COUNT_DTOR(LayerManagerData); + } /** * Tracks which frames have layers associated with them. @@ -304,18 +309,26 @@ protected: /** * The address of gThebesDisplayItemLayerUserData is used as the user - * data pointer for ThebesLayers created by FrameLayerBuilder. + * data key for ThebesLayers created by FrameLayerBuilder. * It identifies ThebesLayers used to draw non-layer content, which are * therefore eligible for recycling. We want display items to be able to * create their own dedicated ThebesLayers in BuildLayer, if necessary, * and we wouldn't want to accidentally recycle those. + * The user data is null. */ -static PRUint8 gThebesDisplayItemLayerUserData; +PRUint8 gThebesDisplayItemLayerUserData; /** * The address of gColorLayerUserData is used as the user - * data pointer for ColorLayers + * data key for ColorLayers created by FrameLayerBuilder. + * The user data is null. */ -static PRUint8 gColorLayerUserData; +PRUint8 gColorLayerUserData; +/** + * The address of gLayerManagerUserData is used as the user + * data key for retained LayerManagers managed by FrameLayerBuilder. + * The user data is a LayerManagerData. + */ +PRUint8 gLayerManagerUserData; } // anonymous namespace @@ -342,12 +355,11 @@ FrameLayerBuilder::InternalDestroyDisplayItemData(nsIFrame* aFrame, if (aRemoveFromFramesWithLayers) { LayerManager* manager = array->ElementAt(0).mLayer->Manager(); LayerManagerData* data = static_cast - (manager->GetUserData()); + (manager->GetUserData(&gLayerManagerUserData)); NS_ASSERTION(data, "Frame with layer should have been recorded"); data->mFramesWithLayers.RemoveEntry(aFrame); if (data->mFramesWithLayers.Count() == 0) { - delete data; - manager->SetUserData(nsnull); + manager->RemoveUserData(&gLayerManagerUserData); // Consume the reference we added when we set the user data // in DidEndTransaction. But don't actually release until we've // released all the layers in the DisplayItemData array below! @@ -371,7 +383,7 @@ FrameLayerBuilder::WillBeginRetainedLayerTransaction(LayerManager* aManager) { mRetainingManager = aManager; LayerManagerData* data = static_cast - (aManager->GetUserData()); + (aManager->GetUserData(&gLayerManagerUserData)); if (data) { mInvalidateAllThebesContent = data->mInvalidateAllThebesContent; mInvalidateAllLayers = data->mInvalidateAllLayers; @@ -420,13 +432,13 @@ FrameLayerBuilder::WillEndTransaction(LayerManager* aManager) // correctly and the NS_FRAME_HAS_CONTAINER_LAYER bits will be set // correctly. LayerManagerData* data = static_cast - (mRetainingManager->GetUserData()); + (mRetainingManager->GetUserData(&gLayerManagerUserData)); if (data) { // Update all the frames that used to have layers. data->mFramesWithLayers.EnumerateEntries(UpdateDisplayItemDataForFrame, this); } else { data = new LayerManagerData(); - mRetainingManager->SetUserData(data); + mRetainingManager->SetUserData(&gLayerManagerUserData, data); // Addref mRetainingManager. We'll release it when 'data' is // removed. NS_ADDREF(mRetainingManager); @@ -595,7 +607,7 @@ ContainerState::CreateOrRecycleColorLayer() if (!layer) return nsnull; // Mark this layer as being used for Thebes-painting display items - layer->SetUserData(&gColorLayerUserData); + layer->SetUserData(&gColorLayerUserData, nsnull); } return layer.forget(); } @@ -637,7 +649,7 @@ ContainerState::CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot) if (!layer) return nsnull; // Mark this layer as being used for Thebes-painting display items - layer->SetUserData(&gThebesDisplayItemLayerUserData); + layer->SetUserData(&gThebesDisplayItemLayerUserData, nsnull); } // Set up transform so that 0,0 in the Thebes layer corresponds to the @@ -965,7 +977,7 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList, // Update that layer's clip and visible rects. NS_ASSERTION(ownLayer->Manager() == mManager, "Wrong manager"); - NS_ASSERTION(ownLayer->GetUserData() != &gThebesDisplayItemLayerUserData, + NS_ASSERTION(!ownLayer->HasUserData(&gLayerManagerUserData), "We shouldn't have a FrameLayerBuilder-managed layer here!"); // It has its own layer. Update that layer's clip and visible rects. if (aClipRect) { @@ -1119,10 +1131,9 @@ ContainerState::CollectOldLayers() { for (Layer* layer = mContainerLayer->GetFirstChild(); layer; layer = layer->GetNextSibling()) { - void* data = layer->GetUserData(); - if (data == &gColorLayerUserData) { + if (layer->HasUserData(&gColorLayerUserData)) { mRecycledColorLayers.AppendElement(static_cast(layer)); - } else if (data == &gThebesDisplayItemLayerUserData) { + } else if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) { NS_ASSERTION(layer->AsThebesLayer(), "Wrong layer type"); mRecycledThebesLayers.AppendElement(static_cast(layer)); } @@ -1203,7 +1214,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder, Layer* oldLayer = GetOldLayerFor(aContainerFrame, containerDisplayItemKey); if (oldLayer) { NS_ASSERTION(oldLayer->Manager() == aManager, "Wrong manager"); - if (oldLayer->GetUserData() == &gThebesDisplayItemLayerUserData) { + if (oldLayer->HasUserData(&gThebesDisplayItemLayerUserData)) { // The old layer for this item is actually our ThebesLayer // because we rendered its layer into that ThebesLayer. So we // don't actually have a retained container layer. @@ -1276,7 +1287,7 @@ FrameLayerBuilder::GetLeafLayerFor(nsDisplayListBuilder* aBuilder, Layer* layer = GetOldLayerFor(f, aItem->GetPerFrameKey()); if (!layer) return nsnull; - if (layer->GetUserData() == &gThebesDisplayItemLayerUserData) { + if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) { // This layer was created to render Thebes-rendered content for this // display item. The display item should not use it for its own // layer rendering. @@ -1352,7 +1363,7 @@ FrameLayerBuilder::InvalidateThebesLayersInSubtree(nsIFrame* aFrame) FrameLayerBuilder::InvalidateAllThebesLayerContents(LayerManager* aManager) { LayerManagerData* data = static_cast - (aManager->GetUserData()); + (aManager->GetUserData(&gLayerManagerUserData)); if (data) { data->mInvalidateAllThebesContent = PR_TRUE; } @@ -1362,7 +1373,7 @@ FrameLayerBuilder::InvalidateAllThebesLayerContents(LayerManager* aManager) FrameLayerBuilder::InvalidateAllLayers(LayerManager* aManager) { LayerManagerData* data = static_cast - (aManager->GetUserData()); + (aManager->GetUserData(&gLayerManagerUserData)); if (data) { data->mInvalidateAllLayers = PR_TRUE; } @@ -1380,9 +1391,9 @@ FrameLayerBuilder::HasDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey) (reinterpret_cast*>(&propValue)); for (PRUint32 i = 0; i < array->Length(); ++i) { if (array->ElementAt(i).mDisplayItemKey == aDisplayItemKey) { - void* layerUserData = array->ElementAt(i).mLayer->GetUserData(); - if (layerUserData != &gColorLayerUserData && - layerUserData != &gThebesDisplayItemLayerUserData) + Layer* layer = array->ElementAt(i).mLayer; + if (!layer->HasUserData(&gColorLayerUserData) && + !layer->HasUserData(&gThebesDisplayItemLayerUserData)) return PR_TRUE; } } From 0cbed2f6567a7c7ad7cde47519f4bcf0281adefb Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 21:18:39 +1200 Subject: [PATCH 006/222] Bug 579276. Part 2: If a transparent layer is over a solid background color, hoist that color into the layer to make it opaque. r=tnikkel --- layout/base/FrameLayerBuilder.cpp | 148 ++++++++++++++++++++++++++---- layout/base/FrameLayerBuilder.h | 20 ++++ 2 files changed, 148 insertions(+), 20 deletions(-) diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index df505c492ba5..3949bef8d325 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -64,10 +64,13 @@ public: mInvalidateAllLayers(PR_FALSE) { MOZ_COUNT_CTOR(LayerManagerData); - mFramesWithLayers.Init(); } ~LayerManagerData() { + // Remove display item data properties now, since we won't be able + // to find these frames again without mFramesWithLayers. + mFramesWithLayers.EnumerateEntries( + FrameLayerBuilder::RemoveDisplayItemDataForFrame, nsnull); MOZ_COUNT_DTOR(LayerManagerData); } @@ -250,6 +253,12 @@ protected: * aItem in that layer. */ void InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer); + /** + * Try to determine whether the ThebesLayer at aThebesLayerIndex + * has an opaque single color covering the visible area behind it. + * If successful, return that color, otherwise return NS_RGBA(0,0,0,0). + */ + nscolor FindOpaqueBackgroundColorFor(PRInt32 aThebesLayerIndex); /** * Indicate that we are done adding items to the ThebesLayer at the top of * mThebesLayerDataStack. Set the final visible region and opaque-content @@ -307,6 +316,15 @@ protected: PRPackedBool mInvalidateAllThebesContent; }; +class ThebesDisplayItemLayerUserData : public LayerUserData +{ +public: + ThebesDisplayItemLayerUserData() : + mForcedBackgroundColor(NS_RGBA(0,0,0,0)) {} + + nscolor mForcedBackgroundColor; +}; + /** * The address of gThebesDisplayItemLayerUserData is used as the user * data key for ThebesLayers created by FrameLayerBuilder. @@ -314,7 +332,7 @@ protected: * therefore eligible for recycling. We want display items to be able to * create their own dedicated ThebesLayers in BuildLayer, if necessary, * and we wouldn't want to accidentally recycle those. - * The user data is null. + * The user data is a ThebesDisplayItemLayerUserData. */ PRUint8 gThebesDisplayItemLayerUserData; /** @@ -462,7 +480,7 @@ FrameLayerBuilder::UpdateDisplayItemDataForFrame(nsPtrHashKey* aEntry, nsIFrame* f = aEntry->GetKey(); FrameProperties props = f->Properties(); DisplayItemDataEntry* newDisplayItems = - builder->mNewDisplayItemData.GetEntry(f); + builder ? builder->mNewDisplayItemData.GetEntry(f) : nsnull; if (!newDisplayItems) { // This frame was visible, but isn't anymore. PRBool found; @@ -649,7 +667,8 @@ ContainerState::CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot) if (!layer) return nsnull; // Mark this layer as being used for Thebes-painting display items - layer->SetUserData(&gThebesDisplayItemLayerUserData, nsnull); + layer->SetUserData(&gThebesDisplayItemLayerUserData, + new ThebesDisplayItemLayerUserData()); } // Set up transform so that 0,0 in the Thebes layer corresponds to the @@ -709,6 +728,39 @@ SetVisibleRectForLayer(Layer* aLayer, const nsIntRect& aRect) } } +nscolor +ContainerState::FindOpaqueBackgroundColorFor(PRInt32 aThebesLayerIndex) +{ + ThebesLayerData* target = mThebesLayerDataStack[aThebesLayerIndex]; + for (PRInt32 i = aThebesLayerIndex - 1; i >= 0; --i) { + ThebesLayerData* candidate = mThebesLayerDataStack[i]; + nsIntRegion visibleAboveIntersection; + visibleAboveIntersection.And(candidate->mVisibleAboveRegion, target->mVisibleRegion); + if (!visibleAboveIntersection.IsEmpty()) { + // Some non-Thebes content between target and candidate; this is + // hopeless + break; + } + + nsIntRegion intersection; + intersection.And(candidate->mVisibleRegion, target->mVisibleRegion); + if (intersection.IsEmpty()) { + // The layer doesn't intersect our target, ignore it and move on + continue; + } + + // The candidate intersects our target. If any layer has a solid-color + // area behind our target, this must be it. Scan its display items. + nsPresContext* presContext = mContainerFrame->PresContext(); + nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); + nsRect rect = + target->mVisibleRegion.GetBounds().ToAppUnits(appUnitsPerDevPixel); + return mBuilder->LayerBuilder()-> + FindOpaqueColorCovering(mBuilder, candidate->mLayer, rect); + } + return NS_RGBA(0,0,0,0); +} + void ContainerState::PopThebesLayerData() { @@ -717,21 +769,6 @@ ContainerState::PopThebesLayerData() PRInt32 lastIndex = mThebesLayerDataStack.Length() - 1; ThebesLayerData* data = mThebesLayerDataStack[lastIndex]; - if (lastIndex > 0) { - // Since we're going to pop off the last ThebesLayerData, the - // mVisibleAboveRegion of the second-to-last item will need to include - // the regions of the last item. - ThebesLayerData* nextData = mThebesLayerDataStack[lastIndex - 1]; - nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion, - data->mVisibleAboveRegion); - nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion, - data->mVisibleRegion); - nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion, - data->mDrawAboveRegion); - nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion, - data->mDrawRegion); - } - Layer* layer; if (data->mIsSolidColorInVisibleRegion) { nsRefPtr colorLayer = CreateOrRecycleColorLayer(); @@ -778,7 +815,47 @@ ContainerState::PopThebesLayerData() nsIntRegion transparentRegion; transparentRegion.Sub(data->mVisibleRegion, data->mOpaqueRegion); - layer->SetIsOpaqueContent(transparentRegion.IsEmpty()); + PRBool isOpaque = transparentRegion.IsEmpty(); + // For translucent ThebesLayers, try to find an opaque background + // color that covers the entire area beneath it so we can pull that + // color into this layer to make it opaque. + if (layer == data->mLayer) { + nscolor backgroundColor = NS_RGBA(0,0,0,0); + if (!isOpaque) { + backgroundColor = FindOpaqueBackgroundColorFor(lastIndex); + if (NS_GET_A(backgroundColor) == 255) { + isOpaque = PR_TRUE; + } + } + + // Store the background color + ThebesDisplayItemLayerUserData* userData = + static_cast + (data->mLayer->GetUserData(&gThebesDisplayItemLayerUserData)); + NS_ASSERTION(userData, "where did our user data go?"); + if (userData->mForcedBackgroundColor != backgroundColor) { + // Invalidate the entire target ThebesLayer since we're changing + // the background color + data->mLayer->InvalidateRegion(data->mLayer->GetValidRegion()); + } + userData->mForcedBackgroundColor = backgroundColor; + } + layer->SetIsOpaqueContent(isOpaque); + + if (lastIndex > 0) { + // Since we're going to pop off the last ThebesLayerData, the + // mVisibleAboveRegion of the second-to-last item will need to include + // the regions of the last item. + ThebesLayerData* nextData = mThebesLayerDataStack[lastIndex - 1]; + nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion, + data->mVisibleAboveRegion); + nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion, + data->mVisibleRegion); + nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion, + data->mDrawAboveRegion); + nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion, + data->mDrawRegion); + } mThebesLayerDataStack.RemoveElementAt(lastIndex); } @@ -1126,6 +1203,28 @@ FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer, } } +nscolor +FrameLayerBuilder::FindOpaqueColorCovering(nsDisplayListBuilder* aBuilder, + ThebesLayer* aLayer, + const nsRect& aRect) +{ + ThebesLayerItemsEntry* entry = mThebesLayerItems.GetEntry(aLayer); + NS_ASSERTION(entry, "Must know about this layer!"); + for (PRInt32 i = entry->mItems.Length() - 1; i >= 0; --i) { + nsDisplayItem* item = entry->mItems[i].mItem; + const nsRect& visible = item->GetVisibleRect(); + if (!visible.Intersects(aRect)) + continue; + + nscolor color; + if (visible.Contains(aRect) && item->IsUniform(aBuilder, &color) && + NS_GET_A(color) == 255) + return color; + break; + } + return NS_RGBA(0,0,0,0); +} + void ContainerState::CollectOldLayers() { @@ -1422,6 +1521,15 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer, // so 'entry' could become invalid. } + ThebesDisplayItemLayerUserData* userData = + static_cast + (aLayer->GetUserData(&gThebesDisplayItemLayerUserData)); + NS_ASSERTION(userData, "where did our user data go?"); + if (NS_GET_A(userData->mForcedBackgroundColor) > 0) { + aContext->SetColor(gfxRGBA(userData->mForcedBackgroundColor)); + aContext->Paint(); + } + gfxMatrix transform; if (!aLayer->GetTransform().Is2D(&transform)) { NS_ERROR("non-2D transform in our Thebes layer!"); diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h index e3e082068994..4cce9ebbcb70 100644 --- a/layout/base/FrameLayerBuilder.h +++ b/layout/base/FrameLayerBuilder.h @@ -243,6 +243,26 @@ public: */ Layer* GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey); + /** + * A useful hashtable iteration function that removes the + * DisplayItemData property for the frame, clears its + * NS_FRAME_HAS_CONTAINER_LAYER bit and returns PL_DHASH_REMOVE. + * aClosure is ignored. + */ + static PLDHashOperator RemoveDisplayItemDataForFrame(nsPtrHashKey* aEntry, + void* aClosure) + { + return UpdateDisplayItemDataForFrame(aEntry, nsnull); + } + + /** + * Try to determine whether the ThebesLayer aLayer paints an opaque + * single color everywhere it's visible in aRect. + * If successful, return that color, otherwise return NS_RGBA(0,0,0,0). + */ + nscolor FindOpaqueColorCovering(nsDisplayListBuilder* aBuilder, + ThebesLayer* aLayer, const nsRect& aRect); + protected: /** * We store an array of these for each frame that is associated with From 78d1a0aa883c03ef0829d0421aaafe098bdf2fd0 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 21:18:39 +1200 Subject: [PATCH 007/222] Bug 579276. Part 8: Bump scroll timeout up a lot. r=tnikkel --- layout/generic/nsGfxScrollFrame.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index df8ff01b4f95..364bf10385b5 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1251,9 +1251,9 @@ IsSmoothScrollingEnabled() class ScrollFrameActivityTracker : public nsExpirationTracker { public: - // Wait for 75-100ms between scrolls before we switch the appearance back to - // subpixel AA. That's 4 generations of 25ms each. - enum { TIMEOUT_MS = 25 }; + // Wait for 3-4s between scrolls before we remove our layers. + // That's 4 generations of 1s each. + enum { TIMEOUT_MS = 1000 }; ScrollFrameActivityTracker() : nsExpirationTracker(TIMEOUT_MS) {} ~ScrollFrameActivityTracker() { From 9558a29d0c231c74da83b70ceb1b1db8562ad92d Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 21:18:39 +1200 Subject: [PATCH 008/222] Bug 579276. Part 4: Move nsDisplayItem parameter down to ThebesLayerData::Accumulate. r=tnikkel --- layout/base/FrameLayerBuilder.cpp | 56 +++++++++++++------------------ 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 3949bef8d325..1932ea1a5127 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -173,10 +173,10 @@ protected: * @param aSolidColor if non-null, the visible area of the item is * a constant color given by *aSolidColor */ - void Accumulate(const nsIntRect& aVisibleRect, - const nsIntRect& aDrawRect, - const nsIntRect* aOpaqueRect, - nscolor* aSolidColor); + void Accumulate(nsDisplayListBuilder* aBuilder, + nsDisplayItem* aItem, + const nsIntRect& aVisibleRect, + const nsIntRect& aDrawRect); nsIFrame* GetActiveScrolledRoot() { return mActiveScrolledRoot; } /** @@ -282,11 +282,10 @@ protected: * @param aSolidColor if non-null, indicates that every pixel in aVisibleRect * will be painted with aSolidColor by the item */ - already_AddRefed FindThebesLayerFor(const nsIntRect& aVisibleRect, + already_AddRefed FindThebesLayerFor(nsDisplayItem* aItem, + const nsIntRect& aVisibleRect, const nsIntRect& aDrawRect, - nsIFrame* aActiveScrolledRoot, - const nsIntRect* aOpaqueRect, - nscolor* aSolidColor); + nsIFrame* aActiveScrolledRoot); ThebesLayerData* GetTopThebesLayerData() { return mThebesLayerDataStack.IsEmpty() ? nsnull @@ -861,20 +860,21 @@ ContainerState::PopThebesLayerData() } void -ContainerState::ThebesLayerData::Accumulate(const nsIntRect& aVisibleRect, - const nsIntRect& aDrawRect, - const nsIntRect* aOpaqueRect, - nscolor* aSolidColor) +ContainerState::ThebesLayerData::Accumulate(nsDisplayListBuilder* aBuilder, + nsDisplayItem* aItem, + const nsIntRect& aVisibleRect, + const nsIntRect& aDrawRect) { - if (aSolidColor) { + nscolor uniformColor; + if (aItem->IsUniform(aBuilder, &uniformColor)) { if (mVisibleRegion.IsEmpty()) { // This color is all we have - mSolidColor = *aSolidColor; + mSolidColor = uniformColor; mIsSolidColorInVisibleRegion = PR_TRUE; } else if (mIsSolidColorInVisibleRegion && mVisibleRegion.IsEqual(nsIntRegion(aVisibleRect))) { // we can just blend the colors together - mSolidColor = NS_ComposeColors(mSolidColor, *aSolidColor); + mSolidColor = NS_ComposeColors(mSolidColor, uniformColor); } else { mIsSolidColorInVisibleRegion = PR_FALSE; } @@ -886,14 +886,15 @@ ContainerState::ThebesLayerData::Accumulate(const nsIntRect& aVisibleRect, mVisibleRegion.SimplifyOutward(4); mDrawRegion.Or(mDrawRegion, aDrawRect); mDrawRegion.SimplifyOutward(4); - if (aOpaqueRect) { + + if (aItem->IsOpaque(aBuilder)) { // We don't use SimplifyInward here since it's not defined exactly // what it will discard. For our purposes the most important case // is a large opaque background at the bottom of z-order (e.g., // a canvas background), so we need to make sure that the first rect // we see doesn't get discarded. nsIntRegion tmp; - tmp.Or(mOpaqueRegion, *aOpaqueRect); + tmp.Or(mOpaqueRegion, aDrawRect); if (tmp.GetNumRects() <= 4) { mOpaqueRegion = tmp; } @@ -901,11 +902,10 @@ ContainerState::ThebesLayerData::Accumulate(const nsIntRect& aVisibleRect, } already_AddRefed -ContainerState::FindThebesLayerFor(const nsIntRect& aVisibleRect, +ContainerState::FindThebesLayerFor(nsDisplayItem* aItem, + const nsIntRect& aVisibleRect, const nsIntRect& aDrawRect, - nsIFrame* aActiveScrolledRoot, - const nsIntRect* aOpaqueRect, - nscolor* aSolidColor) + nsIFrame* aActiveScrolledRoot) { PRInt32 i; PRInt32 lowestUsableLayerWithScrolledRoot = -1; @@ -959,7 +959,7 @@ ContainerState::FindThebesLayerFor(const nsIntRect& aVisibleRect, layer = thebesLayerData->mLayer; } - thebesLayerData->Accumulate(aVisibleRect, aDrawRect, aOpaqueRect, aSolidColor); + thebesLayerData->Accumulate(mBuilder, aItem, aVisibleRect, aDrawRect); return layer.forget(); } @@ -1105,17 +1105,9 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList, nsLayoutUtils::GetActiveScrolledRootFor(viewportFrame, mBuilder->ReferenceFrame()); } - nscolor uniformColor; - PRBool isUniform = item->IsUniform(mBuilder, &uniformColor); - PRBool isOpaque = item->IsOpaque(mBuilder); - nsIntRect opaqueRect; - if (isOpaque) { - opaqueRect = item->GetBounds(mBuilder).ToNearestPixels(appUnitsPerDevPixel); - } nsRefPtr thebesLayer = - FindThebesLayerFor(itemVisibleRect, itemDrawRect, activeScrolledRoot, - isOpaque ? &opaqueRect : nsnull, - isUniform ? &uniformColor : nsnull); + FindThebesLayerFor(item, itemVisibleRect, itemDrawRect, + activeScrolledRoot); InvalidateForLayerChange(item, thebesLayer); From 93076398d19c78cbe84db4ed7e6eaffbaebe52f7 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 21:18:40 +1200 Subject: [PATCH 009/222] Bug 579276. Part 3: Change Set/IsOpaqueContent API to a more generic Get/SetContentFlags API. r=cjones,sr=vlad --- content/canvas/src/WebGLContext.cpp | 4 +- .../canvas/src/nsCanvasRenderingContext2D.cpp | 3 +- gfx/layers/Layers.cpp | 20 ++++++--- gfx/layers/Layers.h | 41 ++++++++++++++----- gfx/layers/basic/BasicLayers.cpp | 4 +- gfx/layers/d3d9/ThebesLayerD3D9.cpp | 35 ++++------------ gfx/layers/ipc/PLayers.ipdl | 2 +- gfx/layers/ipc/ShadowLayers.cpp | 2 +- gfx/layers/ipc/ShadowLayersParent.cpp | 2 +- layout/base/FrameLayerBuilder.cpp | 6 ++- 10 files changed, 67 insertions(+), 52 deletions(-) diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index 9ac05fa7c7f6..071c3a3804fa 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -63,6 +63,7 @@ using namespace mozilla; using namespace mozilla::gl; +using namespace mozilla::layers; nsresult NS_NewCanvasRenderingContextWebGL(nsICanvasRenderingContextWebGL** aResult); @@ -542,7 +543,8 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer, data.mGLBufferIsPremultiplied = PR_FALSE; canvasLayer->Initialize(data); - canvasLayer->SetIsOpaqueContent(gl->CreationFormat().alpha == 0 ? PR_TRUE : PR_FALSE); + PRUint32 flags = gl->CreationFormat().alpha == 0 ? Layer::CONTENT_OPAQUE : 0; + canvasLayer->SetContentFlags(flags); canvasLayer->Updated(nsIntRect(0, 0, mWidth, mHeight)); mInvalidated = PR_FALSE; diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index d76eee6f82e8..49a9e52f909a 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -4174,7 +4174,8 @@ nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer, data.mSize = nsIntSize(mWidth, mHeight); canvasLayer->Initialize(data); - canvasLayer->SetIsOpaqueContent(mOpaque); + PRUint32 flags = mOpaque ? Layer::CONTENT_OPAQUE : 0; + canvasLayer->SetContentFlags(flags); canvasLayer->Updated(nsIntRect(0, 0, mWidth, mHeight)); mResetLayer = PR_FALSE; diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index cccbd3d76a4d..d622b01a5e9e 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -147,7 +147,7 @@ Layer::CanUseOpaqueSurface() { // If the visible content in the layer is opaque, there is no need // for an alpha channel. - if (IsOpaqueContent()) + if (GetContentFlags() & CONTENT_OPAQUE) return PR_TRUE; // Also, if this layer is the bottommost layer in a container which // doesn't need an alpha channel, we can use an opaque surface for this @@ -221,14 +221,24 @@ Layer::PrintInfo(nsACString& aTo, const char* aPrefix) if (mUseClipRect) { AppendToString(aTo, mClipRect, " [clip=", "]"); } - if (!mTransform.IsIdentity()) + if (!mTransform.IsIdentity()) { AppendToString(aTo, mTransform, " [transform=", "]"); - if (!mVisibleRegion.IsEmpty()) + } + if (!mVisibleRegion.IsEmpty()) { AppendToString(aTo, mVisibleRegion, " [visible=", "]"); - if (1.0 != mOpacity) + } + if (1.0 != mOpacity) { aTo.AppendPrintf(" [opacity=%g]", mOpacity); - if (IsOpaqueContent()) + } + if (GetContentFlags() & CONTENT_OPAQUE) { aTo += " [opaqueContent]"; + } + if (GetContentFlags() & CONTENT_NO_TEXT) { + aTo += " [noText]"; + } + if (GetContentFlags() & CONTENT_NO_TEXT_OVER_TRANSPARENT) { + aTo += " [noTextOverTransparent]"; + } return aTo; } diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 6643d60f0062..66cd7798ecb9 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -416,17 +416,37 @@ public: */ LayerManager* Manager() { return mManager; } + enum { + /** + * If this is set, the caller is promising that by the end of this + * transaction the entire visible region (as specified by + * SetVisibleRegion) will be filled with opaque content. + */ + CONTENT_OPAQUE = 0x01, + /** + * ThebesLayers only! + * If this is set, the caller is promising that the visible region + * contains no text at all. If this is set, + * CONTENT_NO_TEXT_OVER_TRANSPARENT will also be set. + */ + CONTENT_NO_TEXT = 0x02, + /** + * ThebesLayers only! + * If this is set, the caller is promising that the visible region + * contains no text over transparent pixels (any text, if present, + * is over fully opaque pixels). + */ + CONTENT_NO_TEXT_OVER_TRANSPARENT = 0x04 + }; /** * CONSTRUCTION PHASE ONLY - * If this is called with aOpaque set to true, the caller is promising - * that by the end of this transaction the entire visible region - * (as specified by SetVisibleRegion) will be filled with opaque - * content. This enables some internal quality and performance - * optimizations. + * This lets layout make some promises about what will be drawn into the + * visible region of the ThebesLayer. This enables internal quality + * and performance optimizations. */ - void SetIsOpaqueContent(PRBool aOpaque) + void SetContentFlags(PRUint32 aFlags) { - mIsOpaqueContent = aOpaque; + mContentFlags = aFlags; Mutated(); } /** @@ -509,7 +529,7 @@ public: // These getters can be used anytime. float GetOpacity() { return mOpacity; } const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nsnull; } - PRBool IsOpaqueContent() { return mIsOpaqueContent; } + PRUint32 GetContentFlags() { return mContentFlags; } const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; } ContainerLayer* GetParent() { return mParent; } Layer* GetNextSibling() { return mNextSibling; } @@ -611,7 +631,8 @@ protected: mImplData(aImplData), mOpacity(1.0), mUseClipRect(PR_FALSE), - mIsOpaqueContent(PR_FALSE) + mContentFlags(0), + mUseClipRect(PR_FALSE) {} void Mutated() { mManager->Mutated(this); } @@ -633,8 +654,8 @@ protected: gfx3DMatrix mTransform; float mOpacity; nsIntRect mClipRect; + PRUint32 mContentFlags; PRPackedBool mUseClipRect; - PRPackedBool mIsOpaqueContent; }; /** diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index 217ad5926375..1cbac945e8a8 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -682,7 +682,7 @@ BasicCanvasLayer::Updated(const nsIntRect& aRect) if (mGLContext) { nsRefPtr isurf = new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height), - IsOpaqueContent() + (GetContentFlags() & CONTENT_OPAQUE) ? gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32); if (!isurf || isurf->CairoStatus() != 0) { @@ -793,7 +793,7 @@ MayHaveOverlappingOrTransparentLayers(Layer* aLayer, const nsIntRect& aBounds, nsIntRegion* aDirtyVisibleRegionInContainer) { - if (!aLayer->IsOpaqueContent()) { + if (!(aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE)) { return PR_TRUE; } diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.cpp b/gfx/layers/d3d9/ThebesLayerD3D9.cpp index 2c567b987577..a4147715fb40 100644 --- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp +++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp @@ -46,27 +46,6 @@ namespace mozilla { namespace layers { -// Returns true if it's OK to save the contents of aLayer in an -// opaque surface (a surface without an alpha channel). -// If we can use a surface without an alpha channel, we should, because -// it will often make painting of antialiased text faster and higher -// quality. -static PRBool -UseOpaqueSurface(Layer* aLayer) -{ - // If the visible content in the layer is opaque, there is no need - // for an alpha channel. - if (aLayer->IsOpaqueContent()) - return PR_TRUE; - // Also, if this layer is the bottommost layer in a container which - // doesn't need an alpha channel, we can use an opaque surface for this - // layer too. Any transparent areas must be covered by something else - // in the container. - ContainerLayer* parent = aLayer->GetParent(); - return parent && parent->GetFirstChild() == aLayer && - UseOpaqueSurface(parent); -} - ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager) : ThebesLayer(aManager, NULL) , LayerD3D9(aManager) @@ -104,7 +83,7 @@ ThebesLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion) return; } - D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ? + D3DFORMAT fmt = (CanUseOpaqueSurface() && !mD2DSurface) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8; D3DSURFACE_DESC desc; @@ -198,7 +177,7 @@ ThebesLayerD3D9::RenderLayer() // We differentiate between these formats since D3D9 will only allow us to // call GetDC on an opaque surface. - D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ? + D3DFORMAT fmt = (CanUseOpaqueSurface() && !mD2DSurface) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8; if (mTexture) { @@ -314,7 +293,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion) } #endif - D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8; + D3DFORMAT fmt = CanUseOpaqueSurface() ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8; nsIntRect bounds = aRegion.GetBounds(); gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32; @@ -327,7 +306,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion) nsRefPtr surf; HDC dc; - if (UseOpaqueSurface(this)) { + if (CanUseOpaqueSurface()) { hr = tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surf)); if (FAILED(hr)) { @@ -360,7 +339,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion) LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo(); cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData); - if (UseOpaqueSurface(this)) { + if (CanUseOpaqueSurface()) { surf->ReleaseDC(dc); } else { D3DLOCKED_RECT r; @@ -423,7 +402,7 @@ ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize) D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, getter_AddRefs(mTexture), &sharedHandle); - mD2DSurface = new gfxD2DSurface(sharedHandle, UseOpaqueSurface(this) ? + mD2DSurface = new gfxD2DSurface(sharedHandle, CanUseOpaqueSurface() ? gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA); // If there's an error, go on and do what we always do. @@ -436,7 +415,7 @@ ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize) #endif if (!mTexture) { device()->CreateTexture(aSize.width, aSize.height, 1, - D3DUSAGE_RENDERTARGET, UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8, + D3DUSAGE_RENDERTARGET, CanUseOpaqueSurface() ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL); } } diff --git a/gfx/layers/ipc/PLayers.ipdl b/gfx/layers/ipc/PLayers.ipdl index 7f90abff46c9..fdde16ca6893 100644 --- a/gfx/layers/ipc/PLayers.ipdl +++ b/gfx/layers/ipc/PLayers.ipdl @@ -93,7 +93,7 @@ struct OpCreateImageBuffer { struct CommonLayerAttributes { nsIntRegion visibleRegion; gfx3DMatrix transform; - bool isOpaqueContent; + PRUint32 contentFlags; float opacity; bool useClipRect; nsIntRect clipRect; diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index f0222eb63c08..dc6b1ea6de32 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -271,7 +271,7 @@ ShadowLayerForwarder::EndTransaction(nsTArray* aReplies) CommonLayerAttributes& common = attrs.common(); common.visibleRegion() = mutant->GetVisibleRegion(); common.transform() = mutant->GetTransform(); - common.isOpaqueContent() = mutant->IsOpaqueContent(); + common.contentFlags() = mutant->GetContentFlags(); common.opacity() = mutant->GetOpacity(); common.useClipRect() = !!mutant->GetClipRect(); common.clipRect() = (common.useClipRect() ? diff --git a/gfx/layers/ipc/ShadowLayersParent.cpp b/gfx/layers/ipc/ShadowLayersParent.cpp index 9b4b71428132..e61d886bce39 100644 --- a/gfx/layers/ipc/ShadowLayersParent.cpp +++ b/gfx/layers/ipc/ShadowLayersParent.cpp @@ -229,7 +229,7 @@ ShadowLayersParent::RecvUpdate(const nsTArray& cset, const CommonLayerAttributes& common = attrs.common(); layer->SetVisibleRegion(common.visibleRegion()); - layer->SetIsOpaqueContent(common.isOpaqueContent()); + layer->SetContentFlags(common.contentFlags()); layer->SetOpacity(common.opacity()); layer->SetClipRect(common.useClipRect() ? &common.clipRect() : NULL); layer->SetTransform(common.transform()); diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 1932ea1a5127..d35fa352770d 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -839,7 +839,8 @@ ContainerState::PopThebesLayerData() } userData->mForcedBackgroundColor = backgroundColor; } - layer->SetIsOpaqueContent(isOpaque); + PRUint32 flags = isOpaque ? Layer::CONTENT_OPAQUE : 0; + layer->SetContentFlags(flags); if (lastIndex > 0) { // Since we're going to pop off the last ThebesLayerData, the @@ -1361,7 +1362,8 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder, state.ProcessDisplayItems(aChildren, nsnull); state.Finish(); - containerLayer->SetIsOpaqueContent(aChildren.IsOpaque()); + PRUint32 flags = aChildren.IsOpaque() ? Layer::CONTENT_OPAQUE : 0; + containerLayer->SetContentFlags(flags); return containerLayer.forget(); } From 396aec34d835b116ece14ff5ba6a9f22217dbbef Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 21:18:40 +1200 Subject: [PATCH 010/222] Bug 579276. Part 5: Set CONTENT_NO_TEXT and CONTENT_NO_TEXT_OVER_TRANSPARENT flags. r=tnikkel --- layout/base/FrameLayerBuilder.cpp | 38 +++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index d35fa352770d..b0dcb3c1bcec 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -159,7 +159,8 @@ protected: public: ThebesLayerData() : mActiveScrolledRoot(nsnull), mLayer(nsnull), - mIsSolidColorInVisibleRegion(PR_FALSE) {} + mIsSolidColorInVisibleRegion(PR_FALSE), + mHasText(PR_FALSE), mHasTextOverTransparent(PR_FALSE) {} /** * Record that an item has been added to the ThebesLayer, so we * need to update our regions. @@ -228,6 +229,15 @@ protected: * True if every pixel in mVisibleRegion will have color mSolidColor. */ PRPackedBool mIsSolidColorInVisibleRegion; + /** + * True if there is any text visible in the layer. + */ + PRPackedBool mHasText; + /** + * True if there is any text visible in the layer that's over + * transparent pixels in the layer. + */ + PRPackedBool mHasTextOverTransparent; }; /** @@ -839,7 +849,10 @@ ContainerState::PopThebesLayerData() } userData->mForcedBackgroundColor = backgroundColor; } - PRUint32 flags = isOpaque ? Layer::CONTENT_OPAQUE : 0; + PRUint32 flags = + (isOpaque ? Layer::CONTENT_OPAQUE : 0) | + (data->mHasText ? 0 : Layer::CONTENT_NO_TEXT) | + (data->mHasTextOverTransparent ? 0 : Layer::CONTENT_NO_TEXT_OVER_TRANSPARENT); layer->SetContentFlags(flags); if (lastIndex > 0) { @@ -860,6 +873,22 @@ ContainerState::PopThebesLayerData() mThebesLayerDataStack.RemoveElementAt(lastIndex); } +static PRBool +IsText(nsDisplayItem* aItem) { + switch (aItem->GetType()) { + case nsDisplayItem::TYPE_TEXT: + case nsDisplayItem::TYPE_BULLET: + case nsDisplayItem::TYPE_HEADER_FOOTER: + case nsDisplayItem::TYPE_MATHML_CHAR_FOREGROUND: +#ifdef MOZ_XUL + case nsDisplayItem::TYPE_XUL_TEXT_BOX: +#endif + return PR_TRUE; + default: + return PR_FALSE; + } +} + void ContainerState::ThebesLayerData::Accumulate(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, @@ -899,6 +928,11 @@ ContainerState::ThebesLayerData::Accumulate(nsDisplayListBuilder* aBuilder, if (tmp.GetNumRects() <= 4) { mOpaqueRegion = tmp; } + } else if (IsText(aItem)) { + mHasText = PR_TRUE; + if (!mOpaqueRegion.Contains(aVisibleRect)) { + mHasTextOverTransparent = PR_TRUE; + } } } From 359694e23433cfa051d66091d8742ea124cf4490 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 21:18:41 +1200 Subject: [PATCH 011/222] Bug 579276. Part 6: Add gfxASurface::GetTextQualityInTransparentSurfaces API. r=jrmuizel,sr=vlad --- gfx/thebes/gfxASurface.h | 35 +++++++++++++++++++++++++++++++++- gfx/thebes/gfxD2DSurface.h | 6 ++++++ gfx/thebes/gfxQuartzSurface.h | 4 ++++ gfx/thebes/gfxWindowsSurface.h | 5 +++++ gfx/thebes/gfxXlibSurface.h | 5 +++++ 5 files changed, 54 insertions(+), 1 deletion(-) diff --git a/gfx/thebes/gfxASurface.h b/gfx/thebes/gfxASurface.h index 9ee195608ad0..4a746f717d2b 100644 --- a/gfx/thebes/gfxASurface.h +++ b/gfx/thebes/gfxASurface.h @@ -153,7 +153,40 @@ public: */ virtual PRBool AreSimilarSurfacesSensitiveToContentType() { - return PR_TRUE; + return PR_TRUE; + } + + enum TextQuality { + /** + * TEXT_QUALITY_OK means that text is always rendered to a + * transparent surface just as well as it would be rendered to an + * opaque surface. This would normally only be true if + * subpixel antialiasing is disabled or if the platform's + * transparent surfaces support component alpha. + */ + TEXT_QUALITY_OK, + /** + * TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS means that text is rendered + * to a transparent surface just as well as it would be rendered to an + * opaque surface, but only if all the pixels the text is drawn + * over already have opaque alpha values. + */ + TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS, + /** + * TEXT_QUALITY_BAD means that text is rendered + * to a transparent surface worse than it would be rendered to an + * opaque surface, even if all the pixels the text is drawn + * over already have opaque alpha values. + */ + TEXT_QUALITY_BAD + }; + /** + * Determine how well text would be rendered in transparent surfaces that + * are similar to this surface. + */ + virtual TextQuality GetTextQualityInTransparentSurfaces() + { + return TEXT_QUALITY_BAD; } int CairoStatus(); diff --git a/gfx/thebes/gfxD2DSurface.h b/gfx/thebes/gfxD2DSurface.h index 1a3d641fdc57..3a08ffc5e103 100644 --- a/gfx/thebes/gfxD2DSurface.h +++ b/gfx/thebes/gfxD2DSurface.h @@ -57,6 +57,12 @@ public: virtual ~gfxD2DSurface(); + virtual TextQuality GetTextQualityInTransparentSurfaces() + { + // D2D always draws text in transparent surfaces with grayscale-AA, + // even if the text is over opaque pixels. + return TEXT_QUALITY_BAD; + } void Present(); void Scroll(const nsIntPoint &aDelta, const nsIntRect &aClip); diff --git a/gfx/thebes/gfxQuartzSurface.h b/gfx/thebes/gfxQuartzSurface.h index 5fbbe4040865..1fd5fd773175 100644 --- a/gfx/thebes/gfxQuartzSurface.h +++ b/gfx/thebes/gfxQuartzSurface.h @@ -60,6 +60,10 @@ public: { return PR_FALSE; } + virtual TextQuality GetTextQualityInTransparentSurfaces() + { + return TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS; + } const gfxSize& GetSize() const { return mSize; } diff --git a/gfx/thebes/gfxWindowsSurface.h b/gfx/thebes/gfxWindowsSurface.h index 20230ec799b6..0da4fe3d1f77 100644 --- a/gfx/thebes/gfxWindowsSurface.h +++ b/gfx/thebes/gfxWindowsSurface.h @@ -81,6 +81,11 @@ public: const gfxIntSize& size, gfxImageFormat format); + virtual TextQuality GetTextQualityInTransparentSurfaces() + { + return TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS; + } + nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName); nsresult EndPrinting(); nsresult AbortPrinting(); diff --git a/gfx/thebes/gfxXlibSurface.h b/gfx/thebes/gfxXlibSurface.h index ad07f74d1efe..e3b1d1f0b613 100644 --- a/gfx/thebes/gfxXlibSurface.h +++ b/gfx/thebes/gfxXlibSurface.h @@ -77,6 +77,11 @@ public: virtual already_AddRefed CreateSimilarSurface(gfxContentType aType, const gfxIntSize& aSize); + virtual TextQuality GetTextQualityInTransparentSurfaces() + { + return TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS; + } + const gfxIntSize& GetSize() { return mSize; } Display* XDisplay() { return mDisplay; } From 2fb2fc7212c953d52a05a873bb38abfa3d0fff82 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 21:18:41 +1200 Subject: [PATCH 012/222] Bug 579276. Part 7: Don't retain transparent layers that would hurt text rendering. r=cjones --- gfx/layers/basic/BasicLayers.cpp | 41 +++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index 1cbac945e8a8..1bb1a8e539a9 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -367,6 +367,23 @@ InheritContextFlags(gfxContext* aSource, gfxContext* aDest) } } +static PRBool +ShouldRetainTransparentSurface(PRUint32 aContentFlags, + gfxASurface* aTargetSurface) +{ + if (aContentFlags & Layer::CONTENT_NO_TEXT) + return PR_TRUE; + + switch (aTargetSurface->GetTextQualityInTransparentSurfaces()) { + case gfxASurface::TEXT_QUALITY_OK: + return PR_TRUE; + case gfxASurface::TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS: + return (aContentFlags & Layer::CONTENT_NO_TEXT_OVER_TRANSPARENT) != 0; + default: + return PR_FALSE; + } +} + void BasicThebesLayer::Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, @@ -377,15 +394,20 @@ BasicThebesLayer::Paint(gfxContext* aContext, "Can only draw in drawing phase"); gfxContext* target = BasicManager()->GetTarget(); NS_ASSERTION(target, "We shouldn't be called if there's no target"); + nsRefPtr targetSurface = aContext->CurrentSurface(); + + PRBool canUseOpaqueSurface = CanUseOpaqueSurface(); + if (!BasicManager()->IsRetained() || + (aOpacity == 1.0 && !canUseOpaqueSurface && + !ShouldRetainTransparentSurface(mContentFlags, targetSurface))) { + mValidRegion.SetEmpty(); + mBuffer.Clear(); - if (!BasicManager()->IsRetained()) { if (aOpacity != 1.0) { target->Save(); ClipToContain(target, mVisibleRegion.GetBounds()); target->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA); } - mValidRegion.SetEmpty(); - mBuffer.Clear(); aCallback(this, target, mVisibleRegion, nsIntRegion(), aCallbackData); if (aOpacity != 1.0) { target->PopGroupToSource(); @@ -395,15 +417,12 @@ BasicThebesLayer::Paint(gfxContext* aContext, return; } - nsRefPtr targetSurface = aContext->CurrentSurface(); - PRBool isOpaqueContent = - (targetSurface->AreSimilarSurfacesSensitiveToContentType() && - aOpacity == 1.0 && - CanUseOpaqueSurface()); { + PRBool opaqueBuffer = canUseOpaqueSurface && + targetSurface->AreSimilarSurfacesSensitiveToContentType(); Buffer::ContentType contentType = - isOpaqueContent ? gfxASurface::CONTENT_COLOR : - gfxASurface::CONTENT_COLOR_ALPHA; + opaqueBuffer ? gfxASurface::CONTENT_COLOR : + gfxASurface::CONTENT_COLOR_ALPHA; Buffer::PaintState state = mBuffer.BeginPaint(this, contentType); mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate); @@ -425,7 +444,7 @@ BasicThebesLayer::Paint(gfxContext* aContext, } } - mBuffer.DrawTo(this, isOpaqueContent, target, aOpacity); + mBuffer.DrawTo(this, canUseOpaqueSurface, target, aOpacity); } void From 7cf896283abf3df90f74ef21070e0fd0d9dd36dd Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 21:18:41 +1200 Subject: [PATCH 013/222] Bug 579276. Part 9: Backout 4d1dc2ea47fd since we no longer need those test changes --- layout/reftests/bidi/logicalmarquee.html | 2 +- layout/reftests/bidi/marquee-ref.html | 2 +- layout/reftests/bidi/visualmarquee.html | 2 +- layout/reftests/marquee/413027-4-ref.html | 2 +- layout/reftests/marquee/413027-4.html | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/layout/reftests/bidi/logicalmarquee.html b/layout/reftests/bidi/logicalmarquee.html index 9ba9d6306cf4..cb13827dec7b 100644 --- a/layout/reftests/bidi/logicalmarquee.html +++ b/layout/reftests/bidi/logicalmarquee.html @@ -6,6 +6,6 @@ - עד שיפוח היום ונסו הצלילים + עד שיפוח היום ונסו הצלילים diff --git a/layout/reftests/bidi/marquee-ref.html b/layout/reftests/bidi/marquee-ref.html index 724e4f8559d2..d8778dc88063 100644 --- a/layout/reftests/bidi/marquee-ref.html +++ b/layout/reftests/bidi/marquee-ref.html @@ -6,6 +6,6 @@ -
עד שיפוח היום ונסו הצלילים
+
עד שיפוח היום ונסו הצלילים
diff --git a/layout/reftests/bidi/visualmarquee.html b/layout/reftests/bidi/visualmarquee.html index 51a559469124..932fd775a191 100644 --- a/layout/reftests/bidi/visualmarquee.html +++ b/layout/reftests/bidi/visualmarquee.html @@ -6,6 +6,6 @@ - םילילצה וסנו םויה חופיש דע + םילילצה וסנו םויה חופיש דע diff --git a/layout/reftests/marquee/413027-4-ref.html b/layout/reftests/marquee/413027-4-ref.html index fbe705e414da..22fdd42e6016 100644 --- a/layout/reftests/marquee/413027-4-ref.html +++ b/layout/reftests/marquee/413027-4-ref.html @@ -4,7 +4,7 @@
-
text
+
text
diff --git a/layout/reftests/marquee/413027-4.html b/layout/reftests/marquee/413027-4.html index beb15e6f752a..d57f2f121517 100644 --- a/layout/reftests/marquee/413027-4.html +++ b/layout/reftests/marquee/413027-4.html @@ -8,7 +8,7 @@ -
text
+
text
From 83b82d6db1dd2c5a4fbd582937fa0c471d0d2aab Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 21:19:24 +1200 Subject: [PATCH 014/222] Bug 579276. Part 10: add a couple of scrolling tests to ensure that text looks good when scrolled in an overflow:auto div. a=blocking --- layout/reftests/scrolling/fixed-text-1.html | 7 +++++++ layout/reftests/scrolling/reftest.list | 2 ++ layout/reftests/scrolling/text-1.html | 10 ++++++++++ 3 files changed, 19 insertions(+) create mode 100644 layout/reftests/scrolling/fixed-text-1.html create mode 100644 layout/reftests/scrolling/text-1.html diff --git a/layout/reftests/scrolling/fixed-text-1.html b/layout/reftests/scrolling/fixed-text-1.html new file mode 100644 index 000000000000..d470a7c6415d --- /dev/null +++ b/layout/reftests/scrolling/fixed-text-1.html @@ -0,0 +1,7 @@ + + + + +

Hello Kitty + + diff --git a/layout/reftests/scrolling/reftest.list b/layout/reftests/scrolling/reftest.list index bfdc32a7ad77..e227cefd356b 100644 --- a/layout/reftests/scrolling/reftest.list +++ b/layout/reftests/scrolling/reftest.list @@ -1,5 +1,7 @@ HTTP == fixed-1.html fixed-1.html?ref +HTTP == fixed-text-1.html fixed-text-1.html?ref HTTP == opacity-mixed-scrolling-1.html opacity-mixed-scrolling-1.html?ref HTTP == simple-1.html simple-1.html?ref +HTTP == text-1.html text-1.html?ref == uncovering-1.html uncovering-1-ref.html == uncovering-2.html uncovering-2-ref.html diff --git a/layout/reftests/scrolling/text-1.html b/layout/reftests/scrolling/text-1.html new file mode 100644 index 000000000000..0ede92a6fa28 --- /dev/null +++ b/layout/reftests/scrolling/text-1.html @@ -0,0 +1,10 @@ + + + + +

+
Hello Kitty
+
+
+ + From df7ddc69f934b510816948e190674e00c338e8c8 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 22:15:17 +1200 Subject: [PATCH 015/222] Fixing bustage, a=me --- gfx/layers/Layers.h | 1 - 1 file changed, 1 deletion(-) diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 66cd7798ecb9..fe1e996f2979 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -630,7 +630,6 @@ protected: mPrevSibling(nsnull), mImplData(aImplData), mOpacity(1.0), - mUseClipRect(PR_FALSE), mContentFlags(0), mUseClipRect(PR_FALSE) {} From cfb7f48514d4f9338fa55ecbbd1e9ccf1bcd1c65 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 23:14:25 +1200 Subject: [PATCH 016/222] Backing out bug 579276. a=me --- content/canvas/src/WebGLContext.cpp | 8 +- .../canvas/src/nsCanvasRenderingContext2D.cpp | 7 +- gfx/layers/Layers.cpp | 20 +- gfx/layers/Layers.h | 155 ++------- gfx/layers/basic/BasicLayers.cpp | 45 +-- gfx/layers/d3d9/ThebesLayerD3D9.cpp | 35 ++- gfx/layers/ipc/PLayers.ipdl | 2 +- gfx/layers/ipc/ShadowLayers.cpp | 2 +- gfx/layers/ipc/ShadowLayersParent.cpp | 2 +- gfx/thebes/gfxASurface.h | 35 +-- gfx/thebes/gfxD2DSurface.h | 6 - gfx/thebes/gfxQuartzSurface.h | 4 - gfx/thebes/gfxWindowsSurface.h | 5 - gfx/thebes/gfxXlibSurface.h | 5 - layout/base/FrameLayerBuilder.cpp | 297 +++++------------- layout/base/FrameLayerBuilder.h | 20 -- layout/generic/nsGfxScrollFrame.cpp | 6 +- layout/reftests/bidi/logicalmarquee.html | 2 +- layout/reftests/bidi/marquee-ref.html | 2 +- layout/reftests/bidi/visualmarquee.html | 2 +- layout/reftests/marquee/413027-4-ref.html | 2 +- layout/reftests/marquee/413027-4.html | 2 +- layout/reftests/scrolling/fixed-text-1.html | 7 - layout/reftests/scrolling/reftest.list | 2 - layout/reftests/scrolling/text-1.html | 10 - 25 files changed, 162 insertions(+), 521 deletions(-) delete mode 100644 layout/reftests/scrolling/fixed-text-1.html delete mode 100644 layout/reftests/scrolling/text-1.html diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index 071c3a3804fa..5b4f9dfbc177 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -63,7 +63,6 @@ using namespace mozilla; using namespace mozilla::gl; -using namespace mozilla::layers; nsresult NS_NewCanvasRenderingContextWebGL(nsICanvasRenderingContextWebGL** aResult); @@ -509,7 +508,7 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer, LayerManager *aManager) { if (!mResetLayer && aOldLayer && - aOldLayer->HasUserData(&gWebGLLayerUserData)) { + aOldLayer->GetUserData() == &gWebGLLayerUserData) { NS_ADDREF(aOldLayer); if (mInvalidated) { aOldLayer->Updated(nsIntRect(0, 0, mWidth, mHeight)); @@ -523,7 +522,7 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer, NS_WARNING("CreateCanvasLayer returned null!"); return nsnull; } - canvasLayer->SetUserData(&gWebGLLayerUserData, nsnull); + canvasLayer->SetUserData(&gWebGLLayerUserData); CanvasLayer::Data data; @@ -543,8 +542,7 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer, data.mGLBufferIsPremultiplied = PR_FALSE; canvasLayer->Initialize(data); - PRUint32 flags = gl->CreationFormat().alpha == 0 ? Layer::CONTENT_OPAQUE : 0; - canvasLayer->SetContentFlags(flags); + canvasLayer->SetIsOpaqueContent(gl->CreationFormat().alpha == 0 ? PR_TRUE : PR_FALSE); canvasLayer->Updated(nsIntRect(0, 0, mWidth, mHeight)); mInvalidated = PR_FALSE; diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index 49a9e52f909a..c0a9f753d196 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -4154,7 +4154,7 @@ nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer, return nsnull; if (!mResetLayer && aOldLayer && - aOldLayer->HasUserData(&g2DContextLayerUserData)) { + aOldLayer->GetUserData() == &g2DContextLayerUserData) { NS_ADDREF(aOldLayer); // XXX Need to just update the changed area here aOldLayer->Updated(nsIntRect(0, 0, mWidth, mHeight)); @@ -4166,7 +4166,7 @@ nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer, NS_WARNING("CreateCanvasLayer returned null!"); return nsnull; } - canvasLayer->SetUserData(&g2DContextLayerUserData, nsnull); + canvasLayer->SetUserData(&g2DContextLayerUserData); CanvasLayer::Data data; @@ -4174,8 +4174,7 @@ nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer, data.mSize = nsIntSize(mWidth, mHeight); canvasLayer->Initialize(data); - PRUint32 flags = mOpaque ? Layer::CONTENT_OPAQUE : 0; - canvasLayer->SetContentFlags(flags); + canvasLayer->SetIsOpaqueContent(mOpaque); canvasLayer->Updated(nsIntRect(0, 0, mWidth, mHeight)); mResetLayer = PR_FALSE; diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index d622b01a5e9e..cccbd3d76a4d 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -147,7 +147,7 @@ Layer::CanUseOpaqueSurface() { // If the visible content in the layer is opaque, there is no need // for an alpha channel. - if (GetContentFlags() & CONTENT_OPAQUE) + if (IsOpaqueContent()) return PR_TRUE; // Also, if this layer is the bottommost layer in a container which // doesn't need an alpha channel, we can use an opaque surface for this @@ -221,24 +221,14 @@ Layer::PrintInfo(nsACString& aTo, const char* aPrefix) if (mUseClipRect) { AppendToString(aTo, mClipRect, " [clip=", "]"); } - if (!mTransform.IsIdentity()) { + if (!mTransform.IsIdentity()) AppendToString(aTo, mTransform, " [transform=", "]"); - } - if (!mVisibleRegion.IsEmpty()) { + if (!mVisibleRegion.IsEmpty()) AppendToString(aTo, mVisibleRegion, " [visible=", "]"); - } - if (1.0 != mOpacity) { + if (1.0 != mOpacity) aTo.AppendPrintf(" [opacity=%g]", mOpacity); - } - if (GetContentFlags() & CONTENT_OPAQUE) { + if (IsOpaqueContent()) aTo += " [opaqueContent]"; - } - if (GetContentFlags() & CONTENT_NO_TEXT) { - aTo += " [noText]"; - } - if (GetContentFlags() & CONTENT_NO_TEXT_OVER_TRANSPARENT) { - aTo += " [noTextOverTransparent]"; - } return aTo; } diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index fe1e996f2979..47a9baab9b75 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -83,14 +83,6 @@ class SpecificLayerAttributes; virtual const char* Name() const { return n; } \ virtual LayerType GetType() const { return e; } -/** - * Base class for userdata objects attached to layers and layer managers. - */ -class THEBES_API LayerUserData { -public: - virtual ~LayerUserData() {} -}; - /* * Motivation: For truly smooth animation and video playback, we need to * be able to compose frames and render them on a dedicated thread (i.e. @@ -117,52 +109,6 @@ public: * BasicLayerManager for such an implementation. */ -/** - * Helper class to manage user data for layers and LayerManagers. - */ -class THEBES_API LayerUserDataSet { -public: - LayerUserDataSet() : mKey(nsnull) {} - - void Set(void* aKey, LayerUserData* aValue) - { - NS_ASSERTION(!mKey || mKey == aKey, - "Multiple LayerUserData objects not supported"); - mKey = aKey; - mValue = aValue; - } - /** - * This can be used anytime. Ownership passes to the caller! - */ - LayerUserData* Remove(void* aKey) - { - if (mKey == aKey) { - mKey = nsnull; - LayerUserData* d = mValue.forget(); - return d; - } - return nsnull; - } - /** - * This getter can be used anytime. - */ - PRBool Has(void* aKey) - { - return mKey == aKey; - } - /** - * This getter can be used anytime. Ownership is retained by this object. - */ - LayerUserData* Get(void* aKey) - { - return mKey == aKey ? mValue.get() : nsnull; - } - -private: - void* mKey; - nsAutoPtr mValue; -}; - /** * A LayerManager controls a tree of layers. All layers in the tree * must use the same LayerManager. @@ -196,7 +142,7 @@ public: LAYERS_D3D9 }; - LayerManager() : mDestroyed(PR_FALSE) + LayerManager() : mUserData(nsnull), mDestroyed(PR_FALSE) { InitLog(); } @@ -321,28 +267,10 @@ public: */ virtual LayersBackend GetBackendType() = 0; - /** - * This setter can be used anytime. The user data for all keys is - * initially null. Ownership pases to the layer manager. - */ - void SetUserData(void* aKey, LayerUserData* aData) - { mUserData.Set(aKey, aData); } - /** - * This can be used anytime. Ownership passes to the caller! - */ - nsAutoPtr RemoveUserData(void* aKey) - { nsAutoPtr d(mUserData.Remove(aKey)); return d; } - /** - * This getter can be used anytime. - */ - PRBool HasUserData(void* aKey) - { return mUserData.Has(aKey); } - /** - * This getter can be used anytime. Ownership is retained by the layer - * manager. - */ - LayerUserData* GetUserData(void* aKey) - { return mUserData.Get(aKey); } + // This setter and getter can be used anytime. The user data is initially + // null. + void SetUserData(void* aData) { mUserData = aData; } + void* GetUserData() { return mUserData; } // We always declare the following logging symbols, because it's // extremely tricky to conditionally declare them. However, for @@ -377,7 +305,7 @@ public: protected: nsRefPtr mRoot; - LayerUserDataSet mUserData; + void* mUserData; PRPackedBool mDestroyed; // Print interesting information about this into aTo. Internally @@ -416,37 +344,17 @@ public: */ LayerManager* Manager() { return mManager; } - enum { - /** - * If this is set, the caller is promising that by the end of this - * transaction the entire visible region (as specified by - * SetVisibleRegion) will be filled with opaque content. - */ - CONTENT_OPAQUE = 0x01, - /** - * ThebesLayers only! - * If this is set, the caller is promising that the visible region - * contains no text at all. If this is set, - * CONTENT_NO_TEXT_OVER_TRANSPARENT will also be set. - */ - CONTENT_NO_TEXT = 0x02, - /** - * ThebesLayers only! - * If this is set, the caller is promising that the visible region - * contains no text over transparent pixels (any text, if present, - * is over fully opaque pixels). - */ - CONTENT_NO_TEXT_OVER_TRANSPARENT = 0x04 - }; /** * CONSTRUCTION PHASE ONLY - * This lets layout make some promises about what will be drawn into the - * visible region of the ThebesLayer. This enables internal quality - * and performance optimizations. + * If this is called with aOpaque set to true, the caller is promising + * that by the end of this transaction the entire visible region + * (as specified by SetVisibleRegion) will be filled with opaque + * content. This enables some internal quality and performance + * optimizations. */ - void SetContentFlags(PRUint32 aFlags) + void SetIsOpaqueContent(PRBool aOpaque) { - mContentFlags = aFlags; + mIsOpaqueContent = aOpaque; Mutated(); } /** @@ -529,7 +437,7 @@ public: // These getters can be used anytime. float GetOpacity() { return mOpacity; } const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nsnull; } - PRUint32 GetContentFlags() { return mContentFlags; } + PRBool IsOpaqueContent() { return mIsOpaqueContent; } const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; } ContainerLayer* GetParent() { return mParent; } Layer* GetNextSibling() { return mNextSibling; } @@ -552,28 +460,10 @@ public: // quality. PRBool CanUseOpaqueSurface(); - /** - * This setter can be used anytime. The user data for all keys is - * initially null. Ownership pases to the layer manager. - */ - void SetUserData(void* aKey, LayerUserData* aData) - { mUserData.Set(aKey, aData); } - /** - * This can be used anytime. Ownership passes to the caller! - */ - nsAutoPtr RemoveUserData(void* aKey) - { nsAutoPtr d(mUserData.Remove(aKey)); return d; } - /** - * This getter can be used anytime. - */ - PRBool HasUserData(void* aKey) - { return mUserData.Has(aKey); } - /** - * This getter can be used anytime. Ownership is retained by the layer - * manager. - */ - LayerUserData* GetUserData(void* aKey) - { return mUserData.Get(aKey); } + // This setter and getter can be used anytime. The user data is initially + // null. + void SetUserData(void* aData) { mUserData = aData; } + void* GetUserData() { return mUserData; } /** * Dynamic downcast to a Thebes layer. Returns null if this is not @@ -629,9 +519,10 @@ protected: mNextSibling(nsnull), mPrevSibling(nsnull), mImplData(aImplData), + mUserData(nsnull), mOpacity(1.0), - mContentFlags(0), - mUseClipRect(PR_FALSE) + mUseClipRect(PR_FALSE), + mIsOpaqueContent(PR_FALSE) {} void Mutated() { mManager->Mutated(this); } @@ -648,13 +539,13 @@ protected: Layer* mNextSibling; Layer* mPrevSibling; void* mImplData; - LayerUserDataSet mUserData; + void* mUserData; nsIntRegion mVisibleRegion; gfx3DMatrix mTransform; float mOpacity; nsIntRect mClipRect; - PRUint32 mContentFlags; PRPackedBool mUseClipRect; + PRPackedBool mIsOpaqueContent; }; /** diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index 1bb1a8e539a9..217ad5926375 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -367,23 +367,6 @@ InheritContextFlags(gfxContext* aSource, gfxContext* aDest) } } -static PRBool -ShouldRetainTransparentSurface(PRUint32 aContentFlags, - gfxASurface* aTargetSurface) -{ - if (aContentFlags & Layer::CONTENT_NO_TEXT) - return PR_TRUE; - - switch (aTargetSurface->GetTextQualityInTransparentSurfaces()) { - case gfxASurface::TEXT_QUALITY_OK: - return PR_TRUE; - case gfxASurface::TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS: - return (aContentFlags & Layer::CONTENT_NO_TEXT_OVER_TRANSPARENT) != 0; - default: - return PR_FALSE; - } -} - void BasicThebesLayer::Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, @@ -394,20 +377,15 @@ BasicThebesLayer::Paint(gfxContext* aContext, "Can only draw in drawing phase"); gfxContext* target = BasicManager()->GetTarget(); NS_ASSERTION(target, "We shouldn't be called if there's no target"); - nsRefPtr targetSurface = aContext->CurrentSurface(); - - PRBool canUseOpaqueSurface = CanUseOpaqueSurface(); - if (!BasicManager()->IsRetained() || - (aOpacity == 1.0 && !canUseOpaqueSurface && - !ShouldRetainTransparentSurface(mContentFlags, targetSurface))) { - mValidRegion.SetEmpty(); - mBuffer.Clear(); + if (!BasicManager()->IsRetained()) { if (aOpacity != 1.0) { target->Save(); ClipToContain(target, mVisibleRegion.GetBounds()); target->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA); } + mValidRegion.SetEmpty(); + mBuffer.Clear(); aCallback(this, target, mVisibleRegion, nsIntRegion(), aCallbackData); if (aOpacity != 1.0) { target->PopGroupToSource(); @@ -417,12 +395,15 @@ BasicThebesLayer::Paint(gfxContext* aContext, return; } + nsRefPtr targetSurface = aContext->CurrentSurface(); + PRBool isOpaqueContent = + (targetSurface->AreSimilarSurfacesSensitiveToContentType() && + aOpacity == 1.0 && + CanUseOpaqueSurface()); { - PRBool opaqueBuffer = canUseOpaqueSurface && - targetSurface->AreSimilarSurfacesSensitiveToContentType(); Buffer::ContentType contentType = - opaqueBuffer ? gfxASurface::CONTENT_COLOR : - gfxASurface::CONTENT_COLOR_ALPHA; + isOpaqueContent ? gfxASurface::CONTENT_COLOR : + gfxASurface::CONTENT_COLOR_ALPHA; Buffer::PaintState state = mBuffer.BeginPaint(this, contentType); mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate); @@ -444,7 +425,7 @@ BasicThebesLayer::Paint(gfxContext* aContext, } } - mBuffer.DrawTo(this, canUseOpaqueSurface, target, aOpacity); + mBuffer.DrawTo(this, isOpaqueContent, target, aOpacity); } void @@ -701,7 +682,7 @@ BasicCanvasLayer::Updated(const nsIntRect& aRect) if (mGLContext) { nsRefPtr isurf = new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height), - (GetContentFlags() & CONTENT_OPAQUE) + IsOpaqueContent() ? gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32); if (!isurf || isurf->CairoStatus() != 0) { @@ -812,7 +793,7 @@ MayHaveOverlappingOrTransparentLayers(Layer* aLayer, const nsIntRect& aBounds, nsIntRegion* aDirtyVisibleRegionInContainer) { - if (!(aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE)) { + if (!aLayer->IsOpaqueContent()) { return PR_TRUE; } diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.cpp b/gfx/layers/d3d9/ThebesLayerD3D9.cpp index a4147715fb40..2c567b987577 100644 --- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp +++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp @@ -46,6 +46,27 @@ namespace mozilla { namespace layers { +// Returns true if it's OK to save the contents of aLayer in an +// opaque surface (a surface without an alpha channel). +// If we can use a surface without an alpha channel, we should, because +// it will often make painting of antialiased text faster and higher +// quality. +static PRBool +UseOpaqueSurface(Layer* aLayer) +{ + // If the visible content in the layer is opaque, there is no need + // for an alpha channel. + if (aLayer->IsOpaqueContent()) + return PR_TRUE; + // Also, if this layer is the bottommost layer in a container which + // doesn't need an alpha channel, we can use an opaque surface for this + // layer too. Any transparent areas must be covered by something else + // in the container. + ContainerLayer* parent = aLayer->GetParent(); + return parent && parent->GetFirstChild() == aLayer && + UseOpaqueSurface(parent); +} + ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager) : ThebesLayer(aManager, NULL) , LayerD3D9(aManager) @@ -83,7 +104,7 @@ ThebesLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion) return; } - D3DFORMAT fmt = (CanUseOpaqueSurface() && !mD2DSurface) ? + D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8; D3DSURFACE_DESC desc; @@ -177,7 +198,7 @@ ThebesLayerD3D9::RenderLayer() // We differentiate between these formats since D3D9 will only allow us to // call GetDC on an opaque surface. - D3DFORMAT fmt = (CanUseOpaqueSurface() && !mD2DSurface) ? + D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8; if (mTexture) { @@ -293,7 +314,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion) } #endif - D3DFORMAT fmt = CanUseOpaqueSurface() ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8; + D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8; nsIntRect bounds = aRegion.GetBounds(); gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32; @@ -306,7 +327,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion) nsRefPtr surf; HDC dc; - if (CanUseOpaqueSurface()) { + if (UseOpaqueSurface(this)) { hr = tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surf)); if (FAILED(hr)) { @@ -339,7 +360,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion) LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo(); cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData); - if (CanUseOpaqueSurface()) { + if (UseOpaqueSurface(this)) { surf->ReleaseDC(dc); } else { D3DLOCKED_RECT r; @@ -402,7 +423,7 @@ ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize) D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, getter_AddRefs(mTexture), &sharedHandle); - mD2DSurface = new gfxD2DSurface(sharedHandle, CanUseOpaqueSurface() ? + mD2DSurface = new gfxD2DSurface(sharedHandle, UseOpaqueSurface(this) ? gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA); // If there's an error, go on and do what we always do. @@ -415,7 +436,7 @@ ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize) #endif if (!mTexture) { device()->CreateTexture(aSize.width, aSize.height, 1, - D3DUSAGE_RENDERTARGET, CanUseOpaqueSurface() ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8, + D3DUSAGE_RENDERTARGET, UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL); } } diff --git a/gfx/layers/ipc/PLayers.ipdl b/gfx/layers/ipc/PLayers.ipdl index fdde16ca6893..7f90abff46c9 100644 --- a/gfx/layers/ipc/PLayers.ipdl +++ b/gfx/layers/ipc/PLayers.ipdl @@ -93,7 +93,7 @@ struct OpCreateImageBuffer { struct CommonLayerAttributes { nsIntRegion visibleRegion; gfx3DMatrix transform; - PRUint32 contentFlags; + bool isOpaqueContent; float opacity; bool useClipRect; nsIntRect clipRect; diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index dc6b1ea6de32..f0222eb63c08 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -271,7 +271,7 @@ ShadowLayerForwarder::EndTransaction(nsTArray* aReplies) CommonLayerAttributes& common = attrs.common(); common.visibleRegion() = mutant->GetVisibleRegion(); common.transform() = mutant->GetTransform(); - common.contentFlags() = mutant->GetContentFlags(); + common.isOpaqueContent() = mutant->IsOpaqueContent(); common.opacity() = mutant->GetOpacity(); common.useClipRect() = !!mutant->GetClipRect(); common.clipRect() = (common.useClipRect() ? diff --git a/gfx/layers/ipc/ShadowLayersParent.cpp b/gfx/layers/ipc/ShadowLayersParent.cpp index e61d886bce39..9b4b71428132 100644 --- a/gfx/layers/ipc/ShadowLayersParent.cpp +++ b/gfx/layers/ipc/ShadowLayersParent.cpp @@ -229,7 +229,7 @@ ShadowLayersParent::RecvUpdate(const nsTArray& cset, const CommonLayerAttributes& common = attrs.common(); layer->SetVisibleRegion(common.visibleRegion()); - layer->SetContentFlags(common.contentFlags()); + layer->SetIsOpaqueContent(common.isOpaqueContent()); layer->SetOpacity(common.opacity()); layer->SetClipRect(common.useClipRect() ? &common.clipRect() : NULL); layer->SetTransform(common.transform()); diff --git a/gfx/thebes/gfxASurface.h b/gfx/thebes/gfxASurface.h index 4a746f717d2b..9ee195608ad0 100644 --- a/gfx/thebes/gfxASurface.h +++ b/gfx/thebes/gfxASurface.h @@ -153,40 +153,7 @@ public: */ virtual PRBool AreSimilarSurfacesSensitiveToContentType() { - return PR_TRUE; - } - - enum TextQuality { - /** - * TEXT_QUALITY_OK means that text is always rendered to a - * transparent surface just as well as it would be rendered to an - * opaque surface. This would normally only be true if - * subpixel antialiasing is disabled or if the platform's - * transparent surfaces support component alpha. - */ - TEXT_QUALITY_OK, - /** - * TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS means that text is rendered - * to a transparent surface just as well as it would be rendered to an - * opaque surface, but only if all the pixels the text is drawn - * over already have opaque alpha values. - */ - TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS, - /** - * TEXT_QUALITY_BAD means that text is rendered - * to a transparent surface worse than it would be rendered to an - * opaque surface, even if all the pixels the text is drawn - * over already have opaque alpha values. - */ - TEXT_QUALITY_BAD - }; - /** - * Determine how well text would be rendered in transparent surfaces that - * are similar to this surface. - */ - virtual TextQuality GetTextQualityInTransparentSurfaces() - { - return TEXT_QUALITY_BAD; + return PR_TRUE; } int CairoStatus(); diff --git a/gfx/thebes/gfxD2DSurface.h b/gfx/thebes/gfxD2DSurface.h index 3a08ffc5e103..1a3d641fdc57 100644 --- a/gfx/thebes/gfxD2DSurface.h +++ b/gfx/thebes/gfxD2DSurface.h @@ -57,12 +57,6 @@ public: virtual ~gfxD2DSurface(); - virtual TextQuality GetTextQualityInTransparentSurfaces() - { - // D2D always draws text in transparent surfaces with grayscale-AA, - // even if the text is over opaque pixels. - return TEXT_QUALITY_BAD; - } void Present(); void Scroll(const nsIntPoint &aDelta, const nsIntRect &aClip); diff --git a/gfx/thebes/gfxQuartzSurface.h b/gfx/thebes/gfxQuartzSurface.h index 1fd5fd773175..5fbbe4040865 100644 --- a/gfx/thebes/gfxQuartzSurface.h +++ b/gfx/thebes/gfxQuartzSurface.h @@ -60,10 +60,6 @@ public: { return PR_FALSE; } - virtual TextQuality GetTextQualityInTransparentSurfaces() - { - return TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS; - } const gfxSize& GetSize() const { return mSize; } diff --git a/gfx/thebes/gfxWindowsSurface.h b/gfx/thebes/gfxWindowsSurface.h index 0da4fe3d1f77..20230ec799b6 100644 --- a/gfx/thebes/gfxWindowsSurface.h +++ b/gfx/thebes/gfxWindowsSurface.h @@ -81,11 +81,6 @@ public: const gfxIntSize& size, gfxImageFormat format); - virtual TextQuality GetTextQualityInTransparentSurfaces() - { - return TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS; - } - nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName); nsresult EndPrinting(); nsresult AbortPrinting(); diff --git a/gfx/thebes/gfxXlibSurface.h b/gfx/thebes/gfxXlibSurface.h index e3b1d1f0b613..ad07f74d1efe 100644 --- a/gfx/thebes/gfxXlibSurface.h +++ b/gfx/thebes/gfxXlibSurface.h @@ -77,11 +77,6 @@ public: virtual already_AddRefed CreateSimilarSurface(gfxContentType aType, const gfxIntSize& aSize); - virtual TextQuality GetTextQualityInTransparentSurfaces() - { - return TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS; - } - const gfxIntSize& GetSize() { return mSize; } Display* XDisplay() { return mDisplay; } diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index b0dcb3c1bcec..01c9797f776b 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -57,22 +57,14 @@ namespace { /** * This is the userdata we associate with a layer manager. */ -class LayerManagerData : public LayerUserData { +class LayerManagerData { public: LayerManagerData() : mInvalidateAllThebesContent(PR_FALSE), mInvalidateAllLayers(PR_FALSE) { - MOZ_COUNT_CTOR(LayerManagerData); mFramesWithLayers.Init(); } - ~LayerManagerData() { - // Remove display item data properties now, since we won't be able - // to find these frames again without mFramesWithLayers. - mFramesWithLayers.EnumerateEntries( - FrameLayerBuilder::RemoveDisplayItemDataForFrame, nsnull); - MOZ_COUNT_DTOR(LayerManagerData); - } /** * Tracks which frames have layers associated with them. @@ -159,8 +151,7 @@ protected: public: ThebesLayerData() : mActiveScrolledRoot(nsnull), mLayer(nsnull), - mIsSolidColorInVisibleRegion(PR_FALSE), - mHasText(PR_FALSE), mHasTextOverTransparent(PR_FALSE) {} + mIsSolidColorInVisibleRegion(PR_FALSE) {} /** * Record that an item has been added to the ThebesLayer, so we * need to update our regions. @@ -174,10 +165,10 @@ protected: * @param aSolidColor if non-null, the visible area of the item is * a constant color given by *aSolidColor */ - void Accumulate(nsDisplayListBuilder* aBuilder, - nsDisplayItem* aItem, - const nsIntRect& aVisibleRect, - const nsIntRect& aDrawRect); + void Accumulate(const nsIntRect& aVisibleRect, + const nsIntRect& aDrawRect, + const nsIntRect* aOpaqueRect, + nscolor* aSolidColor); nsIFrame* GetActiveScrolledRoot() { return mActiveScrolledRoot; } /** @@ -229,15 +220,6 @@ protected: * True if every pixel in mVisibleRegion will have color mSolidColor. */ PRPackedBool mIsSolidColorInVisibleRegion; - /** - * True if there is any text visible in the layer. - */ - PRPackedBool mHasText; - /** - * True if there is any text visible in the layer that's over - * transparent pixels in the layer. - */ - PRPackedBool mHasTextOverTransparent; }; /** @@ -263,12 +245,6 @@ protected: * aItem in that layer. */ void InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer); - /** - * Try to determine whether the ThebesLayer at aThebesLayerIndex - * has an opaque single color covering the visible area behind it. - * If successful, return that color, otherwise return NS_RGBA(0,0,0,0). - */ - nscolor FindOpaqueBackgroundColorFor(PRInt32 aThebesLayerIndex); /** * Indicate that we are done adding items to the ThebesLayer at the top of * mThebesLayerDataStack. Set the final visible region and opaque-content @@ -292,10 +268,11 @@ protected: * @param aSolidColor if non-null, indicates that every pixel in aVisibleRect * will be painted with aSolidColor by the item */ - already_AddRefed FindThebesLayerFor(nsDisplayItem* aItem, - const nsIntRect& aVisibleRect, + already_AddRefed FindThebesLayerFor(const nsIntRect& aVisibleRect, const nsIntRect& aDrawRect, - nsIFrame* aActiveScrolledRoot); + nsIFrame* aActiveScrolledRoot, + const nsIntRect* aOpaqueRect, + nscolor* aSolidColor); ThebesLayerData* GetTopThebesLayerData() { return mThebesLayerDataStack.IsEmpty() ? nsnull @@ -325,37 +302,20 @@ protected: PRPackedBool mInvalidateAllThebesContent; }; -class ThebesDisplayItemLayerUserData : public LayerUserData -{ -public: - ThebesDisplayItemLayerUserData() : - mForcedBackgroundColor(NS_RGBA(0,0,0,0)) {} - - nscolor mForcedBackgroundColor; -}; - /** * The address of gThebesDisplayItemLayerUserData is used as the user - * data key for ThebesLayers created by FrameLayerBuilder. + * data pointer for ThebesLayers created by FrameLayerBuilder. * It identifies ThebesLayers used to draw non-layer content, which are * therefore eligible for recycling. We want display items to be able to * create their own dedicated ThebesLayers in BuildLayer, if necessary, * and we wouldn't want to accidentally recycle those. - * The user data is a ThebesDisplayItemLayerUserData. */ -PRUint8 gThebesDisplayItemLayerUserData; +static PRUint8 gThebesDisplayItemLayerUserData; /** * The address of gColorLayerUserData is used as the user - * data key for ColorLayers created by FrameLayerBuilder. - * The user data is null. + * data pointer for ColorLayers */ -PRUint8 gColorLayerUserData; -/** - * The address of gLayerManagerUserData is used as the user - * data key for retained LayerManagers managed by FrameLayerBuilder. - * The user data is a LayerManagerData. - */ -PRUint8 gLayerManagerUserData; +static PRUint8 gColorLayerUserData; } // anonymous namespace @@ -382,11 +342,12 @@ FrameLayerBuilder::InternalDestroyDisplayItemData(nsIFrame* aFrame, if (aRemoveFromFramesWithLayers) { LayerManager* manager = array->ElementAt(0).mLayer->Manager(); LayerManagerData* data = static_cast - (manager->GetUserData(&gLayerManagerUserData)); + (manager->GetUserData()); NS_ASSERTION(data, "Frame with layer should have been recorded"); data->mFramesWithLayers.RemoveEntry(aFrame); if (data->mFramesWithLayers.Count() == 0) { - manager->RemoveUserData(&gLayerManagerUserData); + delete data; + manager->SetUserData(nsnull); // Consume the reference we added when we set the user data // in DidEndTransaction. But don't actually release until we've // released all the layers in the DisplayItemData array below! @@ -410,7 +371,7 @@ FrameLayerBuilder::WillBeginRetainedLayerTransaction(LayerManager* aManager) { mRetainingManager = aManager; LayerManagerData* data = static_cast - (aManager->GetUserData(&gLayerManagerUserData)); + (aManager->GetUserData()); if (data) { mInvalidateAllThebesContent = data->mInvalidateAllThebesContent; mInvalidateAllLayers = data->mInvalidateAllLayers; @@ -459,13 +420,13 @@ FrameLayerBuilder::WillEndTransaction(LayerManager* aManager) // correctly and the NS_FRAME_HAS_CONTAINER_LAYER bits will be set // correctly. LayerManagerData* data = static_cast - (mRetainingManager->GetUserData(&gLayerManagerUserData)); + (mRetainingManager->GetUserData()); if (data) { // Update all the frames that used to have layers. data->mFramesWithLayers.EnumerateEntries(UpdateDisplayItemDataForFrame, this); } else { data = new LayerManagerData(); - mRetainingManager->SetUserData(&gLayerManagerUserData, data); + mRetainingManager->SetUserData(data); // Addref mRetainingManager. We'll release it when 'data' is // removed. NS_ADDREF(mRetainingManager); @@ -489,7 +450,7 @@ FrameLayerBuilder::UpdateDisplayItemDataForFrame(nsPtrHashKey* aEntry, nsIFrame* f = aEntry->GetKey(); FrameProperties props = f->Properties(); DisplayItemDataEntry* newDisplayItems = - builder ? builder->mNewDisplayItemData.GetEntry(f) : nsnull; + builder->mNewDisplayItemData.GetEntry(f); if (!newDisplayItems) { // This frame was visible, but isn't anymore. PRBool found; @@ -634,7 +595,7 @@ ContainerState::CreateOrRecycleColorLayer() if (!layer) return nsnull; // Mark this layer as being used for Thebes-painting display items - layer->SetUserData(&gColorLayerUserData, nsnull); + layer->SetUserData(&gColorLayerUserData); } return layer.forget(); } @@ -676,8 +637,7 @@ ContainerState::CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot) if (!layer) return nsnull; // Mark this layer as being used for Thebes-painting display items - layer->SetUserData(&gThebesDisplayItemLayerUserData, - new ThebesDisplayItemLayerUserData()); + layer->SetUserData(&gThebesDisplayItemLayerUserData); } // Set up transform so that 0,0 in the Thebes layer corresponds to the @@ -737,39 +697,6 @@ SetVisibleRectForLayer(Layer* aLayer, const nsIntRect& aRect) } } -nscolor -ContainerState::FindOpaqueBackgroundColorFor(PRInt32 aThebesLayerIndex) -{ - ThebesLayerData* target = mThebesLayerDataStack[aThebesLayerIndex]; - for (PRInt32 i = aThebesLayerIndex - 1; i >= 0; --i) { - ThebesLayerData* candidate = mThebesLayerDataStack[i]; - nsIntRegion visibleAboveIntersection; - visibleAboveIntersection.And(candidate->mVisibleAboveRegion, target->mVisibleRegion); - if (!visibleAboveIntersection.IsEmpty()) { - // Some non-Thebes content between target and candidate; this is - // hopeless - break; - } - - nsIntRegion intersection; - intersection.And(candidate->mVisibleRegion, target->mVisibleRegion); - if (intersection.IsEmpty()) { - // The layer doesn't intersect our target, ignore it and move on - continue; - } - - // The candidate intersects our target. If any layer has a solid-color - // area behind our target, this must be it. Scan its display items. - nsPresContext* presContext = mContainerFrame->PresContext(); - nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); - nsRect rect = - target->mVisibleRegion.GetBounds().ToAppUnits(appUnitsPerDevPixel); - return mBuilder->LayerBuilder()-> - FindOpaqueColorCovering(mBuilder, candidate->mLayer, rect); - } - return NS_RGBA(0,0,0,0); -} - void ContainerState::PopThebesLayerData() { @@ -778,6 +705,21 @@ ContainerState::PopThebesLayerData() PRInt32 lastIndex = mThebesLayerDataStack.Length() - 1; ThebesLayerData* data = mThebesLayerDataStack[lastIndex]; + if (lastIndex > 0) { + // Since we're going to pop off the last ThebesLayerData, the + // mVisibleAboveRegion of the second-to-last item will need to include + // the regions of the last item. + ThebesLayerData* nextData = mThebesLayerDataStack[lastIndex - 1]; + nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion, + data->mVisibleAboveRegion); + nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion, + data->mVisibleRegion); + nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion, + data->mDrawAboveRegion); + nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion, + data->mDrawRegion); + } + Layer* layer; if (data->mIsSolidColorInVisibleRegion) { nsRefPtr colorLayer = CreateOrRecycleColorLayer(); @@ -824,87 +766,26 @@ ContainerState::PopThebesLayerData() nsIntRegion transparentRegion; transparentRegion.Sub(data->mVisibleRegion, data->mOpaqueRegion); - PRBool isOpaque = transparentRegion.IsEmpty(); - // For translucent ThebesLayers, try to find an opaque background - // color that covers the entire area beneath it so we can pull that - // color into this layer to make it opaque. - if (layer == data->mLayer) { - nscolor backgroundColor = NS_RGBA(0,0,0,0); - if (!isOpaque) { - backgroundColor = FindOpaqueBackgroundColorFor(lastIndex); - if (NS_GET_A(backgroundColor) == 255) { - isOpaque = PR_TRUE; - } - } - - // Store the background color - ThebesDisplayItemLayerUserData* userData = - static_cast - (data->mLayer->GetUserData(&gThebesDisplayItemLayerUserData)); - NS_ASSERTION(userData, "where did our user data go?"); - if (userData->mForcedBackgroundColor != backgroundColor) { - // Invalidate the entire target ThebesLayer since we're changing - // the background color - data->mLayer->InvalidateRegion(data->mLayer->GetValidRegion()); - } - userData->mForcedBackgroundColor = backgroundColor; - } - PRUint32 flags = - (isOpaque ? Layer::CONTENT_OPAQUE : 0) | - (data->mHasText ? 0 : Layer::CONTENT_NO_TEXT) | - (data->mHasTextOverTransparent ? 0 : Layer::CONTENT_NO_TEXT_OVER_TRANSPARENT); - layer->SetContentFlags(flags); - - if (lastIndex > 0) { - // Since we're going to pop off the last ThebesLayerData, the - // mVisibleAboveRegion of the second-to-last item will need to include - // the regions of the last item. - ThebesLayerData* nextData = mThebesLayerDataStack[lastIndex - 1]; - nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion, - data->mVisibleAboveRegion); - nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion, - data->mVisibleRegion); - nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion, - data->mDrawAboveRegion); - nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion, - data->mDrawRegion); - } + layer->SetIsOpaqueContent(transparentRegion.IsEmpty()); mThebesLayerDataStack.RemoveElementAt(lastIndex); } -static PRBool -IsText(nsDisplayItem* aItem) { - switch (aItem->GetType()) { - case nsDisplayItem::TYPE_TEXT: - case nsDisplayItem::TYPE_BULLET: - case nsDisplayItem::TYPE_HEADER_FOOTER: - case nsDisplayItem::TYPE_MATHML_CHAR_FOREGROUND: -#ifdef MOZ_XUL - case nsDisplayItem::TYPE_XUL_TEXT_BOX: -#endif - return PR_TRUE; - default: - return PR_FALSE; - } -} - void -ContainerState::ThebesLayerData::Accumulate(nsDisplayListBuilder* aBuilder, - nsDisplayItem* aItem, - const nsIntRect& aVisibleRect, - const nsIntRect& aDrawRect) +ContainerState::ThebesLayerData::Accumulate(const nsIntRect& aVisibleRect, + const nsIntRect& aDrawRect, + const nsIntRect* aOpaqueRect, + nscolor* aSolidColor) { - nscolor uniformColor; - if (aItem->IsUniform(aBuilder, &uniformColor)) { + if (aSolidColor) { if (mVisibleRegion.IsEmpty()) { // This color is all we have - mSolidColor = uniformColor; + mSolidColor = *aSolidColor; mIsSolidColorInVisibleRegion = PR_TRUE; } else if (mIsSolidColorInVisibleRegion && mVisibleRegion.IsEqual(nsIntRegion(aVisibleRect))) { // we can just blend the colors together - mSolidColor = NS_ComposeColors(mSolidColor, uniformColor); + mSolidColor = NS_ComposeColors(mSolidColor, *aSolidColor); } else { mIsSolidColorInVisibleRegion = PR_FALSE; } @@ -916,31 +797,26 @@ ContainerState::ThebesLayerData::Accumulate(nsDisplayListBuilder* aBuilder, mVisibleRegion.SimplifyOutward(4); mDrawRegion.Or(mDrawRegion, aDrawRect); mDrawRegion.SimplifyOutward(4); - - if (aItem->IsOpaque(aBuilder)) { + if (aOpaqueRect) { // We don't use SimplifyInward here since it's not defined exactly // what it will discard. For our purposes the most important case // is a large opaque background at the bottom of z-order (e.g., // a canvas background), so we need to make sure that the first rect // we see doesn't get discarded. nsIntRegion tmp; - tmp.Or(mOpaqueRegion, aDrawRect); + tmp.Or(mOpaqueRegion, *aOpaqueRect); if (tmp.GetNumRects() <= 4) { mOpaqueRegion = tmp; } - } else if (IsText(aItem)) { - mHasText = PR_TRUE; - if (!mOpaqueRegion.Contains(aVisibleRect)) { - mHasTextOverTransparent = PR_TRUE; - } } } already_AddRefed -ContainerState::FindThebesLayerFor(nsDisplayItem* aItem, - const nsIntRect& aVisibleRect, +ContainerState::FindThebesLayerFor(const nsIntRect& aVisibleRect, const nsIntRect& aDrawRect, - nsIFrame* aActiveScrolledRoot) + nsIFrame* aActiveScrolledRoot, + const nsIntRect* aOpaqueRect, + nscolor* aSolidColor) { PRInt32 i; PRInt32 lowestUsableLayerWithScrolledRoot = -1; @@ -994,7 +870,7 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem, layer = thebesLayerData->mLayer; } - thebesLayerData->Accumulate(mBuilder, aItem, aVisibleRect, aDrawRect); + thebesLayerData->Accumulate(aVisibleRect, aDrawRect, aOpaqueRect, aSolidColor); return layer.forget(); } @@ -1089,7 +965,7 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList, // Update that layer's clip and visible rects. NS_ASSERTION(ownLayer->Manager() == mManager, "Wrong manager"); - NS_ASSERTION(!ownLayer->HasUserData(&gLayerManagerUserData), + NS_ASSERTION(ownLayer->GetUserData() != &gThebesDisplayItemLayerUserData, "We shouldn't have a FrameLayerBuilder-managed layer here!"); // It has its own layer. Update that layer's clip and visible rects. if (aClipRect) { @@ -1140,9 +1016,17 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList, nsLayoutUtils::GetActiveScrolledRootFor(viewportFrame, mBuilder->ReferenceFrame()); } + nscolor uniformColor; + PRBool isUniform = item->IsUniform(mBuilder, &uniformColor); + PRBool isOpaque = item->IsOpaque(mBuilder); + nsIntRect opaqueRect; + if (isOpaque) { + opaqueRect = item->GetBounds(mBuilder).ToNearestPixels(appUnitsPerDevPixel); + } nsRefPtr thebesLayer = - FindThebesLayerFor(item, itemVisibleRect, itemDrawRect, - activeScrolledRoot); + FindThebesLayerFor(itemVisibleRect, itemDrawRect, activeScrolledRoot, + isOpaque ? &opaqueRect : nsnull, + isUniform ? &uniformColor : nsnull); InvalidateForLayerChange(item, thebesLayer); @@ -1230,36 +1114,15 @@ FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer, } } -nscolor -FrameLayerBuilder::FindOpaqueColorCovering(nsDisplayListBuilder* aBuilder, - ThebesLayer* aLayer, - const nsRect& aRect) -{ - ThebesLayerItemsEntry* entry = mThebesLayerItems.GetEntry(aLayer); - NS_ASSERTION(entry, "Must know about this layer!"); - for (PRInt32 i = entry->mItems.Length() - 1; i >= 0; --i) { - nsDisplayItem* item = entry->mItems[i].mItem; - const nsRect& visible = item->GetVisibleRect(); - if (!visible.Intersects(aRect)) - continue; - - nscolor color; - if (visible.Contains(aRect) && item->IsUniform(aBuilder, &color) && - NS_GET_A(color) == 255) - return color; - break; - } - return NS_RGBA(0,0,0,0); -} - void ContainerState::CollectOldLayers() { for (Layer* layer = mContainerLayer->GetFirstChild(); layer; layer = layer->GetNextSibling()) { - if (layer->HasUserData(&gColorLayerUserData)) { + void* data = layer->GetUserData(); + if (data == &gColorLayerUserData) { mRecycledColorLayers.AppendElement(static_cast(layer)); - } else if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) { + } else if (data == &gThebesDisplayItemLayerUserData) { NS_ASSERTION(layer->AsThebesLayer(), "Wrong layer type"); mRecycledThebesLayers.AppendElement(static_cast(layer)); } @@ -1340,7 +1203,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder, Layer* oldLayer = GetOldLayerFor(aContainerFrame, containerDisplayItemKey); if (oldLayer) { NS_ASSERTION(oldLayer->Manager() == aManager, "Wrong manager"); - if (oldLayer->HasUserData(&gThebesDisplayItemLayerUserData)) { + if (oldLayer->GetUserData() == &gThebesDisplayItemLayerUserData) { // The old layer for this item is actually our ThebesLayer // because we rendered its layer into that ThebesLayer. So we // don't actually have a retained container layer. @@ -1396,8 +1259,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder, state.ProcessDisplayItems(aChildren, nsnull); state.Finish(); - PRUint32 flags = aChildren.IsOpaque() ? Layer::CONTENT_OPAQUE : 0; - containerLayer->SetContentFlags(flags); + containerLayer->SetIsOpaqueContent(aChildren.IsOpaque()); return containerLayer.forget(); } @@ -1414,7 +1276,7 @@ FrameLayerBuilder::GetLeafLayerFor(nsDisplayListBuilder* aBuilder, Layer* layer = GetOldLayerFor(f, aItem->GetPerFrameKey()); if (!layer) return nsnull; - if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) { + if (layer->GetUserData() == &gThebesDisplayItemLayerUserData) { // This layer was created to render Thebes-rendered content for this // display item. The display item should not use it for its own // layer rendering. @@ -1490,7 +1352,7 @@ FrameLayerBuilder::InvalidateThebesLayersInSubtree(nsIFrame* aFrame) FrameLayerBuilder::InvalidateAllThebesLayerContents(LayerManager* aManager) { LayerManagerData* data = static_cast - (aManager->GetUserData(&gLayerManagerUserData)); + (aManager->GetUserData()); if (data) { data->mInvalidateAllThebesContent = PR_TRUE; } @@ -1500,7 +1362,7 @@ FrameLayerBuilder::InvalidateAllThebesLayerContents(LayerManager* aManager) FrameLayerBuilder::InvalidateAllLayers(LayerManager* aManager) { LayerManagerData* data = static_cast - (aManager->GetUserData(&gLayerManagerUserData)); + (aManager->GetUserData()); if (data) { data->mInvalidateAllLayers = PR_TRUE; } @@ -1518,9 +1380,9 @@ FrameLayerBuilder::HasDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey) (reinterpret_cast*>(&propValue)); for (PRUint32 i = 0; i < array->Length(); ++i) { if (array->ElementAt(i).mDisplayItemKey == aDisplayItemKey) { - Layer* layer = array->ElementAt(i).mLayer; - if (!layer->HasUserData(&gColorLayerUserData) && - !layer->HasUserData(&gThebesDisplayItemLayerUserData)) + void* layerUserData = array->ElementAt(i).mLayer->GetUserData(); + if (layerUserData != &gColorLayerUserData && + layerUserData != &gThebesDisplayItemLayerUserData) return PR_TRUE; } } @@ -1549,15 +1411,6 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer, // so 'entry' could become invalid. } - ThebesDisplayItemLayerUserData* userData = - static_cast - (aLayer->GetUserData(&gThebesDisplayItemLayerUserData)); - NS_ASSERTION(userData, "where did our user data go?"); - if (NS_GET_A(userData->mForcedBackgroundColor) > 0) { - aContext->SetColor(gfxRGBA(userData->mForcedBackgroundColor)); - aContext->Paint(); - } - gfxMatrix transform; if (!aLayer->GetTransform().Is2D(&transform)) { NS_ERROR("non-2D transform in our Thebes layer!"); diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h index 4cce9ebbcb70..e3e082068994 100644 --- a/layout/base/FrameLayerBuilder.h +++ b/layout/base/FrameLayerBuilder.h @@ -243,26 +243,6 @@ public: */ Layer* GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey); - /** - * A useful hashtable iteration function that removes the - * DisplayItemData property for the frame, clears its - * NS_FRAME_HAS_CONTAINER_LAYER bit and returns PL_DHASH_REMOVE. - * aClosure is ignored. - */ - static PLDHashOperator RemoveDisplayItemDataForFrame(nsPtrHashKey* aEntry, - void* aClosure) - { - return UpdateDisplayItemDataForFrame(aEntry, nsnull); - } - - /** - * Try to determine whether the ThebesLayer aLayer paints an opaque - * single color everywhere it's visible in aRect. - * If successful, return that color, otherwise return NS_RGBA(0,0,0,0). - */ - nscolor FindOpaqueColorCovering(nsDisplayListBuilder* aBuilder, - ThebesLayer* aLayer, const nsRect& aRect); - protected: /** * We store an array of these for each frame that is associated with diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 364bf10385b5..df8ff01b4f95 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1251,9 +1251,9 @@ IsSmoothScrollingEnabled() class ScrollFrameActivityTracker : public nsExpirationTracker { public: - // Wait for 3-4s between scrolls before we remove our layers. - // That's 4 generations of 1s each. - enum { TIMEOUT_MS = 1000 }; + // Wait for 75-100ms between scrolls before we switch the appearance back to + // subpixel AA. That's 4 generations of 25ms each. + enum { TIMEOUT_MS = 25 }; ScrollFrameActivityTracker() : nsExpirationTracker(TIMEOUT_MS) {} ~ScrollFrameActivityTracker() { diff --git a/layout/reftests/bidi/logicalmarquee.html b/layout/reftests/bidi/logicalmarquee.html index cb13827dec7b..9ba9d6306cf4 100644 --- a/layout/reftests/bidi/logicalmarquee.html +++ b/layout/reftests/bidi/logicalmarquee.html @@ -6,6 +6,6 @@ - עד שיפוח היום ונסו הצלילים + עד שיפוח היום ונסו הצלילים diff --git a/layout/reftests/bidi/marquee-ref.html b/layout/reftests/bidi/marquee-ref.html index d8778dc88063..724e4f8559d2 100644 --- a/layout/reftests/bidi/marquee-ref.html +++ b/layout/reftests/bidi/marquee-ref.html @@ -6,6 +6,6 @@ -
עד שיפוח היום ונסו הצלילים
+
עד שיפוח היום ונסו הצלילים
diff --git a/layout/reftests/bidi/visualmarquee.html b/layout/reftests/bidi/visualmarquee.html index 932fd775a191..51a559469124 100644 --- a/layout/reftests/bidi/visualmarquee.html +++ b/layout/reftests/bidi/visualmarquee.html @@ -6,6 +6,6 @@ - םילילצה וסנו םויה חופיש דע + םילילצה וסנו םויה חופיש דע diff --git a/layout/reftests/marquee/413027-4-ref.html b/layout/reftests/marquee/413027-4-ref.html index 22fdd42e6016..fbe705e414da 100644 --- a/layout/reftests/marquee/413027-4-ref.html +++ b/layout/reftests/marquee/413027-4-ref.html @@ -4,7 +4,7 @@
-
text
+
text
diff --git a/layout/reftests/marquee/413027-4.html b/layout/reftests/marquee/413027-4.html index d57f2f121517..beb15e6f752a 100644 --- a/layout/reftests/marquee/413027-4.html +++ b/layout/reftests/marquee/413027-4.html @@ -8,7 +8,7 @@ -
text
+
text
diff --git a/layout/reftests/scrolling/fixed-text-1.html b/layout/reftests/scrolling/fixed-text-1.html deleted file mode 100644 index d470a7c6415d..000000000000 --- a/layout/reftests/scrolling/fixed-text-1.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - -

Hello Kitty - - diff --git a/layout/reftests/scrolling/reftest.list b/layout/reftests/scrolling/reftest.list index e227cefd356b..bfdc32a7ad77 100644 --- a/layout/reftests/scrolling/reftest.list +++ b/layout/reftests/scrolling/reftest.list @@ -1,7 +1,5 @@ HTTP == fixed-1.html fixed-1.html?ref -HTTP == fixed-text-1.html fixed-text-1.html?ref HTTP == opacity-mixed-scrolling-1.html opacity-mixed-scrolling-1.html?ref HTTP == simple-1.html simple-1.html?ref -HTTP == text-1.html text-1.html?ref == uncovering-1.html uncovering-1-ref.html == uncovering-2.html uncovering-2-ref.html diff --git a/layout/reftests/scrolling/text-1.html b/layout/reftests/scrolling/text-1.html deleted file mode 100644 index 0ede92a6fa28..000000000000 --- a/layout/reftests/scrolling/text-1.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - -

-
Hello Kitty
-
-
- - From ab510e7491f2650199b1269e337771ee99158940 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 2 Sep 2010 12:28:48 +0100 Subject: [PATCH 017/222] bug 569531 - enable harfbuzz by default on windows. r=roc approval2.0=roc --- layout/reftests/bidi/reftest.list | 4 ++-- layout/reftests/font-features/reftest.list | 10 ++++------ layout/reftests/svg/reftest.list | 2 +- modules/libpref/src/init/all.js | 4 ---- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/layout/reftests/bidi/reftest.list b/layout/reftests/bidi/reftest.list index 64552fbc392e..0e483be389a8 100644 --- a/layout/reftests/bidi/reftest.list +++ b/layout/reftests/bidi/reftest.list @@ -31,10 +31,10 @@ random-if(gtk2Widget) == mixedChartype-03-j.html mixedChartype-03-ref.html == 115921-1.html 115921-1-ref.html == 115921-2.html 115921-2-ref.html == 258928-1.html 258928-1-ref.html -== 267459-1.html 267459-1-ref.html +random-if(winWidget) == 267459-1.html 267459-1-ref.html # depends on windows version, see bug 590101 == 267459-2.html 267459-2-ref.html == 299065-1.html 299065-1-ref.html -== 305643-1.html 305643-1-ref.html +random-if(winWidget) == 305643-1.html 305643-1-ref.html # depends on windows version, see bug 590101 == 332655-1.html 332655-1-ref.html == 332655-2.html 332655-2-ref.html == 381279-1.html 381279-1-ref.html diff --git a/layout/reftests/font-features/reftest.list b/layout/reftests/font-features/reftest.list index e9299769d238..3d34a7d11d3f 100644 --- a/layout/reftests/font-features/reftest.list +++ b/layout/reftests/font-features/reftest.list @@ -7,19 +7,17 @@ # check that Turkish language causes a change in rendering (no fi ligature) # (also works via Pango) -# marking as random on windows until we turn on harfbuzz, because behavior depends on uniscribe version -random-if(winWidget) HTTP(..) != font-features-turkish.html font-features-ref.html +HTTP(..) != font-features-turkish.html font-features-ref.html # check that disabling ligatures causes a change -fails-if(!cocoaWidget) HTTP(..) != font-features-noliga.html font-features-ref.html +fails-if(gtk2Widget) HTTP(..) != font-features-noliga.html font-features-ref.html # check that enabling optional ligatures causes a change -fails-if(!cocoaWidget) HTTP(..) != font-features-hlig.html font-features-ref.html +fails-if(gtk2Widget) HTTP(..) != font-features-hlig.html font-features-ref.html # compare Turkish rendering with reference using ZWNJ to break the ligature # (also works via Pango) -# marking as random on windows until we turn on harfbuzz, because behavior depends on uniscribe version -random-if(winWidget) HTTP(..) == font-features-turkish.html font-features-turkish-ref.html +HTTP(..) == font-features-turkish.html font-features-turkish-ref.html # compare Turkish rendering with explicitly disabled ligatures # (fails on Linux because Pango recognizes the Turkish lang but not the feature setting) diff --git a/layout/reftests/svg/reftest.list b/layout/reftests/svg/reftest.list index 2ecfa10002c2..ab4af5e2452a 100644 --- a/layout/reftests/svg/reftest.list +++ b/layout/reftests/svg/reftest.list @@ -150,7 +150,7 @@ fails-if(gtk2Widget) == objectBoundingBox-and-fePointLight-01.svg objectBounding random-if(gtk2Widget) == text-font-weight-01.svg text-font-weight-01-ref.svg # bug 386713 == switch-01.svg pass.svg == text-gradient-01.svg text-gradient-01-ref.svg -== text-gradient-02.svg text-gradient-02-ref.svg +random-if(winWidget) == text-gradient-02.svg text-gradient-02-ref.svg # see bug 590101 == text-in-link-01.svg text-in-link-01-ref.svg == text-in-link-02.svg text-in-link-02-ref.svg == text-in-link-03.svg text-in-link-03-ref.svg diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 79a33d62facd..5b2f4765842a 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -183,11 +183,7 @@ pref("gfx.3d_video.enabled", false); pref("gfx.downloadable_fonts.enabled", true); -#ifdef XP_MACOSX pref("gfx.font_rendering.harfbuzz.level", 1); -#else -pref("gfx.font_rendering.harfbuzz.level", 0); -#endif #ifdef XP_WIN #ifndef WINCE From fcc649f98aa4beb939ccfbd1fba8e9e32252d2e7 Mon Sep 17 00:00:00 2001 From: Kurt Schultz Date: Sat, 28 Aug 2010 11:24:43 -0400 Subject: [PATCH 018/222] Bug 590738 - Adjust color of menu separators in the app button menu. r=dao --HG-- extra : rebase_source : cea6aefb986df9e8d0660f12cb119b62e3c7c371 --- browser/base/content/browser.xul | 8 ++++---- browser/themes/winstripe/browser/browser.css | 11 +++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index 57456b936cab..d951453c2312 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -488,7 +488,7 @@ startlabel="&privateBrowsingCmd.start.label;" stoplabel="&privateBrowsingCmd.stop.label;" command="Tools:PrivateBrowsing"/> - + - + @@ -541,7 +541,7 @@ - + @@ -563,7 +563,7 @@ oncommand="BrowserOffline.toggleOfflineStatus();"/> - + Date: Sun, 29 Aug 2010 09:36:28 -0400 Subject: [PATCH 019/222] Bug 587295 - Remove "Bookmark This Tab" from the tab context menu. r=dao ui-r=faabobrg --HG-- extra : rebase_source : a6265f02b7537d123116dd8b92299d59f388bdba --- browser/base/content/browser.js | 5 ----- browser/base/content/browser.xul | 4 ---- browser/locales/en-US/chrome/browser/browser.dtd | 2 -- 3 files changed, 11 deletions(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 71a90d4f9752..debad768d3ad 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -324,11 +324,6 @@ function SetClickAndHoldHandlers() { } #endif -function BookmarkThisTab(aTab) { - PlacesCommandHook.bookmarkPage(aTab.linkedBrowser, - PlacesUtils.bookmarksMenuFolderId, true); -} - const gSessionHistoryObserver = { observe: function(subject, topic, data) { diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index d951453c2312..386237ca5ea9 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -136,10 +136,6 @@ - - - From a501a996a89d1d79e3864866764825564228524a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Thu, 2 Sep 2010 13:37:41 +0200 Subject: [PATCH 020/222] Bug 591125 - Sanitize the app name for the UA string. r=dwitte a=jst --HG-- extra : rebase_source : caccb90b5338953d35f4a98c90bf2d7ed12fd06c --- netwerk/protocol/http/nsHttpHandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/netwerk/protocol/http/nsHttpHandler.cpp b/netwerk/protocol/http/nsHttpHandler.cpp index 1fb60f34282a..f7b0cc8fc77c 100644 --- a/netwerk/protocol/http/nsHttpHandler.cpp +++ b/netwerk/protocol/http/nsHttpHandler.cpp @@ -283,6 +283,7 @@ nsHttpHandler::Init() if (mAppName.Length() == 0 && appInfo) { appInfo->GetName(mAppName); appInfo->GetVersion(mAppVersion); + mAppName.StripChars(" ()<>@,;:\\\"/[]?={}"); } else { mAppVersion.AssignLiteral(MOZ_APP_UA_VERSION); } From f87313f708539b6a71918f60f4f8c6aba4e2860a Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Thu, 2 Sep 2010 19:11:11 +0200 Subject: [PATCH 021/222] Backout nsHttpChannel part of bug 513008, r=michal a=bsmedberg --- netwerk/cache/nsCacheService.cpp | 5 +- netwerk/protocol/http/nsHttpChannel.cpp | 374 ++++++++---------------- netwerk/protocol/http/nsHttpChannel.h | 17 +- 3 files changed, 132 insertions(+), 264 deletions(-) diff --git a/netwerk/cache/nsCacheService.cpp b/netwerk/cache/nsCacheService.cpp index d9cdd31f29eb..6eae5546400d 100644 --- a/netwerk/cache/nsCacheService.cpp +++ b/netwerk/cache/nsCacheService.cpp @@ -1298,6 +1298,7 @@ nsCacheService::OpenCacheEntry(nsCacheSession * session, CACHE_LOG_DEBUG(("Created request %p\n", request)); +#if 0 // Disabled because of bug 589296 // Process the request on the background thread if we are on the main thread // and the the request is asynchronous if (NS_IsMainThread() && listener && gService->mCacheIOThread) { @@ -1313,7 +1314,9 @@ nsCacheService::OpenCacheEntry(nsCacheSession * session, if (NS_FAILED(rv)) delete request; } - else { + else +#endif + { rv = gService->ProcessRequest(request, PR_TRUE, result); // delete requests that have completed diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index bc154299361e..ffb12f9e743a 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -117,8 +117,6 @@ nsHttpChannel::nsHttpChannel() , mCacheAccess(0) , mPostID(0) , mRequestTime(0) - , mOnCacheEntryAvailableCallback(nsnull) - , mAsyncCacheOpen(PR_FALSE) , mPendingAsyncCallOnResume(nsnull) , mSuspendCount(0) , mApplyConversion(PR_TRUE) @@ -225,6 +223,8 @@ nsHttpChannel::Connect(PRBool firstTime) // true when called from AsyncOpen if (firstTime) { + PRBool delayed = PR_FALSE; + // are we offline? PRBool offline = gIOService->IsOffline(); if (offline) @@ -239,7 +239,7 @@ nsHttpChannel::Connect(PRBool firstTime) } // open a cache entry for this channel... - rv = OpenCacheEntry(); + rv = OpenCacheEntry(offline, &delayed); if (NS_FAILED(rv)) { LOG(("OpenCacheEntry failed [rv=%x]\n", rv)); @@ -263,7 +263,7 @@ nsHttpChannel::Connect(PRBool firstTime) if (NS_FAILED(rv)) return rv; } - if (NS_SUCCEEDED(rv) && mAsyncCacheOpen) + if (NS_SUCCEEDED(rv) && delayed) return NS_OK; } @@ -296,14 +296,6 @@ nsHttpChannel::Connect(PRBool firstTime) return NS_ERROR_DOCUMENT_NOT_CACHED; } } - else if (mLoadFlags & LOAD_ONLY_FROM_CACHE) { - // If we have a fallback URI (and we're not already - // falling back), process the fallback asynchronously. - if (!mFallbackChannel && !mFallbackKey.IsEmpty()) { - return AsyncCall(&nsHttpChannel::HandleAsyncFallback); - } - return NS_ERROR_DOCUMENT_NOT_CACHED; - } // check to see if authorization headers should be included mAuthProvider->AddAuthorizationHeaders(); @@ -1942,11 +1934,11 @@ IsSubRangeRequest(nsHttpRequestHead &aRequestHead) } nsresult -nsHttpChannel::OpenCacheEntry() +nsHttpChannel::OpenCacheEntry(PRBool offline, PRBool *delayed) { nsresult rv; - mAsyncCacheOpen = PR_FALSE; + *delayed = PR_FALSE; mLoadedFromApplicationCache = PR_FALSE; LOG(("nsHttpChannel::OpenCacheEntry [this=%p]", this)); @@ -1982,10 +1974,23 @@ nsHttpChannel::OpenCacheEntry() GenerateCacheKey(mPostID, cacheKey); + // Get a cache session with appropriate storage policy + nsCacheStoragePolicy storagePolicy = DetermineStoragePolicy(); + // Set the desired cache access mode accordingly... nsCacheAccessMode accessRequested; - rv = DetermineCacheAccess(&accessRequested); - if (NS_FAILED(rv)) return rv; + if (offline || (mLoadFlags & INHIBIT_CACHING)) { + // If we have been asked to bypass the cache and not write to the + // cache, then don't use the cache at all. Unless we're actually + // offline, which takes precedence over BYPASS_LOCAL_CACHE. + if (BYPASS_LOCAL_CACHE(mLoadFlags) && !offline) + return NS_ERROR_NOT_AVAILABLE; + accessRequested = nsICache::ACCESS_READ; + } + else if (BYPASS_LOCAL_CACHE(mLoadFlags)) + accessRequested = nsICache::ACCESS_WRITE; // replace cache entry + else + accessRequested = nsICache::ACCESS_READ_WRITE; // normal browsing if (!mApplicationCache && mInheritApplicationCache) { // Pick up an application cache from the notification @@ -2014,6 +2019,10 @@ nsHttpChannel::OpenCacheEntry() nsCOMPtr session; + // Will be set to true if we've found the right session, but need + // to open the cache entry asynchronously. + PRBool waitingForValidation = PR_FALSE; + // If we have an application cache, we check it first. if (mApplicationCache) { nsCAutoString appCacheClientID; @@ -2029,217 +2038,107 @@ nsHttpChannel::OpenCacheEntry() getter_AddRefs(session)); NS_ENSURE_SUCCESS(rv, rv); - if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) { - // must use synchronous open for LOAD_BYPASS_LOCAL_CACHE_IF_BUSY - rv = session->OpenCacheEntry(cacheKey, - nsICache::ACCESS_READ, PR_FALSE, - getter_AddRefs(mCacheEntry)); - if (NS_SUCCEEDED(rv)) { - mCacheEntry->GetAccessGranted(&mCacheAccess); - LOG(("nsHttpChannel::OpenCacheEntry [this=%p grantedAccess=%d]", - this, mCacheAccess)); - mLoadedFromApplicationCache = PR_TRUE; - return NS_OK; - } else if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) { - LOG(("bypassing local cache since it is busy\n")); - // Don't try to load normal cache entry - return NS_ERROR_NOT_AVAILABLE; - } - } else { - mOnCacheEntryAvailableCallback = - &nsHttpChannel::OnOfflineCacheEntryAvailable; - // We open with ACCESS_READ only, because we don't want to - // overwrite the offline cache entry non-atomically. - // ACCESS_READ will prevent us from writing to the offline - // cache as a normal cache entry. - rv = session->AsyncOpenCacheEntry(cacheKey, - nsICache::ACCESS_READ, - this); - - if (NS_SUCCEEDED(rv)) { - mAsyncCacheOpen = PR_TRUE; - return NS_OK; - } + // we'll try to synchronously open the cache entry... however, + // it may be in use and not yet validated, in which case we'll + // try asynchronously opening the cache entry. + // + // We open with ACCESS_READ only, because we don't want to + // overwrite the offline cache entry non-atomically. + // ACCESS_READ will prevent us from writing to the offline + // cache as a normal cache entry. + rv = session->OpenCacheEntry(cacheKey, + nsICache::ACCESS_READ, PR_FALSE, + getter_AddRefs(mCacheEntry)); + if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) { + accessRequested = nsICache::ACCESS_READ; + waitingForValidation = PR_TRUE; + rv = NS_OK; } - // sync or async opening failed - return OnOfflineCacheEntryAvailable(nsnull, nsICache::ACCESS_NONE, - rv, PR_TRUE); - } - - return OpenNormalCacheEntry(PR_TRUE); -} - -nsresult -nsHttpChannel::OnOfflineCacheEntryAvailable(nsICacheEntryDescriptor *aEntry, - nsCacheAccessMode aAccess, - nsresult aEntryStatus, - PRBool aIsSync) -{ - nsresult rv; - - if (NS_SUCCEEDED(aEntryStatus)) { - // We successfully opened an offline cache session and the entry, - // so indicate we will load from the offline cache. - mLoadedFromApplicationCache = PR_TRUE; - mCacheEntry = aEntry; - mCacheAccess = aAccess; - } - - if (mCanceled && NS_FAILED(mStatus)) { - LOG(("channel was canceled [this=%p status=%x]\n", this, mStatus)); - return mStatus; - } - - if (NS_SUCCEEDED(aEntryStatus)) - // Called from OnCacheEntryAvailable, advance to the next state - return Connect(PR_FALSE); - - if (!mCacheForOfflineUse && !mFallbackChannel) { - nsCAutoString cacheKey; - GenerateCacheKey(mPostID, cacheKey); - - // Check for namespace match. - nsCOMPtr namespaceEntry; - rv = mApplicationCache->GetMatchingNamespace - (cacheKey, getter_AddRefs(namespaceEntry)); - if (NS_FAILED(rv) && !aIsSync) - return Connect(PR_FALSE); - NS_ENSURE_SUCCESS(rv, rv); - - PRUint32 namespaceType = 0; - if (!namespaceEntry || - NS_FAILED(namespaceEntry->GetItemType(&namespaceType)) || - (namespaceType & - (nsIApplicationCacheNamespace::NAMESPACE_FALLBACK | - nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC | - nsIApplicationCacheNamespace::NAMESPACE_BYPASS)) == 0) { - // When loading from an application cache, only items - // on the whitelist or matching a - // fallback/opportunistic namespace should hit the - // network... - mLoadFlags |= LOAD_ONLY_FROM_CACHE; - - // ... and if there were an application cache entry, - // we would have found it earlier. - return aIsSync ? NS_ERROR_CACHE_KEY_NOT_FOUND : Connect(PR_FALSE); - } - - if (namespaceType & - nsIApplicationCacheNamespace::NAMESPACE_FALLBACK) { - rv = namespaceEntry->GetData(mFallbackKey); - if (NS_FAILED(rv) && !aIsSync) - return Connect(PR_FALSE); + if (NS_FAILED(rv) && !mCacheForOfflineUse && !mFallbackChannel) { + // Check for namespace match. + nsCOMPtr namespaceEntry; + rv = mApplicationCache->GetMatchingNamespace + (cacheKey, getter_AddRefs(namespaceEntry)); NS_ENSURE_SUCCESS(rv, rv); + + PRUint32 namespaceType = 0; + if (!namespaceEntry || + NS_FAILED(namespaceEntry->GetItemType(&namespaceType)) || + (namespaceType & + (nsIApplicationCacheNamespace::NAMESPACE_FALLBACK | + nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC | + nsIApplicationCacheNamespace::NAMESPACE_BYPASS)) == 0) { + // When loading from an application cache, only items + // on the whitelist or matching a + // fallback/opportunistic namespace should hit the + // network... + mLoadFlags |= LOAD_ONLY_FROM_CACHE; + + // ... and if there were an application cache entry, + // we would have found it earlier. + return NS_ERROR_CACHE_KEY_NOT_FOUND; + } + + if (namespaceType & + nsIApplicationCacheNamespace::NAMESPACE_FALLBACK) { + rv = namespaceEntry->GetData(mFallbackKey); + NS_ENSURE_SUCCESS(rv, rv); + } + + if ((namespaceType & + nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC) && + mLoadFlags & LOAD_DOCUMENT_URI) { + // Document loads for items in an opportunistic namespace + // should be placed in the offline cache. + nsCString clientID; + mApplicationCache->GetClientID(clientID); + + mCacheForOfflineUse = !clientID.IsEmpty(); + SetOfflineCacheClientID(clientID); + mCachingOpportunistically = PR_TRUE; + } } - - if ((namespaceType & - nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC) && - mLoadFlags & LOAD_DOCUMENT_URI) { - // Document loads for items in an opportunistic namespace - // should be placed in the offline cache. - nsCString clientID; - mApplicationCache->GetClientID(clientID); - - mCacheForOfflineUse = !clientID.IsEmpty(); - SetOfflineCacheClientID(clientID); - mCachingOpportunistically = PR_TRUE; + else if (NS_SUCCEEDED(rv)) { + // We successfully opened an offline cache session and the entry, + // now indiciate we load from the offline cache. + mLoadedFromApplicationCache = PR_TRUE; } } - return OpenNormalCacheEntry(aIsSync); -} + if (!mCacheEntry && !waitingForValidation) { + rv = gHttpHandler->GetCacheSession(storagePolicy, + getter_AddRefs(session)); + if (NS_FAILED(rv)) return rv; - -nsresult -nsHttpChannel::OpenNormalCacheEntry(PRBool aIsSync) -{ - NS_ASSERTION(!mCacheEntry, "We have already mCacheEntry"); - - nsresult rv; - - nsCAutoString cacheKey; - GenerateCacheKey(mPostID, cacheKey); - - nsCacheStoragePolicy storagePolicy = DetermineStoragePolicy(); - - nsCOMPtr session; - rv = gHttpHandler->GetCacheSession(storagePolicy, - getter_AddRefs(session)); - if (NS_FAILED(rv)) return rv; - - nsCacheAccessMode accessRequested; - rv = DetermineCacheAccess(&accessRequested); - if (NS_FAILED(rv)) return rv; - - if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) { - if (!aIsSync) { - // Unexpected state: we were called from OnCacheEntryAvailable(), - // so LOAD_BYPASS_LOCAL_CACHE_IF_BUSY shouldn't be set. Unless - // somebody altered mLoadFlags between OpenCacheEntry() and - // OnCacheEntryAvailable()... - NS_WARNING( - "OpenNormalCacheEntry() called from OnCacheEntryAvailable() " - "when LOAD_BYPASS_LOCAL_CACHE_IF_BUSY was specified"); - } - - // must use synchronous open for LOAD_BYPASS_LOCAL_CACHE_IF_BUSY rv = session->OpenCacheEntry(cacheKey, accessRequested, PR_FALSE, getter_AddRefs(mCacheEntry)); - if (NS_SUCCEEDED(rv)) { - mCacheEntry->GetAccessGranted(&mCacheAccess); - LOG(("nsHttpChannel::OpenCacheEntry [this=%p grantedAccess=%d]", - this, mCacheAccess)); + if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) { + waitingForValidation = PR_TRUE; + rv = NS_OK; } - else if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) { + if (NS_FAILED(rv)) return rv; + } + + if (waitingForValidation) { + // access to the cache entry has been denied (because the + // cache entry is probably in use by another channel). + if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) { LOG(("bypassing local cache since it is busy\n")); - rv = NS_ERROR_NOT_AVAILABLE; + return NS_ERROR_NOT_AVAILABLE; } - } - else { - mOnCacheEntryAvailableCallback = - &nsHttpChannel::OnNormalCacheEntryAvailable; rv = session->AsyncOpenCacheEntry(cacheKey, accessRequested, this); - if (NS_SUCCEEDED(rv)) { - mAsyncCacheOpen = PR_TRUE; - return NS_OK; - } + if (NS_FAILED(rv)) return rv; + // we'll have to wait for the cache entry + *delayed = PR_TRUE; + } + else if (NS_SUCCEEDED(rv)) { + mCacheEntry->GetAccessGranted(&mCacheAccess); + LOG(("nsHttpChannel::OpenCacheEntry [this=%p grantedAccess=%d]", this, mCacheAccess)); } - - if (!aIsSync) - // Called from OnCacheEntryAvailable, advance to the next state - rv = Connect(PR_FALSE); - return rv; } -nsresult -nsHttpChannel::OnNormalCacheEntryAvailable(nsICacheEntryDescriptor *aEntry, - nsCacheAccessMode aAccess, - nsresult aEntryStatus, - PRBool aIsSync) -{ - NS_ASSERTION(!aIsSync, "aIsSync should be false"); - - if (NS_SUCCEEDED(aEntryStatus)) { - mCacheEntry = aEntry; - mCacheAccess = aAccess; - } - - if (mCanceled && NS_FAILED(mStatus)) { - LOG(("channel was canceled [this=%p status=%x]\n", this, mStatus)); - return mStatus; - } - - if ((mLoadFlags & LOAD_ONLY_FROM_CACHE) && NS_FAILED(aEntryStatus)) - // if this channel is only allowed to pull from the cache, then - // we must fail if we were unable to open a cache entry. - return NS_ERROR_DOCUMENT_NOT_CACHED; - - // advance to the next state... - return Connect(PR_FALSE); -} - nsresult nsHttpChannel::OpenOfflineCacheEntryForWriting() @@ -4436,8 +4335,6 @@ nsHttpChannel::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry, nsCacheAccessMode access, nsresult status) { - nsresult rv; - LOG(("nsHttpChannel::OnCacheEntryAvailable [this=%p entry=%p " "access=%x status=%x]\n", this, entry, access, status)); @@ -4446,24 +4343,28 @@ nsHttpChannel::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry, if (!mIsPending) return NS_OK; - nsOnCacheEntryAvailableCallback callback = mOnCacheEntryAvailableCallback; - mOnCacheEntryAvailableCallback = nsnull; + // otherwise, we have to handle this event. + if (NS_SUCCEEDED(status)) { + mCacheEntry = entry; + mCacheAccess = access; + } - NS_ASSERTION(callback, - "nsHttpChannel::OnCacheEntryAvailable called without callback"); - rv = ((*this).*callback)(entry, access, status, PR_FALSE); + nsresult rv; + if (mCanceled && NS_FAILED(mStatus)) { + LOG(("channel was canceled [this=%p status=%x]\n", this, mStatus)); + rv = mStatus; + } + else if ((mLoadFlags & LOAD_ONLY_FROM_CACHE) && NS_FAILED(status)) + // if this channel is only allowed to pull from the cache, then + // we must fail if we were unable to open a cache entry. + rv = NS_ERROR_DOCUMENT_NOT_CACHED; + else + // advance to the next state... + rv = Connect(PR_FALSE); + + // a failure from Connect means that we have to abort the channel. if (NS_FAILED(rv)) { - LOG(("AsyncOpenCacheEntry failed [rv=%x]\n", rv)); - if (mLoadFlags & LOAD_ONLY_FROM_CACHE) { - // If we have a fallback URI (and we're not already - // falling back), process the fallback asynchronously. - if (!mFallbackChannel && !mFallbackKey.IsEmpty()) { - rv = AsyncCall(&nsHttpChannel::HandleAsyncFallback); - if (NS_SUCCEEDED(rv)) - return rv; - } - } CloseCacheEntry(PR_TRUE); AsyncAbort(rv); } @@ -4930,27 +4831,6 @@ nsHttpChannel::DetermineStoragePolicy() return policy; } -nsresult -nsHttpChannel::DetermineCacheAccess(nsCacheAccessMode *_retval) -{ - PRBool offline = gIOService->IsOffline(); - - if (offline || (mLoadFlags & INHIBIT_CACHING)) { - // If we have been asked to bypass the cache and not write to the - // cache, then don't use the cache at all. Unless we're actually - // offline, which takes precedence over BYPASS_LOCAL_CACHE. - if (BYPASS_LOCAL_CACHE(mLoadFlags) && !offline) - return NS_ERROR_NOT_AVAILABLE; - *_retval = nsICache::ACCESS_READ; - } - else if (BYPASS_LOCAL_CACHE(mLoadFlags)) - *_retval = nsICache::ACCESS_WRITE; // replace cache entry - else - *_retval = nsICache::ACCESS_READ_WRITE; // normal browsing - - return NS_OK; -} - void nsHttpChannel::AsyncOnExamineCachedResponse() { diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h index ca77de3bf799..fa8539fc20b9 100644 --- a/netwerk/protocol/http/nsHttpChannel.h +++ b/netwerk/protocol/http/nsHttpChannel.h @@ -217,16 +217,7 @@ private: nsresult ResolveProxy(); // cache specific methods - nsresult OpenCacheEntry(); - nsresult OnOfflineCacheEntryAvailable(nsICacheEntryDescriptor *aEntry, - nsCacheAccessMode aAccess, - nsresult aResult, - PRBool aSync); - nsresult OpenNormalCacheEntry(PRBool aSync); - nsresult OnNormalCacheEntryAvailable(nsICacheEntryDescriptor *aEntry, - nsCacheAccessMode aAccess, - nsresult aResult, - PRBool aSync); + nsresult OpenCacheEntry(PRBool offline, PRBool *delayed); nsresult OpenOfflineCacheEntryForWriting(); nsresult GenerateCacheKey(PRUint32 postID, nsACString &key); nsresult UpdateExpirationTime(); @@ -244,7 +235,6 @@ private: nsresult InstallOfflineCacheListener(); void MaybeInvalidateCacheEntryForSubsequentGet(); nsCacheStoragePolicy DetermineStoragePolicy(); - nsresult DetermineCacheAccess(nsCacheAccessMode *_retval); void AsyncOnExamineCachedResponse(); // Handle the bogus Content-Encoding Apache sometimes sends @@ -287,11 +277,6 @@ private: PRUint32 mPostID; PRUint32 mRequestTime; - typedef nsresult (nsHttpChannel:: *nsOnCacheEntryAvailableCallback)( - nsICacheEntryDescriptor *, nsCacheAccessMode, nsresult, PRBool); - nsOnCacheEntryAvailableCallback mOnCacheEntryAvailableCallback; - PRBool mAsyncCacheOpen; - nsCOMPtr mOfflineCacheEntry; nsCacheAccessMode mOfflineCacheAccess; nsCString mOfflineCacheClientID; From c323cf4ed9b9637b018a342ffeba2254a23e1fd4 Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Thu, 2 Sep 2010 13:59:54 -0400 Subject: [PATCH 022/222] Backed out changeset be48a89b9561. Asked for by Mossop and dietrich. --- .../extensions/content/extensions-content.js | 2 +- .../extensions/test/xpinstall/Makefile.in | 2 - .../browser_unsigned_trigger_iframe.js | 50 ------------------- .../test/xpinstall/installtrigger_frame.html | 29 ----------- 4 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js delete mode 100644 toolkit/mozapps/extensions/test/xpinstall/installtrigger_frame.html diff --git a/toolkit/mozapps/extensions/content/extensions-content.js b/toolkit/mozapps/extensions/content/extensions-content.js index 0f2f5b7c88b2..32262753c071 100644 --- a/toolkit/mozapps/extensions/content/extensions-content.js +++ b/toolkit/mozapps/extensions/content/extensions-content.js @@ -250,7 +250,7 @@ function InstallTriggerManager() { InstallTriggerManager.prototype = { handleEvent: function handleEvent(aEvent) { - var window = aEvent.target.defaultView; + var window = aEvent.originalTarget.defaultView.content; // Need to make sure we are called on what we care about - // content windows. DOMWindowCreated is called on *all* HTMLDocuments, diff --git a/toolkit/mozapps/extensions/test/xpinstall/Makefile.in b/toolkit/mozapps/extensions/test/xpinstall/Makefile.in index da3810ca2650..b65413bea67a 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/Makefile.in +++ b/toolkit/mozapps/extensions/test/xpinstall/Makefile.in @@ -46,7 +46,6 @@ include $(topsrcdir)/config/rules.mk _BROWSER_FILES = head.js \ browser_unsigned_url.js \ browser_unsigned_trigger.js \ - browser_unsigned_trigger_iframe.js \ browser_whitelist.js \ browser_whitelist2.js \ browser_whitelist3.js \ @@ -101,7 +100,6 @@ _BROWSER_FILES = head.js \ multipackage.xpi \ enabled.html \ installtrigger.html \ - installtrigger_frame.html \ startsoftwareupdate.html \ installchrome.html \ triggerredirect.html \ diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js deleted file mode 100644 index e0422a5e601f..000000000000 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js +++ /dev/null @@ -1,50 +0,0 @@ -// ---------------------------------------------------------------------------- -// Test for bug 589598 - Ensure that installing through InstallTrigger -// works in an iframe in web content. - -function test() { - Harness.installConfirmCallback = confirm_install; - Harness.installEndedCallback = install_ended; - Harness.installsCompletedCallback = finish_test; - Harness.setup(); - - var pm = Services.perms; - pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); - - var triggers = encodeURIComponent(JSON.stringify({ - "Unsigned XPI": { - URL: TESTROOT + "unsigned.xpi", - IconURL: TESTROOT + "icon.png", - toString: function() { return this.URL; } - } - })); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.loadURI(TESTROOT + "installtrigger_frame.html?" + triggers); -} - -function confirm_install(window) { - items = window.document.getElementById("itemList").childNodes; - is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); - is(items[0].name, "XPI Test", "Should have seen the name"); - is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); - is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); - is(items[0].signed, "false", "Should have listed the item as unsigned"); - return true; -} - -function install_ended(install, addon) { - install.cancel(); -} - -function finish_test(count) { - is(count, 1, "1 Add-on should have been successfully installed"); - - Services.perms.remove("example.com", "install"); - - var doc = gBrowser.contentWindow.frames[0].document; // Document of iframe - is(doc.getElementById("return").textContent, "true", "installTrigger in iframe should have claimed success"); - is(doc.getElementById("status").textContent, "0", "Callback in iframe should have seen a success"); - - gBrowser.removeCurrentTab(); - Harness.finish(); -} diff --git a/toolkit/mozapps/extensions/test/xpinstall/installtrigger_frame.html b/toolkit/mozapps/extensions/test/xpinstall/installtrigger_frame.html deleted file mode 100644 index 11af0f35f038..000000000000 --- a/toolkit/mozapps/extensions/test/xpinstall/installtrigger_frame.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - -InstallTrigger frame tests - - - - - - -

InstallTrigger tests

-

-

- - From 8c37d3bfef808a6ff29b8809b04827923a4323fd Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 14:07:37 -0400 Subject: [PATCH 023/222] Bug 584494 - Regression: Transform rotation testcase performs significantly worse - r=dbaron --- layout/generic/nsAbsoluteContainingBlock.cpp | 10 +-- layout/generic/nsBlockFrame.cpp | 24 +++--- layout/generic/nsFrame.cpp | 89 ++++++++++++-------- layout/generic/nsIFrame.h | 10 +-- layout/reftests/bugs/389224-1-ref.html | 7 ++ layout/reftests/bugs/389224-1.html | 16 ++++ layout/reftests/bugs/389224-2.html | 16 ++++ layout/reftests/bugs/reftest.list | 2 + layout/style/nsStyleStruct.cpp | 7 +- 9 files changed, 116 insertions(+), 65 deletions(-) create mode 100644 layout/reftests/bugs/389224-1-ref.html create mode 100644 layout/reftests/bugs/389224-1.html create mode 100644 layout/reftests/bugs/389224-2.html diff --git a/layout/generic/nsAbsoluteContainingBlock.cpp b/layout/generic/nsAbsoluteContainingBlock.cpp index 58fc2ac8eeb1..4ada3da23f26 100644 --- a/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/layout/generic/nsAbsoluteContainingBlock.cpp @@ -494,14 +494,8 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat } if (oldRect.TopLeft() != rect.TopLeft() || - (aDelegatingFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) || - (kidDesiredSize.mOverflowArea + rect.TopLeft() != oldOverflowRect && - (kidDesiredSize.mOverflowArea + rect.TopLeft() != rect || oldRect != oldOverflowRect))) { - // The frame moved; we have to invalidate the whole frame - // because the children may have moved after they were reflowed - // We also have to invalidate when we have overflow and the overflow - // changes because the change might be caused by clipping - // XXX This could be optimized in some cases, especially clipping changes + (aDelegatingFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) { + // The frame moved aKidFrame->GetParent()->Invalidate(oldOverflowRect); aKidFrame->GetParent()->Invalidate(kidDesiredSize.mOverflowArea + rect.TopLeft()); diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 24cf695e26d2..e7b8460e2e06 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -520,17 +520,21 @@ nsBlockFrame::InvalidateInternal(const nsRect& aDamageRect, PRUint32 aFlags) { // Optimize by suppressing invalidation of areas that are clipped out - // with CSS 'clip'. - const nsStyleDisplay* disp = GetStyleDisplay(); - nsRect absPosClipRect; - if (GetAbsPosClipRect(disp, &absPosClipRect, GetSize())) { - // Restrict the invalidated area to abs-pos clip rect - // abs-pos clipping clips everything in the frame - nsRect r; - if (r.IntersectRect(aDamageRect, absPosClipRect - nsPoint(aX, aY))) { - nsBlockFrameSuper::InvalidateInternal(r, aX, aY, this, aFlags); + // with CSS 'clip'. Don't suppress invalidation of *this* frame directly, + // because when 'clip' shrinks we need to invalidate this frame and + // be able to invalidate areas outside the 'clip'. + if (aForChild) { + const nsStyleDisplay* disp = GetStyleDisplay(); + nsRect absPosClipRect; + if (GetAbsPosClipRect(disp, &absPosClipRect, GetSize())) { + // Restrict the invalidated area to abs-pos clip rect + // abs-pos clipping clips everything in the frame + nsRect r; + if (r.IntersectRect(aDamageRect, absPosClipRect - nsPoint(aX, aY))) { + nsBlockFrameSuper::InvalidateInternal(r, aX, aY, this, aFlags); + } + return; } - return; } nsBlockFrameSuper::InvalidateInternal(aDamageRect, aX, aY, this, aFlags); diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 2a97d8565393..4d073ef6cfe7 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -5866,26 +5866,6 @@ IsInlineFrame(nsIFrame *aFrame) type == nsGkAtoms::positionedInlineFrame; } -nsRect -nsIFrame::GetAdditionalOverflow(const nsRect& aOverflowArea, - const nsSize& aNewSize, - PRBool* aHasOutlineOrEffects) -{ - nsRect overflowRect = - ComputeOutlineAndEffectsRect(this, aHasOutlineOrEffects, - aOverflowArea, aNewSize, PR_TRUE); - - // Absolute position clipping - PRBool hasAbsPosClip; - nsRect absPosClipRect; - hasAbsPosClip = GetAbsPosClipRect(GetStyleDisplay(), &absPosClipRect, aNewSize); - if (hasAbsPosClip) { - overflowRect.IntersectRect(overflowRect, absPosClipRect); - } - - return overflowRect; -} - void nsIFrame::FinishAndStoreOverflow(nsRect* aOverflowArea, nsSize aNewSize) { @@ -5931,8 +5911,20 @@ nsIFrame::FinishAndStoreOverflow(nsRect* aOverflowArea, nsSize aNewSize) } PRBool hasOutlineOrEffects; - *aOverflowArea = GetAdditionalOverflow(*aOverflowArea, aNewSize, - &hasOutlineOrEffects); + *aOverflowArea = + ComputeOutlineAndEffectsRect(this, &hasOutlineOrEffects, + *aOverflowArea, aNewSize, PR_TRUE); + + // Absolute position clipping + PRBool didHaveAbsPosClip = (GetStateBits() & NS_FRAME_HAS_CLIP) != 0; + nsRect absPosClipRect; + PRBool hasAbsPosClip = GetAbsPosClipRect(disp, &absPosClipRect, aNewSize); + if (hasAbsPosClip) { + aOverflowArea->IntersectRect(*aOverflowArea, absPosClipRect); + AddStateBits(NS_FRAME_HAS_CLIP); + } else { + RemoveStateBits(NS_FRAME_HAS_CLIP); + } /* If we're transformed, transform the overflow rect by the current transformation. */ PRBool hasTransform = IsTransformed(); @@ -5962,19 +5954,46 @@ nsIFrame::FinishAndStoreOverflow(nsRect* aOverflowArea, nsSize aNewSize) } } - if (overflowChanged && (hasOutlineOrEffects || hasTransform)) { - // When there's an outline or box-shadow or SVG effects or transform, - // changes to those styles might require repainting of the old and new - // overflow areas. Repainting of the old overflow area is handled in - // nsCSSFrameConstructor::DoApplyRenderingChangeToTree in response - // to nsChangeHint_RepaintFrame. Since the new overflow area is not - // known at that time, we have to handle it here. - // If the overflow area hasn't changed, then we don't have to do - // anything here since repainting the old overflow area was enough. - // If there is no outline or other effects now, then we don't have - // to do anything here since removing those styles can't require - // repainting of areas that weren't in the old overflow area. - Invalidate(*aOverflowArea); + if (overflowChanged) { + if (hasOutlineOrEffects) { + // When there's an outline or box-shadow or SVG effects, + // changes to those styles might require repainting of the old and new + // overflow areas. Repainting of the old overflow area is handled in + // nsCSSFrameConstructor::DoApplyRenderingChangeToTree in response + // to nsChangeHint_RepaintFrame. Since the new overflow area is not + // known at that time, we have to handle it here. + // If the overflow area hasn't changed, then we don't have to do + // anything here since repainting the old overflow area was enough. + // If there is no outline or other effects now, then we don't have + // to do anything here since removing those styles can't require + // repainting of areas that weren't in the old overflow area. + Invalidate(*aOverflowArea); + } else if (hasAbsPosClip || didHaveAbsPosClip) { + // If we are (or were) clipped by the 'clip' property, and our + // overflow area changes, it might be because the clipping changed. + // The nsChangeHint_RepaintFrame for the style change will only + // repaint the old overflow area, so if the overflow area has + // changed (in particular, if it grows), we have to repaint the + // new area here. + Invalidate(*aOverflowArea); + } else if (hasTransform) { + // When there's a transform, changes to that style might require + // repainting of the old and new overflow areas in the widget. + // Repainting of the frame itself will not be required if there's + // a retained layer, so we can call InvalidateLayer here + // which will avoid repainting ThebesLayers if possible. + // nsCSSFrameConstructor::DoApplyRenderingChangeToTree repaints + // the old overflow area in the widget in response to + // nsChangeHint_UpdateTransformLayer. But since the new overflow + // area is not known at that time, we have to handle it here. + // If the overflow area hasn't changed, then it doesn't matter that + // we didn't reach here since repainting the old overflow area was enough. + // If there is no transform now, then the container layer for + // the transform will go away and the frame contents will change + // ThebesLayers, forcing it to be invalidated, so it doesn't matter + // that we didn't reach here. + InvalidateLayer(*aOverflowArea, nsDisplayItem::TYPE_TRANSFORM); + } } } diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 68285e4de876..4ae237585904 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -266,6 +266,9 @@ typedef PRUint64 nsFrameState; // NS_FRAME_HAS_CONTAINER_LAYER bit. #define NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT NS_FRAME_STATE_BIT(34) +// Frame's overflow area was clipped by the 'clip' property. +#define NS_FRAME_HAS_CLIP NS_FRAME_STATE_BIT(35) + // The lower 20 bits and upper 32 bits of the frame state are reserved // by this API. #define NS_FRAME_RESERVED ~NS_FRAME_IMPL_RESERVED @@ -2519,13 +2522,6 @@ protected: */ void InvalidateRoot(const nsRect& aDamageRect, PRUint32 aFlags); - /** - * Gets the overflow area for any properties that are common to all types of frames - * e.g. outlines. - */ - nsRect GetAdditionalOverflow(const nsRect& aOverflowArea, const nsSize& aNewSize, - PRBool* aHasOutlineOrEffects); - /** * Can we stop inside this frame when we're skipping non-rendered whitespace? * @param aForward [in] Are we moving forward (or backward) in content order. diff --git a/layout/reftests/bugs/389224-1-ref.html b/layout/reftests/bugs/389224-1-ref.html new file mode 100644 index 000000000000..8e96f277737f --- /dev/null +++ b/layout/reftests/bugs/389224-1-ref.html @@ -0,0 +1,7 @@ + + + +
+
+ + diff --git a/layout/reftests/bugs/389224-1.html b/layout/reftests/bugs/389224-1.html new file mode 100644 index 000000000000..7fe96421100b --- /dev/null +++ b/layout/reftests/bugs/389224-1.html @@ -0,0 +1,16 @@ + + + +
+
+
+ + + diff --git a/layout/reftests/bugs/389224-2.html b/layout/reftests/bugs/389224-2.html new file mode 100644 index 000000000000..ef9838fedc1b --- /dev/null +++ b/layout/reftests/bugs/389224-2.html @@ -0,0 +1,16 @@ + + + +
+
+
+ + + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index bd708068329d..19987537fe57 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -725,6 +725,8 @@ random == 387876-2.html 387876-2-ref.html # bug 471630 == 388367-1.html about:blank == 388980-1.html 388980-1-ref.html == 389074-1.html 389074-1-ref.html +== 389224-1.html 389224-1-ref.html +== 389224-2.html about:blank == 389468-1.html 389468-1-ref.html == 389623-1.html 389623-1-ref.html == 389636-1.html about:blank # assertion test diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index af9032f4fdb1..089d182244e5 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1983,16 +1983,13 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const nsChangeHint_NeedDirtyReflow))); } - if (mClipFlags != aOther.mClipFlags || mClip != aOther.mClip) { - // FIXME: Bug 507764. Could we use a more precise hint here? - NS_UpdateHint(hint, nsChangeHint_ReflowFrame); - } // XXX the following is conservative, for now: changing float breaking shouldn't // necessarily require a repaint, reflow should suffice. if (mBreakType != aOther.mBreakType || mBreakBefore != aOther.mBreakBefore || mBreakAfter != aOther.mBreakAfter - || mAppearance != aOther.mAppearance) + || mAppearance != aOther.mAppearance + || mClipFlags != aOther.mClipFlags || mClip != aOther.mClip) NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame)); if (mOpacity != aOther.mOpacity) { From cde83c5f2c55a5898fc6fd594ef7513934989f53 Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Thu, 2 Sep 2010 10:28:38 -0400 Subject: [PATCH 024/222] Bug 591042 - validation fix in copyTexImage2D and update list of failing tests - r=vladimir, a=blocking2.0 --- content/canvas/src/WebGLContextGL.cpp | 6 ++++++ content/canvas/test/webgl/failing_tests.txt | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 921322b4afb6..7947718f3789 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -580,6 +580,12 @@ WebGLContext::CopyTexImage2D(WebGLenum target, if (level < 0) return ErrorInvalidValue("copyTexImage2D: level may not be negative"); + if (level >= 1) { + if (!(is_pot_assuming_nonnegative(width) && + is_pot_assuming_nonnegative(height))) + return ErrorInvalidValue("copyTexImage2D: with level > 0, width and height must be powers of two"); + } + if (!CanvasUtils::CheckSaneSubrectSize(x,y,width, height, mWidth, mHeight)) return ErrorInvalidOperation("CopyTexImage2D: copied rectangle out of bounds"); diff --git a/content/canvas/test/webgl/failing_tests.txt b/content/canvas/test/webgl/failing_tests.txt index 19a04e4c9da0..193483fa32c6 100644 --- a/content/canvas/test/webgl/failing_tests.txt +++ b/content/canvas/test/webgl/failing_tests.txt @@ -38,14 +38,12 @@ conformance/tex-input-validation.html conformance/texparameter-test.html conformance/texture-active-bind-2.html conformance/texture-formats-test.html -conformance/texture-npot.html conformance/uniform-samplers-test.html conformance/viewport-unchanged-upon-resize.html more/conformance/constants.html more/conformance/getContext.html more/conformance/quickCheckAPI.html more/conformance/quickCheckAPIBadArgs.html -more/conformance/webGLArrays.html more/functions/bufferDataBadArgs.html more/functions/copyTexImage2D.html more/functions/copyTexImage2DBadArgs.html From f6ebb04f65d8a0f35c4b059d22202ee1168509a8 Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Thu, 2 Sep 2010 10:29:41 -0400 Subject: [PATCH 025/222] Bug 591084 - various WebGLTexture improvements - r=vladimir --- content/canvas/src/WebGLContext.h | 74 +++++++++++++++--------- content/canvas/src/WebGLContextGL.cpp | 8 ++- content/canvas/src/WebGLContextUtils.cpp | 4 +- 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index 1af669443a41..26be386183a7 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -685,7 +685,7 @@ public: mFacesCount(0), mMaxLevelWithCustomImages(0), mHaveGeneratedMipmap(PR_FALSE), - mFakeBlackStatus(DontKnowIfNeedFakeBlack) + mFakeBlackStatus(DoNotNeedFakeBlack) {} void Delete() { @@ -913,12 +913,13 @@ public: mHaveGeneratedMipmap = PR_FALSE; } - PRBool IsGenerateMipmapAllowed() const { - const ImageInfo &first = ImageInfoAt(0, 0); - if (!first.IsPowerOfTwo()) - return PR_FALSE; - for (size_t face = 0; face < mFacesCount; ++face) { - if (ImageInfoAt(0, face) != first) + PRBool IsFirstImagePowerOfTwo() const { + return ImageInfoAt(0, 0).IsPowerOfTwo(); + } + + PRBool AreAllLevel0ImageInfosEqual() const { + for (size_t face = 1; face < mFacesCount; ++face) { + if (ImageInfoAt(0, face) != ImageInfoAt(0, 0)) return PR_FALSE; } return PR_TRUE; @@ -927,7 +928,7 @@ public: PRBool IsMipmapTexture2DComplete() const { if (mTarget != LOCAL_GL_TEXTURE_2D) return PR_FALSE; - if (!mImageInfos[0].IsPositive()) + if (!ImageInfoAt(0, 0).IsPositive()) return PR_FALSE; if (mHaveGeneratedMipmap) return PR_TRUE; @@ -940,11 +941,7 @@ public: const ImageInfo &first = ImageInfoAt(0, 0); if (!first.IsPositive() || !first.IsSquare()) return PR_FALSE; - for (size_t face = 0; face < mFacesCount; ++face) { - if (ImageInfoAt(0, face) != first) - return PR_FALSE; - } - return PR_TRUE; + return AreAllLevel0ImageInfosEqual(); } PRBool IsMipmapCubeComplete() const { @@ -966,26 +963,39 @@ public: // Determine if the texture needs to be faked as a black texture. // See 3.8.2 Shader Execution in the OpenGL ES 2.0.24 spec. + const char *msg_rendering_as_black + = "A texture is going to be rendered as if it were black, as per the OpenGL ES 2.0.24 spec section 3.8.2, " + "because it"; + if (mTarget == LOCAL_GL_TEXTURE_2D) { if (DoesMinFilterRequireMipmap()) { - if (!IsMipmapTexture2DComplete() || - !mImageInfos[0].IsPowerOfTwo()) - { + if (!IsMipmapTexture2DComplete()) { + mContext->LogMessage("%s is a 2D texture, with a minification filter requiring a mipmap, " + "and is not mipmap complete (as defined in section 3.7.10).", msg_rendering_as_black); + mFakeBlackStatus = DoNeedFakeBlack; + } else if (!ImageInfoAt(0, 0).IsPowerOfTwo()) { + mContext->LogMessage("%s is a 2D texture, with a minification filter requiring a mipmap, " + "and either its width or height is not a power of two.", msg_rendering_as_black); mFakeBlackStatus = DoNeedFakeBlack; } } else // no mipmap required { - if (!mImageInfos[0].IsPositive() || - (!AreBothWrapModesClampToEdge() && !mImageInfos[0].IsPowerOfTwo())) - { + if (!ImageInfoAt(0, 0).IsPositive()) { + mContext->LogMessage("%s is a 2D texture and its width or height is equal to zero.", + msg_rendering_as_black); + mFakeBlackStatus = DoNeedFakeBlack; + } else if (!AreBothWrapModesClampToEdge() && !ImageInfoAt(0, 0).IsPowerOfTwo()) { + mContext->LogMessage("%s is a 2D texture, with a minification filter not requiring a mipmap, " + "with its width or height not a power of two, and with a wrap mode " + "different from CLAMP_TO_EDGE.", msg_rendering_as_black); mFakeBlackStatus = DoNeedFakeBlack; } } } - else if (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP) + else // cube map { PRBool areAllLevel0ImagesPOT = PR_TRUE; for (size_t face = 0; face < mFacesCount; ++face) @@ -993,17 +1003,29 @@ public: if (DoesMinFilterRequireMipmap()) { - if (!IsMipmapCubeComplete() || - !areAllLevel0ImagesPOT) - { + if (!IsMipmapCubeComplete()) { + mContext->LogMessage("%s is a cube map texture, with a minification filter requiring a mipmap, " + "and is not mipmap cube complete (as defined in section 3.7.10).", + msg_rendering_as_black); + mFakeBlackStatus = DoNeedFakeBlack; + } else if (!areAllLevel0ImagesPOT) { + mContext->LogMessage("%s is a cube map texture, with a minification filter requiring a mipmap, " + "and either the width or the height of some level 0 image is not a power of two.", + msg_rendering_as_black); mFakeBlackStatus = DoNeedFakeBlack; } } else // no mipmap required { - if (!IsCubeComplete() || - (!AreBothWrapModesClampToEdge() && !areAllLevel0ImagesPOT)) - { + if (!IsCubeComplete()) { + mContext->LogMessage("%s is a cube map texture, with a minification filter not requiring a mipmap, " + "and is not cube complete (as defined in section 3.7.10).", + msg_rendering_as_black); + mFakeBlackStatus = DoNeedFakeBlack; + } else if (!AreBothWrapModesClampToEdge() && !areAllLevel0ImagesPOT) { + mContext->LogMessage("%s is a cube map texture, with a minification filter not requiring a mipmap, " + "with some level 0 image having width or height not a power of two, and with a wrap mode " + "different from CLAMP_TO_EDGE.", msg_rendering_as_black); mFakeBlackStatus = DoNeedFakeBlack; } } diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 7947718f3789..392ea3b1d6b4 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -1254,8 +1254,12 @@ WebGLContext::GenerateMipmap(WebGLenum target) if (!tex) return ErrorInvalidOperation("generateMipmap: no texture is bound to this target"); - if (!tex->IsGenerateMipmapAllowed()) { - return ErrorInvalidOperation("generateMipmap: texture does not satisfy requirements for generateMipmap"); + if (!tex->IsFirstImagePowerOfTwo()) { + return ErrorInvalidOperation("generateMipmap: the width or height of this texture is not a power of two"); + } + + if (!tex->AreAllLevel0ImageInfosEqual()) { + return ErrorInvalidOperation("generateMipmap: the six faces of this cube map have different dimensions, format, or type."); } tex->SetGeneratedMipmap(); diff --git a/content/canvas/src/WebGLContextUtils.cpp b/content/canvas/src/WebGLContextUtils.cpp index 6dafab047ea5..ee5c64926e04 100644 --- a/content/canvas/src/WebGLContextUtils.cpp +++ b/content/canvas/src/WebGLContextUtils.cpp @@ -213,11 +213,11 @@ WebGLContext::LogMessage(const char *fmt, ...) void WebGLContext::LogMessage(const char *fmt, va_list ap) { - char buf[256]; + char buf[1024]; nsCOMPtr console(do_GetService(NS_CONSOLESERVICE_CONTRACTID)); if (console) { - PR_vsnprintf(buf, 256, fmt, ap); + PR_vsnprintf(buf, 1024, fmt, ap); console->LogStringMessage(NS_ConvertUTF8toUTF16(nsDependentCString(buf)).get()); fprintf(stderr, "%s\n", buf); } From 013b076d34d22d3fa739bd756c1a08ae5919e689 Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Thu, 2 Sep 2010 10:30:26 -0400 Subject: [PATCH 026/222] Bug 588918 - fix many valgrind uninitialized value errors - r=vladimir --- content/canvas/src/WebGLContextGL.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 392ea3b1d6b4..91a40d97d510 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -2556,6 +2556,9 @@ WebGLContext::RenderbufferStorage(WebGLenum target, WebGLenum internalformat, We MakeContextCurrent(); gl->fRenderbufferStorage(target, internalformat, width, height); + // now we need to initialize the renderbuffer to 0 as per the thread "about RenderBufferStorage" + // on the public_webgl list + return NS_OK; } From 4a993e198e8ad17bc391cb49592e1842506a113d Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Thu, 2 Sep 2010 10:31:08 -0400 Subject: [PATCH 027/222] Bug 591438 - disable getParameter random testing - r=vladimir --- content/canvas/test/webgl/more/conformance/quickCheckAPI.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/content/canvas/test/webgl/more/conformance/quickCheckAPI.js b/content/canvas/test/webgl/more/conformance/quickCheckAPI.js index 108bd05c95a9..d0f25cc6f7cf 100644 --- a/content/canvas/test/webgl/more/conformance/quickCheckAPI.js +++ b/content/canvas/test/webgl/more/conformance/quickCheckAPI.js @@ -845,8 +845,9 @@ ArgGenerators = { } }, getParameter : { - generate : function() { return [getParameterPname.random()]; }, - checkArgValidity : function(p) { return getParameterPname.has(p); } +// FIXME disabled because crashes, see bug 576620 +// generate : function() { return [getParameterPname.random()]; }, +// checkArgValidity : function(p) { return getParameterPname.has(p); } }, getBufferParameter : {}, // FIXME getError : { From 5ada19ecd0ad165a13ea0cc3387b1c723d47343e Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Thu, 2 Sep 2010 10:34:08 -0400 Subject: [PATCH 028/222] Bug 571054 - emulate vertex attrib 0 on desktop GL - r=vladimir --- content/canvas/src/WebGLContext.cpp | 6 + content/canvas/src/WebGLContext.h | 12 +- content/canvas/src/WebGLContextGL.cpp | 191 +++++++++++++++++--- content/canvas/src/WebGLContextValidate.cpp | 5 + content/canvas/test/webgl/failing_tests.txt | 1 - 5 files changed, 186 insertions(+), 29 deletions(-) diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index 5b4f9dfbc177..5882206473e4 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -102,6 +102,12 @@ WebGLContext::WebGLContext() mBlackTexturesAreInitialized = PR_FALSE; mFakeBlackStatus = DoNotNeedFakeBlack; + + mFakeVertexAttrib0Array = nsnull; + mVertexAttrib0Vector[0] = 0; + mVertexAttrib0Vector[1] = 0; + mVertexAttrib0Vector[2] = 0; + mVertexAttrib0Vector[3] = 1; } WebGLContext::~WebGLContext() diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index 26be386183a7..8d878c43713a 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -226,7 +226,7 @@ class WebGLBuffer; struct WebGLVertexAttribData { WebGLVertexAttribData() - : buf(0), stride(0), size(0), byteOffset(0), type(0), enabled(PR_FALSE) + : buf(0), stride(0), size(0), byteOffset(0), type(0), enabled(PR_FALSE), normalized(PR_FALSE) { } WebGLObjectRefPtr buf; @@ -235,6 +235,7 @@ struct WebGLVertexAttribData { GLuint byteOffset; GLenum type; PRBool enabled; + PRBool normalized; GLuint componentSize() const { switch(type) { @@ -331,10 +332,13 @@ public: } PRBool NeedFakeBlack(); - void BindFakeBlackTextures(); void UnbindFakeBlackTextures(); + PRBool NeedFakeVertexAttrib0(); + void DoFakeVertexAttrib0(WebGLuint vertexCount); + void UndoFakeVertexAttrib0(); + protected: nsCOMPtr mCanvasElement; nsHTMLCanvasElement *HTMLCanvasElement() { @@ -475,6 +479,9 @@ protected: WebGLuint mBlackTexture2D, mBlackTextureCubeMap; PRBool mBlackTexturesAreInitialized; + WebGLfloat mVertexAttrib0Vector[4]; + nsAutoArrayPtr mFakeVertexAttrib0Array; + public: // console logging helpers static void LogMessage (const char *fmt, ...); @@ -1342,7 +1349,6 @@ protected: NS_DEFINE_STATIC_IID_ACCESSOR(WebGLActiveInfo, WEBGLACTIVEINFO_PRIVATE_IID) - /** ** Template implementations **/ diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 91a40d97d510..d1a4f70cf4bb 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -866,12 +866,55 @@ WebGLContext::DisableVertexAttribArray(WebGLuint index) MakeContextCurrent(); - gl->fDisableVertexAttribArray(index); + if (index || gl->IsGLES2()) + gl->fDisableVertexAttribArray(index); + mAttribBuffers[index].enabled = PR_FALSE; return NS_OK; } +PRBool +WebGLContext::NeedFakeVertexAttrib0() +{ + return !gl->IsGLES2() && + !mAttribBuffers[0].enabled; +} + +void +WebGLContext::DoFakeVertexAttrib0(WebGLuint vertexCount) +{ + if (!NeedFakeVertexAttrib0()) + return; + + mFakeVertexAttrib0Array = new WebGLfloat[4 * vertexCount]; + + for(size_t i = 0; i < vertexCount; ++i) { + mFakeVertexAttrib0Array[4 * i + 0] = mVertexAttrib0Vector[0]; + mFakeVertexAttrib0Array[4 * i + 1] = mVertexAttrib0Vector[1]; + mFakeVertexAttrib0Array[4 * i + 2] = mVertexAttrib0Vector[2]; + mFakeVertexAttrib0Array[4 * i + 3] = mVertexAttrib0Vector[3]; + } + + gl->fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, mFakeVertexAttrib0Array); +} + +void +WebGLContext::UndoFakeVertexAttrib0() +{ + if (!NeedFakeVertexAttrib0()) + return; + + mFakeVertexAttrib0Array = nsnull; + + gl->fVertexAttribPointer(0, + mAttribBuffers[0].size, + mAttribBuffers[0].type, + mAttribBuffers[0].normalized, + mAttribBuffers[0].stride, + (const GLvoid *) mAttribBuffers[0].byteOffset); +} + PRBool WebGLContext::NeedFakeBlack() { @@ -989,7 +1032,11 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count) MakeContextCurrent(); BindFakeBlackTextures(); + DoFakeVertexAttrib0(checked_firstPlusCount.value()); + gl->fDrawArrays(mode, first, count); + + UndoFakeVertexAttrib0(); UnbindFakeBlackTextures(); Invalidate(); @@ -1062,7 +1109,11 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web MakeContextCurrent(); BindFakeBlackTextures(); + DoFakeVertexAttrib0(checked_neededCount.value()); + gl->fDrawElements(mode, count, type, (GLvoid*) (byteOffset)); + + UndoFakeVertexAttrib0(); UnbindFakeBlackTextures(); Invalidate(); @@ -2210,10 +2261,17 @@ WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname, nsIVariant **ret case LOCAL_GL_CURRENT_VERTEX_ATTRIB: { - GLfloat fv[4] = { 0 }; - gl->fGetVertexAttribfv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, fv); + WebGLfloat vec[4] = {0, 0, 0, 1}; + if (index) { + gl->fGetVertexAttribfv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, &vec[0]); + } else { + vec[0] = mVertexAttrib0Vector[0]; + vec[1] = mVertexAttrib0Vector[1]; + vec[2] = mVertexAttrib0Vector[2]; + vec[3] = mVertexAttrib0Vector[3]; + } wrval->SetAsArray(nsIDataType::VTYPE_FLOAT, nsnull, - 4, static_cast(fv)); + 4, vec); } break; case LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED: @@ -2779,23 +2837,6 @@ WebGLContext::name##_array(nsIWebGLUniformLocation *ploc, js::TypedArray *wa) \ return NS_OK; \ } -#define SIMPLE_ARRAY_METHOD_NO_COUNT(name, cnt, arrayType, ptrType) \ -NS_IMETHODIMP \ -WebGLContext::name(PRInt32 dummy) { \ - return NS_ERROR_NOT_IMPLEMENTED; \ -} \ -NS_IMETHODIMP \ -WebGLContext::name##_array(WebGLuint idx, js::TypedArray *wa) \ -{ \ - if (!wa || wa->type != js::TypedArray::arrayType) \ - return ErrorInvalidOperation(#name ": array must be " #arrayType); \ - if (wa->length < cnt) \ - return ErrorInvalidOperation(#name ": array must be >= %d elements", cnt); \ - MakeContextCurrent(); \ - gl->f##name(idx, (ptrType *)wa->data); \ - return NS_OK; \ -} - #define SIMPLE_MATRIX_METHOD_UNIFORM(name, dim, arrayType, ptrType) \ NS_IMETHODIMP \ WebGLContext::name(PRInt32 dummy) { \ @@ -2864,10 +2905,109 @@ SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix2fv, 2, TYPE_FLOAT32, WebGLfloat) SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix3fv, 3, TYPE_FLOAT32, WebGLfloat) SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix4fv, 4, TYPE_FLOAT32, WebGLfloat) -GL_SAME_METHOD_2(VertexAttrib1f, VertexAttrib1f, PRUint32, WebGLfloat) -GL_SAME_METHOD_3(VertexAttrib2f, VertexAttrib2f, PRUint32, WebGLfloat, WebGLfloat) -GL_SAME_METHOD_4(VertexAttrib3f, VertexAttrib3f, PRUint32, WebGLfloat, WebGLfloat, WebGLfloat) -GL_SAME_METHOD_5(VertexAttrib4f, VertexAttrib4f, PRUint32, WebGLfloat, WebGLfloat, WebGLfloat, WebGLfloat) +NS_IMETHODIMP +WebGLContext::VertexAttrib1f(PRUint32 index, WebGLfloat x0) +{ + MakeContextCurrent(); + + if (index) { + gl->fVertexAttrib1f(index, x0); + } else { + mVertexAttrib0Vector[0] = x0; + mVertexAttrib0Vector[1] = 0; + mVertexAttrib0Vector[2] = 0; + mVertexAttrib0Vector[3] = 1; + if (gl->IsGLES2()) + gl->fVertexAttrib1f(index, x0); + } + + return NS_OK; +} + +NS_IMETHODIMP +WebGLContext::VertexAttrib2f(PRUint32 index, WebGLfloat x0, WebGLfloat x1) +{ + MakeContextCurrent(); + + if (index) { + gl->fVertexAttrib2f(index, x0, x1); + } else { + mVertexAttrib0Vector[0] = x0; + mVertexAttrib0Vector[1] = x1; + mVertexAttrib0Vector[2] = 0; + mVertexAttrib0Vector[3] = 1; + if (gl->IsGLES2()) + gl->fVertexAttrib2f(index, x0, x1); + } + + return NS_OK; +} + +NS_IMETHODIMP +WebGLContext::VertexAttrib3f(PRUint32 index, WebGLfloat x0, WebGLfloat x1, WebGLfloat x2) +{ + MakeContextCurrent(); + + if (index) { + gl->fVertexAttrib3f(index, x0, x1, x2); + } else { + mVertexAttrib0Vector[0] = x0; + mVertexAttrib0Vector[1] = x1; + mVertexAttrib0Vector[2] = x2; + mVertexAttrib0Vector[3] = 1; + if (gl->IsGLES2()) + gl->fVertexAttrib3f(index, x0, x1, x2); + } + + return NS_OK; +} + +NS_IMETHODIMP +WebGLContext::VertexAttrib4f(PRUint32 index, WebGLfloat x0, WebGLfloat x1, + WebGLfloat x2, WebGLfloat x3) +{ + MakeContextCurrent(); + + if (index) { + gl->fVertexAttrib4f(index, x0, x1, x2, x3); + } else { + mVertexAttrib0Vector[0] = x0; + mVertexAttrib0Vector[1] = x1; + mVertexAttrib0Vector[2] = x2; + mVertexAttrib0Vector[3] = x3; + if (gl->IsGLES2()) + gl->fVertexAttrib4f(index, x0, x1, x2, x3); + } + + return NS_OK; +} + +#define SIMPLE_ARRAY_METHOD_NO_COUNT(name, cnt, arrayType, ptrType) \ +NS_IMETHODIMP \ +WebGLContext::name(PRInt32 dummy) { \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} \ +NS_IMETHODIMP \ +WebGLContext::name##_array(WebGLuint idx, js::TypedArray *wa) \ +{ \ + if (!wa || wa->type != js::TypedArray::arrayType) \ + return ErrorInvalidOperation(#name ": array must be " #arrayType); \ + if (wa->length < cnt) \ + return ErrorInvalidOperation(#name ": array must be >= %d elements", cnt); \ + MakeContextCurrent(); \ + ptrType *ptr = (ptrType *)wa->data; \ + if (idx) { \ + gl->f##name(idx, ptr); \ + } else { \ + mVertexAttrib0Vector[0] = ptr[0]; \ + mVertexAttrib0Vector[1] = cnt > 1 ? ptr[1] : ptrType(0); \ + mVertexAttrib0Vector[2] = cnt > 2 ? ptr[2] : ptrType(0); \ + mVertexAttrib0Vector[3] = cnt > 3 ? ptr[3] : ptrType(1); \ + if (gl->IsGLES2()) \ + gl->f##name(idx, ptr); \ + } \ + return NS_OK; \ +} SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib1fv, 1, TYPE_FLOAT32, WebGLfloat) SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib2fv, 2, TYPE_FLOAT32, WebGLfloat) @@ -3182,6 +3322,7 @@ WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type vd.size = size; vd.byteOffset = byteOffset; vd.type = type; + vd.normalized = normalized; MakeContextCurrent(); diff --git a/content/canvas/src/WebGLContextValidate.cpp b/content/canvas/src/WebGLContextValidate.cpp index c1c7ee300baf..60837078877c 100644 --- a/content/canvas/src/WebGLContextValidate.cpp +++ b/content/canvas/src/WebGLContextValidate.cpp @@ -384,6 +384,11 @@ WebGLContext::InitAndValidateGL() MakeContextCurrent(); + // on desktop OpenGL, we always keep vertex attrib 0 array enabled + if (!gl->IsGLES2()) { + gl->fEnableVertexAttribArray(0); + } + gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, (GLint*) &mGLMaxVertexAttribs); if (mGLMaxVertexAttribs < 8) { LogMessage("GL_MAX_VERTEX_ATTRIBS: %d is < 8!", mGLMaxVertexAttribs); diff --git a/content/canvas/test/webgl/failing_tests.txt b/content/canvas/test/webgl/failing_tests.txt index 193483fa32c6..17803e7e0d53 100644 --- a/content/canvas/test/webgl/failing_tests.txt +++ b/content/canvas/test/webgl/failing_tests.txt @@ -19,7 +19,6 @@ conformance/gl-scissor-test.html conformance/gl-teximage.html conformance/gl-uniform-arrays.html conformance/gl-unknown-uniform.html -conformance/gl-vertex-attrib.html conformance/glsl-2types-of-textures-on-same-unit.html conformance/glsl-conformance.html conformance/invalid-passed-params.html From fd8083f61d82a4ad07b2408797773a792de17116 Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Thu, 2 Sep 2010 10:38:26 -0400 Subject: [PATCH 029/222] Bug 592416 - Various WebGL fixes - r=vladimir --- content/canvas/src/WebGLContextGL.cpp | 52 +++++++++++++++---- content/canvas/test/webgl/failing_tests.txt | 3 -- .../more/functions/vertexAttribPointer.html | 1 - .../canvas/nsICanvasRenderingContextWebGL.idl | 3 +- 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index d1a4f70cf4bb..58f1eaeec7bd 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -223,7 +223,7 @@ WebGLContext::BindFramebuffer(WebGLenum target, nsIWebGLFramebuffer *fbobj) WebGLFramebuffer *wfb; if (target != LOCAL_GL_FRAMEBUFFER) - return ErrorInvalidOperation("BindFramebuffer: target must be GL_FRAMEBUFFER"); + return ErrorInvalidEnum("BindFramebuffer: target must be GL_FRAMEBUFFER"); if (!GetConcreteObjectAndGLName("bindFramebuffer", fbobj, &wfb, &framebuffername, &isNull)) return NS_OK; @@ -1751,7 +1751,7 @@ WebGLContext::GetFramebufferAttachmentParameter(WebGLenum target, WebGLenum atta break; default: - return ErrorInvalidEnum("GetFramebufferAttachmentParameter: invalid parameter"); + return ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: pname", pname); } } else if (atype == LOCAL_GL_TEXTURE) { switch (pname) { @@ -1777,10 +1777,18 @@ WebGLContext::GetFramebufferAttachmentParameter(WebGLenum target, WebGLenum atta break; default: - return ErrorInvalidEnum("GetFramebufferAttachmentParameter: invalid parameter"); + return ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: pname", pname); } - } else { - NS_WARNING("Unknown framebuffer attachment type?"); + } else if (atype == LOCAL_GL_NONE) { + switch (pname) { + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + wrval->SetAsInt32(atype); + break; + + default: + return ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: pname", pname); + } + } else { // GL bug? should never happen return NS_ERROR_FAILURE; } @@ -3282,39 +3290,61 @@ WebGLContext::ShaderSource(nsIWebGLShader *sobj, const nsAString& source) NS_IMETHODIMP WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type, - WebGLboolean normalized, WebGLuint stride, - WebGLuint byteOffset) + WebGLboolean normalized, WebGLsizei stride, + WebGLsizeiptr byteOffset) { if (mBoundArrayBuffer == nsnull) return ErrorInvalidOperation("VertexAttribPointer: must have valid GL_ARRAY_BUFFER binding"); + WebGLsizei requiredAlignment = 1; switch (type) { case LOCAL_GL_BYTE: case LOCAL_GL_UNSIGNED_BYTE: + requiredAlignment = 1; + break; case LOCAL_GL_SHORT: case LOCAL_GL_UNSIGNED_SHORT: + requiredAlignment = 2; + break; // XXX case LOCAL_GL_FIXED: case LOCAL_GL_FLOAT: + requiredAlignment = 4; break; default: return ErrorInvalidEnumInfo("VertexAttribPointer: type", type); } + // requiredAlignment should always be a power of two. + WebGLsizei requiredAlignmentMask = requiredAlignment - 1; + if (index >= mAttribBuffers.Length()) return ErrorInvalidValue("VertexAttribPointer: index out of range - %d >= %d", index, mAttribBuffers.Length()); if (size < 1 || size > 4) return ErrorInvalidValue("VertexAttribPointer: invalid element size"); + if (stride < 0 || stride > 255) // see WebGL spec section 6.6 "Vertex Attribute Data Stride" + return ErrorInvalidValue("VertexAttribPointer: negative stride"); + + if (byteOffset < 0) + return ErrorInvalidValue("VertexAttribPointer: negative offset"); + + if (stride & requiredAlignmentMask) { + return ErrorInvalidValue("VertexAttribPointer: stride doesn't satisfy the alignment " + "requirement of given type"); + } + + if (byteOffset & requiredAlignmentMask) { + return ErrorInvalidValue("VertexAttribPointer: byteOffset doesn't satisfy the alignment " + "requirement of given type"); + + } + /* XXX make work with bufferSubData & heterogeneous types if (type != mBoundArrayBuffer->GLType()) return ErrorInvalidOperation("VertexAttribPointer: type must match bound VBO type: %d != %d", type, mBoundArrayBuffer->GLType()); */ - // XXX 0 stride? - //if (stride < (GLuint) size) - // return ErrorInvalidOperation("VertexAttribPointer: stride must be >= size!"); - WebGLVertexAttribData &vd = mAttribBuffers[index]; vd.buf = mBoundArrayBuffer; diff --git a/content/canvas/test/webgl/failing_tests.txt b/content/canvas/test/webgl/failing_tests.txt index 17803e7e0d53..2fa38a31484b 100644 --- a/content/canvas/test/webgl/failing_tests.txt +++ b/content/canvas/test/webgl/failing_tests.txt @@ -8,7 +8,6 @@ conformance/context-attributes-alpha-depth-stencil-antialias.html conformance/context-attributes.html conformance/context-type-test.html conformance/framebuffer-object-attachment.html -conformance/framebuffer-test.html conformance/get-active-test.html conformance/gl-bind-attrib-location-test.html conformance/gl-enum-tests.html @@ -58,7 +57,5 @@ more/functions/texSubImage2DHTMLBadArgs.html more/functions/uniformfBadArgs.html more/functions/uniformiBadArgs.html more/functions/uniformMatrixBadArgs.html -more/functions/vertexAttribPointer.html -more/functions/vertexAttribPointerBadArgs.html more/glsl/arrayOutOfBounds.html conformance/renderbuffer-initialization.html diff --git a/content/canvas/test/webgl/more/functions/vertexAttribPointer.html b/content/canvas/test/webgl/more/functions/vertexAttribPointer.html index 70658ab48813..1e9c448d4468 100644 --- a/content/canvas/test/webgl/more/functions/vertexAttribPointer.html +++ b/content/canvas/test/webgl/more/functions/vertexAttribPointer.html @@ -65,7 +65,6 @@ Tests.endUnit = function(gl, prog, v,n,t) { } Tests.testVertexAttribPointerVBO = function(gl, prog, v,n,t) { -console.log(v); var vbo = gl.createBuffer(); var vertsArr = new Float32Array(verts); gl.bindBuffer(gl.ARRAY_BUFFER, vbo); diff --git a/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl b/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl index 5fed505fd499..99f20a5b7033 100644 --- a/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl +++ b/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl @@ -49,6 +49,7 @@ typedef boolean WebGLboolean; typedef unsigned long WebGLbitfield; typedef long WebGLint; typedef long WebGLsizei; +typedef long WebGLsizeiptr; typedef unsigned long WebGLuint; typedef float WebGLfloat; typedef float WebGLclampf; @@ -830,7 +831,7 @@ interface nsICanvasRenderingContextWebGL : nsISupports [noscript] void vertexAttrib4fv_array(in WebGLuint indx, in WebGLArrayPtr values); // size is number of elements per attrib; offset, stride are in bytes - void vertexAttribPointer(in WebGLuint idx, in WebGLint size, in WebGLenum type, in WebGLboolean normalized, in WebGLuint stride, in WebGLuint offset); + void vertexAttribPointer(in WebGLuint idx, in WebGLint size, in WebGLenum type, in WebGLboolean normalized, in WebGLsizei stride, in WebGLsizeiptr offset); void viewport(in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height); }; From ef120138b8f72820ca973a18d939f5b169b40e18 Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Thu, 2 Sep 2010 10:46:51 -0400 Subject: [PATCH 030/222] Bug 592737 - vertexAttrib3fv crash [@JSObject::getClass] - r=vladimir, a=blocking2.0 --- content/canvas/src/CustomQS_WebGL.h | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/content/canvas/src/CustomQS_WebGL.h b/content/canvas/src/CustomQS_WebGL.h index 64eb1481ee93..d2421bb90ca4 100644 --- a/content/canvas/src/CustomQS_WebGL.h +++ b/content/canvas/src/CustomQS_WebGL.h @@ -532,7 +532,7 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(JSContext *cx, uintN argc, js return JS_FALSE; } - if (!JSVAL_IS_OBJECT(argv[1])) { + if (JSVAL_IS_PRIMITIVE(argv[1])) { xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1); return JS_FALSE; } @@ -606,7 +606,7 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(JSContext *cx, uintN argc, js return JS_FALSE; } - if (!JSVAL_IS_OBJECT(argv[1])) { + if (JSVAL_IS_PRIMITIVE(argv[1])) { xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1); return JS_FALSE; } @@ -684,7 +684,7 @@ helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(JSContext *cx, uintN ar if (!JS_ValueToECMAInt32(cx, argv[1], &transpose)) return JS_FALSE; - if (!JSVAL_IS_OBJECT(argv[2])) { + if (JSVAL_IS_PRIMITIVE(argv[2])) { xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 2); return JS_FALSE; } @@ -751,7 +751,7 @@ helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(JSContext *cx, uintN arg if (!JS_ValueToECMAUint32(cx, argv[0], &location)) return JS_FALSE; - if (!JSVAL_IS_OBJECT(argv[1])) { + if (JSVAL_IS_PRIMITIVE(argv[1])) { xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1); return JS_FALSE; } @@ -901,6 +901,11 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(JSContext *cx, JSObject *o return; } + if (!arg) { + xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformNiv"); + js_SetTraceableNativeFailed(cx); + } + js::AutoValueRooter obj_tvr(cx); nsIWebGLUniformLocation *location; @@ -964,6 +969,11 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(JSContext *cx, JSObject *o return; } + if (!arg) { + xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformNfv"); + js_SetTraceableNativeFailed(cx); + } + js::AutoValueRooter obj_tvr(cx); nsIWebGLUniformLocation *location; @@ -1029,6 +1039,11 @@ helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(JSContext *cx, JSObj return; } + if (!arg) { + xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformMatrixNfv"); + js_SetTraceableNativeFailed(cx); + } + js::AutoValueRooter obj_tvr(cx); nsIWebGLUniformLocation *location; From c59e3e67d249d38aad4329b32755805a213f327b Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 4 Jun 2010 14:58:02 -0400 Subject: [PATCH 031/222] Bug 570192 - Make sure that XUL textbox's constructor does not fail if we don't have a frame available; r,a=gavin --HG-- extra : rebase_source : c5b6768df4a5286d85df39b45858f90ea376638c --- toolkit/content/tests/chrome/Makefile.in | 1 + .../content/tests/chrome/test_bug570192.xul | 57 +++++++++++++++++++ toolkit/content/widgets/textbox.xml | 2 +- 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 toolkit/content/tests/chrome/test_bug570192.xul diff --git a/toolkit/content/tests/chrome/Makefile.in b/toolkit/content/tests/chrome/Makefile.in index 6383205403b1..a80d555b178d 100644 --- a/toolkit/content/tests/chrome/Makefile.in +++ b/toolkit/content/tests/chrome/Makefile.in @@ -69,6 +69,7 @@ _TEST_FILES = findbar_window.xul \ bug451540_window.xul \ test_bug451540.xul \ test_bug471776.xul \ + test_bug570192.xul \ test_popup_preventdefault_chrome.xul \ window_popup_preventdefault_chrome.xul \ test_largemenu.xul \ diff --git a/toolkit/content/tests/chrome/test_bug570192.xul b/toolkit/content/tests/chrome/test_bug570192.xul new file mode 100644 index 000000000000..0ee8815cd910 --- /dev/null +++ b/toolkit/content/tests/chrome/test_bug570192.xul @@ -0,0 +1,57 @@ + + + + + + + Test for Bug 570192 + + + + + + + + Mozilla Bug 570192 + + +

+

+ +
+    
+ + + +
diff --git a/toolkit/content/widgets/textbox.xml b/toolkit/content/widgets/textbox.xml index ce0c6897f76c..d5cd73d58943 100644 --- a/toolkit/content/widgets/textbox.xml +++ b/toolkit/content/widgets/textbox.xml @@ -132,7 +132,7 @@ Date: Sun, 11 Jul 2010 16:26:26 -0400 Subject: [PATCH 032/222] Bug 240933 - Part 1: Do not split multiline text into textframes separated by BR elements; r=roc a=dbaron --HG-- extra : rebase_source : 45cbd49946c1577786a5bd141384d92f9daf27c4 --- editor/libeditor/text/nsTextEditRules.cpp | 97 +++++-------------- .../caret_on_textarea_lastline-ref.html | 6 ++ .../editor/caret_on_textarea_lastline.html | 7 ++ layout/reftests/editor/reftest.list | 1 + 4 files changed, 36 insertions(+), 75 deletions(-) create mode 100644 layout/reftests/editor/caret_on_textarea_lastline-ref.html create mode 100644 layout/reftests/editor/caret_on_textarea_lastline.html diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp index 56e2b655bc6d..5212de932d98 100644 --- a/editor/libeditor/text/nsTextEditRules.cpp +++ b/editor/libeditor/text/nsTextEditRules.cpp @@ -756,83 +756,20 @@ nsTextEditRules::WillInsertText(PRInt32 aAction, // don't spaz my selection in subtransactions nsAutoTxnsConserveSelection dontSpazMySelection(mEditor); - nsString tString(*outString); - const PRUnichar *unicodeBuf = tString.get(); - nsCOMPtr unused; - PRInt32 pos = 0; - // for efficiency, break out the pre case separately. This is because - // it's a lot cheaper to search the input string for only newlines than - // it is to search for both tabs and newlines. if (isPRE) { - while (unicodeBuf && (pos != -1) && ((PRUint32)pos < tString.Length())) - { - PRInt32 oldPos = pos; - PRInt32 subStrLen; - pos = tString.FindChar(nsCRT::LF, oldPos); - - if (pos != -1) - { - subStrLen = pos - oldPos; - // if first char is newline, then use just it - if (subStrLen == 0) - subStrLen = 1; - } - else - { - subStrLen = tString.Length() - oldPos; - pos = tString.Length(); - } - - nsDependentSubstring subStr(tString, oldPos, subStrLen); - - // is it a return? - if (subStr.EqualsLiteral(LFSTR)) - { - if (IsSingleLineEditor()) - { - NS_ASSERTION((mEditor->mNewlineHandling == nsIPlaintextEditor::eNewlinesPasteIntact), - "Newline improperly getting into single-line edit field!"); - res = mEditor->InsertTextImpl(subStr, address_of(curNode), &curOffset, doc); - } - else - { - res = mEditor->CreateBRImpl(address_of(curNode), &curOffset, address_of(unused), nsIEditor::eNone); - - // If the newline is the last character in the string, and the BR we - // just inserted is the last node in the content tree, we need to add - // a mozBR so that a blank line is created. - - if (NS_SUCCEEDED(res) && curNode && pos == (PRInt32)(tString.Length() - 1)) - { - nsCOMPtr nextChild = mEditor->GetChildAt(curNode, curOffset); - - if (!nextChild) - { - // We must be at the end since there isn't a nextChild. - // - // curNode and curOffset should be set to the position after - // the BR we added above, so just create a mozBR at that position. - // - // Note that we don't update curOffset after we've created/inserted - // the mozBR since we never want the selection to be placed after it. - - res = CreateMozBR(curNode, curOffset, address_of(unused)); - } - } - } - pos++; - } - else - { - res = mEditor->InsertTextImpl(subStr, address_of(curNode), &curOffset, doc); - } - NS_ENSURE_SUCCESS(res, res); - } + res = mEditor->InsertTextImpl(*outString, address_of(curNode), + &curOffset, doc); + NS_ENSURE_SUCCESS(res, res); } else { + const nsString& tString = PromiseFlatString(*outString); + const PRUnichar *unicodeBuf = tString.get(); + nsCOMPtr unused; + PRInt32 pos = 0; + char specialChars[] = {TAB, nsCRT::LF, 0}; while (unicodeBuf && (pos != -1) && ((PRUint32)pos < tString.Length())) { @@ -873,18 +810,28 @@ nsTextEditRules::WillInsertText(PRInt32 aAction, } NS_ENSURE_SUCCESS(res, res); } + outString->Assign(tString); } - outString->Assign(tString); if (curNode) { - aSelection->Collapse(curNode, curOffset); - // Make the caret attach to the inserted text, unless this text ends with a LF, // in which case make the caret attach to the next line. - PRBool endsWithLF = !tString.IsEmpty() && tString.get()[tString.Length() - 1] == nsCRT::LF; + PRBool endsWithLF = + !outString->IsEmpty() && outString->Last() == nsCRT::LF; nsCOMPtrselPrivate(do_QueryInterface(aSelection)); selPrivate->SetInterlinePosition(endsWithLF); + + // If the last character is a linefeed character, make sure that we inject + // a BR element for correct caret positioning. + if (endsWithLF) { + nsCOMPtr mozBR; + res = CreateMozBR(curNode, curOffset, address_of(mozBR)); + NS_ENSURE_SUCCESS(res, res); + curNode = mozBR; + curOffset = 0; + } + aSelection->Collapse(curNode, curOffset); } } ASSERT_PASSWORD_LENGTHS_EQUAL() diff --git a/layout/reftests/editor/caret_on_textarea_lastline-ref.html b/layout/reftests/editor/caret_on_textarea_lastline-ref.html new file mode 100644 index 000000000000..6acd3d9b90e7 --- /dev/null +++ b/layout/reftests/editor/caret_on_textarea_lastline-ref.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/layout/reftests/editor/caret_on_textarea_lastline.html b/layout/reftests/editor/caret_on_textarea_lastline.html new file mode 100644 index 000000000000..35973aa82858 --- /dev/null +++ b/layout/reftests/editor/caret_on_textarea_lastline.html @@ -0,0 +1,7 @@ + + + + + + diff --git a/layout/reftests/editor/reftest.list b/layout/reftests/editor/reftest.list index 8a65c717a1f2..f95fdeaacbc4 100644 --- a/layout/reftests/editor/reftest.list +++ b/layout/reftests/editor/reftest.list @@ -18,3 +18,4 @@ include xul/reftest.list == emptypasswd-2.html emptypasswd-ref.html == caret_on_positioned.html caret_on_positioned-ref.html == spellcheck-1.html spellcheck-ref.html +!= caret_on_textarea_lastline.html caret_on_textarea_lastline-ref.html From 9bfb381743b615a8258dfc11b17d9e9ae4a928c8 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 12 Jul 2010 23:02:03 -0400 Subject: [PATCH 033/222] Bug 240933 - Part 2: Fix the accessibility test to only expect two children for textarea's; r=surkov a=dbaron --HG-- extra : rebase_source : c4ed0124ad3ab8e36227dc9077f8c216f4d48a5e --- accessible/tests/mochitest/tree/test_txtctrl.html | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/accessible/tests/mochitest/tree/test_txtctrl.html b/accessible/tests/mochitest/tree/test_txtctrl.html index 204da2b0f553..bc690b3e2df5 100644 --- a/accessible/tests/mochitest/tree/test_txtctrl.html +++ b/accessible/tests/mochitest/tree/test_txtctrl.html @@ -50,19 +50,7 @@ role: ROLE_ENTRY, children: [ { - role: ROLE_TEXT_LEAF // hello1 text - }, - { - role: ROLE_WHITESPACE - }, - { - role: ROLE_TEXT_LEAF, // hello2 text - }, - { - role: ROLE_WHITESPACE - }, - { - role: ROLE_TEXT_LEAF, // whitepsace text + role: ROLE_TEXT_LEAF // hello1\nhello2 text }, { role: ROLE_WHITESPACE From da0113546ac5efab6244800471ad63835a3c83d6 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 13 Jul 2010 21:49:16 -0400 Subject: [PATCH 034/222] Bug 240933 - Part 3: Correct the caret movement throughout textareas (and pre elements with caret browsing turned on as well); r=roc a=dbaron --HG-- extra : rebase_source : 198f679bb5cea82b710c921576fa44c59f77aa23 --- layout/generic/nsFrame.cpp | 11 +++- layout/generic/nsTextFrameThebes.cpp | 30 ++++----- layout/generic/test/test_bug288789.html | 61 ++++++++++++++++++- .../test/test_movement_by_characters.html | 8 +-- 4 files changed, 88 insertions(+), 22 deletions(-) diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 4d073ef6cfe7..b5bb78d707d8 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -5219,6 +5219,7 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct* aPos) { PRBool eatingNonRenderableWS = PR_FALSE; PRBool done = PR_FALSE; + PRBool jumpedLine = PR_FALSE; while (!done) { PRBool movingInFrameDirection = @@ -5230,7 +5231,6 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct* aPos) done = current->PeekOffsetCharacter(movingInFrameDirection, &offset); if (!done) { - PRBool jumpedLine; result = current->GetFrameFromDirection(aPos->mDirection, aPos->mVisual, aPos->mJumpLines, aPos->mScrollViewStop, @@ -5251,6 +5251,15 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct* aPos) aPos->mResultContent = range.content; // Output offset is relative to content, not frame aPos->mContentOffset = offset < 0 ? range.end : range.start + offset; + // If we're dealing with a text frame and moving backward positions us at + // the end of that line, decrease the offset by one to make sure that + // we're placed before the linefeed character on the previous line. + if (offset < 0 && jumpedLine && + aPos->mDirection == eDirPrevious && + current->GetStyleText()->NewlineIsSignificant() && + current->HasTerminalNewline()) { + --aPos->mContentOffset; + } break; } diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 7f698d207d94..c10c92ec1361 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -5425,8 +5425,7 @@ IsAcceptableCaretPosition(const gfxSkipCharsIterator& aIter, gfxTextRun* aTextRu PRUint32 index = aIter.GetSkippedOffset(); if (!aTextRun->IsClusterStart(index)) return PR_FALSE; - return !(aFrame->GetStyleText()->NewlineIsSignificant() && - aTextRun->GetChar(index) == '\n'); + return PR_TRUE; } PRBool @@ -5451,8 +5450,8 @@ nsTextFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset) PRInt32 startOffset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset); if (!aForward) { - PRInt32 i; - for (i = NS_MIN(trimmed.GetEnd(), startOffset) - 1; + // If at the beginning of the line, look at the previous continuation + for (PRInt32 i = NS_MIN(trimmed.GetEnd(), startOffset) - 1; i >= trimmed.mStart; --i) { iter.SetOriginalOffset(i); if (IsAcceptableCaretPosition(iter, mTextRun, this)) { @@ -5462,16 +5461,19 @@ nsTextFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset) } *aOffset = 0; } else { - PRInt32 i; - for (i = startOffset + 1; i <= trimmed.GetEnd(); ++i) { - iter.SetOriginalOffset(i); - // XXX we can't necessarily stop at the end of this frame, - // but we really have no choice right now. We need to do a deeper - // fix/restructuring of PeekOffsetCharacter - if (i == trimmed.GetEnd() || - IsAcceptableCaretPosition(iter, mTextRun, this)) { - *aOffset = i - mContentOffset; - return PR_TRUE; + // If we're at the end of a line, look at the next continuation + iter.SetOriginalOffset(startOffset); + if (iter.GetSkippedOffset() <= PRUint32(trimmed.GetEnd()) && + !(iter.GetSkippedOffset() < PRUint32(trimmed.GetEnd()) && + GetStyleText()->NewlineIsSignificant() && + mTextRun->GetChar(iter.GetSkippedOffset()) == '\n')) { + for (PRInt32 i = startOffset + 1; i <= trimmed.GetEnd(); ++i) { + iter.SetOriginalOffset(i); + if (i == trimmed.GetEnd() || + IsAcceptableCaretPosition(iter, mTextRun, this)) { + *aOffset = i - mContentOffset; + return PR_TRUE; + } } } *aOffset = contentLength; diff --git a/layout/generic/test/test_bug288789.html b/layout/generic/test/test_bug288789.html index 5e2f15f6272c..e21f2d4ee722 100644 --- a/layout/generic/test/test_bug288789.html +++ b/layout/generic/test/test_bug288789.html @@ -18,6 +18,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=288789 אaב + +
@@ -50,9 +55,59 @@ function test() {
 
   textarea.focus();
   collapse(0);
-  testLeft(1);
-  collapse(5);
-  testRight(4);
+  ok(true, "Testing forward movement in RTL mode");
+  for (var i = 0; i < textarea.textContent.length; ++i) {
+    if (i == 0) {
+      testRight(i);
+    }
+    if (textarea.textContent[i] == 'a') {
+      testLeft(i);
+    } else {
+      testLeft(i + 1);
+    }
+    if (i == textarea.textContent.length - 1) {
+      testLeft(i + 1);
+    }
+  }
+  ok(true, "Testing backward movement in RTL mode");
+  for (var i = textarea.textContent.length; i > 0; --i) {
+    if (i == textarea.textContent.length) {
+      testLeft(i);
+    }
+    if (i > 0 && textarea.textContent[i - 1] == 'a') {
+      testRight(i);
+    } else {
+      testRight(i - 1);
+    }
+    if (i == 1) {
+      testRight(i - 1);
+    }
+  }
+
+  textarea = $("tb");
+  textarea.focus();
+  collapse(0);
+  ok(true, "Testing forward movement in LTR mode");
+  for (var i = 0; i < textarea.textContent.length; ++i) {
+    if (i == 0) {
+      testLeft(i);
+    }
+    testRight(i + 1);
+    if (i == textarea.textContent.length - 1) {
+      testRight(i + 1);
+    }
+  }
+  ok(true, "Testing backward movement in LTR mode");
+  for (var i = textarea.textContent.length; i > 0; --i) {
+    if (i == textarea.textContent.length) {
+      testRight(i);
+    }
+    testLeft(i - 1);
+    if (i == 1) {
+      testLeft(i - 1);
+    }
+  }
+
   SimpleTest.finish();
 }
 
diff --git a/layout/generic/test/test_movement_by_characters.html b/layout/generic/test/test_movement_by_characters.html
index b8a0c4f616eb..61fff0865e08 100644
--- a/layout/generic/test/test_movement_by_characters.html
+++ b/layout/generic/test/test_movement_by_characters.html
@@ -68,13 +68,13 @@ function test() {
   editor.innerHTML = "
aa\nbb
"; sel.collapse(editor.firstChild.firstChild, 0); testRight(editor.firstChild.firstChild, 1); - // at the 'bb' but HINTLEFT so appears at the end of the first line - testRight(editor.firstChild.firstChild, 3); + // at the end of the first line, before the \n + testRight(editor.firstChild.firstChild, 2); testRight(editor.firstChild.firstChild, 3); testRight(editor.firstChild.firstChild, 4); testLeft(editor.firstChild.firstChild, 3); - // at the 'bb' but HINTLEFT so appears at the end of the first line - testLeft(editor.firstChild.firstChild, 3); + // at the end of the first line, before the \n + testLeft(editor.firstChild.firstChild, 2); testLeft(editor.firstChild.firstChild, 1); testLeft(editor.firstChild.firstChild, 0); From 262d16a6c3de656633ca4d5fda103ee8f9a3d592 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 16 Jul 2010 17:34:36 -0400 Subject: [PATCH 035/222] Bug 240933 - Part 3.1: Position the selection before the terminating newline when clicking to the right of the line; r=roc a=dbaron --HG-- extra : rebase_source : 51ab2d6caf2b8827cf2e1eb88e5034d75268f658 --- layout/generic/nsTextFrameThebes.cpp | 7 ++++ layout/generic/test/Makefile.in | 1 + layout/generic/test/test_bug240933.html | 46 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 layout/generic/test/test_bug240933.html diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index c10c92ec1361..4dc203f467a7 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -5062,6 +5062,13 @@ nsTextFrame::GetCharacterOffsetAtFramePointInternal(const nsPoint &aPoint, // intrinsic widths. selectedOffset = provider.GetStart().GetOriginalOffset() + provider.GetOriginalLength(); + // If we're at the end of a preformatted line which has a terminating + // linefeed, we want to reduce the offset by one to make sure that the + // selection is placed before the linefeed character. + if (GetStyleText()->NewlineIsSignificant() && + HasTerminalNewline()) { + --selectedOffset; + } } offsets.content = GetContent(); diff --git a/layout/generic/test/Makefile.in b/layout/generic/test/Makefile.in index 2b0dc6c5fe11..44e456b47658 100644 --- a/layout/generic/test/Makefile.in +++ b/layout/generic/test/Makefile.in @@ -58,6 +58,7 @@ _TEST_FILES = \ plugin_clipping_lib.js \ plugin_focus_helper.html \ test_backspace_delete.xul \ + test_bug240933.html \ test_bug263683.html \ test_bug288789.html \ test_bug290397.html \ diff --git a/layout/generic/test/test_bug240933.html b/layout/generic/test/test_bug240933.html new file mode 100644 index 000000000000..fa90106bafbe --- /dev/null +++ b/layout/generic/test/test_bug240933.html @@ -0,0 +1,46 @@ + + + + + + Test for Bug 240933 + + + + + + + + + Mozilla Bug 240933 + +

+ + +
+    
+  
+ + + + + From f4fa8fbaff44ccd624815aa205aeb242e9cca507 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 16 Jul 2010 17:34:59 -0400 Subject: [PATCH 036/222] Bug 240933 - Part 4: Remove the code responsible for handling non-preformatted text in WillInsertText; r=roc a=dbaron --HG-- extra : rebase_source : cb4457edb5716727801fad0152eff55d3f4d9b09 --- editor/libeditor/text/nsTextEditRules.cpp | 64 +------------------ .../test_texteditor_keyevent_handling.html | 16 ++++- 2 files changed, 16 insertions(+), 64 deletions(-) diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp index 5212de932d98..5c5dfe5cb717 100644 --- a/editor/libeditor/text/nsTextEditRules.cpp +++ b/editor/libeditor/text/nsTextEditRules.cpp @@ -748,70 +748,12 @@ nsTextEditRules::WillInsertText(PRInt32 aAction, nsCOMPtr curNode = selNode; PRInt32 curOffset = selOffset; - // is our text going to be PREformatted? - // We remember this so that we know how to handle tabs. - PRBool isPRE; - res = mEditor->IsPreformatted(selNode, &isPRE); - NS_ENSURE_SUCCESS(res, res); - // don't spaz my selection in subtransactions nsAutoTxnsConserveSelection dontSpazMySelection(mEditor); - if (isPRE) - { - res = mEditor->InsertTextImpl(*outString, address_of(curNode), - &curOffset, doc); - NS_ENSURE_SUCCESS(res, res); - } - else - { - const nsString& tString = PromiseFlatString(*outString); - const PRUnichar *unicodeBuf = tString.get(); - nsCOMPtr unused; - PRInt32 pos = 0; - - char specialChars[] = {TAB, nsCRT::LF, 0}; - while (unicodeBuf && (pos != -1) && ((PRUint32)pos < tString.Length())) - { - PRInt32 oldPos = pos; - PRInt32 subStrLen; - pos = tString.FindCharInSet(specialChars, oldPos); - - if (pos != -1) - { - subStrLen = pos - oldPos; - // if first char is newline, then use just it - if (subStrLen == 0) - subStrLen = 1; - } - else - { - subStrLen = tString.Length() - oldPos; - pos = tString.Length(); - } - - nsDependentSubstring subStr(tString, oldPos, subStrLen); - - // is it a tab? - if (subStr.EqualsLiteral("\t")) - { - res = mEditor->InsertTextImpl(NS_LITERAL_STRING(" "), address_of(curNode), &curOffset, doc); - pos++; - } - // is it a return? - else if (subStr.EqualsLiteral(LFSTR)) - { - res = mEditor->CreateBRImpl(address_of(curNode), &curOffset, address_of(unused), nsIEditor::eNone); - pos++; - } - else - { - res = mEditor->InsertTextImpl(subStr, address_of(curNode), &curOffset, doc); - } - NS_ENSURE_SUCCESS(res, res); - } - outString->Assign(tString); - } + res = mEditor->InsertTextImpl(*outString, address_of(curNode), + &curOffset, doc); + NS_ENSURE_SUCCESS(res, res); if (curNode) { diff --git a/editor/libeditor/text/tests/test_texteditor_keyevent_handling.html b/editor/libeditor/text/tests/test_texteditor_keyevent_handling.html index 1aa0d8ae0053..627ebd5bb290 100644 --- a/editor/libeditor/text/tests/test_texteditor_keyevent_handling.html +++ b/editor/libeditor/text/tests/test_texteditor_keyevent_handling.html @@ -287,13 +287,23 @@ function runTests() synthesizeKey("VK_TAB", { }); check(aDescription + "Tab", true, true, !aIsTabbable && !aIsReadonly); - // The tab char is converted to 4 space characters because textarea/input - // elements are not preformatted editor. - is(aElement.value, !aIsTabbable && !aIsReadonly ? "a " : "a", + is(aElement.value, !aIsTabbable && !aIsReadonly ? "a\t" : "a", aDescription + "Tab"); is(fm.focusedElement, aElement, aDescription + "focus moved unexpectedly (Tab)"); + // If the editor is not tabbable, make sure that it accepts tab characters + // even if it's empty. + if (!aIsTabbable && !aIsReadonly) { + reset(""); + synthesizeKey("VK_TAB", {}); + check(aDescription + "Tab on empty textarea", + true, true, !aIsReadonly); + is(aElement.value, "\t", aDescription + "Tab on empty textarea"); + is(fm.focusedElement, aElement, + aDescription + "focus moved unexpectedly (Tab on empty textarea"); + } + reset("a"); synthesizeKey("VK_TAB", { shiftKey: true }); check(aDescription + "Shift+Tab", true, true, false); From c2ade13b05ab2dbc282306f65bd9856832dfa31b Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Sat, 17 Jul 2010 19:40:22 -0400 Subject: [PATCH 037/222] Bug 240933 - Part 5: Inject linefeed characters instead of BR elements when the user presses Enter; r=roc a=dbaron --HG-- extra : rebase_source : af405de4d02ba543dffacea04dd026a1dd24c8bf --- editor/libeditor/text/nsPlaintextEditor.cpp | 77 ++++++++++----------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/editor/libeditor/text/nsPlaintextEditor.cpp b/editor/libeditor/text/nsPlaintextEditor.cpp index 7dc9d3e3806c..dda0f07f55ac 100644 --- a/editor/libeditor/text/nsPlaintextEditor.cpp +++ b/editor/libeditor/text/nsPlaintextEditor.cpp @@ -867,52 +867,49 @@ NS_IMETHODIMP nsPlaintextEditor::InsertLineBreak() NS_ENSURE_SUCCESS(res, res); if (!cancel && !handled) { - // create the new BR node - nsCOMPtr newNode; - res = DeleteSelectionAndCreateNode(NS_LITERAL_STRING("br"), getter_AddRefs(newNode)); - if (!newNode) res = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called + // get the (collapsed) selection location + nsCOMPtr selNode; + PRInt32 selOffset; + res = GetStartNodeAndOffset(selection, getter_AddRefs(selNode), &selOffset); + NS_ENSURE_SUCCESS(res, res); + + // don't put text in places that can't have it + if (!IsTextNode(selNode) && !CanContainTag(selNode, NS_LITERAL_STRING("#text"))) + return NS_ERROR_FAILURE; + + // we need to get the doc + nsCOMPtr doc; + res = GetDocument(getter_AddRefs(doc)); + NS_ENSURE_SUCCESS(res, res); + NS_ENSURE_TRUE(doc, NS_ERROR_NULL_POINTER); + + // don't spaz my selection in subtransactions + nsAutoTxnsConserveSelection dontSpazMySelection(this); + + // insert a linefeed character + res = InsertTextImpl(NS_LITERAL_STRING("\n"), address_of(selNode), + &selOffset, doc); + if (!selNode) res = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called if (NS_SUCCEEDED(res)) { - // set the selection to the new node - nsCOMPtrparent; - res = newNode->GetParentNode(getter_AddRefs(parent)); - if (!parent) res = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called + // set the selection to the correct location + res = selection->Collapse(selNode, selOffset); + if (NS_SUCCEEDED(res)) { - PRInt32 offsetInParent=-1; // we use the -1 as a marker to see if we need to compute this or not - nsCOMPtrnextNode; - newNode->GetNextSibling(getter_AddRefs(nextNode)); - if (nextNode) - { - nsCOMPtrnextTextNode = do_QueryInterface(nextNode); - if (!nextTextNode) { - nextNode = do_QueryInterface(newNode); // is this QI needed? - } - else { - offsetInParent=0; - } - } - else { - nextNode = do_QueryInterface(newNode); // is this QI needed? - } + // see if we're at the end of the editor range + nsCOMPtr endNode; + PRInt32 endOffset; + res = GetEndNodeAndOffset(selection, getter_AddRefs(endNode), &endOffset); - if (-1==offsetInParent) + if (NS_SUCCEEDED(res) && endNode == selNode && endOffset == selOffset) { - nextNode->GetParentNode(getter_AddRefs(parent)); - res = GetChildOffset(nextNode, parent, offsetInParent); - if (NS_SUCCEEDED(res)) { - // SetInterlinePosition(PR_TRUE) means we want the caret to stick to the content on the "right". - // We want the caret to stick to whatever is past the break. This is - // because the break is on the same line we were on, but the next content - // will be on the following line. - nsCOMPtr selPriv(do_QueryInterface(selection)); - selPriv->SetInterlinePosition(PR_TRUE); - res = selection->Collapse(parent, offsetInParent+1); // +1 to insert just after the break - } - } - else - { - res = selection->Collapse(nextNode, offsetInParent); + // SetInterlinePosition(PR_TRUE) means we want the caret to stick to the content on the "right". + // We want the caret to stick to whatever is past the break. This is + // because the break is on the same line we were on, but the next content + // will be on the following line. + nsCOMPtr selPriv(do_QueryInterface(selection)); + selPriv->SetInterlinePosition(PR_TRUE); } } } From ebd843aa1ee496e2bedc644508bc3c573c89539c Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 19 Jul 2010 16:19:27 -0400 Subject: [PATCH 038/222] Bug 240933 - Part 6: Put the selection on the moz BR element if the user presses Enter at the end of a textarea; r=roc a=dbaron --HG-- extra : rebase_source : d992d0950cd15c24d68f976d6e628eb349de5150 --- editor/libeditor/text/nsTextEditRules.cpp | 48 +++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp index 5c5dfe5cb717..1c7036302657 100644 --- a/editor/libeditor/text/nsTextEditRules.cpp +++ b/editor/libeditor/text/nsTextEditRules.cpp @@ -463,40 +463,40 @@ nsTextEditRules::DidInsertBreak(nsISelection *aSelection, nsresult aResult) return NS_OK; } - // if we are at the end of the document, we need to insert - // a special mozBR following the normal br, and then set the - // selection to stick to the mozBR. + // if we are at the end of the textarea, we need to set the + // selection to stick to the mozBR at the end of the textarea. PRInt32 selOffset; nsCOMPtr selNode; nsresult res; res = mEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(selNode), &selOffset); NS_ENSURE_SUCCESS(res, res); - // confirm we are at end of document - if (selOffset == 0) return NS_OK; // can't be after a br if we are at offset 0 - nsIDOMElement *rootElem = mEditor->GetRoot(); + nsCOMPtr nodeAsText = do_QueryInterface(selNode); + if (!nodeAsText) return NS_OK; // nothing to do if we're not at a text node + + PRUint32 length; + res = nodeAsText->GetLength(&length); + NS_ENSURE_SUCCESS(res, res); + + // nothing to do if we're not at the end of the text node + if (selOffset != length) return NS_OK; + + nsCOMPtr parentNode; + PRInt32 parentOffset; + res = nsEditor::GetNodeLocation(selNode, address_of(parentNode), + &parentOffset); + NS_ENSURE_SUCCESS(res, res); + + nsIDOMElement *rootElem = mEditor->GetRoot(); nsCOMPtr root = do_QueryInterface(rootElem); NS_ENSURE_TRUE(root, NS_ERROR_NULL_POINTER); - if (selNode != root) return NS_OK; // must be inside text node or somewhere other than end of root + if (parentNode != root) return NS_OK; - nsCOMPtr temp = mEditor->GetChildAt(selNode, selOffset); - if (temp) return NS_OK; // can't be at end if there is a node after us. - - nsCOMPtr nearNode = mEditor->GetChildAt(selNode, selOffset-1); - if (nearNode && nsTextEditUtils::IsBreak(nearNode) && !nsTextEditUtils::IsMozBR(nearNode)) + nsCOMPtr nextNode = mEditor->GetChildAt(parentNode, + parentOffset + 1); + if (nextNode && nsTextEditUtils::IsMozBR(nextNode)) { - nsCOMPtrselPrivate(do_QueryInterface(aSelection)); - // need to insert special moz BR. Why? Because if we don't - // the user will see no new line for the break. Also, things - // like table cells won't grow in height. - nsCOMPtr brNode; - res = CreateMozBR(selNode, selOffset, address_of(brNode)); - NS_ENSURE_SUCCESS(res, res); - - res = nsEditor::GetNodeLocation(brNode, address_of(selNode), &selOffset); - NS_ENSURE_SUCCESS(res, res); - selPrivate->SetInterlinePosition(PR_TRUE); - res = aSelection->Collapse(selNode, selOffset); + res = aSelection->Collapse(parentNode, parentOffset + 1); NS_ENSURE_SUCCESS(res, res); } return res; From 29d308b3ae19ffc7f485bc74692141371f67100a Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Wed, 1 Sep 2010 18:06:52 -0400 Subject: [PATCH 039/222] Bug 240933 - Part 7: Collapse the selection in textarea's to the trailing BR if needed after every edit operation; r,a=roc --HG-- extra : rebase_source : a13c6c277ddb545614eb8c93131112bc793c1348 --- editor/libeditor/text/nsTextEditRules.cpp | 9 +++++++++ editor/libeditor/text/nsTextEditRules.h | 2 ++ layout/base/tests/Makefile.in | 3 +++ layout/base/tests/bug240933-1-ref.html | 10 ++++++++++ layout/base/tests/bug240933-1.html | 14 ++++++++++++++ layout/base/tests/bug240933-2.html | 16 ++++++++++++++++ layout/base/tests/test_reftests_with_caret.html | 2 ++ 7 files changed, 56 insertions(+) create mode 100644 layout/base/tests/bug240933-1-ref.html create mode 100644 layout/base/tests/bug240933-1.html create mode 100644 layout/base/tests/bug240933-2.html diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp index 1c7036302657..26eb907d51ff 100644 --- a/editor/libeditor/text/nsTextEditRules.cpp +++ b/editor/libeditor/text/nsTextEditRules.cpp @@ -267,6 +267,9 @@ nsTextEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection) // insure trailing br node res = CreateTrailingBRIfNeeded(); NS_ENSURE_SUCCESS(res, res); + + // collapse the selection to the trailing BR if it's at the end of our text node + CollapseSelectionToTrailingBRIfNeeded(selection); /* After inserting text the cursor Bidi level must be set to the level of the inserted text. * This is difficult, because we cannot know what the level is until after the Bidi algorithm @@ -455,6 +458,12 @@ nsTextEditRules::WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, PRBo nsresult nsTextEditRules::DidInsertBreak(nsISelection *aSelection, nsresult aResult) +{ + return NS_OK; +} + +nsresult +nsTextEditRules::CollapseSelectionToTrailingBRIfNeeded(nsISelection* aSelection) { // we only need to execute the stuff below if we are a plaintext editor. // html editors have a different mechanism for putting in mozBR's diff --git a/editor/libeditor/text/nsTextEditRules.h b/editor/libeditor/text/nsTextEditRules.h index ba1eadb4a5e6..48d1b3fe882e 100644 --- a/editor/libeditor/text/nsTextEditRules.h +++ b/editor/libeditor/text/nsTextEditRules.h @@ -233,6 +233,8 @@ protected: nsresult HideLastPWInput(); + nsresult CollapseSelectionToTrailingBRIfNeeded(nsISelection *aSelection); + PRBool IsPasswordEditor() const { return mEditor ? mEditor->IsPasswordEditor() : PR_FALSE; diff --git a/layout/base/tests/Makefile.in b/layout/base/tests/Makefile.in index ff72f1e331fd..83fef4b7d4b2 100644 --- a/layout/base/tests/Makefile.in +++ b/layout/base/tests/Makefile.in @@ -92,6 +92,9 @@ _TEST_FILES = \ bug106855-1.html \ bug106855-2.html \ bug106855-1-ref.html \ + bug240933-1.html \ + bug240933-2.html \ + bug240933-1-ref.html \ bug482484.html \ bug482484-ref.html \ bug512295-1.html \ diff --git a/layout/base/tests/bug240933-1-ref.html b/layout/base/tests/bug240933-1-ref.html new file mode 100644 index 000000000000..c3aa0a57e9cd --- /dev/null +++ b/layout/base/tests/bug240933-1-ref.html @@ -0,0 +1,10 @@ + + + + + + diff --git a/layout/base/tests/bug240933-1.html b/layout/base/tests/bug240933-1.html new file mode 100644 index 000000000000..c64ea3ac4a59 --- /dev/null +++ b/layout/base/tests/bug240933-1.html @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/layout/base/tests/bug240933-2.html b/layout/base/tests/bug240933-2.html new file mode 100644 index 000000000000..789b28542581 --- /dev/null +++ b/layout/base/tests/bug240933-2.html @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/layout/base/tests/test_reftests_with_caret.html b/layout/base/tests/test_reftests_with_caret.html index e129684ebbc7..2b54805ebbd5 100644 --- a/layout/base/tests/test_reftests_with_caret.html +++ b/layout/base/tests/test_reftests_with_caret.html @@ -88,6 +88,8 @@ function endTest() { var tests = [ [ 'bug106855-1.html' , 'bug106855-1-ref.html' ] , [ 'bug106855-2.html' , 'bug106855-1-ref.html' ] , + [ 'bug240933-1.html' , 'bug240933-1-ref.html' ] , + [ 'bug240933-2.html' , 'bug240933-1-ref.html' ] , [ 'bug482484.html' , 'bug482484-ref.html' ] , [ 'bug512295-1.html' , 'bug512295-1-ref.html' ] , [ 'bug512295-2.html' , 'bug512295-2-ref.html' ] , From 57f8ffa5cbc2d8cd2545fb3cf52c40f0e45df04e Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 19 Jul 2010 16:47:52 -0400 Subject: [PATCH 040/222] Bug 240933 - Part 8: Avoid creating multiple textnodes when adding text to textareas; r=roc a=dbaron --HG-- extra : rebase_source : 7ca0900e7c97215684b523e249a9b5cef7cbdaac --- editor/libeditor/base/Makefile.in | 1 + editor/libeditor/base/nsEditor.cpp | 45 +++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/editor/libeditor/base/Makefile.in b/editor/libeditor/base/Makefile.in index 81c5bdc964bb..acedb86f4994 100644 --- a/editor/libeditor/base/Makefile.in +++ b/editor/libeditor/base/Makefile.in @@ -90,6 +90,7 @@ FORCE_STATIC_LIB = 1 include $(topsrcdir)/config/rules.mk INCLUDES += \ + -I$(topsrcdir)/editor/libeditor/text \ -I$(topsrcdir)/content/base/src \ -I$(topsrcdir)/content/events/src \ -I$(topsrcdir)/layout/style \ diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index 5adc2f26d48e..4b35ca417bcf 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -113,6 +113,7 @@ #include "nsITransferable.h" #include "nsComputedDOMStyle.h" +#include "nsTextEditUtils.h" #include "mozilla/FunctionTimer.h" @@ -2273,11 +2274,53 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsAString& aStringToInsert, // class to turn off txn selection updating. Caller also turned on rules sniffing // if desired. + nsresult res; NS_ENSURE_TRUE(aInOutNode && *aInOutNode && aInOutOffset && aDoc, NS_ERROR_NULL_POINTER); if (!mInIMEMode && aStringToInsert.IsEmpty()) return NS_OK; nsCOMPtr nodeAsText = do_QueryInterface(*aInOutNode); + if (!nodeAsText && IsPlaintextEditor()) { + // In some cases, aInOutNode is the anonymous DIV, and aInOutOffset is 0. + // To avoid injecting unneeded text nodes, we first look to see if we have + // one available. In that case, we'll just adjust aInOutNode and aInOutOffset + // accordingly. + if (*aInOutNode == GetRoot() && *aInOutOffset == 0) { + nsCOMPtr possibleTextNode; + res = (*aInOutNode)->GetFirstChild(getter_AddRefs(possibleTextNode)); + if (NS_SUCCEEDED(res)) { + nodeAsText = do_QueryInterface(possibleTextNode); + if (nodeAsText) { + *aInOutNode = possibleTextNode; + } + } + } + // In some other cases, aInOutNode is the anonymous DIV, and aInOutOffset points + // to the terminating mozBR. In that case, we'll adjust aInOutNode and aInOutOffset + // to the preceding text node, if any. + if (!nodeAsText && *aInOutNode == GetRoot() && *aInOutOffset > 0) { + nsCOMPtr children; + res = (*aInOutNode)->GetChildNodes(getter_AddRefs(children)); + if (NS_SUCCEEDED(res)) { + nsCOMPtr possibleMozBRNode; + res = children->Item(*aInOutOffset, getter_AddRefs(possibleMozBRNode)); + if (NS_SUCCEEDED(res) && nsTextEditUtils::IsMozBR(possibleMozBRNode)) { + nsCOMPtr possibleTextNode; + res = children->Item(*aInOutOffset - 1, getter_AddRefs(possibleTextNode)); + if (NS_SUCCEEDED(res)) { + nodeAsText = do_QueryInterface(possibleTextNode); + if (nodeAsText) { + PRUint32 length; + res = nodeAsText->GetLength(&length); + if (NS_SUCCEEDED(res)) { + *aInOutOffset = PRInt32(length); + *aInOutNode = possibleTextNode; + } + } + } + } + } + } + } PRInt32 offset = *aInOutOffset; - nsresult res; if (mInIMEMode) { if (!nodeAsText) From 58248ee66ac1124f111b8e21af894297984052d9 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 20 Jul 2010 08:47:28 -0400 Subject: [PATCH 041/222] Bug 240933 - Part 9: Simplify text control frame's DOM point to offset conversion code; r=roc a=dbaron --HG-- extra : rebase_source : 134895e08a57c7aeb39f25266d8925cde4595159 --- layout/forms/nsTextControlFrame.cpp | 132 ++++++------------------- layout/reftests/bugs/240933-1-ref.html | 25 +++++ layout/reftests/bugs/240933-1.html | 19 ++++ layout/reftests/bugs/240933-2-ref.html | 29 ++++++ layout/reftests/bugs/240933-2.html | 19 ++++ layout/reftests/bugs/reftest.list | 2 + 6 files changed, 125 insertions(+), 101 deletions(-) create mode 100644 layout/reftests/bugs/240933-1-ref.html create mode 100644 layout/reftests/bugs/240933-1.html create mode 100644 layout/reftests/bugs/240933-2-ref.html create mode 100644 layout/reftests/bugs/240933-2.html diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index 2dac683f0622..db7a72a590fa 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -998,51 +998,27 @@ nsTextControlFrame::DOMPointToOffset(nsIDOMNode* aNode, if (!length || aNodeOffset < 0) return NS_OK; - PRInt32 i, textOffset = 0; - PRInt32 lastIndex = (PRInt32)length - 1; + NS_ASSERTION(length <= 2, "We should have one text node and one mozBR at most"); - for (i = 0; i < (PRInt32)length; i++) { - if (rootNode == aNode && i == aNodeOffset) { - *aResult = textOffset; - return NS_OK; - } + nsCOMPtr firstNode; + rv = nodeList->Item(0, getter_AddRefs(firstNode)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr textNode = do_QueryInterface(firstNode); - nsCOMPtr item; - rv = nodeList->Item(i, getter_AddRefs(item)); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(item, NS_ERROR_FAILURE); - - nsCOMPtr domText(do_QueryInterface(item)); - - if (domText) { - PRUint32 textLength = 0; - - rv = domText->GetLength(&textLength); + nsCOMPtr nodeAsText = do_QueryInterface(aNode); + if (nodeAsText || (aNode == rootNode && aNodeOffset == 0)) { + // Selection is somewhere inside the text node; the offset is aNodeOffset + *aResult = aNodeOffset; + } else { + // Selection is on the mozBR node, so offset should be set to the length + // of the text node. + if (textNode) { + rv = textNode->GetLength(&length); NS_ENSURE_SUCCESS(rv, rv); - - if (item == aNode) { - NS_ASSERTION((aNodeOffset >= 0 && aNodeOffset <= (PRInt32)textLength), - "Invalid aNodeOffset!"); - *aResult = textOffset + aNodeOffset; - return NS_OK; - } - - textOffset += textLength; - } - else { - // Must be a BR node. If it's not the last BR node - // under the root, count it as a newline. - - if (i != lastIndex) - ++textOffset; + *aResult = PRInt32(length); } } - NS_ASSERTION((aNode == rootNode && aNodeOffset == (PRInt32)length), - "Invalid node offset!"); - - *aResult = textOffset; - return NS_OK; } @@ -1074,71 +1050,25 @@ nsTextControlFrame::OffsetToDOMPoint(PRInt32 aOffset, rv = nodeList->GetLength(&length); NS_ENSURE_SUCCESS(rv, rv); - if (!length || aOffset < 0) { + NS_ASSERTION(length <= 2, "We should have one text node and one mozBR at most"); + + nsCOMPtr firstNode; + rv = nodeList->Item(0, getter_AddRefs(firstNode)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr textNode = do_QueryInterface(firstNode); + + if (length == 0 || aOffset < 0) { + NS_IF_ADDREF(*aResult = rootNode); + *aPosition = 0; + } else if (textNode) { + NS_IF_ADDREF(*aResult = firstNode); + *aPosition = aOffset; + } else { + NS_IF_ADDREF(*aResult = rootNode); *aPosition = 0; - *aResult = rootNode; - NS_ADDREF(*aResult); - return NS_OK; } - PRInt32 textOffset = 0; - PRUint32 lastIndex = length - 1; - - for (PRUint32 i=0; i item; - rv = nodeList->Item(i, getter_AddRefs(item)); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(item, NS_ERROR_FAILURE); - - nsCOMPtr domText(do_QueryInterface(item)); - - if (domText) { - PRUint32 textLength = 0; - - rv = domText->GetLength(&textLength); - NS_ENSURE_SUCCESS(rv, rv); - - // Check if aOffset falls within this range. - if (aOffset >= textOffset && aOffset <= textOffset+(PRInt32)textLength) { - *aPosition = aOffset - textOffset; - *aResult = item; - NS_ADDREF(*aResult); - return NS_OK; - } - - textOffset += textLength; - - // If there aren't any more siblings after this text node, - // return the point at the end of this text node! - - if (i == lastIndex) { - *aPosition = textLength; - *aResult = item; - NS_ADDREF(*aResult); - return NS_OK; - } - } - else { - // Must be a BR node, count it as a newline. - - if (aOffset == textOffset || i == lastIndex) { - // We've found the correct position, or aOffset takes us - // beyond the last child under rootNode, just return the point - // under rootNode that is in front of this br. - - *aPosition = i; - *aResult = rootNode; - NS_ADDREF(*aResult); - return NS_OK; - } - - ++textOffset; - } - } - - NS_ERROR("We should never get here!"); - - return NS_ERROR_FAILURE; + return NS_OK; } NS_IMETHODIMP diff --git a/layout/reftests/bugs/240933-1-ref.html b/layout/reftests/bugs/240933-1-ref.html new file mode 100644 index 000000000000..0d727af3a286 --- /dev/null +++ b/layout/reftests/bugs/240933-1-ref.html @@ -0,0 +1,25 @@ + + + + + + +
+
+ + + + diff --git a/layout/reftests/bugs/240933-1.html b/layout/reftests/bugs/240933-1.html new file mode 100644 index 000000000000..e180c5f484de --- /dev/null +++ b/layout/reftests/bugs/240933-1.html @@ -0,0 +1,19 @@ + + + + + + +
6
+
6
+ + + diff --git a/layout/reftests/bugs/240933-2-ref.html b/layout/reftests/bugs/240933-2-ref.html new file mode 100644 index 000000000000..7dbc082a58a5 --- /dev/null +++ b/layout/reftests/bugs/240933-2-ref.html @@ -0,0 +1,29 @@ + + + + + + +
+
+ + + + diff --git a/layout/reftests/bugs/240933-2.html b/layout/reftests/bugs/240933-2.html new file mode 100644 index 000000000000..0fb9b9d5069c --- /dev/null +++ b/layout/reftests/bugs/240933-2.html @@ -0,0 +1,19 @@ + + + + + + +
3
+
3
+ + + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 19987537fe57..204fe7060443 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -205,6 +205,8 @@ random == 99850-1b.html 99850-1-ref.html # bug 471629 == 236539-1.html 236539-1-ref.html == 240029-1.html 240029-1-ref.html == 240470-1.html 240470-1-ref.html +== 240933-1.html 240933-1-ref.html +== 240933-2.html 240933-2-ref.html == 243266-1.html 243266-1-ref.html == 243302-1.html 243302-1-ref.html == 243519-1.html 243519-1-ref.html From 06dfe9b12645870099e72b7ad7cee34b5c6dbbdd Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Wed, 21 Jul 2010 16:08:52 -0400 Subject: [PATCH 042/222] Bug 240933 - Part 10: Only hide/show the caret once when placeholder transactions finish; r=roc a=dbaron --HG-- extra : rebase_source : 21823fb610b02859893f1461e8adaf38f5d61e94 --- editor/libeditor/base/nsEditor.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index 4b35ca417bcf..2f7b4e258078 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -904,14 +904,27 @@ nsEditor::EndPlaceHolderTransaction() if (selPrivate) { selPrivate->SetCanCacheFrameOffset(PR_TRUE); } - - // time to turn off the batch - EndUpdateViewBatch(); - // make sure selection is in view - // After ScrollSelectionIntoView(), the pending notifications might be - // flushed and PresShell/PresContext/Frames may be dead. See bug 418470. - ScrollSelectionIntoView(PR_FALSE); + { + // Hide the caret here to avoid hiding it twice, once in EndUpdateViewBatch + // and once in ScrollSelectionIntoView. + nsRefPtr caret; + nsCOMPtr presShell; + GetPresShell(getter_AddRefs(presShell)); + + if (presShell) + caret = presShell->GetCaret(); + + StCaretHider caretHider(caret); + + // time to turn off the batch + EndUpdateViewBatch(); + // make sure selection is in view + + // After ScrollSelectionIntoView(), the pending notifications might be + // flushed and PresShell/PresContext/Frames may be dead. See bug 418470. + ScrollSelectionIntoView(PR_FALSE); + } // cached for frame offset are Not available now if (selPrivate) { From 41095d22376cde445962f1cc65a58bdd2fdd882c Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Wed, 21 Jul 2010 19:29:06 -0400 Subject: [PATCH 043/222] Bug 240933 - Part 11: Optimize setting the bidi flag for modifications to large DOM text nodes; r=smontagu a=dbaron --HG-- extra : rebase_source : bdd58373ec59cdcdc231ca9eb61bc7a1a0c9191f --- content/base/src/nsGenericDOMDataNode.cpp | 6 +++--- content/base/src/nsGenericDOMDataNode.h | 2 +- content/base/src/nsTextFragment.cpp | 6 +++--- content/base/src/nsTextFragment.h | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/content/base/src/nsGenericDOMDataNode.cpp b/content/base/src/nsGenericDOMDataNode.cpp index 34344f644b28..166fa69205c7 100644 --- a/content/base/src/nsGenericDOMDataNode.cpp +++ b/content/base/src/nsGenericDOMDataNode.cpp @@ -385,7 +385,7 @@ nsGenericDOMDataNode::SetTextInternal(PRUint32 aOffset, PRUint32 aCount, delete [] to; } - SetBidiStatus(); + UpdateBidiStatus(aBuffer, aLength); // Notify observers if (aNotify) { @@ -1084,7 +1084,7 @@ nsGenericDOMDataNode::AppendTextTo(nsAString& aResult) mText.AppendTo(aResult); } -void nsGenericDOMDataNode::SetBidiStatus() +void nsGenericDOMDataNode::UpdateBidiStatus(const PRUnichar* aBuffer, PRUint32 aLength) { nsIDocument *document = GetCurrentDoc(); if (document && document->GetBidiEnabled()) { @@ -1092,7 +1092,7 @@ void nsGenericDOMDataNode::SetBidiStatus() return; } - mText.SetBidiFlag(); + mText.UpdateBidiFlag(aBuffer, aLength); if (document && mText.IsBidi()) { document->SetBidiEnabled(); diff --git a/content/base/src/nsGenericDOMDataNode.h b/content/base/src/nsGenericDOMDataNode.h index a90f7243e01f..83c461fbb93d 100644 --- a/content/base/src/nsGenericDOMDataNode.h +++ b/content/base/src/nsGenericDOMDataNode.h @@ -358,7 +358,7 @@ protected: nsTextFragment mText; private: - void SetBidiStatus(); + void UpdateBidiStatus(const PRUnichar* aBuffer, PRUint32 aLength); already_AddRefed GetCurrentValueAtom(); }; diff --git a/content/base/src/nsTextFragment.cpp b/content/base/src/nsTextFragment.cpp index ce1aab9f3924..87f4f8e91dd2 100644 --- a/content/base/src/nsTextFragment.cpp +++ b/content/base/src/nsTextFragment.cpp @@ -372,11 +372,11 @@ nsTextFragment::Append(const PRUnichar* aBuffer, PRUint32 aLength) // To save time we only do this when we really want to know, not during // every allocation void -nsTextFragment::SetBidiFlag() +nsTextFragment::UpdateBidiFlag(const PRUnichar* aBuffer, PRUint32 aLength) { if (mState.mIs2b && !mState.mIsBidi) { - const PRUnichar* cp = m2b; - const PRUnichar* end = cp + mState.mLength; + const PRUnichar* cp = aBuffer; + const PRUnichar* end = cp + aLength; while (cp < end) { PRUnichar ch1 = *cp++; PRUint32 utf32Char = ch1; diff --git a/content/base/src/nsTextFragment.h b/content/base/src/nsTextFragment.h index bbdd602c3961..4a5c27aca21e 100644 --- a/content/base/src/nsTextFragment.h +++ b/content/base/src/nsTextFragment.h @@ -112,7 +112,7 @@ public: /** * Return PR_TRUE if this fragment contains Bidi text * For performance reasons this flag is not set automatically, but - * requires an explicit call to SetBidiFlag() + * requires an explicit call to UpdateBidiFlag() */ PRBool IsBidi() const { @@ -209,7 +209,7 @@ public: * Scan the contents of the fragment and turn on mState.mIsBidi if it * includes any Bidi characters. */ - void SetBidiFlag(); + void UpdateBidiFlag(const PRUnichar* aBuffer, PRUint32 aLength); struct FragmentBits { // PRUint32 to ensure that the values are unsigned, because we From 3a2d80139f8226afadd96224ca384158fc5122af Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 13 Aug 2010 18:58:24 -0400 Subject: [PATCH 044/222] Bug 240933 - Part 12: Avoid injecting textnodes as children of br nodes; r,a=roc --HG-- extra : rebase_source : 8e6451d2e1414a61e15a9ffaf94470e02d2d0b72 --- editor/libeditor/base/nsEditor.cpp | 22 ++++++++++++++++++++++ layout/generic/test/test_bug240933.html | 10 ++++++++++ 2 files changed, 32 insertions(+) diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index 2f7b4e258078..585dab4ada9b 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -2332,6 +2332,28 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsAString& aStringToInsert, } } } + // Sometimes, aInOutNode is the mozBR element itself. In that case, we'll + // adjust the insertion point to the previous text node, if one exists, or + // to the parent anonymous DIV. + if (nsTextEditUtils::IsMozBR(*aInOutNode) && *aInOutOffset == 0) { + nsCOMPtr previous; + (*aInOutNode)->GetPreviousSibling(getter_AddRefs(previous)); + nodeAsText = do_QueryInterface(previous); + if (nodeAsText) { + PRUint32 length; + res = nodeAsText->GetLength(&length); + if (NS_SUCCEEDED(res)) { + *aInOutOffset = PRInt32(length); + *aInOutNode = previous; + } + } else { + nsCOMPtr parent; + (*aInOutNode)->GetParentNode(getter_AddRefs(parent)); + if (parent == GetRoot()) { + *aInOutNode = parent; + } + } + } } PRInt32 offset = *aInOutOffset; if (mInIMEMode) diff --git a/layout/generic/test/test_bug240933.html b/layout/generic/test/test_bug240933.html index fa90106bafbe..620d1fb4924a 100644 --- a/layout/generic/test/test_bug240933.html +++ b/layout/generic/test/test_bug240933.html @@ -33,6 +33,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=240933 synthesizeMouse(t, t.clientWidth / 2, 5, {}, window); is(t.selectionStart, 3, "The selection should be set before the newline"); is(t.selectionEnd, 3, "The selection should be set before the newline"); + + t = document.getElementById("ta"); + t.focus(); + var val = t.value; + synthesizeKey("VK_ENTER", {}); + is(t.value, val + "\n", "Pressing enter right after focusing the textarea should work"); SimpleTest.finish(); }); @@ -40,6 +46,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=240933
+ From bb655020399b6931ccaf83f3d80d4706fa455865 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 13 Aug 2010 18:58:26 -0400 Subject: [PATCH 045/222] Bug 240933 - Part 13: Consider text frame continuations containing only newlines editable; r,a=roc --HG-- extra : rebase_source : b66535705ec25cd4dca7378424b78cc3bef94e46 --- editor/libeditor/base/nsEditor.cpp | 5 +++-- layout/generic/nsIFrame.h | 8 ++++++++ layout/generic/nsTextFrame.h | 2 ++ layout/generic/nsTextFrameThebes.cpp | 11 +++++++++++ layout/generic/test/test_bug240933.html | 12 ++++++++++++ 5 files changed, 36 insertions(+), 2 deletions(-) diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index 585dab4ada9b..39d9c693f425 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -3624,8 +3624,9 @@ nsEditor::IsEditable(nsIDOMNode *aNode) // and uses enhanced logic to find out in the HTML world. return IsTextInDirtyFrameVisible(aNode); } - if (resultFrame->GetSize().width > 0) - return PR_TRUE; // text node has width + if (resultFrame->HasAnyNoncollapsedCharacters()) { + return PR_TRUE; + } resultFrame = resultFrame->GetNextContinuation(); } } diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 4ae237585904..98b92b1cb12a 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -1635,6 +1635,14 @@ public: PRUint32 aSkippedMaxLength = PR_UINT32_MAX) { return NS_ERROR_NOT_IMPLEMENTED; } + /** + * Returns true if the frame contains any non-collapsed characters. + * This method is only available for text frames, and it will return false + * for all other frame types. + */ + virtual PRBool HasAnyNoncollapsedCharacters() + { return PR_FALSE; } + /** * Accessor functions to get/set the associated view object * diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index e2275096490b..acd26537791a 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -460,6 +460,8 @@ protected: PRBool aForInsertionPoint); void ClearFrameOffsetCache(); + + virtual PRBool HasAnyNoncollapsedCharacters(); }; #endif diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 4dc203f467a7..8dd3924c0d37 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -7131,3 +7131,14 @@ nsTextFrame::IsAtEndOfLine() const { return (GetStateBits() & TEXT_END_OF_LINE) != 0; } + +PRBool +nsTextFrame::HasAnyNoncollapsedCharacters() +{ + gfxSkipCharsIterator iter = EnsureTextRun(); + PRInt32 offset = GetContentOffset(), + offsetEnd = GetContentEnd(); + PRInt32 skippedOffset = iter.ConvertOriginalToSkipped(offset); + PRInt32 skippedOffsetEnd = iter.ConvertOriginalToSkipped(offsetEnd); + return skippedOffset != skippedOffsetEnd; +} diff --git a/layout/generic/test/test_bug240933.html b/layout/generic/test/test_bug240933.html index 620d1fb4924a..e8d7ffde9d94 100644 --- a/layout/generic/test/test_bug240933.html +++ b/layout/generic/test/test_bug240933.html @@ -39,6 +39,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=240933 var val = t.value; synthesizeKey("VK_ENTER", {}); is(t.value, val + "\n", "Pressing enter right after focusing the textarea should work"); + + t = document.getElementById("tb"); + t.focus(); + synthesizeKey("VK_ENTER", {}); + is(t.value, "\n", "Pressing enter for the first time should work"); + synthesizeKey("VK_ENTER", {}); + is(t.value, "\n\n", "Pressing enter for the second time should work"); + synthesizeKey("VK_BACK_SPACE", {}); + is(t.value, "\n", "Pressing backspace for the first time should work"); + synthesizeKey("VK_BACK_SPACE", {}); + is(t.value, "", "Pressing backspace for the second time should work"); SimpleTest.finish(); }); @@ -51,6 +62,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=240933 test + From b63cc0ba47ac0ba10812aff62d306f2f398f6c27 Mon Sep 17 00:00:00 2001 From: Joe Drew Date: Fri, 3 Sep 2010 23:21:26 -0400 Subject: [PATCH 046/222] Bug 593521 - Don't chain to nsBaseWidget::GetLayerManager, because it can do things we don't want (like use OpenGL). r=vlad a=blocking2.0:beta6+ --- widget/src/windows/nsWindow.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 12e2f6017aa5..3dcf07fe72e4 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -3162,20 +3162,6 @@ nsWindow::HasPendingInputEvent() mozilla::layers::LayerManager* nsWindow::GetLayerManager() { - nsWindow *topWindow = GetNSWindowPtr(GetTopLevelHWND(mWnd, PR_TRUE)); - - if (!topWindow) { - return nsBaseWidget::GetLayerManager(); - } - - /* We don't currently support using an accelerated layer manager with - * transparent windows so don't even try. I'm also not sure if we even - * want to support this case. See bug #593471 */ - if (eTransparencyTransparent == mTransparencyMode) { - mUseAcceleratedRendering = PR_FALSE; - return nsBaseWidget::GetLayerManager(); - } - #ifndef WINCE if (!mLayerManager) { nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); @@ -3196,6 +3182,12 @@ nsWindow::GetLayerManager() accelerateByDefault = accelerateByDefault || (acceleratedEnv && (*acceleratedEnv != '0')); + /* We don't currently support using an accelerated layer manager with + * transparent windows so don't even try. I'm also not sure if we even + * want to support this case. See bug #593471 */ + disableAcceleration = disableAcceleration || + eTransparencyTransparent == mTransparencyMode; + nsCOMPtr xr = do_GetService("@mozilla.org/xre/runtime;1"); PRBool safeMode = PR_FALSE; if (xr) @@ -3224,10 +3216,14 @@ nsWindow::GetLayerManager() } } } + + // Fall back to software if we couldn't use any hardware backends. + if (!mLayerManager) + mLayerManager = new BasicLayerManager(this); } #endif - return nsBaseWidget::GetLayerManager(); + return mLayerManager; } /************************************************************** From 881a4c21e1b9d780e6971d1a2ab9dafa94daa87e Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Fri, 3 Sep 2010 23:21:26 -0400 Subject: [PATCH 047/222] Bug 593530 - Don't leak the DeviceManagerD3D9 if initializing it fails. r=joe a=blocking2.0:beta6+ --- gfx/layers/d3d9/DeviceManagerD3D9.cpp | 3 +++ gfx/layers/d3d9/DeviceManagerD3D9.h | 8 ++++++-- gfx/layers/d3d9/LayerManagerD3D9.cpp | 10 ++++++---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/gfx/layers/d3d9/DeviceManagerD3D9.cpp b/gfx/layers/d3d9/DeviceManagerD3D9.cpp index 228fe9adcb86..f2618106e7b9 100644 --- a/gfx/layers/d3d9/DeviceManagerD3D9.cpp +++ b/gfx/layers/d3d9/DeviceManagerD3D9.cpp @@ -189,6 +189,9 @@ DeviceManagerD3D9::~DeviceManagerD3D9() LayerManagerD3D9::OnDeviceManagerDestroy(this); } +NS_IMPL_ADDREF(DeviceManagerD3D9) +NS_IMPL_RELEASE(DeviceManagerD3D9) + bool DeviceManagerD3D9::Init() { diff --git a/gfx/layers/d3d9/DeviceManagerD3D9.h b/gfx/layers/d3d9/DeviceManagerD3D9.h index 095a5c3423a0..05e412821329 100644 --- a/gfx/layers/d3d9/DeviceManagerD3D9.h +++ b/gfx/layers/d3d9/DeviceManagerD3D9.h @@ -106,9 +106,13 @@ class THEBES_API DeviceManagerD3D9 { public: DeviceManagerD3D9(); + NS_IMETHOD_(nsrefcnt) AddRef(void); + NS_IMETHOD_(nsrefcnt) Release(void); +protected: + nsAutoRefCnt mRefCnt; + NS_DECL_OWNINGTHREAD - NS_INLINE_DECL_REFCOUNTING(DeviceManagerD3D9) - +public: bool Init(); /** diff --git a/gfx/layers/d3d9/LayerManagerD3D9.cpp b/gfx/layers/d3d9/LayerManagerD3D9.cpp index 130c5ac57a35..9fa607a83d4a 100644 --- a/gfx/layers/d3d9/LayerManagerD3D9.cpp +++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp @@ -65,8 +65,8 @@ LayerManagerD3D9::~LayerManagerD3D9() */ mSwapChain = nsnull; - if (mDeviceManager) { - mDeviceManager->Release(); + if (mDeviceManager && mDeviceManager->Release() == 0) { + mDeviceManager = nsnull; } } @@ -79,15 +79,17 @@ LayerManagerD3D9::Initialize() if (!mDeviceManager) { mDeviceManager = new DeviceManagerD3D9; + mDeviceManager->AddRef(); if (!mDeviceManager->Init()) { + mDeviceManager->Release(); mDeviceManager = nsnull; return PR_FALSE; } + } else { + mDeviceManager->AddRef(); } - mDeviceManager->AddRef(); - mSwapChain = mDeviceManager-> CreateSwapChain((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW)); From 8ab02d729b167c5894240b05c944b4d30d9bd0be Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Fri, 27 Aug 2010 16:58:53 +1200 Subject: [PATCH 048/222] Bug 591155 - Temporarily disable certain failing reftests which are visually indistinguishable when running with accelerated layers. r=vlad a=blocking2.0:beta6+ --- layout/reftests/bidi/reftest.list | 4 ++-- layout/reftests/box-shadow/reftest.list | 2 +- layout/reftests/bugs/reftest.list | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/layout/reftests/bidi/reftest.list b/layout/reftests/bidi/reftest.list index 0e483be389a8..9a0f69ec2a9e 100644 --- a/layout/reftests/bidi/reftest.list +++ b/layout/reftests/bidi/reftest.list @@ -9,8 +9,8 @@ == bidi-005.html bidi-005-ref.html == bidi-006.html bidi-006-ref.html == bidi-006-j.html bidi-006-ref.html -== visualmarquee.html marquee-ref.html -== logicalmarquee.html marquee-ref.html +random-if(layersGPUAccelerated) == visualmarquee.html marquee-ref.html +random-if(layersGPUAccelerated) == logicalmarquee.html marquee-ref.html == visualmarquee.html logicalmarquee.html # test for glyph mirroring in right-to-left text == mirroring-01.html mirroring-01-ref.html diff --git a/layout/reftests/box-shadow/reftest.list b/layout/reftests/box-shadow/reftest.list index d8f0d53fed81..fc11c3a33e33 100644 --- a/layout/reftests/box-shadow/reftest.list +++ b/layout/reftests/box-shadow/reftest.list @@ -10,7 +10,7 @@ == boxshadow-button.html boxshadow-button-ref.html == boxshadow-fileupload.html boxshadow-fileupload-ref.html == boxshadow-inner-basic.html boxshadow-inner-basic-ref.svg -== boxshadow-mixed.html boxshadow-mixed-ref.html +random-if(layersGPUAccelerated) == boxshadow-mixed.html boxshadow-mixed-ref.html random-if(d2d) == boxshadow-rounded-spread.html boxshadow-rounded-spread-ref.html HTTP(..) == boxshadow-dynamic.xul boxshadow-dynamic-ref.xul random-if(d2d) == boxshadow-onecorner.html boxshadow-onecorner-ref.html diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 19987537fe57..20bb75526415 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1467,7 +1467,7 @@ random-if(d2d) == 555388-1.html 555388-1-ref.html == 563584-10b.html 563584-10-ref.html == 563584-11.html 563584-11-ref.html == 564054-1.html 564054-1-ref.html -== 564991-1.html 564991-1-ref.html +random-if(layersGPUAccelerated) == 564991-1.html 564991-1-ref.html == 565819-1.html 565819-ref.html == 565819-2.html 565819-ref.html == 568441.html 568441-ref.html @@ -1489,7 +1489,7 @@ random-if(d2d) == 555388-1.html 555388-1-ref.html == 579323-1.html 579323-1-ref.html == 579349-1.html 579349-1-ref.html == 580160-1.html 580160-1-ref.html -== 581317-1.html 581317-1-ref.html +random-if(layersGPUAccelerated) == 581317-1.html 581317-1-ref.html == 581579-1.html 581579-1-ref.html == 582037-1a.html 582037-1-ref.html == 582037-1b.html 582037-1-ref.html From 074274faef6f37e5942c46166764e8b318a2bf3d Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 27 Aug 2010 01:36:09 -0400 Subject: [PATCH 049/222] Bug 590554 - maxlength in textarea does not prevent newline characters from being inserted; r,a=roc --HG-- extra : rebase_source : bc351ffd6cd3a346b57808f338e4367e2c731947 --- editor/libeditor/text/nsPlaintextEditor.cpp | 8 +++- editor/libeditor/text/nsTextEditRules.cpp | 36 +++++++++++++++--- editor/libeditor/text/nsTextEditRules.h | 6 ++- editor/libeditor/text/tests/Makefile.in | 1 + .../libeditor/text/tests/test_bug590554.html | 37 +++++++++++++++++++ 5 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 editor/libeditor/text/tests/test_bug590554.html diff --git a/editor/libeditor/text/nsPlaintextEditor.cpp b/editor/libeditor/text/nsPlaintextEditor.cpp index dda0f07f55ac..7da8d30e54a8 100644 --- a/editor/libeditor/text/nsPlaintextEditor.cpp +++ b/editor/libeditor/text/nsPlaintextEditor.cpp @@ -623,7 +623,12 @@ nsPlaintextEditor::GetTextSelectionOffsets(nsISelection *aSelection, } } #ifdef NS_DEBUG - ++nodeCount; + // The post content iterator might return the parent node (which is the + // editor's root node) as the last item. Don't count the root node itself + // as one of its children! + if (!SameCOMIdentity(currentNode, rootNode)) { + ++nodeCount; + } #endif } @@ -862,6 +867,7 @@ NS_IMETHODIMP nsPlaintextEditor::InsertLineBreak() shell->MaybeInvalidateCaretPosition(); nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertBreak); + ruleInfo.maxLength = mMaxTextLength; PRBool cancel, handled; res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); NS_ENSURE_SUCCESS(res, res); diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp index 26eb907d51ff..aea336ce7529 100644 --- a/editor/libeditor/text/nsTextEditRules.cpp +++ b/editor/libeditor/text/nsTextEditRules.cpp @@ -312,7 +312,7 @@ nsTextEditRules::WillDoAction(nsISelection *aSelection, switch (info->action) { case kInsertBreak: - return WillInsertBreak(aSelection, aCancel, aHandled); + return WillInsertBreak(aSelection, aCancel, aHandled, info->maxLength); case kInsertText: case kInsertTextIME: return WillInsertText(info->action, @@ -424,7 +424,10 @@ nsTextEditRules::DidInsert(nsISelection *aSelection, nsresult aResult) } nsresult -nsTextEditRules::WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, PRBool *aHandled) +nsTextEditRules::WillInsertBreak(nsISelection *aSelection, + PRBool *aCancel, + PRBool *aHandled, + PRInt32 aMaxLength) { if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; } CANCEL_OPERATION_IF_READONLY_OR_DISABLED @@ -434,11 +437,24 @@ nsTextEditRules::WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, PRBo } else { + // handle docs with a max length + // NOTE, this function copies inString into outString for us. + NS_NAMED_LITERAL_STRING(inString, "\n"); + nsAutoString outString; + PRBool didTruncate; + nsresult res = TruncateInsertionIfNeeded(aSelection, &inString, &outString, + aMaxLength, &didTruncate); + NS_ENSURE_SUCCESS(res, res); + if (didTruncate) { + *aCancel = PR_TRUE; + return NS_OK; + } + *aCancel = PR_FALSE; // if the selection isn't collapsed, delete it. PRBool bCollapsed; - nsresult res = aSelection->GetIsCollapsed(&bCollapsed); + res = aSelection->GetIsCollapsed(&bCollapsed); NS_ENSURE_SUCCESS(res, res); if (!bCollapsed) { @@ -642,7 +658,7 @@ nsTextEditRules::WillInsertText(PRInt32 aAction, // handle docs with a max length // NOTE, this function copies inString into outString for us. - nsresult res = TruncateInsertionIfNeeded(aSelection, inString, outString, aMaxLength); + nsresult res = TruncateInsertionIfNeeded(aSelection, inString, outString, aMaxLength, nsnull); NS_ENSURE_SUCCESS(res, res); PRUint32 start = 0; @@ -1256,12 +1272,16 @@ nsresult nsTextEditRules::TruncateInsertionIfNeeded(nsISelection *aSelection, const nsAString *aInString, nsAString *aOutString, - PRInt32 aMaxLength) + PRInt32 aMaxLength, + PRBool *aTruncated) { if (!aSelection || !aInString || !aOutString) {return NS_ERROR_NULL_POINTER;} nsresult res = NS_OK; *aOutString = *aInString; + if (aTruncated) { + *aTruncated = PR_FALSE; + } if ((-1 != aMaxLength) && IsPlaintextEditor() && !mEditor->IsIMEComposing() ) { @@ -1294,6 +1314,9 @@ nsTextEditRules::TruncateInsertionIfNeeded(nsISelection *aSelection, if (resultingDocLength >= aMaxLength) { aOutString->Truncate(); + if (aTruncated) { + *aTruncated = PR_TRUE; + } } else { @@ -1301,6 +1324,9 @@ nsTextEditRules::TruncateInsertionIfNeeded(nsISelection *aSelection, if (inCount + resultingDocLength > aMaxLength) { aOutString->Truncate(aMaxLength - resultingDocLength); + if (aTruncated) { + *aTruncated = PR_TRUE; + } } } } diff --git a/editor/libeditor/text/nsTextEditRules.h b/editor/libeditor/text/nsTextEditRules.h index 48d1b3fe882e..bd74bb44b624 100644 --- a/editor/libeditor/text/nsTextEditRules.h +++ b/editor/libeditor/text/nsTextEditRules.h @@ -160,7 +160,8 @@ protected: nsresult DidInsertText(nsISelection *aSelection, nsresult aResult); nsresult GetTopEnclosingPre(nsIDOMNode *aNode, nsIDOMNode** aOutPreNode); - nsresult WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, PRBool *aHandled); + nsresult WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, + PRBool *aHandled, PRInt32 aMaxLength); nsresult DidInsertBreak(nsISelection *aSelection, nsresult aResult); nsresult WillInsert(nsISelection *aSelection, PRBool *aCancel); @@ -218,7 +219,8 @@ protected: nsresult TruncateInsertionIfNeeded(nsISelection *aSelection, const nsAString *aInString, nsAString *aOutString, - PRInt32 aMaxLength); + PRInt32 aMaxLength, + PRBool *aTruncated); /** Remove IME composition text from password buffer */ nsresult RemoveIMETextFromPWBuf(PRUint32 &aStart, nsAString *aIMEString); diff --git a/editor/libeditor/text/tests/Makefile.in b/editor/libeditor/text/tests/Makefile.in index 98aa6f079400..ad7125d51628 100644 --- a/editor/libeditor/text/tests/Makefile.in +++ b/editor/libeditor/text/tests/Makefile.in @@ -47,6 +47,7 @@ include $(topsrcdir)/config/rules.mk _TEST_FILES = \ test_bug471722.html \ test_bug569988.html \ + test_bug590554.html \ $(NULL) # disables the key handling test on gtk2 because gtk2 overrides some key events diff --git a/editor/libeditor/text/tests/test_bug590554.html b/editor/libeditor/text/tests/test_bug590554.html new file mode 100644 index 000000000000..9fdff7480de5 --- /dev/null +++ b/editor/libeditor/text/tests/test_bug590554.html @@ -0,0 +1,37 @@ + + + + + + Test for Bug 590554 + + + + + + + + + + + + + From 09f276ccbb9c13feb1a4a887fe5354a9e3475cf7 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 27 Aug 2010 15:03:09 -0400 Subject: [PATCH 050/222] Bug 591378 - REFTEST TEST-UNEXPECTED-PASS | file:///home/cltbld/talos-slave/mozilla-central_fedora-debug_test-crashtest/build/reftest/tests/editor/libeditor/html/crashtests/448329-3.html | assertion count 8 is less than expected 16 assertions; r=roc a=NPOTB --HG-- extra : rebase_source : 486646660fa6970a7371a149eec08f5bbaaa569e --- editor/libeditor/html/crashtests/crashtests.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/libeditor/html/crashtests/crashtests.list b/editor/libeditor/html/crashtests/crashtests.list index 79bbac00da33..5799dd134198 100644 --- a/editor/libeditor/html/crashtests/crashtests.list +++ b/editor/libeditor/html/crashtests/crashtests.list @@ -8,7 +8,7 @@ load 428489-1.html load 431086-1.xhtml load 448329-1.html load 448329-2.html -asserts(16-20) load 448329-3.html +asserts(8-20) load 448329-3.html load 456727-1.html load 456727-2.html asserts(1) load 467647-1.html # bug 382210 From a61b24c639cdedcddec8b1185658810b20b90e2f Mon Sep 17 00:00:00 2001 From: Simon Montagu Date: Thu, 2 Sep 2010 14:20:56 -0400 Subject: [PATCH 051/222] Use member boolean instead of Window style to identify right-to-left windows. Bug 588735; r=jmathies a=blocking2.0:betaN+ --HG-- extra : rebase_source : f5c09abea4775e41c1bccb431ab620b46e25da32 --- widget/src/windows/nsWindow.cpp | 5 +---- widget/src/windows/nsWindow.h | 5 +++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 85c775725c7b..d59cb8c3cd14 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -553,14 +553,11 @@ nsWindow::Create(nsIWidget *aParent, mPopupType = aInitData->mPopupHint; mContentType = aInitData->mContentType; + mIsRTL = aInitData->mRTL; DWORD style = WindowStyle(); DWORD extendedStyle = WindowExStyle(); - if (aInitData->mRTL) { - extendedStyle |= WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT; - } - if (mWindowType == eWindowType_popup) { if (!aParent) parent = NULL; diff --git a/widget/src/windows/nsWindow.h b/widget/src/windows/nsWindow.h index 2d7f9919934b..b599a6e0413e 100644 --- a/widget/src/windows/nsWindow.h +++ b/widget/src/windows/nsWindow.h @@ -473,6 +473,9 @@ protected: PRPackedBool mPainting; PRPackedBool mExitToNonClientArea; PRPackedBool mTouchWindow; + PRPackedBool mDisplayPanFeedback; + PRPackedBool mHideChrome; + PRPackedBool mIsRTL; PRUint32 mBlurSuppressLevel; nsContentType mContentType; DWORD_PTR mOldStyle; @@ -482,8 +485,6 @@ protected: nsNativeDragTarget* mNativeDragTarget; HKL mLastKeyboardLayout; nsPopupType mPopupType; - PRPackedBool mDisplayPanFeedback; - PRPackedBool mHideChrome; nsSizeMode mOldSizeMode; WindowHook mWindowHook; static PRUint32 sInstanceCount; From a62b4f26138dd58368a3fb9fbe0a7ed7222f3536 Mon Sep 17 00:00:00 2001 From: Raymond Lee Date: Tue, 31 Aug 2010 15:22:10 +0800 Subject: [PATCH 052/222] Bug 591448 - On tab switch, 'gWindow is not defined' after closing a window that opened Panorama [r=dao a=gavin] --HG-- extra : rebase_source : d9d049b80efac0297dd40a58e5c733cbecaf3ef3 --- browser/base/content/tabview/ui.js | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/browser/base/content/tabview/ui.js b/browser/base/content/tabview/ui.js index bcc86761704a..bd9e63e403d0 100644 --- a/browser/base/content/tabview/ui.js +++ b/browser/base/content/tabview/ui.js @@ -81,6 +81,10 @@ var UIManager = { // Used to facilitate zooming down from a previous tab. _currentTab : null, + // Variable: _eventListeners + // Keeps track of event listeners added to the AllTabs object. + _eventListeners: {}, + // ---------- // Function: init // Must be called after the object is created. @@ -238,6 +242,7 @@ var UIManager = { GroupItems.uninit(); Storage.uninit(); + this._removeTabActionHandlers(); this._currentTab = null; this._pageBounds = null; this._reorderTabItemsOnShow = null; @@ -407,7 +412,7 @@ var UIManager = { _addTabActionHandlers: function() { var self = this; - AllTabs.register("close", function(tab) { + this._eventListeners.close = function(tab) { if (tab.ownerDocument.defaultView != gWindow) return; @@ -438,23 +443,34 @@ var UIManager = { } } } - }); + }; - AllTabs.register("move", function(tab) { + this._eventListeners.move = function(tab) { if (tab.ownerDocument.defaultView != gWindow) return; let activeGroupItem = GroupItems.getActiveGroupItem(); if (activeGroupItem) self.setReorderTabItemsOnShow(activeGroupItem); - }); + }; - AllTabs.register("select", function(tab) { + this._eventListeners.select = function(tab) { if (tab.ownerDocument.defaultView != gWindow) return; self.onTabSelect(tab); - }); + }; + + for (let name in this._eventListeners) + AllTabs.register(name, this._eventListeners[name]); + }, + + // ---------- + // Function: _removeTabActionHandlers + // Removes handlers to handle tab actions. + _removeTabActionHandlers: function() { + for (let name in this._eventListeners) + AllTabs.unregister(name, this._eventListeners[name]); }, // ---------- From 8ae2d337285d6d8ce1663d590fa1fef92d302822 Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Thu, 2 Sep 2010 15:07:26 -0400 Subject: [PATCH 053/222] Bug 592024 - Don't clear shared D3D9/D2D surfaces in cairo_d2d_create_for_handle because D3D9 and D2D need a lot of synchronization points. Instead, put a clear in DrawRegion, which already has synchronization points. r=jrmuizel a=blocking --- gfx/cairo/cairo/src/cairo-d2d-surface.cpp | 2 -- gfx/layers/d3d9/ThebesLayerD3D9.cpp | 8 +++++++- gfx/layers/d3d9/ThebesLayerD3D9.h | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp index 7019cbbbd234..995a3a63aa31 100644 --- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp +++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp @@ -3628,8 +3628,6 @@ cairo_d2d_surface_create_for_handle(cairo_device_t *device, HANDLE handle, cairo newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush); - _d2d_clear_surface(newSurf); - newSurf->device = d2d_device; cairo_addref_device(device); diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.cpp b/gfx/layers/d3d9/ThebesLayerD3D9.cpp index 2c567b987577..438e73f0eea3 100644 --- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp +++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp @@ -70,6 +70,7 @@ UseOpaqueSurface(Layer* aLayer) ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager) : ThebesLayer(aManager, NULL) , LayerD3D9(aManager) + , mD2DSurfaceInitialized(false) { mImplData = static_cast(this); aManager->deviceManager()->mThebesLayers.AppendElement(this); @@ -289,6 +290,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion) if (mD2DSurface) { context = new gfxContext(mD2DSurface); nsIntRegionRectIterator iter(aRegion); + context->Translate(gfxPoint(-visibleRect.x, -visibleRect.y)); context->NewPath(); const nsIntRect *iterRect; @@ -296,11 +298,14 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion) context->Rectangle(gfxRect(iterRect->x, iterRect->y, iterRect->width, iterRect->height)); } context->Clip(); - if (mD2DSurface->GetContentType() != gfxASurface::CONTENT_COLOR) { + if (!mD2DSurfaceInitialized || + mD2DSurface->GetContentType() != gfxASurface::CONTENT_COLOR) { context->SetOperator(gfxContext::OPERATOR_CLEAR); context->Paint(); context->SetOperator(gfxContext::OPERATOR_OVER); + mD2DSurfaceInitialized = true; } + LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo(); cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData); mD2DSurface->Flush(); @@ -423,6 +428,7 @@ ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize) D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, getter_AddRefs(mTexture), &sharedHandle); + mD2DSurfaceInitialized = false; mD2DSurface = new gfxD2DSurface(sharedHandle, UseOpaqueSurface(this) ? gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA); diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.h b/gfx/layers/d3d9/ThebesLayerD3D9.h index d51a9a86d4c5..d4e9ee608776 100644 --- a/gfx/layers/d3d9/ThebesLayerD3D9.h +++ b/gfx/layers/d3d9/ThebesLayerD3D9.h @@ -73,6 +73,8 @@ private: /* This contains the D2D surface if we have one */ nsRefPtr mD2DSurface; + bool mD2DSurfaceInitialized; + /* Have a region of our layer drawn */ void DrawRegion(const nsIntRegion &aRegion); From 23c6f17b467351467a7feecbc0fb910003e8455b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Thu, 2 Sep 2010 22:08:05 +0200 Subject: [PATCH 054/222] Bug 320638 - Allow dropping links in-between tabs. r=gavin --- browser/base/content/tabbrowser.xml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 3bf80c045702..b8857daea70b 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -2773,7 +2773,16 @@ boxObject.screenX + boxObject.width * .75) + return null; + } + return tab; ]]> @@ -3022,6 +3031,7 @@ this._dragTime = Date.now(); if (Date.now() >= this._dragTime + this._dragOverDelay) this.selectedItem = tab; + ind.collapsed = true; return; } } From f38944642b9e453581291cacb79cf205b9f39379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Thu, 2 Sep 2010 22:08:37 +0200 Subject: [PATCH 055/222] Bug 577096 - App Tabs should indicate change of state in . r=gavin ui-r=beltzner --- browser/base/content/tabbrowser.xml | 4 ++++ browser/themes/gnomestripe/browser/browser.css | 4 ++++ browser/themes/pinstripe/browser/browser.css | 4 ++++ browser/themes/winstripe/browser/browser.css | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index b8857daea70b..664f8b800e87 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -808,6 +808,8 @@ this._fastFind.setDocShell(this.mCurrentBrowser.docShell); this.updateTitlebar(); + + this.mCurrentTab.removeAttribute("titlechanged"); } // If the new tab is busy, and our current state is not busy, then @@ -2449,6 +2451,8 @@ this.setTabTitle(tab); if (tab == this.mCurrentTab) this.updateTitlebar(); + else if (!tab.hasAttribute("busy")) + tab.setAttribute("titlechanged", "true"); ]]> </handler> </handlers> diff --git a/browser/themes/gnomestripe/browser/browser.css b/browser/themes/gnomestripe/browser/browser.css index b3741dccdc68..b446647f8d07 100644 --- a/browser/themes/gnomestripe/browser/browser.css +++ b/browser/themes/gnomestripe/browser/browser.css @@ -1230,6 +1230,10 @@ statusbarpanel#statusbar-display { -moz-margin-start: 0; } +.tabbrowser-tab[pinned][titlechanged]:not([selected="true"]) { + -moz-box-shadow: 0 0 0 1em rgba(255,0,0,.5) inset; +} + .tab-icon-image { width: 16px; height: 16px; diff --git a/browser/themes/pinstripe/browser/browser.css b/browser/themes/pinstripe/browser/browser.css index 74311da3148c..ea4728f75949 100644 --- a/browser/themes/pinstripe/browser/browser.css +++ b/browser/themes/pinstripe/browser/browser.css @@ -1484,6 +1484,10 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { background-color: -moz-mac-chrome-inactive; } +.tabbrowser-tab[pinned][titlechanged]:not([selected="true"]) { + background-color: rgba(255,0,0,.5) !important; +} + #tabbrowser-tabs[tabsontop="true"] > .tabbrowser-tab[selected="true"] { -moz-border-top-colors: rgba(0,0,0,.04) rgba(0,0,0,.17) rgba(255,255,255,.9); -moz-border-right-colors: rgba(0,0,0,.04) rgba(0,0,0,.17) rgba(255,255,255,.6); diff --git a/browser/themes/winstripe/browser/browser.css b/browser/themes/winstripe/browser/browser.css index 0f2eec437cd1..d6b2dc6dbec2 100644 --- a/browser/themes/winstripe/browser/browser.css +++ b/browser/themes/winstripe/browser/browser.css @@ -1367,6 +1367,10 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action- background-image: -moz-linear-gradient(hsla(0,0%,80%,.5), hsla(0,0%,60%,.5) 50%); } +.tabbrowser-tab[pinned][titlechanged]:not([selected="true"]) { + background-image: -moz-linear-gradient(rgba(255,0,0,.5), rgba(255,0,0,.5)) !important; +} + .tabbrowser-tab[busy] > .tab-icon-image { list-style-image: url("chrome://browser/skin/tabbrowser/progress.png") !important; -moz-image-region: rect(0, 16px, 16px, 0); From f2ee8e16afdcebeb711ebd2f394678e23a6a05c9 Mon Sep 17 00:00:00 2001 From: Ms2ger <ms2ger@gmail.com> Date: Thu, 2 Sep 2010 22:12:47 +0200 Subject: [PATCH 056/222] Bug 589871 - Fix GetValidationmessage warnings; r=Olli.Pettay approval2.0=jst --- content/html/content/src/nsHTMLButtonElement.cpp | 2 ++ content/html/content/src/nsHTMLFieldSetElement.cpp | 2 ++ content/html/content/src/nsHTMLInputElement.h | 2 ++ content/html/content/src/nsHTMLOutputElement.cpp | 2 ++ content/html/content/src/nsHTMLSelectElement.h | 2 ++ content/html/content/src/nsHTMLTextAreaElement.cpp | 2 ++ 6 files changed, 12 insertions(+) diff --git a/content/html/content/src/nsHTMLButtonElement.cpp b/content/html/content/src/nsHTMLButtonElement.cpp index b9197a28473e..24a13050c6d2 100644 --- a/content/html/content/src/nsHTMLButtonElement.cpp +++ b/content/html/content/src/nsHTMLButtonElement.cpp @@ -82,6 +82,8 @@ class nsHTMLButtonElement : public nsGenericHTMLFormElement, public nsIConstraintValidation { public: + using nsIConstraintValidation::GetValidationMessage; + nsHTMLButtonElement(already_AddRefed<nsINodeInfo> aNodeInfo); virtual ~nsHTMLButtonElement(); diff --git a/content/html/content/src/nsHTMLFieldSetElement.cpp b/content/html/content/src/nsHTMLFieldSetElement.cpp index e1faf73e9cbd..3b58d98838f1 100644 --- a/content/html/content/src/nsHTMLFieldSetElement.cpp +++ b/content/html/content/src/nsHTMLFieldSetElement.cpp @@ -49,6 +49,8 @@ class nsHTMLFieldSetElement : public nsGenericHTMLFormElement, public nsIConstraintValidation { public: + using nsIConstraintValidation::GetValidationMessage; + nsHTMLFieldSetElement(already_AddRefed<nsINodeInfo> aNodeInfo); virtual ~nsHTMLFieldSetElement(); diff --git a/content/html/content/src/nsHTMLInputElement.h b/content/html/content/src/nsHTMLInputElement.h index fef4b1d394b9..4161a7b55243 100644 --- a/content/html/content/src/nsHTMLInputElement.h +++ b/content/html/content/src/nsHTMLInputElement.h @@ -118,6 +118,8 @@ class nsHTMLInputElement : public nsGenericHTMLFormElement, public nsIConstraintValidation { public: + using nsIConstraintValidation::GetValidationMessage; + nsHTMLInputElement(already_AddRefed<nsINodeInfo> aNodeInfo, PRUint32 aFromParser); virtual ~nsHTMLInputElement(); diff --git a/content/html/content/src/nsHTMLOutputElement.cpp b/content/html/content/src/nsHTMLOutputElement.cpp index 091b7466dab3..c65eddcde5fb 100644 --- a/content/html/content/src/nsHTMLOutputElement.cpp +++ b/content/html/content/src/nsHTMLOutputElement.cpp @@ -49,6 +49,8 @@ class nsHTMLOutputElement : public nsGenericHTMLFormElement, public nsIConstraintValidation { public: + using nsIConstraintValidation::GetValidationMessage; + nsHTMLOutputElement(already_AddRefed<nsINodeInfo> aNodeInfo); virtual ~nsHTMLOutputElement(); diff --git a/content/html/content/src/nsHTMLSelectElement.h b/content/html/content/src/nsHTMLSelectElement.h index 492212d29527..ed2619ef589a 100644 --- a/content/html/content/src/nsHTMLSelectElement.h +++ b/content/html/content/src/nsHTMLSelectElement.h @@ -241,6 +241,8 @@ class nsHTMLSelectElement : public nsGenericHTMLFormElement, public nsIConstraintValidation { public: + using nsIConstraintValidation::GetValidationMessage; + nsHTMLSelectElement(already_AddRefed<nsINodeInfo> aNodeInfo, PRUint32 aFromParser = 0); virtual ~nsHTMLSelectElement(); diff --git a/content/html/content/src/nsHTMLTextAreaElement.cpp b/content/html/content/src/nsHTMLTextAreaElement.cpp index e70a25274687..9c95e3189231 100644 --- a/content/html/content/src/nsHTMLTextAreaElement.cpp +++ b/content/html/content/src/nsHTMLTextAreaElement.cpp @@ -94,6 +94,8 @@ class nsHTMLTextAreaElement : public nsGenericHTMLFormElement, public nsIConstraintValidation { public: + using nsIConstraintValidation::GetValidationMessage; + nsHTMLTextAreaElement(already_AddRefed<nsINodeInfo> aNodeInfo, PRUint32 aFromParser = 0); From 30726f670e27c82534587feac0d72ad74f093ccb Mon Sep 17 00:00:00 2001 From: Ms2ger <ms2ger@gmail.com> Date: Thu, 2 Sep 2010 22:18:04 +0200 Subject: [PATCH 057/222] Bug 590970 - Don't compare PL_strcasecmp's return value to nsnull; r=joshmoz approval2.0=jst --- modules/plugin/base/src/nsPluginHost.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/plugin/base/src/nsPluginHost.cpp b/modules/plugin/base/src/nsPluginHost.cpp index 06321cb66dec..c755a5bccf56 100644 --- a/modules/plugin/base/src/nsPluginHost.cpp +++ b/modules/plugin/base/src/nsPluginHost.cpp @@ -1822,13 +1822,13 @@ static PRBool isUnwantedPlugin(nsPluginTag * tag) return PR_TRUE; for (PRInt32 i = 0; i < tag->mVariants; ++i) { - if (nsnull == PL_strcasecmp(tag->mMimeTypeArray[i], "application/pdf")) + if (!PL_strcasecmp(tag->mMimeTypeArray[i], "application/pdf")) return PR_FALSE; - if (nsnull == PL_strcasecmp(tag->mMimeTypeArray[i], "application/x-shockwave-flash")) + if (!PL_strcasecmp(tag->mMimeTypeArray[i], "application/x-shockwave-flash")) return PR_FALSE; - if (nsnull == PL_strcasecmp(tag->mMimeTypeArray[i],"application/x-director")) + if (!PL_strcasecmp(tag->mMimeTypeArray[i], "application/x-director")) return PR_FALSE; } From 1c0c4eb2089610b1c1e3b710cfb9abbe417d2134 Mon Sep 17 00:00:00 2001 From: Margaret Leibovic <margaret.leibovic@gmail.com> Date: Mon, 30 Aug 2010 12:55:17 -0400 Subject: [PATCH 058/222] Bug 573536: add 'Learn more' link to geolocation notifications, r=gavin, a=blocking --- browser/base/content/browser.css | 4 +++ browser/base/content/urlbarBindings.xml | 33 +++++++++++++++++++ .../themes/gnomestripe/browser/browser.css | 5 +++ browser/themes/pinstripe/browser/browser.css | 9 ++--- browser/themes/winstripe/browser/browser.css | 4 +++ 5 files changed, 51 insertions(+), 4 deletions(-) diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css index e675b6985a9e..3331daf75dca 100644 --- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -348,3 +348,7 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m #notification-popup-box[anchorid="addons-notification-icon"] > #addons-notification-icon { display: -moz-box; } + +#geolocation-notification { + -moz-binding: url("chrome://browser/content/urlbarBindings.xml#geolocation-notification"); +} diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index f32c96fd1066..cd7726aee8db 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -688,4 +688,37 @@ </implementation> </binding> + + <binding id="geolocation-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification"> + <content> + <xul:image class="popup-notification-icon" + xbl:inherits="popupid"/> + <xul:vbox> + <xul:description class="popup-notification-description" + xbl:inherits="value=label"/> + <xul:spacer flex="1"/> + <xul:hbox pack="end"> + <xul:label anonid="learnmore" class="text-link geolocation-text-link"/> + <xul:spacer flex="1"/> + <xul:button anonid="button" + class="popup-notification-menubutton" + xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey,type=buttontype"> + <xul:menupopup anonid="menupopup" + xbl:inherits="oncommand=menucommand"> + <children/> + </xul:menupopup> + </xul:button> + </xul:hbox> + </xul:vbox> + </content> + <implementation> + <constructor><![CDATA[ + let link = document.getAnonymousElementByAttribute(this, "anonid", "learnmore"); + link.value = gNavigatorBundle.getString("geolocation.learnMore"); + + let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter); + link.href = formatter.formatURLPref("browser.geolocation.warning.infoURL"); + ]]></constructor> + </implementation> + </binding> </bindings> diff --git a/browser/themes/gnomestripe/browser/browser.css b/browser/themes/gnomestripe/browser/browser.css index b446647f8d07..f6a882867aa6 100644 --- a/browser/themes/gnomestripe/browser/browser.css +++ b/browser/themes/gnomestripe/browser/browser.css @@ -1027,6 +1027,11 @@ toolbar[iconsize="small"] #fullscreen-button { list-style-image: url(chrome://browser/skin/Geolocation-16.png); } +.geolocation-text-link { + -moz-padding-start: 13px; + padding-top: 10px; +} + #addons-notification-icon { list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-16.png); } diff --git a/browser/themes/pinstripe/browser/browser.css b/browser/themes/pinstripe/browser/browser.css index ea4728f75949..53fad9b08b13 100644 --- a/browser/themes/pinstripe/browser/browser.css +++ b/browser/themes/pinstripe/browser/browser.css @@ -1859,6 +1859,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { } #notification-popup { + color: #fff; margin-top: -1px; margin-left: -27px; } @@ -1882,12 +1883,12 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { list-style-image: url(chrome://browser/skin/Geolocation-16.png); } -#addons-notification-icon { - list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-16.png); +.geolocation-text-link { + color: #fff; } -.popup-notification-description { - color: #fff; +#addons-notification-icon { + list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-16.png); } .popup-notification-icon { diff --git a/browser/themes/winstripe/browser/browser.css b/browser/themes/winstripe/browser/browser.css index d6b2dc6dbec2..4d73b61dd605 100644 --- a/browser/themes/winstripe/browser/browser.css +++ b/browser/themes/winstripe/browser/browser.css @@ -1807,6 +1807,10 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] { list-style-image: url(chrome://browser/skin/Geolocation-64.png); } +.geolocation-text-link { + padding-top: 5px; +} + .popup-notification-icon[popupid="xpinstall-disabled"], .popup-notification-icon[popupid="addon-install-blocked"], .popup-notification-icon[popupid="addon-install-failed"], From 6b504676d77f32ba8cca2d1eac9d757684edd17c Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari <ehsan@mozilla.com> Date: Mon, 30 Aug 2010 16:38:43 -0400 Subject: [PATCH 059/222] Bug 590554 - Part 2: Disable the end offset assertion for password fields; r=roc --HG-- extra : rebase_source : 0e3dce695eafc269f1efdacd57d56d5383be6bd9 --- editor/libeditor/text/nsPlaintextEditor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/editor/libeditor/text/nsPlaintextEditor.cpp b/editor/libeditor/text/nsPlaintextEditor.cpp index 7da8d30e54a8..0e30aa6e3dcc 100644 --- a/editor/libeditor/text/nsPlaintextEditor.cpp +++ b/editor/libeditor/text/nsPlaintextEditor.cpp @@ -634,7 +634,8 @@ nsPlaintextEditor::GetTextSelectionOffsets(nsISelection *aSelection, if (endOffset == -1) { NS_ASSERTION(endNode == rootNode, "failed to find the end node"); - NS_ASSERTION(endNodeOffset == nodeCount-1 || endNodeOffset == 0, + NS_ASSERTION(IsPasswordEditor() || + (endNodeOffset == nodeCount-1 || endNodeOffset == 0), "invalid end node offset"); endOffset = endNodeOffset == 0 ? 0 : totalLength; } From c58333e9faa6240d561ffa29d449677f9f36ce30 Mon Sep 17 00:00:00 2001 From: Wan-Teh Chang <wtc@google.com> Date: Thu, 2 Sep 2010 13:40:19 -0700 Subject: [PATCH 060/222] Bug 580679: remove preference security.ssl.enable_compression because the change to build NSS with NSS_ENABLE_ZLIB=1 was reverted. Will try again after mozilla 2.0. review+ and approval2.0+ by bsmedberg. --- netwerk/base/public/security-prefs.js | 1 - security/manager/ssl/src/nsNSSComponent.cpp | 6 ------ 2 files changed, 7 deletions(-) diff --git a/netwerk/base/public/security-prefs.js b/netwerk/base/public/security-prefs.js index 191014d1ff6c..e781ffc53275 100644 --- a/netwerk/base/public/security-prefs.js +++ b/netwerk/base/public/security-prefs.js @@ -8,7 +8,6 @@ pref("security.ssl.renego_unrestricted_hosts", ""); pref("security.ssl.treat_unsafe_negotiation_as_broken", false); pref("security.ssl.require_safe_negotiation", false); pref("security.ssl.warn_missing_rfc5746", 1); -pref("security.ssl.enable_compression", false); pref("security.ssl.enable_false_start", true); pref("security.ssl2.rc4_128", false); diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp index 3b216fa71ec3..0bd17002faef 100644 --- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -1719,8 +1719,6 @@ nsNSSComponent::InitializeNSS(PRBool showWarningBox) SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION, enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN); - mPrefBranch->GetBoolPref("security.ssl.enable_compression", &enabled); - SSL_OptionSetDefault(SSL_ENABLE_DEFLATE, enabled); #ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8 mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled); SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled); @@ -2253,10 +2251,6 @@ nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic, PRInt32 warnLevel = 1; mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel); nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel); - } else if (prefName.Equals("security.ssl.enable_compression")) { - mPrefBranch->GetBoolPref("security.ssl.enable_compression", &enabled); - SSL_OptionSetDefault(SSL_ENABLE_DEFLATE, enabled); - clearSessionCache = PR_TRUE; #ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8 } else if (prefName.Equals("security.ssl.enable_false_start")) { mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled); From 1f534c996b5e8eb87b804d04737a809f20952797 Mon Sep 17 00:00:00 2001 From: Julian Viereck <jviereck@mozilla.com> Date: Thu, 2 Sep 2010 14:30:45 -0700 Subject: [PATCH 061/222] Bug 575789: Implements helper $, 2519, clear, keys, values, inspect and pprint. r=sdwilsh a=beta6+ --- .../console/hudservice/HUDService.jsm | 173 +++++++++++++++++- .../console/hudservice/PropertyPanel.jsm | 2 +- .../browser/browser_HUDServiceTestsAll.js | 46 +++++ .../tests/browser/test-console.html | 2 +- .../chrome/global/headsUpDisplay.properties | 1 + 5 files changed, 221 insertions(+), 3 deletions(-) diff --git a/toolkit/components/console/hudservice/HUDService.jsm b/toolkit/components/console/hudservice/HUDService.jsm index 994ee2625836..208a42a7360b 100644 --- a/toolkit/components/console/hudservice/HUDService.jsm +++ b/toolkit/components/console/hudservice/HUDService.jsm @@ -79,6 +79,11 @@ XPCOMUtils.defineLazyGetter(this, "PropertyPanel", function () { return obj.PropertyPanel; }); +XPCOMUtils.defineLazyGetter(this, "namesAndValuesOf", function () { + var obj = {}; + Cu.import("resource://gre/modules/PropertyPanel.jsm", obj); + return obj.namesAndValuesOf; +}); function LogFactory(aMessagePrefix) { @@ -3488,6 +3493,171 @@ function JSPropertyProvider(aScope, aInputValue) // JSTerm ////////////////////////////////////////////////////////////////////////// +/** + * JSTermHelper + * + * Defines a set of functions ("helper functions") that are available from the + * WebConsole but not from the webpage. + * A list of helper functions used by Firebug can be found here: + * http://getfirebug.com/wiki/index.php/Command_Line_API + */ +function JSTermHelper(aJSTerm) +{ + return { + /** + * Returns the result of document.getElementById(aId). + * + * @param string aId + * A string that is passed to window.document.getElementById. + * @returns nsIDOMNode or null + */ + $: function JSTH_$(aId) + { + try { + return aJSTerm._window.document.getElementById(aId); + } + catch (ex) { + aJSTerm.console.error(ex.message); + } + }, + + /** + * Returns the result of document.querySelectorAll(aSelector). + * + * @param string aSelector + * A string that is passed to window.document.querySelectorAll. + * @returns array of nsIDOMNode + */ + $$: function JSTH_$$(aSelector) + { + try { + return aJSTerm._window.document.querySelectorAll(aSelector); + } + catch (ex) { + aJSTerm.console.error(ex.message); + } + }, + + /** + * Runs a xPath query and returns all matched nodes. + * + * @param string aXPath + * xPath search query to execute. + * @param [optional] nsIDOMNode aContext + * Context to run the xPath query on. Uses window.document if not set. + * @returns array of nsIDOMNode + */ + $x: function JSTH_$x(aXPath, aContext) + { + let nodes = []; + let doc = aJSTerm._window.wrappedJSObject.document; + let aContext = aContext || doc; + + try { + let results = doc.evaluate(aXPath, aContext, null, + Ci.nsIDOMXPathResult.ANY_TYPE, null); + + let node; + while (node = results.iterateNext()) { + nodes.push(node); + } + } + catch (ex) { + aJSTerm.console.error(ex.message); + } + + return nodes; + }, + + /** + * Clears the output of the JSTerm. + */ + clear: function JSTH_clear() + { + aJSTerm.clearOutput(); + }, + + /** + * Returns the result of Object.keys(aObject). + * + * @param object aObject + * Object to return the property names from. + * @returns array of string + */ + keys: function JSTH_keys(aObject) + { + try { + return Object.keys(XPCNativeWrapper.unwrap(aObject)); + } + catch (ex) { + aJSTerm.console.error(ex.message); + } + }, + + /** + * Returns the values of all properties on aObject. + * + * @param object aObject + * Object to display the values from. + * @returns array of string + */ + values: function JSTH_values(aObject) + { + let arrValues = []; + let obj = XPCNativeWrapper.unwrap(aObject); + + try { + for (let prop in obj) { + arrValues.push(obj[prop]); + } + } + catch (ex) { + aJSTerm.console.error(ex.message); + } + return arrValues; + }, + + /** + * Inspects the passed aObject. This is done by opening the PropertyPanel. + * + * @param object aObject + * Object to inspect. + * @returns void + */ + inspect: function JSTH_inspect(aObject) + { + let obj = XPCNativeWrapper.unwrap(aObject); + aJSTerm.openPropertyPanel(null, obj); + }, + + /** + * Prints aObject to the output. + * + * @param object aObject + * Object to print to the output. + * @returns void + */ + pprint: function JSTH_pprint(aObject) + { + if (aObject === null || aObject === undefined || aObject === true || aObject === false) { + aJSTerm.console.error(HUDService.getStr("helperFuncUnsupportedTypeError")); + return; + } + let output = []; + if (typeof aObject != "string") { + aObject = XPCNativeWrapper.unwrap(aObject); + } + let pairs = namesAndValuesOf(aObject); + + pairs.forEach(function(pair) { + output.push(" " + pair.display); + }); + + aJSTerm.writeOutput(output.join("\n")); + } + } +} + /** * JSTerm * @@ -3576,6 +3746,7 @@ JSTerm.prototype = { this.sandbox = new Cu.Sandbox(this._window); this.sandbox.window = this._window; this.sandbox.console = this.console; + this.sandbox.__helperFunctions__ = JSTermHelper(this); this.sandbox.__proto__ = this._window.wrappedJSObject; }, @@ -3594,7 +3765,7 @@ JSTerm.prototype = { */ evalInSandbox: function JST_evalInSandbox(aString) { - let execStr = "with(window) {" + aString + "}"; + let execStr = "with(__helperFunctions__) { with(window) {" + aString + "} }"; return Cu.evalInSandbox(execStr, this.sandbox, "default", "HUD Console", 1); }, diff --git a/toolkit/components/console/hudservice/PropertyPanel.jsm b/toolkit/components/console/hudservice/PropertyPanel.jsm index 1ca788ca3bf7..d8e34f165cc3 100644 --- a/toolkit/components/console/hudservice/PropertyPanel.jsm +++ b/toolkit/components/console/hudservice/PropertyPanel.jsm @@ -44,7 +44,7 @@ const Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); -var EXPORTED_SYMBOLS = ["PropertyPanel", "PropertyTreeView"]; +var EXPORTED_SYMBOLS = ["PropertyPanel", "PropertyTreeView", "namesAndValuesOf"]; /////////////////////////////////////////////////////////////////////////// //// Helper for PropertyTreeView diff --git a/toolkit/components/console/hudservice/tests/browser/browser_HUDServiceTestsAll.js b/toolkit/components/console/hudservice/tests/browser/browser_HUDServiceTestsAll.js index f0bd9f7a52a8..da5ee723f6d2 100644 --- a/toolkit/components/console/hudservice/tests/browser/browser_HUDServiceTestsAll.js +++ b/toolkit/components/console/hudservice/tests/browser/browser_HUDServiceTestsAll.js @@ -1049,6 +1049,51 @@ function testExecutionScope() "command was executed in the window scope"); } +function testJSTermHelper() +{ + content.location.href = TEST_URI; + + let HUD = HUDService.hudWeakReferences[hudId].get(); + let jsterm = HUD.jsterm; + + jsterm.clearOutput(); + jsterm.execute("'id=' + $('header').getAttribute('id')"); + let group = jsterm.outputNode.querySelector(".hud-group"); + is(group.childNodes[2].textContent, "id=header", "$() worked"); + + jsterm.clearOutput(); + jsterm.execute("headerQuery = $$('h1')"); + jsterm.execute("'length=' + headerQuery.length"); + let group = jsterm.outputNode.querySelector(".hud-group"); + is(group.childNodes[4].textContent, "length=1", "$$() worked"); + + jsterm.clearOutput(); + jsterm.execute("xpathQuery = $x('.//*', document.body);"); + jsterm.execute("'headerFound=' + (xpathQuery[0] == headerQuery[0])"); + let group = jsterm.outputNode.querySelector(".hud-group"); + is(group.childNodes[4].textContent, "headerFound=true", "$x() worked"); + + // no jsterm.clearOutput() here as we clear the output using the clear() fn. + jsterm.execute("clear()"); + let group = jsterm.outputNode.querySelector(".hud-group"); + is(group.childNodes[1].textContent, "undefined", "clear() worked"); + + jsterm.clearOutput(); + jsterm.execute("'keysResult=' + (keys({b:1})[0] == 'b')"); + let group = jsterm.outputNode.querySelector(".hud-group"); + is(group.childNodes[2].textContent, "keysResult=true", "keys() worked"); + + jsterm.clearOutput(); + jsterm.execute("'valuesResult=' + (values({b:1})[0] == 1)"); + let group = jsterm.outputNode.querySelector(".hud-group"); + is(group.childNodes[2].textContent, "valuesResult=true", "values() worked"); + + jsterm.clearOutput(); + jsterm.execute("pprint({b:2, a:1})"); + let group = jsterm.outputNode.querySelector(".hud-group"); + is(group.childNodes[2].textContent, " a: 1\n b: 2", "pprint() worked"); +} + function testPropertyPanel() { var HUD = HUDService.hudWeakReferences[hudId].get(); @@ -1383,6 +1428,7 @@ function test() { testPropertyProvider(); testJSInputExpand(); testPropertyPanel(); + testJSTermHelper(); // NOTE: Put any sync test above this comment. // diff --git a/toolkit/components/console/hudservice/tests/browser/test-console.html b/toolkit/components/console/hudservice/tests/browser/test-console.html index 19b496cccc48..fcfd5a101ace 100644 --- a/toolkit/components/console/hudservice/tests/browser/test-console.html +++ b/toolkit/components/console/hudservice/tests/browser/test-console.html @@ -16,7 +16,7 @@ </script> </head> <body> - <h1>Heads Up Display Demo</h1> + <h1 id="header">Heads Up Display Demo</h1> <button onclick="test();">Log stuff about Dolske</button> </body> </html> diff --git a/toolkit/locales/en-US/chrome/global/headsUpDisplay.properties b/toolkit/locales/en-US/chrome/global/headsUpDisplay.properties index a91529907305..1fdef08b6dd6 100644 --- a/toolkit/locales/en-US/chrome/global/headsUpDisplay.properties +++ b/toolkit/locales/en-US/chrome/global/headsUpDisplay.properties @@ -63,6 +63,7 @@ jsPropertyTitle=Object Inspector jsPropertyInspectTitle=Inspect: %S copyCmd.label=Copy copyCmd.accesskey=C +helperFuncUnsupportedTypeError=Can't call pprint on this type of object. # LOCALIZATION NOTE (networkUrlWithStatus): # # When the HTTP request is started only the URL of the request is printed to the From c0c9e9da7f64b72482388b0c2481e06fda9d0859 Mon Sep 17 00:00:00 2001 From: Patrick Walton <pcwalton@mozilla.com> Date: Thu, 2 Sep 2010 14:30:48 -0700 Subject: [PATCH 062/222] Bug 592410 - WebConsole: Reloading page while requests are not done causes exception r=sdwilsh a=gavin.sharp --- toolkit/components/console/hudservice/HUDService.jsm | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/toolkit/components/console/hudservice/HUDService.jsm b/toolkit/components/console/hudservice/HUDService.jsm index 208a42a7360b..457efe993d67 100644 --- a/toolkit/components/console/hudservice/HUDService.jsm +++ b/toolkit/components/console/hudservice/HUDService.jsm @@ -165,14 +165,23 @@ ResponseListener.prototype = let httpActivity = this.httpActivity; // Check if the header isn't set yet. if (!httpActivity.response.header) { - httpActivity.response.header = {}; if (aRequest instanceof Ci.nsIHttpChannel) { + httpActivity.response.header = {}; + try { aRequest.visitResponseHeaders({ visitHeader: function(aName, aValue) { httpActivity.response.header[aName] = aValue; } }); } + // Accessing the response header can throw an NS_ERROR_NOT_AVAILABLE + // exception. Catch it and stop it to make it not show up in the. + // This can happen if the response is not finished yet and the user + // reloades the page. + catch (ex) { + delete httpActivity.response.header; + } + } } }, From e859c42f9dcfef14c5f73176a2f8fbe473d9a562 Mon Sep 17 00:00:00 2001 From: Johnathan Nightingale <johnath@mozilla.com> Date: Thu, 2 Sep 2010 14:42:04 -0400 Subject: [PATCH 063/222] Bug 591776 - Add user agent to about:support r=sdwilsh a=blocking2.0beta6+ --- toolkit/content/aboutSupport.js | 1 + toolkit/content/aboutSupport.xhtml | 9 +++++++++ toolkit/locales/en-US/chrome/global/aboutSupport.dtd | 1 + 3 files changed, 11 insertions(+) diff --git a/toolkit/content/aboutSupport.js b/toolkit/content/aboutSupport.js index d185430b7c92..acc0b1648df0 100644 --- a/toolkit/content/aboutSupport.js +++ b/toolkit/content/aboutSupport.js @@ -90,6 +90,7 @@ window.onload = function () { // Update the application basics section. document.getElementById("application-box").textContent = Application.name; document.getElementById("version-box").textContent = Application.version; + document.getElementById("useragent-box").textContent = navigator.userAgent; document.getElementById("supportLink").href = supportUrl; // Update the other sections. diff --git a/toolkit/content/aboutSupport.xhtml b/toolkit/content/aboutSupport.xhtml index 068ee0e7abf6..ebe6f4623a79 100644 --- a/toolkit/content/aboutSupport.xhtml +++ b/toolkit/content/aboutSupport.xhtml @@ -99,6 +99,15 @@ </td> </tr> + <tr> + <th class="column"> + &aboutSupport.appBasicsUserAgent; + </th> + + <td id="useragent-box"> + </td> + </tr> + <tr> <th class="column"> &aboutSupport.appBasicsProfileDir; diff --git a/toolkit/locales/en-US/chrome/global/aboutSupport.dtd b/toolkit/locales/en-US/chrome/global/aboutSupport.dtd index 28b62bbfc8e4..6facad9f5846 100644 --- a/toolkit/locales/en-US/chrome/global/aboutSupport.dtd +++ b/toolkit/locales/en-US/chrome/global/aboutSupport.dtd @@ -19,6 +19,7 @@ <!ENTITY aboutSupport.appBasicsProfileDir "Profile Directory"> <!ENTITY aboutSupport.appBasicsEnabledPlugins "Enabled Plugins"> <!ENTITY aboutSupport.appBasicsBuildConfig "Build Configuration"> +<!ENTITY aboutSupport.appBasicsUserAgent "User Agent"> <!ENTITY aboutSupport.show.label "Open Containing Folder"> From 2d9c2035d3e7f5aadb83ba9cd98d05281c88e5dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= <dao@mozilla.com> Date: Thu, 2 Sep 2010 23:26:58 +0200 Subject: [PATCH 064/222] Disable browser_drag.js r=dao a=ehsan --- browser/base/content/test/Makefile.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/browser/base/content/test/Makefile.in b/browser/base/content/test/Makefile.in index 0634f3f94026..f54073aa090d 100644 --- a/browser/base/content/test/Makefile.in +++ b/browser/base/content/test/Makefile.in @@ -90,6 +90,8 @@ endif # back to the clear recent history dialog (santize.xul), if it ever is (bug # 480169) +# browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638. + _BROWSER_FILES = \ browser_typeAheadFind.js \ browser_NetworkPrioritizer.js \ @@ -148,7 +150,6 @@ _BROWSER_FILES = \ browser_contextSearchTabPosition.js \ browser_ctrlTab.js \ browser_discovery.js \ - browser_drag.js \ browser_duplicateIDs.js \ browser_gestureSupport.js \ browser_getshortcutoruri.js \ From 1d599447d0edc6f15bfdf5e98b74d4dcba99dc27 Mon Sep 17 00:00:00 2001 From: Felipe Gomes <felipc@gmail.com> Date: Thu, 2 Sep 2010 18:50:26 -0300 Subject: [PATCH 065/222] Bug 590035. Middle clicking tab bar with custom window drawing does not open a new tab. r=jmathies a=blocking-final --- widget/src/windows/nsWindow.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index d59cb8c3cd14..5538d41a2e36 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -4894,10 +4894,28 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam, break; case WM_MBUTTONDBLCLK: - result = DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, wParam, lParam, PR_FALSE, + result = DispatchMouseEvent(NS_MOUSE_DOUBLECLICK, wParam, lParam, PR_FALSE, nsMouseEvent::eMiddleButton, MOUSE_INPUT_SOURCE()); break; + case WM_NCMBUTTONDOWN: + result = DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, 0, lParamToClient(lParam), PR_FALSE, + nsMouseEvent::eMiddleButton, MOUSE_INPUT_SOURCE()); + DispatchPendingEvents(); + break; + + case WM_NCMBUTTONUP: + result = DispatchMouseEvent(NS_MOUSE_BUTTON_UP, 0, lParamToClient(lParam), PR_FALSE, + nsMouseEvent::eMiddleButton, MOUSE_INPUT_SOURCE()); + DispatchPendingEvents(); + break; + + case WM_NCMBUTTONDBLCLK: + result = DispatchMouseEvent(NS_MOUSE_DOUBLECLICK, 0, lParamToClient(lParam), PR_FALSE, + nsMouseEvent::eMiddleButton, MOUSE_INPUT_SOURCE()); + DispatchPendingEvents(); + break; + case WM_RBUTTONDOWN: { result = DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, wParam, lParam, PR_FALSE, From 460eff69fc08e67ad68e1eb8fc5a0565f8ec8b7e Mon Sep 17 00:00:00 2001 From: Felipe Gomes <felipc@gmail.com> Date: Thu, 2 Sep 2010 18:50:32 -0300 Subject: [PATCH 066/222] Bug 559991. Zoom flicker when switching quickly between tabs. r=gavin.sharp a=blocking-betaN --- browser/base/content/browser-fullZoom.js | 8 +-- browser/base/content/test/Makefile.in | 1 + .../base/content/test/browser_bug559991.js | 64 +++++++++++++++++++ 3 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 browser/base/content/test/browser_bug559991.js diff --git a/browser/base/content/browser-fullZoom.js b/browser/base/content/browser-fullZoom.js index 0a6470d84490..24ff8df73ffc 100644 --- a/browser/base/content/browser-fullZoom.js +++ b/browser/base/content/browser-fullZoom.js @@ -256,10 +256,10 @@ var FullZoom = { var self = this; Services.contentPrefs.getPref(aURI, this.name, function (aResult) { // Check that we're still where we expect to be in case this took a while. - let isSaneURI = (aBrowser && aBrowser.currentURI) ? - aURI.equals(aBrowser.currentURI) : false; - if (!aBrowser || isSaneURI) - self._applyPrefToSetting(aResult, aBrowser); + let browser = aBrowser || gBrowser.selectedBrowser; + if (aURI.equals(browser.currentURI)) { + self._applyPrefToSetting(aResult, browser); + } }); }, diff --git a/browser/base/content/test/Makefile.in b/browser/base/content/test/Makefile.in index f54073aa090d..4a809bab8bf3 100644 --- a/browser/base/content/test/Makefile.in +++ b/browser/base/content/test/Makefile.in @@ -138,6 +138,7 @@ _BROWSER_FILES = \ browser_bug555224.js \ browser_bug555767.js \ browser_bug556061.js \ + browser_bug559991.js \ browser_bug561623.js \ browser_bug562649.js \ browser_bug563588.js \ diff --git a/browser/base/content/test/browser_bug559991.js b/browser/base/content/test/browser_bug559991.js new file mode 100644 index 000000000000..ce8054d475e5 --- /dev/null +++ b/browser/base/content/test/browser_bug559991.js @@ -0,0 +1,64 @@ +function test() { + + // ---------- + // Test setup + + waitForExplicitFinish(); + + let oldOLC = FullZoom.onLocationChange; + FullZoom.onLocationChange = function(aURI, aIsTabSwitch, aBrowser) { + // Ignore calls that are not about tab switching on this test + if (aIsTabSwitch) + oldOLC.call(FullZoom, aURI, aIsTabSwitch, aBrowser); + }; + + gPrefService.setBoolPref("browser.zoom.updateBackgroundTabs", true); + gPrefService.setBoolPref("browser.zoom.siteSpecific", true); + + let oldAPTS = FullZoom._applyPrefToSetting; + let uri = "http://example.org/browser/browser/base/content/test/dummy_page.html"; + + // ------------------------------------------------------ + // Test 1 - Zoom should not be called if URIs don't match + FullZoom._applyPrefToSetting = function() { + ok(false, "This should not be called"); + }; + FullZoom.onLocationChange(makeURI(uri), true); + + let tab = gBrowser.addTab(); + tab.linkedBrowser.addEventListener("load", function(event) { + tab.linkedBrowser.removeEventListener("load", arguments.callee, true); + + // ------------------------------------------------------------------- + // Test 2 - Trigger a tab switch that should now update the zoom level + FullZoom._applyPrefToSetting = function() { + ok(true, "applyPrefToSetting was called"); + endTest(); + } + gBrowser.selectedTab = tab; + + }, true); + tab.linkedBrowser.loadURI(uri); + + // ------------- + // Test clean-up + function endTest() { + gBrowser.removeTab(tab); + FullZoom._applyPrefToSetting = oldAPTS; + FullZoom.onLocationChange = oldOLC; + + oldAPTS = null; + oldOLC = null; + tab = null; + + if (gPrefService.prefHasUserValue("browser.zoom.updateBackgroundTabs")) + gPrefService.clearUserPref("browser.zoom.updateBackgroundTabs"); + + if (gPrefService.prefHasUserValue("browser.zoom.siteSpecific")) + gPrefService.clearUserPref("browser.zoom.siteSpecific"); + + finish(); + } + +} + From 2676d1a4956a6a2df4f64bf20d802d3931673119 Mon Sep 17 00:00:00 2001 From: Doug Turner <dougt@dougt.org> Date: Thu, 2 Sep 2010 19:02:06 -0300 Subject: [PATCH 067/222] Bug 592308. IsLowMemory() is terribly slow and there is nothing to do about it. r=bsmedberg a=blocking-fennec2.0 --- dom/base/nsJSEnvironment.cpp | 74 --------------------- modules/libpr0n/src/imgFrame.cpp | 22 ------- xpcom/base/nsIMemory.idl | 2 + xpcom/base/nsMemoryImpl.cpp | 71 +------------------- xpcom/tests/Makefile.in | 1 - xpcom/tests/TestOOM.cpp | 108 ------------------------------- 6 files changed, 3 insertions(+), 275 deletions(-) delete mode 100644 xpcom/tests/TestOOM.cpp diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index d5568e7e6506..a81de38013c7 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -961,79 +961,6 @@ nsJSContext::DOMOperationCallback(JSContext *cx) ctx->mOperationCallbackTime = callbackTime; ctx->mModalStateTime = modalStateTime; - // Check to see if we are running OOM - nsCOMPtr<nsIMemory> mem; - NS_GetMemoryManager(getter_AddRefs(mem)); - if (!mem) { - JS_ClearPendingException(cx); - return JS_FALSE; - } - - PRBool lowMemory; - mem->IsLowMemory(&lowMemory); - if (lowMemory) { - // try to clean up: - nsJSContext::CC(); - - // never prevent system scripts from running - if (!::JS_IsSystemObject(cx, ::JS_GetGlobalObject(cx))) { - - // lets see if CC() did anything, if not, cancel the script. - mem->IsLowMemory(&lowMemory); - if (lowMemory) { - - if (nsContentUtils::GetBoolPref("dom.prevent_oom_dialog", PR_FALSE)) { - JS_ClearPendingException(cx); - return JS_FALSE; - } - - nsCOMPtr<nsIScriptError> errorObject = - do_CreateInstance("@mozilla.org/scripterror;1"); - - if (errorObject) { - nsXPIDLString msg; - nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, - "LowMemoryMessage", - msg); - - JSStackFrame *fp, *iterator = nsnull; - fp = ::JS_FrameIterator(cx, &iterator); - PRUint32 lineno = 0; - nsAutoString sourcefile; - if (fp) { - JSScript* script = ::JS_GetFrameScript(cx, fp); - if (script) { - const char* filename = ::JS_GetScriptFilename(cx, script); - if (filename) { - CopyUTF8toUTF16(nsDependentCString(filename), sourcefile); - } - jsbytecode* pc = ::JS_GetFramePC(cx, fp); - if (pc) { - lineno = ::JS_PCToLineNumber(cx, script, pc); - } - } - } - - rv = errorObject->Init(msg.get(), - sourcefile.get(), - EmptyString().get(), - lineno, 0, nsIScriptError::errorFlag, - "content javascript"); - if (NS_SUCCEEDED(rv)) { - nsCOMPtr<nsIConsoleService> consoleService = - do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv); - if (NS_SUCCEEDED(rv)) { - consoleService->LogMessage(errorObject); - } - } - } - - JS_ClearPendingException(cx); - return JS_FALSE; - } - } - } - PRTime now = PR_Now(); if (callbackTime == 0) { @@ -1045,7 +972,6 @@ nsJSContext::DOMOperationCallback(JSContext *cx) if (ctx->mModalStateDepth) { // We're waiting on a modal dialog, nothing more to do here. - return JS_TRUE; } diff --git a/modules/libpr0n/src/imgFrame.cpp b/modules/libpr0n/src/imgFrame.cpp index c233a0b91853..4efaf86aa5dd 100644 --- a/modules/libpr0n/src/imgFrame.cpp +++ b/modules/libpr0n/src/imgFrame.cpp @@ -192,17 +192,6 @@ nsresult imgFrame::Init(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, if (!AllowedImageSize(aWidth, aHeight)) return NS_ERROR_FAILURE; - // Check to see if we are running OOM - nsCOMPtr<nsIMemory> mem; - NS_GetMemoryManager(getter_AddRefs(mem)); - if (!mem) - return NS_ERROR_UNEXPECTED; - - PRBool lowMemory; - mem->IsLowMemory(&lowMemory); - if (lowMemory) - return NS_ERROR_OUT_OF_MEMORY; - mOffset.MoveTo(aX, aY); mSize.SizeTo(aWidth, aHeight); @@ -553,17 +542,6 @@ nsresult imgFrame::Extract(const nsIntRect& aRegion, imgFrame** aResult) nsresult imgFrame::ImageUpdated(const nsIntRect &aUpdateRect) { - // Check to see if we are running OOM - nsCOMPtr<nsIMemory> mem; - NS_GetMemoryManager(getter_AddRefs(mem)); - if (!mem) - return NS_ERROR_UNEXPECTED; - - PRBool lowMemory; - mem->IsLowMemory(&lowMemory); - if (lowMemory) - return NS_ERROR_OUT_OF_MEMORY; - mDecoded.UnionRect(mDecoded, aUpdateRect); // clamp to bounds, in case someone sends a bogus updateRect (I'm looking at diff --git a/xpcom/base/nsIMemory.idl b/xpcom/base/nsIMemory.idl index fd8cf43832c2..5f4fb892dbb5 100644 --- a/xpcom/base/nsIMemory.idl +++ b/xpcom/base/nsIMemory.idl @@ -122,6 +122,8 @@ interface nsIMemory : nsISupports * This predicate can be used to determine if we're in a low-memory * situation (what constitutes low-memory is platform dependent). This * can be used to trigger the memory pressure observers. + * + * DEPRECATED - Always returns false. See bug 592308. */ boolean isLowMemory(); }; diff --git a/xpcom/base/nsMemoryImpl.cpp b/xpcom/base/nsMemoryImpl.cpp index 2bed5ec7d932..f6adb9cb790c 100644 --- a/xpcom/base/nsMemoryImpl.cpp +++ b/xpcom/base/nsMemoryImpl.cpp @@ -54,30 +54,6 @@ #include "nsString.h" #include "mozilla/Services.h" -#if defined(XP_WIN) -#include <windows.h> -#endif - -#if (MOZ_PLATFORM_MAEMO == 5 || MOZ_PLATFORM_MAEMO == 4) && defined(__arm__) -#include <fcntl.h> -#include <unistd.h> -static const char kHighMark[] = "/sys/kernel/high_watermark"; -#endif - -// Some platforms notify you when system memory is low, others do not. -// In the case of those that do not, we want to post low memory -// notifications from IsLowMemory(). For those that can notify us, that -// code usually lives in toolkit. -#ifdef WINCE -#define NOTIFY_LOW_MEMORY -#endif - -#ifdef WINCE_WINDOWS_MOBILE -#include "aygshell.h" -#endif - -#include "nsITimer.h" - static nsMemoryImpl sGlobalMemory; NS_IMPL_QUERY_INTERFACE1(nsMemoryImpl, nsIMemory) @@ -106,56 +82,11 @@ nsMemoryImpl::HeapMinimize(PRBool aImmediate) return FlushMemory(NS_LITERAL_STRING("heap-minimize").get(), aImmediate); } -/* this magic number is something greater than 40mb - * and after all, 40mb should be good enough for any web app - * unless it's part of an office suite. - */ -static const int kRequiredMemory = 0x3000000; - NS_IMETHODIMP nsMemoryImpl::IsLowMemory(PRBool *result) { -#if defined(WINCE_WINDOWS_MOBILE) - MEMORYSTATUS stat; - GlobalMemoryStatus(&stat); - *result = (stat.dwMemoryLoad >= 98); -#elif defined(WINCE) - // Bug 525323 - GlobalMemoryStatus kills perf on WinCE. + NS_ERROR("IsLowMemory is deprecated. See bug 592308."); *result = PR_FALSE; -#elif defined(XP_WIN) - MEMORYSTATUSEX stat; - stat.dwLength = sizeof stat; - GlobalMemoryStatusEx(&stat); - *result = (stat.ullAvailPageFile < kRequiredMemory) && - ((float)stat.ullAvailPageFile / stat.ullTotalPageFile) < 0.1; -#elif (MOZ_PLATFORM_MAEMO == 5 || MOZ_PLATFORM_MAEMO == 4) && defined(__arm__) - static int osso_highmark_fd = -1; - if (osso_highmark_fd == -1) { - osso_highmark_fd = open (kHighMark, O_RDONLY); - - if (osso_highmark_fd == -1) { - NS_ERROR("can't find the osso highmark file"); - *result = PR_FALSE; - return NS_OK; - } - } - - // be kind, rewind. - lseek(osso_highmark_fd, 0L, SEEK_SET); - - int c = 0; - read (osso_highmark_fd, &c, 1); - - *result = (c == '1'); -#else - *result = PR_FALSE; -#endif - -#ifdef NOTIFY_LOW_MEMORY - if (*result) { - sGlobalMemory.FlushMemory(NS_LITERAL_STRING("low-memory").get(), PR_FALSE); - } -#endif return NS_OK; } diff --git a/xpcom/tests/Makefile.in b/xpcom/tests/Makefile.in index aac865cff1ae..2bcd35d83c53 100644 --- a/xpcom/tests/Makefile.in +++ b/xpcom/tests/Makefile.in @@ -73,7 +73,6 @@ CPPSRCS = \ TestRegistrationOrder.cpp \ TestThreadPoolListener.cpp \ TestTimers.cpp \ - TestOOM.cpp \ TestBlockingProcess.cpp \ TestQuickReturn.cpp \ TestArguments.cpp \ diff --git a/xpcom/tests/TestOOM.cpp b/xpcom/tests/TestOOM.cpp deleted file mode 100644 index 3b5d1e1ef0e0..000000000000 --- a/xpcom/tests/TestOOM.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is a simple OOM Test. - * - * The Initial Developer of the Original Code is - * Mozilla Corporation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Doug Turner <dougt@meer.net> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include <stdio.h> -#include <stdlib.h> -#include <math.h> - -#include "nsXPCOM.h" -#include "nsISupportsUtils.h" -#include "nsCOMPtr.h" -#include "nsIMemory.h" - -int main(int argc, char **argv) -{ - nsCOMPtr<nsIMemory> mem; - nsresult rv = NS_GetMemoryManager(getter_AddRefs(mem)); - - if (!mem || NS_FAILED(rv)) - { - printf("Could not get the memory manager\n"); - return -1; - } - - // allocation note. don't use nsIMemory to allocate, - // because we want to test the isLowMemory predicate - // without regard for the nsIMemory impelmentation (the - // implementation might count bytes handed out. however, - // the predicate should work with out having to rely on - // that. - void *big_alloc = malloc(1024 * 1024 * 16); - (void)big_alloc; // Tell compiler we're not using big_alloc, to fix warning - - const int highpower = 500000; - - char* buffers[highpower]; - for (int i=0; i<highpower; i++) - buffers[i] = nsnull; - - for (int i=0; i<highpower; i++) - { - PRBool lowMem = PR_FALSE; - size_t s = 4096; //pow(2,i); - buffers[i] = (char*) malloc(s); - - // You have to touch the buffer - if (!buffers[i]) - printf("Could not allocate a buffer of size %lu\n", (unsigned long)s); - else - { - for (size_t j=0; j<s; j++) - buffers[i][j] = 'a'; - } - - PRIntervalTime start = PR_IntervalNow(); - mem->IsLowMemory(&lowMem); - PRIntervalTime cost = PR_IntervalNow() - start; - - - printf("Total Allocated: %lu. \tLow Memory now? %s\t Took (%d)\n", - (unsigned long)s*i, - lowMem ? "Yes" : "No", - PR_IntervalToMilliseconds(cost)); - - if (lowMem) - break; - } - - for(int i=0; i<highpower; i++) - { - if (buffers[i]) - free(buffers[i]); - } - return 0; -} From 46436ed9f0a4239b296d9479c736ea0bf50a2468 Mon Sep 17 00:00:00 2001 From: Wan-Teh Chang <wtc@google.com> Date: Thu, 2 Sep 2010 16:47:06 -0700 Subject: [PATCH 068/222] Bug 580679: do not define ZLIB_INTERNAL when compiling files outside zlib. This reverts some of the zlib-related changes in Dec. 2004 for libxul (bug 272783 and bug 273876). r=bsmedberg. a=bsmedberg. --- config/config.mk | 3 --- js/src/config/config.mk | 3 --- toolkit/library/dlldeps-zlib.cpp | 1 + toolkit/library/libxul-config.mk | 2 -- 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/config/config.mk b/config/config.mk index 4f8f19c3061e..c73303a4885f 100644 --- a/config/config.mk +++ b/config/config.mk @@ -394,9 +394,6 @@ DEFINES += \ ifndef JS_SHARED_LIBRARY DEFINES += -DSTATIC_EXPORTABLE_JS_API endif -ifndef MOZ_NATIVE_ZLIB -DEFINES += -DZLIB_INTERNAL -endif endif endif diff --git a/js/src/config/config.mk b/js/src/config/config.mk index 4f8f19c3061e..c73303a4885f 100644 --- a/js/src/config/config.mk +++ b/js/src/config/config.mk @@ -394,9 +394,6 @@ DEFINES += \ ifndef JS_SHARED_LIBRARY DEFINES += -DSTATIC_EXPORTABLE_JS_API endif -ifndef MOZ_NATIVE_ZLIB -DEFINES += -DZLIB_INTERNAL -endif endif endif diff --git a/toolkit/library/dlldeps-zlib.cpp b/toolkit/library/dlldeps-zlib.cpp index 51568c9f7a40..3d784e56a74a 100644 --- a/toolkit/library/dlldeps-zlib.cpp +++ b/toolkit/library/dlldeps-zlib.cpp @@ -38,6 +38,7 @@ // Force references to all of the symbols that we want exported from // the dll that are located in the .lib files we link with +#define ZLIB_INTERNAL #include "zlib.h" void xxxNeverCalledZLib() diff --git a/toolkit/library/libxul-config.mk b/toolkit/library/libxul-config.mk index 4030cbf6fe06..f089a10530a4 100644 --- a/toolkit/library/libxul-config.mk +++ b/toolkit/library/libxul-config.mk @@ -58,7 +58,6 @@ RCINCLUDE = xulrunner.rc ifndef MOZ_NATIVE_ZLIB CPPSRCS += dlldeps-zlib.cpp -DEFINES += -DZLIB_INTERNAL endif LOCAL_INCLUDES += -I$(topsrcdir)/widget/src/windows @@ -79,7 +78,6 @@ CPPSRCS += \ ifndef MOZ_NATIVE_ZLIB CPPSRCS += dlldeps-zlib.cpp -DEFINES += -DZLIB_INTERNAL endif ifdef MOZ_ENABLE_LIBXUL From d84bc180241e8e97e71a016d587def2a17de15df Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari <ehsan@mozilla.com> Date: Thu, 2 Sep 2010 19:54:23 -0400 Subject: [PATCH 069/222] Back out bug 240933 and bug 590554 because of reftest failure on Win7 and also bug 593211 --- .../tests/mochitest/tree/test_txtctrl.html | 14 +- content/base/src/nsGenericDOMDataNode.cpp | 6 +- content/base/src/nsGenericDOMDataNode.h | 2 +- content/base/src/nsTextFragment.cpp | 6 +- content/base/src/nsTextFragment.h | 4 +- editor/libeditor/base/Makefile.in | 1 - editor/libeditor/base/nsEditor.cpp | 99 +------- editor/libeditor/text/nsPlaintextEditor.cpp | 90 ++++--- editor/libeditor/text/nsTextEditRules.cpp | 236 ++++++++++++------ editor/libeditor/text/nsTextEditRules.h | 8 +- editor/libeditor/text/tests/Makefile.in | 1 - .../libeditor/text/tests/test_bug590554.html | 37 --- .../test_texteditor_keyevent_handling.html | 16 +- layout/base/tests/Makefile.in | 3 - layout/base/tests/bug240933-1-ref.html | 10 - layout/base/tests/bug240933-1.html | 14 -- layout/base/tests/bug240933-2.html | 16 -- .../base/tests/test_reftests_with_caret.html | 2 - layout/forms/nsTextControlFrame.cpp | 132 +++++++--- layout/generic/nsFrame.cpp | 11 +- layout/generic/nsIFrame.h | 8 - layout/generic/nsTextFrame.h | 2 - layout/generic/nsTextFrameThebes.cpp | 48 ++-- layout/generic/test/Makefile.in | 1 - layout/generic/test/test_bug240933.html | 68 ----- layout/generic/test/test_bug288789.html | 61 +---- .../test/test_movement_by_characters.html | 8 +- layout/reftests/bugs/240933-1-ref.html | 25 -- layout/reftests/bugs/240933-1.html | 19 -- layout/reftests/bugs/240933-2-ref.html | 29 --- layout/reftests/bugs/240933-2.html | 19 -- layout/reftests/bugs/reftest.list | 2 - .../caret_on_textarea_lastline-ref.html | 6 - .../editor/caret_on_textarea_lastline.html | 7 - layout/reftests/editor/reftest.list | 1 - 35 files changed, 359 insertions(+), 653 deletions(-) delete mode 100644 editor/libeditor/text/tests/test_bug590554.html delete mode 100644 layout/base/tests/bug240933-1-ref.html delete mode 100644 layout/base/tests/bug240933-1.html delete mode 100644 layout/base/tests/bug240933-2.html delete mode 100644 layout/generic/test/test_bug240933.html delete mode 100644 layout/reftests/bugs/240933-1-ref.html delete mode 100644 layout/reftests/bugs/240933-1.html delete mode 100644 layout/reftests/bugs/240933-2-ref.html delete mode 100644 layout/reftests/bugs/240933-2.html delete mode 100644 layout/reftests/editor/caret_on_textarea_lastline-ref.html delete mode 100644 layout/reftests/editor/caret_on_textarea_lastline.html diff --git a/accessible/tests/mochitest/tree/test_txtctrl.html b/accessible/tests/mochitest/tree/test_txtctrl.html index bc690b3e2df5..204da2b0f553 100644 --- a/accessible/tests/mochitest/tree/test_txtctrl.html +++ b/accessible/tests/mochitest/tree/test_txtctrl.html @@ -50,7 +50,19 @@ role: ROLE_ENTRY, children: [ { - role: ROLE_TEXT_LEAF // hello1\nhello2 text + role: ROLE_TEXT_LEAF // hello1 text + }, + { + role: ROLE_WHITESPACE + }, + { + role: ROLE_TEXT_LEAF, // hello2 text + }, + { + role: ROLE_WHITESPACE + }, + { + role: ROLE_TEXT_LEAF, // whitepsace text }, { role: ROLE_WHITESPACE diff --git a/content/base/src/nsGenericDOMDataNode.cpp b/content/base/src/nsGenericDOMDataNode.cpp index 166fa69205c7..34344f644b28 100644 --- a/content/base/src/nsGenericDOMDataNode.cpp +++ b/content/base/src/nsGenericDOMDataNode.cpp @@ -385,7 +385,7 @@ nsGenericDOMDataNode::SetTextInternal(PRUint32 aOffset, PRUint32 aCount, delete [] to; } - UpdateBidiStatus(aBuffer, aLength); + SetBidiStatus(); // Notify observers if (aNotify) { @@ -1084,7 +1084,7 @@ nsGenericDOMDataNode::AppendTextTo(nsAString& aResult) mText.AppendTo(aResult); } -void nsGenericDOMDataNode::UpdateBidiStatus(const PRUnichar* aBuffer, PRUint32 aLength) +void nsGenericDOMDataNode::SetBidiStatus() { nsIDocument *document = GetCurrentDoc(); if (document && document->GetBidiEnabled()) { @@ -1092,7 +1092,7 @@ void nsGenericDOMDataNode::UpdateBidiStatus(const PRUnichar* aBuffer, PRUint32 a return; } - mText.UpdateBidiFlag(aBuffer, aLength); + mText.SetBidiFlag(); if (document && mText.IsBidi()) { document->SetBidiEnabled(); diff --git a/content/base/src/nsGenericDOMDataNode.h b/content/base/src/nsGenericDOMDataNode.h index 83c461fbb93d..a90f7243e01f 100644 --- a/content/base/src/nsGenericDOMDataNode.h +++ b/content/base/src/nsGenericDOMDataNode.h @@ -358,7 +358,7 @@ protected: nsTextFragment mText; private: - void UpdateBidiStatus(const PRUnichar* aBuffer, PRUint32 aLength); + void SetBidiStatus(); already_AddRefed<nsIAtom> GetCurrentValueAtom(); }; diff --git a/content/base/src/nsTextFragment.cpp b/content/base/src/nsTextFragment.cpp index 87f4f8e91dd2..ce1aab9f3924 100644 --- a/content/base/src/nsTextFragment.cpp +++ b/content/base/src/nsTextFragment.cpp @@ -372,11 +372,11 @@ nsTextFragment::Append(const PRUnichar* aBuffer, PRUint32 aLength) // To save time we only do this when we really want to know, not during // every allocation void -nsTextFragment::UpdateBidiFlag(const PRUnichar* aBuffer, PRUint32 aLength) +nsTextFragment::SetBidiFlag() { if (mState.mIs2b && !mState.mIsBidi) { - const PRUnichar* cp = aBuffer; - const PRUnichar* end = cp + aLength; + const PRUnichar* cp = m2b; + const PRUnichar* end = cp + mState.mLength; while (cp < end) { PRUnichar ch1 = *cp++; PRUint32 utf32Char = ch1; diff --git a/content/base/src/nsTextFragment.h b/content/base/src/nsTextFragment.h index 4a5c27aca21e..bbdd602c3961 100644 --- a/content/base/src/nsTextFragment.h +++ b/content/base/src/nsTextFragment.h @@ -112,7 +112,7 @@ public: /** * Return PR_TRUE if this fragment contains Bidi text * For performance reasons this flag is not set automatically, but - * requires an explicit call to UpdateBidiFlag() + * requires an explicit call to SetBidiFlag() */ PRBool IsBidi() const { @@ -209,7 +209,7 @@ public: * Scan the contents of the fragment and turn on mState.mIsBidi if it * includes any Bidi characters. */ - void UpdateBidiFlag(const PRUnichar* aBuffer, PRUint32 aLength); + void SetBidiFlag(); struct FragmentBits { // PRUint32 to ensure that the values are unsigned, because we diff --git a/editor/libeditor/base/Makefile.in b/editor/libeditor/base/Makefile.in index acedb86f4994..81c5bdc964bb 100644 --- a/editor/libeditor/base/Makefile.in +++ b/editor/libeditor/base/Makefile.in @@ -90,7 +90,6 @@ FORCE_STATIC_LIB = 1 include $(topsrcdir)/config/rules.mk INCLUDES += \ - -I$(topsrcdir)/editor/libeditor/text \ -I$(topsrcdir)/content/base/src \ -I$(topsrcdir)/content/events/src \ -I$(topsrcdir)/layout/style \ diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index 39d9c693f425..5adc2f26d48e 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -113,7 +113,6 @@ #include "nsITransferable.h" #include "nsComputedDOMStyle.h" -#include "nsTextEditUtils.h" #include "mozilla/FunctionTimer.h" @@ -904,27 +903,14 @@ nsEditor::EndPlaceHolderTransaction() if (selPrivate) { selPrivate->SetCanCacheFrameOffset(PR_TRUE); } + + // time to turn off the batch + EndUpdateViewBatch(); + // make sure selection is in view - { - // Hide the caret here to avoid hiding it twice, once in EndUpdateViewBatch - // and once in ScrollSelectionIntoView. - nsRefPtr<nsCaret> caret; - nsCOMPtr<nsIPresShell> presShell; - GetPresShell(getter_AddRefs(presShell)); - - if (presShell) - caret = presShell->GetCaret(); - - StCaretHider caretHider(caret); - - // time to turn off the batch - EndUpdateViewBatch(); - // make sure selection is in view - - // After ScrollSelectionIntoView(), the pending notifications might be - // flushed and PresShell/PresContext/Frames may be dead. See bug 418470. - ScrollSelectionIntoView(PR_FALSE); - } + // After ScrollSelectionIntoView(), the pending notifications might be + // flushed and PresShell/PresContext/Frames may be dead. See bug 418470. + ScrollSelectionIntoView(PR_FALSE); // cached for frame offset are Not available now if (selPrivate) { @@ -2287,75 +2273,11 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsAString& aStringToInsert, // class to turn off txn selection updating. Caller also turned on rules sniffing // if desired. - nsresult res; NS_ENSURE_TRUE(aInOutNode && *aInOutNode && aInOutOffset && aDoc, NS_ERROR_NULL_POINTER); if (!mInIMEMode && aStringToInsert.IsEmpty()) return NS_OK; nsCOMPtr<nsIDOMText> nodeAsText = do_QueryInterface(*aInOutNode); - if (!nodeAsText && IsPlaintextEditor()) { - // In some cases, aInOutNode is the anonymous DIV, and aInOutOffset is 0. - // To avoid injecting unneeded text nodes, we first look to see if we have - // one available. In that case, we'll just adjust aInOutNode and aInOutOffset - // accordingly. - if (*aInOutNode == GetRoot() && *aInOutOffset == 0) { - nsCOMPtr<nsIDOMNode> possibleTextNode; - res = (*aInOutNode)->GetFirstChild(getter_AddRefs(possibleTextNode)); - if (NS_SUCCEEDED(res)) { - nodeAsText = do_QueryInterface(possibleTextNode); - if (nodeAsText) { - *aInOutNode = possibleTextNode; - } - } - } - // In some other cases, aInOutNode is the anonymous DIV, and aInOutOffset points - // to the terminating mozBR. In that case, we'll adjust aInOutNode and aInOutOffset - // to the preceding text node, if any. - if (!nodeAsText && *aInOutNode == GetRoot() && *aInOutOffset > 0) { - nsCOMPtr<nsIDOMNodeList> children; - res = (*aInOutNode)->GetChildNodes(getter_AddRefs(children)); - if (NS_SUCCEEDED(res)) { - nsCOMPtr<nsIDOMNode> possibleMozBRNode; - res = children->Item(*aInOutOffset, getter_AddRefs(possibleMozBRNode)); - if (NS_SUCCEEDED(res) && nsTextEditUtils::IsMozBR(possibleMozBRNode)) { - nsCOMPtr<nsIDOMNode> possibleTextNode; - res = children->Item(*aInOutOffset - 1, getter_AddRefs(possibleTextNode)); - if (NS_SUCCEEDED(res)) { - nodeAsText = do_QueryInterface(possibleTextNode); - if (nodeAsText) { - PRUint32 length; - res = nodeAsText->GetLength(&length); - if (NS_SUCCEEDED(res)) { - *aInOutOffset = PRInt32(length); - *aInOutNode = possibleTextNode; - } - } - } - } - } - } - // Sometimes, aInOutNode is the mozBR element itself. In that case, we'll - // adjust the insertion point to the previous text node, if one exists, or - // to the parent anonymous DIV. - if (nsTextEditUtils::IsMozBR(*aInOutNode) && *aInOutOffset == 0) { - nsCOMPtr<nsIDOMNode> previous; - (*aInOutNode)->GetPreviousSibling(getter_AddRefs(previous)); - nodeAsText = do_QueryInterface(previous); - if (nodeAsText) { - PRUint32 length; - res = nodeAsText->GetLength(&length); - if (NS_SUCCEEDED(res)) { - *aInOutOffset = PRInt32(length); - *aInOutNode = previous; - } - } else { - nsCOMPtr<nsIDOMNode> parent; - (*aInOutNode)->GetParentNode(getter_AddRefs(parent)); - if (parent == GetRoot()) { - *aInOutNode = parent; - } - } - } - } PRInt32 offset = *aInOutOffset; + nsresult res; if (mInIMEMode) { if (!nodeAsText) @@ -3624,9 +3546,8 @@ nsEditor::IsEditable(nsIDOMNode *aNode) // and uses enhanced logic to find out in the HTML world. return IsTextInDirtyFrameVisible(aNode); } - if (resultFrame->HasAnyNoncollapsedCharacters()) { - return PR_TRUE; - } + if (resultFrame->GetSize().width > 0) + return PR_TRUE; // text node has width resultFrame = resultFrame->GetNextContinuation(); } } diff --git a/editor/libeditor/text/nsPlaintextEditor.cpp b/editor/libeditor/text/nsPlaintextEditor.cpp index 0e30aa6e3dcc..7dc9d3e3806c 100644 --- a/editor/libeditor/text/nsPlaintextEditor.cpp +++ b/editor/libeditor/text/nsPlaintextEditor.cpp @@ -623,19 +623,13 @@ nsPlaintextEditor::GetTextSelectionOffsets(nsISelection *aSelection, } } #ifdef NS_DEBUG - // The post content iterator might return the parent node (which is the - // editor's root node) as the last item. Don't count the root node itself - // as one of its children! - if (!SameCOMIdentity(currentNode, rootNode)) { - ++nodeCount; - } + ++nodeCount; #endif } if (endOffset == -1) { NS_ASSERTION(endNode == rootNode, "failed to find the end node"); - NS_ASSERTION(IsPasswordEditor() || - (endNodeOffset == nodeCount-1 || endNodeOffset == 0), + NS_ASSERTION(endNodeOffset == nodeCount-1 || endNodeOffset == 0, "invalid end node offset"); endOffset = endNodeOffset == 0 ? 0 : totalLength; } @@ -868,55 +862,57 @@ NS_IMETHODIMP nsPlaintextEditor::InsertLineBreak() shell->MaybeInvalidateCaretPosition(); nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertBreak); - ruleInfo.maxLength = mMaxTextLength; PRBool cancel, handled; res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); NS_ENSURE_SUCCESS(res, res); if (!cancel && !handled) { - // get the (collapsed) selection location - nsCOMPtr<nsIDOMNode> selNode; - PRInt32 selOffset; - res = GetStartNodeAndOffset(selection, getter_AddRefs(selNode), &selOffset); - NS_ENSURE_SUCCESS(res, res); - - // don't put text in places that can't have it - if (!IsTextNode(selNode) && !CanContainTag(selNode, NS_LITERAL_STRING("#text"))) - return NS_ERROR_FAILURE; - - // we need to get the doc - nsCOMPtr<nsIDOMDocument> doc; - res = GetDocument(getter_AddRefs(doc)); - NS_ENSURE_SUCCESS(res, res); - NS_ENSURE_TRUE(doc, NS_ERROR_NULL_POINTER); - - // don't spaz my selection in subtransactions - nsAutoTxnsConserveSelection dontSpazMySelection(this); - - // insert a linefeed character - res = InsertTextImpl(NS_LITERAL_STRING("\n"), address_of(selNode), - &selOffset, doc); - if (!selNode) res = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called + // create the new BR node + nsCOMPtr<nsIDOMNode> newNode; + res = DeleteSelectionAndCreateNode(NS_LITERAL_STRING("br"), getter_AddRefs(newNode)); + if (!newNode) res = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called if (NS_SUCCEEDED(res)) { - // set the selection to the correct location - res = selection->Collapse(selNode, selOffset); - + // set the selection to the new node + nsCOMPtr<nsIDOMNode>parent; + res = newNode->GetParentNode(getter_AddRefs(parent)); + if (!parent) res = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called if (NS_SUCCEEDED(res)) { - // see if we're at the end of the editor range - nsCOMPtr<nsIDOMNode> endNode; - PRInt32 endOffset; - res = GetEndNodeAndOffset(selection, getter_AddRefs(endNode), &endOffset); - - if (NS_SUCCEEDED(res) && endNode == selNode && endOffset == selOffset) + PRInt32 offsetInParent=-1; // we use the -1 as a marker to see if we need to compute this or not + nsCOMPtr<nsIDOMNode>nextNode; + newNode->GetNextSibling(getter_AddRefs(nextNode)); + if (nextNode) { - // SetInterlinePosition(PR_TRUE) means we want the caret to stick to the content on the "right". - // We want the caret to stick to whatever is past the break. This is - // because the break is on the same line we were on, but the next content - // will be on the following line. - nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection)); - selPriv->SetInterlinePosition(PR_TRUE); + nsCOMPtr<nsIDOMCharacterData>nextTextNode = do_QueryInterface(nextNode); + if (!nextTextNode) { + nextNode = do_QueryInterface(newNode); // is this QI needed? + } + else { + offsetInParent=0; + } + } + else { + nextNode = do_QueryInterface(newNode); // is this QI needed? + } + + if (-1==offsetInParent) + { + nextNode->GetParentNode(getter_AddRefs(parent)); + res = GetChildOffset(nextNode, parent, offsetInParent); + if (NS_SUCCEEDED(res)) { + // SetInterlinePosition(PR_TRUE) means we want the caret to stick to the content on the "right". + // We want the caret to stick to whatever is past the break. This is + // because the break is on the same line we were on, but the next content + // will be on the following line. + nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection)); + selPriv->SetInterlinePosition(PR_TRUE); + res = selection->Collapse(parent, offsetInParent+1); // +1 to insert just after the break + } + } + else + { + res = selection->Collapse(nextNode, offsetInParent); } } } diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp index aea336ce7529..56e2b655bc6d 100644 --- a/editor/libeditor/text/nsTextEditRules.cpp +++ b/editor/libeditor/text/nsTextEditRules.cpp @@ -267,9 +267,6 @@ nsTextEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection) // insure trailing br node res = CreateTrailingBRIfNeeded(); NS_ENSURE_SUCCESS(res, res); - - // collapse the selection to the trailing BR if it's at the end of our text node - CollapseSelectionToTrailingBRIfNeeded(selection); /* After inserting text the cursor Bidi level must be set to the level of the inserted text. * This is difficult, because we cannot know what the level is until after the Bidi algorithm @@ -312,7 +309,7 @@ nsTextEditRules::WillDoAction(nsISelection *aSelection, switch (info->action) { case kInsertBreak: - return WillInsertBreak(aSelection, aCancel, aHandled, info->maxLength); + return WillInsertBreak(aSelection, aCancel, aHandled); case kInsertText: case kInsertTextIME: return WillInsertText(info->action, @@ -424,10 +421,7 @@ nsTextEditRules::DidInsert(nsISelection *aSelection, nsresult aResult) } nsresult -nsTextEditRules::WillInsertBreak(nsISelection *aSelection, - PRBool *aCancel, - PRBool *aHandled, - PRInt32 aMaxLength) +nsTextEditRules::WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, PRBool *aHandled) { if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; } CANCEL_OPERATION_IF_READONLY_OR_DISABLED @@ -437,24 +431,11 @@ nsTextEditRules::WillInsertBreak(nsISelection *aSelection, } else { - // handle docs with a max length - // NOTE, this function copies inString into outString for us. - NS_NAMED_LITERAL_STRING(inString, "\n"); - nsAutoString outString; - PRBool didTruncate; - nsresult res = TruncateInsertionIfNeeded(aSelection, &inString, &outString, - aMaxLength, &didTruncate); - NS_ENSURE_SUCCESS(res, res); - if (didTruncate) { - *aCancel = PR_TRUE; - return NS_OK; - } - *aCancel = PR_FALSE; // if the selection isn't collapsed, delete it. PRBool bCollapsed; - res = aSelection->GetIsCollapsed(&bCollapsed); + nsresult res = aSelection->GetIsCollapsed(&bCollapsed); NS_ENSURE_SUCCESS(res, res); if (!bCollapsed) { @@ -474,12 +455,6 @@ nsTextEditRules::WillInsertBreak(nsISelection *aSelection, nsresult nsTextEditRules::DidInsertBreak(nsISelection *aSelection, nsresult aResult) -{ - return NS_OK; -} - -nsresult -nsTextEditRules::CollapseSelectionToTrailingBRIfNeeded(nsISelection* aSelection) { // we only need to execute the stuff below if we are a plaintext editor. // html editors have a different mechanism for putting in mozBR's @@ -488,40 +463,40 @@ nsTextEditRules::CollapseSelectionToTrailingBRIfNeeded(nsISelection* aSelection) return NS_OK; } - // if we are at the end of the textarea, we need to set the - // selection to stick to the mozBR at the end of the textarea. + // if we are at the end of the document, we need to insert + // a special mozBR following the normal br, and then set the + // selection to stick to the mozBR. PRInt32 selOffset; nsCOMPtr<nsIDOMNode> selNode; nsresult res; res = mEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(selNode), &selOffset); NS_ENSURE_SUCCESS(res, res); - - nsCOMPtr<nsIDOMText> nodeAsText = do_QueryInterface(selNode); - if (!nodeAsText) return NS_OK; // nothing to do if we're not at a text node - - PRUint32 length; - res = nodeAsText->GetLength(&length); - NS_ENSURE_SUCCESS(res, res); - - // nothing to do if we're not at the end of the text node - if (selOffset != length) return NS_OK; - - nsCOMPtr<nsIDOMNode> parentNode; - PRInt32 parentOffset; - res = nsEditor::GetNodeLocation(selNode, address_of(parentNode), - &parentOffset); - NS_ENSURE_SUCCESS(res, res); - + // confirm we are at end of document + if (selOffset == 0) return NS_OK; // can't be after a br if we are at offset 0 nsIDOMElement *rootElem = mEditor->GetRoot(); + nsCOMPtr<nsIDOMNode> root = do_QueryInterface(rootElem); NS_ENSURE_TRUE(root, NS_ERROR_NULL_POINTER); - if (parentNode != root) return NS_OK; + if (selNode != root) return NS_OK; // must be inside text node or somewhere other than end of root - nsCOMPtr<nsIDOMNode> nextNode = mEditor->GetChildAt(parentNode, - parentOffset + 1); - if (nextNode && nsTextEditUtils::IsMozBR(nextNode)) + nsCOMPtr<nsIDOMNode> temp = mEditor->GetChildAt(selNode, selOffset); + if (temp) return NS_OK; // can't be at end if there is a node after us. + + nsCOMPtr<nsIDOMNode> nearNode = mEditor->GetChildAt(selNode, selOffset-1); + if (nearNode && nsTextEditUtils::IsBreak(nearNode) && !nsTextEditUtils::IsMozBR(nearNode)) { - res = aSelection->Collapse(parentNode, parentOffset + 1); + nsCOMPtr<nsISelectionPrivate>selPrivate(do_QueryInterface(aSelection)); + // need to insert special moz BR. Why? Because if we don't + // the user will see no new line for the break. Also, things + // like table cells won't grow in height. + nsCOMPtr<nsIDOMNode> brNode; + res = CreateMozBR(selNode, selOffset, address_of(brNode)); + NS_ENSURE_SUCCESS(res, res); + + res = nsEditor::GetNodeLocation(brNode, address_of(selNode), &selOffset); + NS_ENSURE_SUCCESS(res, res); + selPrivate->SetInterlinePosition(PR_TRUE); + res = aSelection->Collapse(selNode, selOffset); NS_ENSURE_SUCCESS(res, res); } return res; @@ -658,7 +633,7 @@ nsTextEditRules::WillInsertText(PRInt32 aAction, // handle docs with a max length // NOTE, this function copies inString into outString for us. - nsresult res = TruncateInsertionIfNeeded(aSelection, inString, outString, aMaxLength, nsnull); + nsresult res = TruncateInsertionIfNeeded(aSelection, inString, outString, aMaxLength); NS_ENSURE_SUCCESS(res, res); PRUint32 start = 0; @@ -773,32 +748,143 @@ nsTextEditRules::WillInsertText(PRInt32 aAction, nsCOMPtr<nsIDOMNode> curNode = selNode; PRInt32 curOffset = selOffset; + // is our text going to be PREformatted? + // We remember this so that we know how to handle tabs. + PRBool isPRE; + res = mEditor->IsPreformatted(selNode, &isPRE); + NS_ENSURE_SUCCESS(res, res); + // don't spaz my selection in subtransactions nsAutoTxnsConserveSelection dontSpazMySelection(mEditor); + nsString tString(*outString); + const PRUnichar *unicodeBuf = tString.get(); + nsCOMPtr<nsIDOMNode> unused; + PRInt32 pos = 0; - res = mEditor->InsertTextImpl(*outString, address_of(curNode), - &curOffset, doc); - NS_ENSURE_SUCCESS(res, res); + // for efficiency, break out the pre case separately. This is because + // it's a lot cheaper to search the input string for only newlines than + // it is to search for both tabs and newlines. + if (isPRE) + { + while (unicodeBuf && (pos != -1) && ((PRUint32)pos < tString.Length())) + { + PRInt32 oldPos = pos; + PRInt32 subStrLen; + pos = tString.FindChar(nsCRT::LF, oldPos); + + if (pos != -1) + { + subStrLen = pos - oldPos; + // if first char is newline, then use just it + if (subStrLen == 0) + subStrLen = 1; + } + else + { + subStrLen = tString.Length() - oldPos; + pos = tString.Length(); + } + + nsDependentSubstring subStr(tString, oldPos, subStrLen); + + // is it a return? + if (subStr.EqualsLiteral(LFSTR)) + { + if (IsSingleLineEditor()) + { + NS_ASSERTION((mEditor->mNewlineHandling == nsIPlaintextEditor::eNewlinesPasteIntact), + "Newline improperly getting into single-line edit field!"); + res = mEditor->InsertTextImpl(subStr, address_of(curNode), &curOffset, doc); + } + else + { + res = mEditor->CreateBRImpl(address_of(curNode), &curOffset, address_of(unused), nsIEditor::eNone); + + // If the newline is the last character in the string, and the BR we + // just inserted is the last node in the content tree, we need to add + // a mozBR so that a blank line is created. + + if (NS_SUCCEEDED(res) && curNode && pos == (PRInt32)(tString.Length() - 1)) + { + nsCOMPtr<nsIDOMNode> nextChild = mEditor->GetChildAt(curNode, curOffset); + + if (!nextChild) + { + // We must be at the end since there isn't a nextChild. + // + // curNode and curOffset should be set to the position after + // the BR we added above, so just create a mozBR at that position. + // + // Note that we don't update curOffset after we've created/inserted + // the mozBR since we never want the selection to be placed after it. + + res = CreateMozBR(curNode, curOffset, address_of(unused)); + } + } + } + pos++; + } + else + { + res = mEditor->InsertTextImpl(subStr, address_of(curNode), &curOffset, doc); + } + NS_ENSURE_SUCCESS(res, res); + } + } + else + { + char specialChars[] = {TAB, nsCRT::LF, 0}; + while (unicodeBuf && (pos != -1) && ((PRUint32)pos < tString.Length())) + { + PRInt32 oldPos = pos; + PRInt32 subStrLen; + pos = tString.FindCharInSet(specialChars, oldPos); + + if (pos != -1) + { + subStrLen = pos - oldPos; + // if first char is newline, then use just it + if (subStrLen == 0) + subStrLen = 1; + } + else + { + subStrLen = tString.Length() - oldPos; + pos = tString.Length(); + } + + nsDependentSubstring subStr(tString, oldPos, subStrLen); + + // is it a tab? + if (subStr.EqualsLiteral("\t")) + { + res = mEditor->InsertTextImpl(NS_LITERAL_STRING(" "), address_of(curNode), &curOffset, doc); + pos++; + } + // is it a return? + else if (subStr.EqualsLiteral(LFSTR)) + { + res = mEditor->CreateBRImpl(address_of(curNode), &curOffset, address_of(unused), nsIEditor::eNone); + pos++; + } + else + { + res = mEditor->InsertTextImpl(subStr, address_of(curNode), &curOffset, doc); + } + NS_ENSURE_SUCCESS(res, res); + } + } + outString->Assign(tString); if (curNode) { + aSelection->Collapse(curNode, curOffset); + // Make the caret attach to the inserted text, unless this text ends with a LF, // in which case make the caret attach to the next line. - PRBool endsWithLF = - !outString->IsEmpty() && outString->Last() == nsCRT::LF; + PRBool endsWithLF = !tString.IsEmpty() && tString.get()[tString.Length() - 1] == nsCRT::LF; nsCOMPtr<nsISelectionPrivate>selPrivate(do_QueryInterface(aSelection)); selPrivate->SetInterlinePosition(endsWithLF); - - // If the last character is a linefeed character, make sure that we inject - // a BR element for correct caret positioning. - if (endsWithLF) { - nsCOMPtr<nsIDOMNode> mozBR; - res = CreateMozBR(curNode, curOffset, address_of(mozBR)); - NS_ENSURE_SUCCESS(res, res); - curNode = mozBR; - curOffset = 0; - } - aSelection->Collapse(curNode, curOffset); } } ASSERT_PASSWORD_LENGTHS_EQUAL() @@ -1272,16 +1358,12 @@ nsresult nsTextEditRules::TruncateInsertionIfNeeded(nsISelection *aSelection, const nsAString *aInString, nsAString *aOutString, - PRInt32 aMaxLength, - PRBool *aTruncated) + PRInt32 aMaxLength) { if (!aSelection || !aInString || !aOutString) {return NS_ERROR_NULL_POINTER;} nsresult res = NS_OK; *aOutString = *aInString; - if (aTruncated) { - *aTruncated = PR_FALSE; - } if ((-1 != aMaxLength) && IsPlaintextEditor() && !mEditor->IsIMEComposing() ) { @@ -1314,9 +1396,6 @@ nsTextEditRules::TruncateInsertionIfNeeded(nsISelection *aSelection, if (resultingDocLength >= aMaxLength) { aOutString->Truncate(); - if (aTruncated) { - *aTruncated = PR_TRUE; - } } else { @@ -1324,9 +1403,6 @@ nsTextEditRules::TruncateInsertionIfNeeded(nsISelection *aSelection, if (inCount + resultingDocLength > aMaxLength) { aOutString->Truncate(aMaxLength - resultingDocLength); - if (aTruncated) { - *aTruncated = PR_TRUE; - } } } } diff --git a/editor/libeditor/text/nsTextEditRules.h b/editor/libeditor/text/nsTextEditRules.h index bd74bb44b624..ba1eadb4a5e6 100644 --- a/editor/libeditor/text/nsTextEditRules.h +++ b/editor/libeditor/text/nsTextEditRules.h @@ -160,8 +160,7 @@ protected: nsresult DidInsertText(nsISelection *aSelection, nsresult aResult); nsresult GetTopEnclosingPre(nsIDOMNode *aNode, nsIDOMNode** aOutPreNode); - nsresult WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, - PRBool *aHandled, PRInt32 aMaxLength); + nsresult WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, PRBool *aHandled); nsresult DidInsertBreak(nsISelection *aSelection, nsresult aResult); nsresult WillInsert(nsISelection *aSelection, PRBool *aCancel); @@ -219,8 +218,7 @@ protected: nsresult TruncateInsertionIfNeeded(nsISelection *aSelection, const nsAString *aInString, nsAString *aOutString, - PRInt32 aMaxLength, - PRBool *aTruncated); + PRInt32 aMaxLength); /** Remove IME composition text from password buffer */ nsresult RemoveIMETextFromPWBuf(PRUint32 &aStart, nsAString *aIMEString); @@ -235,8 +233,6 @@ protected: nsresult HideLastPWInput(); - nsresult CollapseSelectionToTrailingBRIfNeeded(nsISelection *aSelection); - PRBool IsPasswordEditor() const { return mEditor ? mEditor->IsPasswordEditor() : PR_FALSE; diff --git a/editor/libeditor/text/tests/Makefile.in b/editor/libeditor/text/tests/Makefile.in index ad7125d51628..98aa6f079400 100644 --- a/editor/libeditor/text/tests/Makefile.in +++ b/editor/libeditor/text/tests/Makefile.in @@ -47,7 +47,6 @@ include $(topsrcdir)/config/rules.mk _TEST_FILES = \ test_bug471722.html \ test_bug569988.html \ - test_bug590554.html \ $(NULL) # disables the key handling test on gtk2 because gtk2 overrides some key events diff --git a/editor/libeditor/text/tests/test_bug590554.html b/editor/libeditor/text/tests/test_bug590554.html deleted file mode 100644 index 9fdff7480de5..000000000000 --- a/editor/libeditor/text/tests/test_bug590554.html +++ /dev/null @@ -1,37 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=590554 ---> - -<head> - <title>Test for Bug 590554 - - - - - - - - - - - - - diff --git a/editor/libeditor/text/tests/test_texteditor_keyevent_handling.html b/editor/libeditor/text/tests/test_texteditor_keyevent_handling.html index 627ebd5bb290..1aa0d8ae0053 100644 --- a/editor/libeditor/text/tests/test_texteditor_keyevent_handling.html +++ b/editor/libeditor/text/tests/test_texteditor_keyevent_handling.html @@ -287,23 +287,13 @@ function runTests() synthesizeKey("VK_TAB", { }); check(aDescription + "Tab", true, true, !aIsTabbable && !aIsReadonly); - is(aElement.value, !aIsTabbable && !aIsReadonly ? "a\t" : "a", + // The tab char is converted to 4 space characters because textarea/input + // elements are not preformatted editor. + is(aElement.value, !aIsTabbable && !aIsReadonly ? "a " : "a", aDescription + "Tab"); is(fm.focusedElement, aElement, aDescription + "focus moved unexpectedly (Tab)"); - // If the editor is not tabbable, make sure that it accepts tab characters - // even if it's empty. - if (!aIsTabbable && !aIsReadonly) { - reset(""); - synthesizeKey("VK_TAB", {}); - check(aDescription + "Tab on empty textarea", - true, true, !aIsReadonly); - is(aElement.value, "\t", aDescription + "Tab on empty textarea"); - is(fm.focusedElement, aElement, - aDescription + "focus moved unexpectedly (Tab on empty textarea"); - } - reset("a"); synthesizeKey("VK_TAB", { shiftKey: true }); check(aDescription + "Shift+Tab", true, true, false); diff --git a/layout/base/tests/Makefile.in b/layout/base/tests/Makefile.in index 83fef4b7d4b2..ff72f1e331fd 100644 --- a/layout/base/tests/Makefile.in +++ b/layout/base/tests/Makefile.in @@ -92,9 +92,6 @@ _TEST_FILES = \ bug106855-1.html \ bug106855-2.html \ bug106855-1-ref.html \ - bug240933-1.html \ - bug240933-2.html \ - bug240933-1-ref.html \ bug482484.html \ bug482484-ref.html \ bug512295-1.html \ diff --git a/layout/base/tests/bug240933-1-ref.html b/layout/base/tests/bug240933-1-ref.html deleted file mode 100644 index c3aa0a57e9cd..000000000000 --- a/layout/base/tests/bug240933-1-ref.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/layout/base/tests/bug240933-1.html b/layout/base/tests/bug240933-1.html deleted file mode 100644 index c64ea3ac4a59..000000000000 --- a/layout/base/tests/bug240933-1.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - diff --git a/layout/base/tests/bug240933-2.html b/layout/base/tests/bug240933-2.html deleted file mode 100644 index 789b28542581..000000000000 --- a/layout/base/tests/bug240933-2.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - diff --git a/layout/base/tests/test_reftests_with_caret.html b/layout/base/tests/test_reftests_with_caret.html index 2b54805ebbd5..e129684ebbc7 100644 --- a/layout/base/tests/test_reftests_with_caret.html +++ b/layout/base/tests/test_reftests_with_caret.html @@ -88,8 +88,6 @@ function endTest() { var tests = [ [ 'bug106855-1.html' , 'bug106855-1-ref.html' ] , [ 'bug106855-2.html' , 'bug106855-1-ref.html' ] , - [ 'bug240933-1.html' , 'bug240933-1-ref.html' ] , - [ 'bug240933-2.html' , 'bug240933-1-ref.html' ] , [ 'bug482484.html' , 'bug482484-ref.html' ] , [ 'bug512295-1.html' , 'bug512295-1-ref.html' ] , [ 'bug512295-2.html' , 'bug512295-2-ref.html' ] , diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index db7a72a590fa..2dac683f0622 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -998,27 +998,51 @@ nsTextControlFrame::DOMPointToOffset(nsIDOMNode* aNode, if (!length || aNodeOffset < 0) return NS_OK; - NS_ASSERTION(length <= 2, "We should have one text node and one mozBR at most"); + PRInt32 i, textOffset = 0; + PRInt32 lastIndex = (PRInt32)length - 1; - nsCOMPtr firstNode; - rv = nodeList->Item(0, getter_AddRefs(firstNode)); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr textNode = do_QueryInterface(firstNode); + for (i = 0; i < (PRInt32)length; i++) { + if (rootNode == aNode && i == aNodeOffset) { + *aResult = textOffset; + return NS_OK; + } - nsCOMPtr nodeAsText = do_QueryInterface(aNode); - if (nodeAsText || (aNode == rootNode && aNodeOffset == 0)) { - // Selection is somewhere inside the text node; the offset is aNodeOffset - *aResult = aNodeOffset; - } else { - // Selection is on the mozBR node, so offset should be set to the length - // of the text node. - if (textNode) { - rv = textNode->GetLength(&length); + nsCOMPtr item; + rv = nodeList->Item(i, getter_AddRefs(item)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(item, NS_ERROR_FAILURE); + + nsCOMPtr domText(do_QueryInterface(item)); + + if (domText) { + PRUint32 textLength = 0; + + rv = domText->GetLength(&textLength); NS_ENSURE_SUCCESS(rv, rv); - *aResult = PRInt32(length); + + if (item == aNode) { + NS_ASSERTION((aNodeOffset >= 0 && aNodeOffset <= (PRInt32)textLength), + "Invalid aNodeOffset!"); + *aResult = textOffset + aNodeOffset; + return NS_OK; + } + + textOffset += textLength; + } + else { + // Must be a BR node. If it's not the last BR node + // under the root, count it as a newline. + + if (i != lastIndex) + ++textOffset; } } + NS_ASSERTION((aNode == rootNode && aNodeOffset == (PRInt32)length), + "Invalid node offset!"); + + *aResult = textOffset; + return NS_OK; } @@ -1050,25 +1074,71 @@ nsTextControlFrame::OffsetToDOMPoint(PRInt32 aOffset, rv = nodeList->GetLength(&length); NS_ENSURE_SUCCESS(rv, rv); - NS_ASSERTION(length <= 2, "We should have one text node and one mozBR at most"); - - nsCOMPtr firstNode; - rv = nodeList->Item(0, getter_AddRefs(firstNode)); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr textNode = do_QueryInterface(firstNode); - - if (length == 0 || aOffset < 0) { - NS_IF_ADDREF(*aResult = rootNode); - *aPosition = 0; - } else if (textNode) { - NS_IF_ADDREF(*aResult = firstNode); - *aPosition = aOffset; - } else { - NS_IF_ADDREF(*aResult = rootNode); + if (!length || aOffset < 0) { *aPosition = 0; + *aResult = rootNode; + NS_ADDREF(*aResult); + return NS_OK; } - return NS_OK; + PRInt32 textOffset = 0; + PRUint32 lastIndex = length - 1; + + for (PRUint32 i=0; i item; + rv = nodeList->Item(i, getter_AddRefs(item)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(item, NS_ERROR_FAILURE); + + nsCOMPtr domText(do_QueryInterface(item)); + + if (domText) { + PRUint32 textLength = 0; + + rv = domText->GetLength(&textLength); + NS_ENSURE_SUCCESS(rv, rv); + + // Check if aOffset falls within this range. + if (aOffset >= textOffset && aOffset <= textOffset+(PRInt32)textLength) { + *aPosition = aOffset - textOffset; + *aResult = item; + NS_ADDREF(*aResult); + return NS_OK; + } + + textOffset += textLength; + + // If there aren't any more siblings after this text node, + // return the point at the end of this text node! + + if (i == lastIndex) { + *aPosition = textLength; + *aResult = item; + NS_ADDREF(*aResult); + return NS_OK; + } + } + else { + // Must be a BR node, count it as a newline. + + if (aOffset == textOffset || i == lastIndex) { + // We've found the correct position, or aOffset takes us + // beyond the last child under rootNode, just return the point + // under rootNode that is in front of this br. + + *aPosition = i; + *aResult = rootNode; + NS_ADDREF(*aResult); + return NS_OK; + } + + ++textOffset; + } + } + + NS_ERROR("We should never get here!"); + + return NS_ERROR_FAILURE; } NS_IMETHODIMP diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index b5bb78d707d8..4d073ef6cfe7 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -5219,7 +5219,6 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct* aPos) { PRBool eatingNonRenderableWS = PR_FALSE; PRBool done = PR_FALSE; - PRBool jumpedLine = PR_FALSE; while (!done) { PRBool movingInFrameDirection = @@ -5231,6 +5230,7 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct* aPos) done = current->PeekOffsetCharacter(movingInFrameDirection, &offset); if (!done) { + PRBool jumpedLine; result = current->GetFrameFromDirection(aPos->mDirection, aPos->mVisual, aPos->mJumpLines, aPos->mScrollViewStop, @@ -5251,15 +5251,6 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct* aPos) aPos->mResultContent = range.content; // Output offset is relative to content, not frame aPos->mContentOffset = offset < 0 ? range.end : range.start + offset; - // If we're dealing with a text frame and moving backward positions us at - // the end of that line, decrease the offset by one to make sure that - // we're placed before the linefeed character on the previous line. - if (offset < 0 && jumpedLine && - aPos->mDirection == eDirPrevious && - current->GetStyleText()->NewlineIsSignificant() && - current->HasTerminalNewline()) { - --aPos->mContentOffset; - } break; } diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 98b92b1cb12a..4ae237585904 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -1635,14 +1635,6 @@ public: PRUint32 aSkippedMaxLength = PR_UINT32_MAX) { return NS_ERROR_NOT_IMPLEMENTED; } - /** - * Returns true if the frame contains any non-collapsed characters. - * This method is only available for text frames, and it will return false - * for all other frame types. - */ - virtual PRBool HasAnyNoncollapsedCharacters() - { return PR_FALSE; } - /** * Accessor functions to get/set the associated view object * diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index acd26537791a..e2275096490b 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -460,8 +460,6 @@ protected: PRBool aForInsertionPoint); void ClearFrameOffsetCache(); - - virtual PRBool HasAnyNoncollapsedCharacters(); }; #endif diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 8dd3924c0d37..7f698d207d94 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -5062,13 +5062,6 @@ nsTextFrame::GetCharacterOffsetAtFramePointInternal(const nsPoint &aPoint, // intrinsic widths. selectedOffset = provider.GetStart().GetOriginalOffset() + provider.GetOriginalLength(); - // If we're at the end of a preformatted line which has a terminating - // linefeed, we want to reduce the offset by one to make sure that the - // selection is placed before the linefeed character. - if (GetStyleText()->NewlineIsSignificant() && - HasTerminalNewline()) { - --selectedOffset; - } } offsets.content = GetContent(); @@ -5432,7 +5425,8 @@ IsAcceptableCaretPosition(const gfxSkipCharsIterator& aIter, gfxTextRun* aTextRu PRUint32 index = aIter.GetSkippedOffset(); if (!aTextRun->IsClusterStart(index)) return PR_FALSE; - return PR_TRUE; + return !(aFrame->GetStyleText()->NewlineIsSignificant() && + aTextRun->GetChar(index) == '\n'); } PRBool @@ -5457,8 +5451,8 @@ nsTextFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset) PRInt32 startOffset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset); if (!aForward) { - // If at the beginning of the line, look at the previous continuation - for (PRInt32 i = NS_MIN(trimmed.GetEnd(), startOffset) - 1; + PRInt32 i; + for (i = NS_MIN(trimmed.GetEnd(), startOffset) - 1; i >= trimmed.mStart; --i) { iter.SetOriginalOffset(i); if (IsAcceptableCaretPosition(iter, mTextRun, this)) { @@ -5468,19 +5462,16 @@ nsTextFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset) } *aOffset = 0; } else { - // If we're at the end of a line, look at the next continuation - iter.SetOriginalOffset(startOffset); - if (iter.GetSkippedOffset() <= PRUint32(trimmed.GetEnd()) && - !(iter.GetSkippedOffset() < PRUint32(trimmed.GetEnd()) && - GetStyleText()->NewlineIsSignificant() && - mTextRun->GetChar(iter.GetSkippedOffset()) == '\n')) { - for (PRInt32 i = startOffset + 1; i <= trimmed.GetEnd(); ++i) { - iter.SetOriginalOffset(i); - if (i == trimmed.GetEnd() || - IsAcceptableCaretPosition(iter, mTextRun, this)) { - *aOffset = i - mContentOffset; - return PR_TRUE; - } + PRInt32 i; + for (i = startOffset + 1; i <= trimmed.GetEnd(); ++i) { + iter.SetOriginalOffset(i); + // XXX we can't necessarily stop at the end of this frame, + // but we really have no choice right now. We need to do a deeper + // fix/restructuring of PeekOffsetCharacter + if (i == trimmed.GetEnd() || + IsAcceptableCaretPosition(iter, mTextRun, this)) { + *aOffset = i - mContentOffset; + return PR_TRUE; } } *aOffset = contentLength; @@ -7131,14 +7122,3 @@ nsTextFrame::IsAtEndOfLine() const { return (GetStateBits() & TEXT_END_OF_LINE) != 0; } - -PRBool -nsTextFrame::HasAnyNoncollapsedCharacters() -{ - gfxSkipCharsIterator iter = EnsureTextRun(); - PRInt32 offset = GetContentOffset(), - offsetEnd = GetContentEnd(); - PRInt32 skippedOffset = iter.ConvertOriginalToSkipped(offset); - PRInt32 skippedOffsetEnd = iter.ConvertOriginalToSkipped(offsetEnd); - return skippedOffset != skippedOffsetEnd; -} diff --git a/layout/generic/test/Makefile.in b/layout/generic/test/Makefile.in index 44e456b47658..2b0dc6c5fe11 100644 --- a/layout/generic/test/Makefile.in +++ b/layout/generic/test/Makefile.in @@ -58,7 +58,6 @@ _TEST_FILES = \ plugin_clipping_lib.js \ plugin_focus_helper.html \ test_backspace_delete.xul \ - test_bug240933.html \ test_bug263683.html \ test_bug288789.html \ test_bug290397.html \ diff --git a/layout/generic/test/test_bug240933.html b/layout/generic/test/test_bug240933.html deleted file mode 100644 index e8d7ffde9d94..000000000000 --- a/layout/generic/test/test_bug240933.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - Test for Bug 240933 - - - - - - - - - Mozilla Bug 240933 - -

- - -
-    
-  
- - - - - - - diff --git a/layout/generic/test/test_bug288789.html b/layout/generic/test/test_bug288789.html index e21f2d4ee722..5e2f15f6272c 100644 --- a/layout/generic/test/test_bug288789.html +++ b/layout/generic/test/test_bug288789.html @@ -18,11 +18,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=288789 אaב - -
@@ -55,59 +50,9 @@ function test() {
 
   textarea.focus();
   collapse(0);
-  ok(true, "Testing forward movement in RTL mode");
-  for (var i = 0; i < textarea.textContent.length; ++i) {
-    if (i == 0) {
-      testRight(i);
-    }
-    if (textarea.textContent[i] == 'a') {
-      testLeft(i);
-    } else {
-      testLeft(i + 1);
-    }
-    if (i == textarea.textContent.length - 1) {
-      testLeft(i + 1);
-    }
-  }
-  ok(true, "Testing backward movement in RTL mode");
-  for (var i = textarea.textContent.length; i > 0; --i) {
-    if (i == textarea.textContent.length) {
-      testLeft(i);
-    }
-    if (i > 0 && textarea.textContent[i - 1] == 'a') {
-      testRight(i);
-    } else {
-      testRight(i - 1);
-    }
-    if (i == 1) {
-      testRight(i - 1);
-    }
-  }
-
-  textarea = $("tb");
-  textarea.focus();
-  collapse(0);
-  ok(true, "Testing forward movement in LTR mode");
-  for (var i = 0; i < textarea.textContent.length; ++i) {
-    if (i == 0) {
-      testLeft(i);
-    }
-    testRight(i + 1);
-    if (i == textarea.textContent.length - 1) {
-      testRight(i + 1);
-    }
-  }
-  ok(true, "Testing backward movement in LTR mode");
-  for (var i = textarea.textContent.length; i > 0; --i) {
-    if (i == textarea.textContent.length) {
-      testRight(i);
-    }
-    testLeft(i - 1);
-    if (i == 1) {
-      testLeft(i - 1);
-    }
-  }
-
+  testLeft(1);
+  collapse(5);
+  testRight(4);
   SimpleTest.finish();
 }
 
diff --git a/layout/generic/test/test_movement_by_characters.html b/layout/generic/test/test_movement_by_characters.html
index 61fff0865e08..b8a0c4f616eb 100644
--- a/layout/generic/test/test_movement_by_characters.html
+++ b/layout/generic/test/test_movement_by_characters.html
@@ -68,13 +68,13 @@ function test() {
   editor.innerHTML = "
aa\nbb
"; sel.collapse(editor.firstChild.firstChild, 0); testRight(editor.firstChild.firstChild, 1); - // at the end of the first line, before the \n - testRight(editor.firstChild.firstChild, 2); + // at the 'bb' but HINTLEFT so appears at the end of the first line + testRight(editor.firstChild.firstChild, 3); testRight(editor.firstChild.firstChild, 3); testRight(editor.firstChild.firstChild, 4); testLeft(editor.firstChild.firstChild, 3); - // at the end of the first line, before the \n - testLeft(editor.firstChild.firstChild, 2); + // at the 'bb' but HINTLEFT so appears at the end of the first line + testLeft(editor.firstChild.firstChild, 3); testLeft(editor.firstChild.firstChild, 1); testLeft(editor.firstChild.firstChild, 0); diff --git a/layout/reftests/bugs/240933-1-ref.html b/layout/reftests/bugs/240933-1-ref.html deleted file mode 100644 index 0d727af3a286..000000000000 --- a/layout/reftests/bugs/240933-1-ref.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - -
-
- - - - diff --git a/layout/reftests/bugs/240933-1.html b/layout/reftests/bugs/240933-1.html deleted file mode 100644 index e180c5f484de..000000000000 --- a/layout/reftests/bugs/240933-1.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - -
6
-
6
- - - diff --git a/layout/reftests/bugs/240933-2-ref.html b/layout/reftests/bugs/240933-2-ref.html deleted file mode 100644 index 7dbc082a58a5..000000000000 --- a/layout/reftests/bugs/240933-2-ref.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - -
-
- - - - diff --git a/layout/reftests/bugs/240933-2.html b/layout/reftests/bugs/240933-2.html deleted file mode 100644 index 0fb9b9d5069c..000000000000 --- a/layout/reftests/bugs/240933-2.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - -
3
-
3
- - - diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 204fe7060443..19987537fe57 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -205,8 +205,6 @@ random == 99850-1b.html 99850-1-ref.html # bug 471629 == 236539-1.html 236539-1-ref.html == 240029-1.html 240029-1-ref.html == 240470-1.html 240470-1-ref.html -== 240933-1.html 240933-1-ref.html -== 240933-2.html 240933-2-ref.html == 243266-1.html 243266-1-ref.html == 243302-1.html 243302-1-ref.html == 243519-1.html 243519-1-ref.html diff --git a/layout/reftests/editor/caret_on_textarea_lastline-ref.html b/layout/reftests/editor/caret_on_textarea_lastline-ref.html deleted file mode 100644 index 6acd3d9b90e7..000000000000 --- a/layout/reftests/editor/caret_on_textarea_lastline-ref.html +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/layout/reftests/editor/caret_on_textarea_lastline.html b/layout/reftests/editor/caret_on_textarea_lastline.html deleted file mode 100644 index 35973aa82858..000000000000 --- a/layout/reftests/editor/caret_on_textarea_lastline.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - diff --git a/layout/reftests/editor/reftest.list b/layout/reftests/editor/reftest.list index f95fdeaacbc4..8a65c717a1f2 100644 --- a/layout/reftests/editor/reftest.list +++ b/layout/reftests/editor/reftest.list @@ -18,4 +18,3 @@ include xul/reftest.list == emptypasswd-2.html emptypasswd-ref.html == caret_on_positioned.html caret_on_positioned-ref.html == spellcheck-1.html spellcheck-ref.html -!= caret_on_textarea_lastline.html caret_on_textarea_lastline-ref.html From 3313bd2660158cff224e120fee2bd8ce57f1d947 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Fri, 3 Sep 2010 12:03:03 +1200 Subject: [PATCH 070/222] Bug 485288 - Update media load algorithm. r=roc a=blocking2.0 --- .../html/content/public/nsHTMLMediaElement.h | 75 +++-- .../html/content/src/nsHTMLMediaElement.cpp | 315 +++++++++++------- content/media/nsBuiltinDecoder.cpp | 6 +- content/media/test/test_constants.html | 27 +- content/media/test/test_decode_error.html | 3 +- content/media/test/test_decoder_disable.html | 30 +- content/media/test/test_info_leak.html | 9 +- content/media/test/test_load.html | 9 +- content/media/test/test_load_candidates.html | 8 +- content/media/test/test_preload_actions.html | 39 ++- content/media/test/test_source_write.html | 4 +- content/media/wave/nsWaveDecoder.cpp | 7 +- .../html/nsIDOMHTMLMediaElement.idl | 5 +- parser/html/nsHtml5TreeBuilderCppSupplement.h | 4 +- widget/public/nsIAppShell.idl | 14 +- widget/src/xpwidgets/nsBaseAppShell.cpp | 37 ++ widget/src/xpwidgets/nsBaseAppShell.h | 7 + 17 files changed, 373 insertions(+), 226 deletions(-) diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h index 1fae80cafc0a..ee8b34000511 100644 --- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -117,9 +117,6 @@ public: virtual void UnbindFromTree(PRBool aDeep = PR_TRUE, PRBool aNullParent = PR_TRUE); - virtual PRBool IsDoneAddingChildren(); - virtual nsresult DoneAddingChildren(PRBool aHaveNotified); - /** * Call this to reevaluate whether we should start/stop due to our owner * document being active or inactive. @@ -149,6 +146,10 @@ public: // resource has a decode error during metadata loading or decoding. void DecodeError(); + // Called by the video decoder object, on the main thread, when the + // resource load has been cancelled. + void LoadAborted(); + // Called by the video decoder object, on the main thread, // when the video playback has ended. void PlaybackEnded(); @@ -280,7 +281,7 @@ public: /** * Called when a child source element is added to this media element. This - * may queue a load() task if appropriate. + * may queue a task to run the select resource algorithm if appropriate. */ void NotifyAddedSource(); @@ -333,8 +334,6 @@ public: protected: class MediaLoadListener; - class LoadNextSourceEvent; - class SelectResourceEvent; /** * Changes mHasPlayedOrSeeked to aValue. If mHasPlayedOrSeeked changes @@ -388,23 +387,25 @@ protected: /** * Attempts to load resources from the children. This is a - * substep of the media selection algorith. Do not call this directly, + * substep of the resource selection algorithm. Do not call this directly, * call QueueLoadFromSourceTask() instead. */ void LoadFromSourceChildren(); /** - * Sends an async event to call LoadFromSourceChildren(). + * Asynchronously awaits a stable state, and then causes + * LoadFromSourceChildren() to be called on the main threads' event loop. */ void QueueLoadFromSourceTask(); /** - * Media selection algorithm. + * Runs the media resource selection algorithm. */ void SelectResource(); /** - * Sends an async event to call SelectResource(). + * Asynchronously awaits a stable state, and then causes SelectResource() + * to be run on the main thread's event loop. */ void QueueSelectResourceTask(); @@ -415,9 +416,10 @@ protected: /** * Selects the next child from which to load a resource. Called - * during the media selection algorithm. + * during the resource selection algorithm. Stores the return value in + * mSourceLoadCandidate before returning. */ - already_AddRefed GetNextSource(); + nsIContent* GetNextSource(); /** * Changes mDelayingLoadEvent, and will call BlockOnLoad()/UnblockOnLoad() @@ -493,6 +495,17 @@ protected: */ void UpdatePreloadAction(); + /** + * Dispatches an error event to a child source element. + */ + void DispatchAsyncSourceError(nsIContent* aSourceElement); + + /** + * Resets the media element for an error condition as per aErrorCode. + * aErrorCode must be one of nsIDOMHTMLMediaError codes. + */ + void Error(PRUint16 aErrorCode); + nsRefPtr mDecoder; // A reference to the ImageContainer which contains the current frame @@ -527,18 +540,19 @@ protected: nsMediaReadyState mReadyState; enum LoadAlgorithmState { - // Not waiting for any src/. + // No load algorithm instance is waiting for a source to be added to the + // media in order to continue loading. NOT_WAITING, - // No src or children, load is waiting at load algorithm step 1. - WAITING_FOR_SRC_OR_SOURCE, - // No src at load time, and all children don't resolve or - // give network errors during fetch, waiting for more children - // to be added. + // We've run the load algorithm, and we tried all source children of the + // media element, and failed to load any successfully. We're waiting for + // another source element to be added to the media element, and will try + // to load any such element when its added. WAITING_FOR_SOURCE }; - // When the load algorithm is waiting for more src/, this denotes - // what type of waiting we're doing. + // Denotes the waiting state of a load algorithm instance. When the load + // algorithm is waiting for a source element child to be added, this is set + // to WAITING_FOR_SOURCE, otherwise it's NOT_WAITING. LoadAlgorithmState mLoadWaitStatus; // Current audio volume @@ -550,11 +564,12 @@ protected: // Current audio sample rate. PRUint32 mRate; - // If we're loading a preload:none media, we'll record the URI we're - // attempting to load in mPreloadURI, and delay loading the resource until - // the user initiates a load by either playing the resource, or explicitly - // loading it. - nsCOMPtr mPreloadURI; + // URI of the resource we're attempting to load. When the decoder is + // successfully initialized, we rely on it to record the URI we're playing, + // and clear mLoadingSrc. This stores the value we return in the currentSrc + // attribute until the decoder is initialized. Use GetCurrentSrc() to access + // the currentSrc attribute. + nsCOMPtr mLoadingSrc; // Stores the current preload action for this element. Initially set to // PRELOAD_UNDEFINED, its value is changed by calling @@ -562,11 +577,15 @@ protected: PreloadAction mPreloadAction; // Size of the media. Updated by the decoder on the main thread if - // it changes. Defaults to a width and height of -1 if not set. + // it changes. Defaults to a width and height of -1 inot set. nsIntSize mMediaSize; nsRefPtr mPrintSurface; + // Reference to the source element last returned by GetNextSource(). + // This is the child source element which we're trying to load from. + nsCOMPtr mSourceLoadCandidate; + // An audio stream for writing audio directly from JS. nsAutoPtr mAudioStream; @@ -604,10 +623,6 @@ protected: // True if the sound is muted PRPackedBool mMuted; - // Flag to indicate if the child elements (eg. ) have been - // parsed. - PRPackedBool mIsDoneAddingChildren; - // If TRUE then the media element was actively playing before the currently // in progress seeking. If FALSE then the media element is either not seeking // or was not actively playing before the current seek. Used to decide whether diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index 6289ffaf392e..782a548ba622 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -57,6 +57,7 @@ #include "nsXPCOMStrings.h" #include "prlock.h" #include "nsThreadUtils.h" +#include "nsIThreadInternal.h" #include "nsContentUtils.h" #include "nsFrameManager.h" @@ -88,6 +89,8 @@ #include #include "nsIDocShellTreeItem.h" #include "nsIAsyncVerifyRedirectCallback.h" +#include "nsIAppShell.h" +#include "nsWidgetsCID.h" #include "nsIPrivateDOMEvent.h" #include "nsIDOMNotifyAudioAvailableEvent.h" @@ -209,50 +212,31 @@ public: } }; -class nsHTMLMediaElement::LoadNextSourceEvent : public nsMediaEvent { +class nsSourceErrorEventRunner : public nsMediaEvent +{ +private: + nsCOMPtr mSource; public: - LoadNextSourceEvent(nsHTMLMediaElement *aElement) - : nsMediaEvent(aElement) {} + nsSourceErrorEventRunner(nsHTMLMediaElement* aElement, + nsIContent* aSource) + : nsMediaEvent(aElement), + mSource(aSource) + { + } + NS_IMETHOD Run() { - if (!IsCancelled()) - mElement->LoadFromSourceChildren(); - return NS_OK; + // Silently cancel if our load has been cancelled. + if (IsCancelled()) + return NS_OK; + LOG_EVENT(PR_LOG_DEBUG, ("%p Dispatching simple event source error", mElement.get())); + return nsContentUtils::DispatchTrustedEvent(mElement->GetOwnerDoc(), + mSource, + NS_LITERAL_STRING("error"), + PR_TRUE, + PR_TRUE); } }; -class nsHTMLMediaElement::SelectResourceEvent : public nsMediaEvent { -public: - SelectResourceEvent(nsHTMLMediaElement *aElement) - : nsMediaEvent(aElement) {} - NS_IMETHOD Run() { - if (!IsCancelled()) { - NS_ASSERTION(mElement->mIsRunningSelectResource, - "Should have flagged that we're running SelectResource()"); - mElement->SelectResource(); - mElement->mIsRunningSelectResource = PR_FALSE; - } - return NS_OK; - } -}; - -void nsHTMLMediaElement::QueueSelectResourceTask() -{ - // Don't allow multiple async select resource calls to be queued. - if (mIsRunningSelectResource) - return; - mIsRunningSelectResource = PR_TRUE; - ChangeDelayLoadStatus(PR_TRUE); - nsCOMPtr event = new SelectResourceEvent(this); - NS_DispatchToMainThread(event); -} - -void nsHTMLMediaElement::QueueLoadFromSourceTask() -{ - ChangeDelayLoadStatus(PR_TRUE); - nsCOMPtr event = new LoadNextSourceEvent(this); - NS_DispatchToMainThread(event); -} - /** * There is a reference cycle involving this class: MediaLoadListener * holds a reference to the nsHTMLMediaElement, which holds a reference @@ -441,6 +425,8 @@ NS_IMETHODIMP nsHTMLMediaElement::GetCurrentSrc(nsAString & aCurrentSrc) if (stream) { stream->URI()->GetSpec(src); } + } else if (mLoadingSrc) { + mLoadingSrc->GetSpec(src); } aCurrentSrc = NS_ConvertUTF8toUTF16(src); @@ -504,7 +490,6 @@ void nsHTMLMediaElement::AbortExistingLoads() if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING || mNetworkState == nsIDOMHTMLMediaElement::NETWORK_IDLE) { - mError = new nsMediaError(nsIDOMMediaError::MEDIA_ERR_ABORTED); DispatchProgressEvent(NS_LITERAL_STRING("abort")); } @@ -551,6 +536,62 @@ void nsHTMLMediaElement::NoSupportedMediaSourceError() ChangeDelayLoadStatus(PR_FALSE); } +typedef void (nsHTMLMediaElement::*SyncSectionFn)(); + +// Runs a "synchronous section", a function that must run once the event loop +// has reached a "stable state". See: +// http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#synchronous-section +class nsSyncSection : public nsMediaEvent +{ +private: + SyncSectionFn mClosure; +public: + nsSyncSection(nsHTMLMediaElement* aElement, + SyncSectionFn aClosure) : + nsMediaEvent(aElement), + mClosure(aClosure) + { + } + + NS_IMETHOD Run() { + // Silently cancel if our load has been cancelled. + if (IsCancelled()) + return NS_OK; + (mElement.get()->*mClosure)(); + return NS_OK; + } +}; + +static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); + +// Asynchronously awaits a stable state, whereupon aClosure runs on the main +// thread. This adds an event which run aClosure to the appshell's list of +// sections synchronous the next time control returns to the event loop. +void AsyncAwaitStableState(nsHTMLMediaElement* aElement, + SyncSectionFn aClosure) +{ + nsCOMPtr event = new nsSyncSection(aElement, aClosure); + nsCOMPtr appShell = do_GetService(kAppShellCID); + appShell->RunInStableState(event); +} + +void nsHTMLMediaElement::QueueLoadFromSourceTask() +{ + ChangeDelayLoadStatus(PR_TRUE); + mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING; + AsyncAwaitStableState(this, &nsHTMLMediaElement::LoadFromSourceChildren); +} + +void nsHTMLMediaElement::QueueSelectResourceTask() +{ + // Don't allow multiple async select resource calls to be queued. + if (mIsRunningSelectResource) + return; + mIsRunningSelectResource = PR_TRUE; + mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE; + AsyncAwaitStableState(this, &nsHTMLMediaElement::SelectResource); +} + /* void load (); */ NS_IMETHODIMP nsHTMLMediaElement::Load() { @@ -591,18 +632,20 @@ static PRBool HasPotentialResource(nsIContent *aElement) void nsHTMLMediaElement::SelectResource() { - NS_ASSERTION(mDelayingLoadEvent, "Load event not delayed during resource selection?"); - + NS_ASSERTION(!mDelayingLoadEvent, + "Load event should not be delayed at start of resource selection."); if (!HasPotentialResource(this)) { - // While the media element has neither a src attribute nor any source - // element children, wait. (This steps might wait forever.) - mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE; - mLoadWaitStatus = WAITING_FOR_SRC_OR_SOURCE; + // The media element has neither a src attribute nor any source + // element children, abort the load. + mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY; // This clears mDelayingLoadEvent, so AddRemoveSelfReference will be called ChangeDelayLoadStatus(PR_FALSE); + mIsRunningSelectResource = PR_FALSE; return; } + ChangeDelayLoadStatus(PR_TRUE); + mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING; // Load event was delayed, and still is, so no need to call // AddRemoveSelfReference, since it must still be held @@ -617,29 +660,37 @@ void nsHTMLMediaElement::SelectResource() if (NS_SUCCEEDED(rv)) { LOG(PR_LOG_DEBUG, ("%p Trying load from src=%s", this, NS_ConvertUTF16toUTF8(src).get())); mIsLoadingFromSrcAttribute = PR_TRUE; + mLoadingSrc = uri; if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) { // preload:none media, suspend the load here before we make any // network requests. SuspendLoad(uri); + mIsRunningSelectResource = PR_FALSE; return; } rv = LoadResource(uri); - if (NS_SUCCEEDED(rv)) + if (NS_SUCCEEDED(rv)) { + mIsRunningSelectResource = PR_FALSE; return; + } } NoSupportedMediaSourceError(); } else { // Otherwise, the source elements will be used. LoadFromSourceChildren(); } + mIsRunningSelectResource = PR_FALSE; } void nsHTMLMediaElement::NotifyLoadError() { if (mIsLoadingFromSrcAttribute) { + LOG(PR_LOG_DEBUG, ("NotifyLoadError(), no supported media error")); NoSupportedMediaSourceError(); } else { + NS_ASSERTION(mSourceLoadCandidate, "Must know the source we were loading from!"); + DispatchAsyncSourceError(mSourceLoadCandidate); QueueLoadFromSourceTask(); } } @@ -682,18 +733,47 @@ void nsHTMLMediaElement::LoadFromSourceChildren() { NS_ASSERTION(mDelayingLoadEvent, "Should delay load event (if in document) during load"); + NS_ASSERTION(!mIsLoadingFromSrcAttribute, + "Must remember we're loading from source children"); while (PR_TRUE) { nsresult rv; - nsCOMPtr uri = GetNextSource(); - if (!uri) { + nsIContent* child = GetNextSource(); + if (!child) { // Exhausted candidates, wait for more candidates to be appended to // the media element. mLoadWaitStatus = WAITING_FOR_SOURCE; - NoSupportedMediaSourceError(); + mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE; + ChangeDelayLoadStatus(PR_FALSE); return; } - mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING; + nsCOMPtr uri; + nsAutoString src,type; + + // Must have src attribute. + if (!child->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) { + DispatchAsyncSourceError(child); + continue; + } + + // If we have a type attribute, it must be a supported type. + if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type) && + GetCanPlay(type) == CANPLAY_NO) + { + DispatchAsyncSourceError(child); + continue; + } + LOG(PR_LOG_DEBUG, ("%p Trying load from =%s type=%s", this, + NS_ConvertUTF16toUTF8(src).get(), NS_ConvertUTF16toUTF8(type).get())); + NewURIFromString(src, getter_AddRefs(uri)); + if (!uri) { + DispatchAsyncSourceError(child); + continue; + } + + mLoadingSrc = uri; + NS_ASSERTION(mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING, + "Network state should be loading"); if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) { // preload:none media, suspend the load here before we make any @@ -707,6 +787,7 @@ void nsHTMLMediaElement::LoadFromSourceChildren() return; // If we fail to load, loop back and try loading the next resource. + DispatchAsyncSourceError(child); } NS_NOTREACHED("Execution should not reach here!"); } @@ -714,7 +795,6 @@ void nsHTMLMediaElement::LoadFromSourceChildren() void nsHTMLMediaElement::SuspendLoad(nsIURI* aURI) { mLoadIsSuspended = PR_TRUE; - mPreloadURI = aURI; mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE; DispatchAsyncProgressEvent(NS_LITERAL_STRING("suspend")); ChangeDelayLoadStatus(PR_FALSE); @@ -723,9 +803,8 @@ void nsHTMLMediaElement::SuspendLoad(nsIURI* aURI) void nsHTMLMediaElement::ResumeLoad(PreloadAction aAction) { NS_ASSERTION(mLoadIsSuspended, "Can only resume preload if halted for one"); - nsCOMPtr uri = mPreloadURI; + nsCOMPtr uri = mLoadingSrc; mLoadIsSuspended = PR_FALSE; - mPreloadURI = nsnull; mPreloadAction = aAction; ChangeDelayLoadStatus(PR_TRUE); mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING; @@ -1063,6 +1142,7 @@ NS_IMETHODIMP nsHTMLMediaElement::GetPaused(PRBool *aPaused) NS_IMETHODIMP nsHTMLMediaElement::Pause() { if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) { + LOG(PR_LOG_DEBUG, ("Loading due to Pause()")); nsresult rv = Load(); NS_ENSURE_SUCCESS(rv, rv); } else if (mDecoder) { @@ -1200,7 +1280,6 @@ nsHTMLMediaElement::nsHTMLMediaElement(already_AddRefed aNodeInfo, mAutoplayEnabled(PR_TRUE), mPaused(PR_TRUE), mMuted(PR_FALSE), - mIsDoneAddingChildren(!aFromParser), mPlayingBeforeSeek(PR_FALSE), mPausedForInactiveDocument(PR_FALSE), mWaitingFired(PR_FALSE), @@ -1369,16 +1448,11 @@ nsresult nsHTMLMediaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, aNotify); if (NS_FAILED(rv)) return rv; + if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) { + Load(); + } if (aNotify && aNameSpaceID == kNameSpaceID_None) { - if (aName == nsGkAtoms::src) { - if (mLoadWaitStatus == WAITING_FOR_SRC_OR_SOURCE) { - // A previous load algorithm instance is waiting on a src - // addition, resume the load. It is waiting at "step 1 of the load - // algorithm". - mLoadWaitStatus = NOT_WAITING; - QueueSelectResourceTask(); - } - } else if (aName == nsGkAtoms::autoplay) { + if (aName == nsGkAtoms::autoplay) { StopSuspendingAfterFirstFrame(); if (mReadyState == nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) { NotifyAutoplayDataReady(); @@ -1429,15 +1503,6 @@ nsresult nsHTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aPar aParent, aBindingParent, aCompileEventHandlers); - if (aDocument) { - if (NS_SUCCEEDED(rv) && - mIsDoneAddingChildren && - mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) - { - QueueSelectResourceTask(); - } - } - mIsBindingToTree = PR_FALSE; return rv; @@ -1813,6 +1878,9 @@ nsresult nsHTMLMediaElement::FinishDecoderSetup(nsMediaDecoder* aDecoder) { mDecoder = aDecoder; + // Decoder has assumed ownership responsibility for remembering the URI. + mLoadingSrc = nsnull; + // Force a same-origin check before allowing events for this media resource. mMediaSecurityVerified = PR_FALSE; @@ -1902,29 +1970,43 @@ void nsHTMLMediaElement::ResourceLoaded() mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE; AddRemoveSelfReference(); ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA); - // The download has stopped + // Ensure a progress event is dispatched at the end of download. + DispatchAsyncProgressEvent(NS_LITERAL_STRING("progress")); + // The download has stopped. DispatchAsyncSimpleEvent(NS_LITERAL_STRING("suspend")); } void nsHTMLMediaElement::NetworkError() { - mError = new nsMediaError(nsIDOMMediaError::MEDIA_ERR_NETWORK); - mBegun = PR_FALSE; - DispatchAsyncProgressEvent(NS_LITERAL_STRING("error")); - mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY; - AddRemoveSelfReference(); - DispatchAsyncSimpleEvent(NS_LITERAL_STRING("emptied")); - ChangeDelayLoadStatus(PR_FALSE); + Error(nsIDOMMediaError::MEDIA_ERR_NETWORK); } void nsHTMLMediaElement::DecodeError() { - mError = new nsMediaError(nsIDOMMediaError::MEDIA_ERR_DECODE); + Error(nsIDOMMediaError::MEDIA_ERR_DECODE); +} + +void nsHTMLMediaElement::LoadAborted() +{ + Error(nsIDOMMediaError::MEDIA_ERR_ABORTED); +} + +void nsHTMLMediaElement::Error(PRUint16 aErrorCode) +{ + NS_ASSERTION(aErrorCode == nsIDOMMediaError::MEDIA_ERR_DECODE || + aErrorCode == nsIDOMMediaError::MEDIA_ERR_NETWORK || + aErrorCode == nsIDOMMediaError::MEDIA_ERR_ABORTED, + "Only use nsIDOMMediaError codes!"); + mError = new nsMediaError(aErrorCode); mBegun = PR_FALSE; DispatchAsyncProgressEvent(NS_LITERAL_STRING("error")); - mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY; + if (mReadyState == nsIDOMHTMLMediaElement::HAVE_NOTHING) { + mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY; + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("emptied")); + } else { + mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE; + } AddRemoveSelfReference(); - DispatchAsyncSimpleEvent(NS_LITERAL_STRING("emptied")); ChangeDelayLoadStatus(PR_FALSE); } @@ -2211,25 +2293,6 @@ nsresult nsHTMLMediaElement::DispatchProgressEvent(const nsAString& aName) return target->DispatchEvent(event, &dummy); } -nsresult nsHTMLMediaElement::DoneAddingChildren(PRBool aHaveNotified) -{ - if (!mIsDoneAddingChildren) { - mIsDoneAddingChildren = PR_TRUE; - - UpdatePreloadAction(); - if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) { - QueueSelectResourceTask(); - } - } - - return NS_OK; -} - -PRBool nsHTMLMediaElement::IsDoneAddingChildren() -{ - return mIsDoneAddingChildren; -} - PRBool nsHTMLMediaElement::IsPotentiallyPlaying() const { // TODO: @@ -2349,21 +2412,41 @@ nsHTMLMediaElement::IsNodeOfType(PRUint32 aFlags) const return !(aFlags & ~(eCONTENT | eMEDIA)); } +void nsHTMLMediaElement::DispatchAsyncSourceError(nsIContent* aSourceElement) +{ + LOG_EVENT(PR_LOG_DEBUG, ("%p Queuing simple source error event", this)); + + nsCOMPtr event = new nsSourceErrorEventRunner(this, aSourceElement); + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); +} + void nsHTMLMediaElement::NotifyAddedSource() { - if (mLoadWaitStatus == WAITING_FOR_SRC_OR_SOURCE) { + // If a source element is inserted as a child of a media element + // that has no src attribute and whose networkState has the value + // NETWORK_EMPTY, the user agent must invoke the media element's + // resource selection algorithm. + if (!HasAttr(kNameSpaceID_None, nsGkAtoms::src) && + mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) + { QueueSelectResourceTask(); - } else if (mLoadWaitStatus == WAITING_FOR_SOURCE) { + } + + // A load was paused in the resource selection algorithm, waiting for + // a new source child to be added, resume the resource selction algorithm. + if (mLoadWaitStatus == WAITING_FOR_SOURCE) { QueueLoadFromSourceTask(); } } -already_AddRefed nsHTMLMediaElement::GetNextSource() +nsIContent* nsHTMLMediaElement::GetNextSource() { nsresult rv = NS_OK; nsCOMPtr thisDomNode = do_QueryInterface(static_cast(this)); + mSourceLoadCandidate = nsnull; + if (!mSourcePointer) { // First time this has been run, create a selection to cover children. mSourcePointer = do_CreateInstance("@mozilla.org/content/range;1"); @@ -2397,27 +2480,13 @@ already_AddRefed nsHTMLMediaElement::GetNextSource() nsIContent* child = GetChildAt(startOffset); - // If child is a element, it may be the next candidate. + // If child is a element, it is the next candidate. if (child && child->Tag() == nsGkAtoms::source && child->IsHTML()) { - nsCOMPtr uri; - nsAutoString src,type; - - // Must have src attribute. - if (!child->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) - continue; - - // If we have a type attribute, it must be a supported type. - if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type) && - GetCanPlay(type) == CANPLAY_NO) - continue; - - LOG(PR_LOG_DEBUG, ("%p Trying load from =%s type=%s", this, - NS_ConvertUTF16toUTF8(src).get(), NS_ConvertUTF16toUTF8(type).get())); - NewURIFromString(src, getter_AddRefs(uri)); - return uri.forget(); + mSourceLoadCandidate = child; + return child; } } NS_NOTREACHED("Execution should not reach here!"); diff --git a/content/media/nsBuiltinDecoder.cpp b/content/media/nsBuiltinDecoder.cpp index faeb6aa177aa..964b2d54a0ff 100644 --- a/content/media/nsBuiltinDecoder.cpp +++ b/content/media/nsBuiltinDecoder.cpp @@ -411,7 +411,6 @@ void nsBuiltinDecoder::ResourceLoaded() // Ensure the final progress event gets fired if (mElement) { - mElement->DispatchAsyncProgressEvent(NS_LITERAL_STRING("progress")); mElement->ResourceLoaded(); } } @@ -566,8 +565,11 @@ void nsBuiltinDecoder::NotifyDownloadEnded(nsresult aStatus) { NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); - if (aStatus == NS_BINDING_ABORTED) + if (aStatus == NS_BINDING_ABORTED) { + // Download has been cancelled by user. + mElement->LoadAborted(); return; + } { MonitorAutoEnter mon(mMonitor); diff --git a/content/media/test/test_constants.html b/content/media/test/test_constants.html index 9bff765e6209..c459bd961cf1 100644 --- a/content/media/test/test_constants.html +++ b/content/media/test/test_constants.html @@ -17,7 +17,6 @@ is(HTMLElement.NETWORK_EMPTY, undefined); is(HTMLElement.NETWORK_IDLE, undefined); is(HTMLElement.NETWORK_LOADING, undefined); -is(HTMLElement.NETWORK_LOADED, undefined); is(HTMLElement.NETWORK_NO_SOURCE, undefined); is(HTMLElement.HAVE_NOTHING, undefined); is(HTMLElement.HAVE_METADATA, undefined); @@ -31,8 +30,7 @@ is(HTMLElement.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined); is(HTMLMediaElement.NETWORK_EMPTY, 0); is(HTMLMediaElement.NETWORK_IDLE, 1); is(HTMLMediaElement.NETWORK_LOADING, 2); -todo_is(HTMLMediaElement.NETWORK_LOADED, undefined); -is(HTMLMediaElement.NETWORK_NO_SOURCE, 4); +is(HTMLMediaElement.NETWORK_NO_SOURCE, 3); is(HTMLMediaElement.HAVE_NOTHING, 0); is(HTMLMediaElement.HAVE_METADATA, 1); is(HTMLMediaElement.HAVE_CURRENT_DATA, 2); @@ -58,7 +56,6 @@ is(HTMLVideoElement.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined); is(HTMLAudioElement.NETWORK_EMPTY, undefined); is(HTMLAudioElement.NETWORK_IDLE, undefined); is(HTMLAudioElement.NETWORK_LOADING, undefined); -is(HTMLAudioElement.NETWORK_LOADED, undefined); is(HTMLAudioElement.NETWORK_NO_SOURCE, undefined); is(HTMLAudioElement.HAVE_NOTHING, undefined); is(HTMLAudioElement.HAVE_METADATA, undefined); @@ -72,7 +69,6 @@ is(HTMLAudioElement.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined); is(HTMLSourceElement.NETWORK_EMPTY, undefined); is(HTMLSourceElement.NETWORK_IDLE, undefined); is(HTMLSourceElement.NETWORK_LOADING, undefined); -is(HTMLSourceElement.NETWORK_LOADED, undefined); is(HTMLSourceElement.NETWORK_NO_SOURCE, undefined); is(HTMLSourceElement.HAVE_NOTHING, undefined); is(HTMLSourceElement.HAVE_METADATA, undefined); @@ -86,7 +82,6 @@ is(HTMLSourceElement.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined); is(MediaError.NETWORK_EMPTY, undefined); is(MediaError.NETWORK_IDLE, undefined); is(MediaError.NETWORK_LOADING, undefined); -is(MediaError.NETWORK_LOADED, undefined); is(MediaError.NETWORK_NO_SOURCE, undefined); is(MediaError.HAVE_NOTHING, undefined); is(MediaError.HAVE_METADATA, undefined); @@ -100,7 +95,6 @@ is(MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED, 4); is(document.body.NETWORK_EMPTY, undefined); is(document.body.NETWORK_IDLE, undefined); is(document.body.NETWORK_LOADING, undefined); -is(document.body.NETWORK_LOADED, undefined); is(document.body.NETWORK_NO_SOURCE, undefined); is(document.body.HAVE_NOTHING, undefined); is(document.body.HAVE_METADATA, undefined); @@ -114,8 +108,7 @@ is(document.body.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined); is(document.getElementsByTagName("video")[0].NETWORK_EMPTY, 0); is(document.getElementsByTagName("video")[0].NETWORK_IDLE, 1); is(document.getElementsByTagName("video")[0].NETWORK_LOADING, 2); -is(document.getElementsByTagName("video")[0].NETWORK_LOADED, 3); -is(document.getElementsByTagName("video")[0].NETWORK_NO_SOURCE, 4); +is(document.getElementsByTagName("video")[0].NETWORK_NO_SOURCE, 3); is(document.getElementsByTagName("video")[0].HAVE_NOTHING, 0); is(document.getElementsByTagName("video")[0].HAVE_METADATA, 1); is(document.getElementsByTagName("video")[0].HAVE_CURRENT_DATA, 2); @@ -128,8 +121,7 @@ is(document.getElementsByTagName("video")[0].MEDIA_ERR_SRC_NOT_SUPPORTED, undefi is(document.getElementsByTagName("audio")[0].NETWORK_EMPTY, 0); is(document.getElementsByTagName("audio")[0].NETWORK_IDLE, 1); is(document.getElementsByTagName("audio")[0].NETWORK_LOADING, 2); -is(document.getElementsByTagName("audio")[0].NETWORK_LOADED, 3); -is(document.getElementsByTagName("audio")[0].NETWORK_NO_SOURCE, 4); +is(document.getElementsByTagName("audio")[0].NETWORK_NO_SOURCE, 3); is(document.getElementsByTagName("audio")[0].HAVE_NOTHING, 0); is(document.getElementsByTagName("audio")[0].HAVE_METADATA, 1); is(document.getElementsByTagName("audio")[0].HAVE_CURRENT_DATA, 2); @@ -142,7 +134,6 @@ is(document.getElementsByTagName("audio")[0].MEDIA_ERR_SRC_NOT_SUPPORTED, undefi is(document.getElementsByTagName("source")[0].NETWORK_EMPTY, undefined); is(document.getElementsByTagName("source")[0].NETWORK_IDLE, undefined); is(document.getElementsByTagName("source")[0].NETWORK_LOADING, undefined); -is(document.getElementsByTagName("source")[0].NETWORK_LOADED, undefined); is(document.getElementsByTagName("source")[0].NETWORK_NO_SOURCE, undefined); is(document.getElementsByTagName("source")[0].HAVE_NOTHING, undefined); is(document.getElementsByTagName("source")[0].HAVE_METADATA, undefined); @@ -156,7 +147,6 @@ is(document.getElementsByTagName("source")[0].MEDIA_ERR_SRC_NOT_SUPPORTED, undef is(HTMLElement.prototype.NETWORK_EMPTY, undefined); is(HTMLElement.prototype.NETWORK_IDLE, undefined); is(HTMLElement.prototype.NETWORK_LOADING, undefined); -is(HTMLElement.prototype.NETWORK_LOADED, undefined); is(HTMLElement.prototype.NETWORK_NO_SOURCE, undefined); is(HTMLElement.prototype.HAVE_NOTHING, undefined); is(HTMLElement.prototype.HAVE_METADATA, undefined); @@ -170,8 +160,7 @@ is(HTMLElement.prototype.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined); todo_is(HTMLMediaElement.prototype.NETWORK_EMPTY, 0, "HTMLMediaElement.prototype.NETWORK_EMPTY"); todo_is(HTMLMediaElement.prototype.NETWORK_IDLE, 1, "HTMLMediaElement.prototype.NETWORK_IDLE"); todo_is(HTMLMediaElement.prototype.NETWORK_LOADING, 2, "HTMLMediaElement.prototype.NETWORK_LOADING"); -todo_is(HTMLMediaElement.prototype.NETWORK_LOADED, 3, "HTMLMediaElement.prototype.NETWORK_LOADED"); -todo_is(HTMLMediaElement.prototype.NETWORK_NO_SOURCE, 4, "HTMLMediaElement.prototype.NETWORK_NO_SOURCE"); +todo_is(HTMLMediaElement.prototype.NETWORK_NO_SOURCE, 3, "HTMLMediaElement.prototype.NETWORK_NO_SOURCE"); todo_is(HTMLMediaElement.prototype.HAVE_NOTHING, 0, "HTMLMediaElement.prototype.HAVE_NOTHING"); todo_is(HTMLMediaElement.prototype.HAVE_METADATA, 1, "HTMLMediaElement.prototype.HAVE_METADATA"); todo_is(HTMLMediaElement.prototype.HAVE_CURRENT_DATA, 2, "HTMLMediaElement.prototype.HAVE_CURRENT_DATA"); @@ -184,8 +173,7 @@ is(HTMLMediaElement.prototype.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined, "HTMLMedia is(HTMLVideoElement.prototype.NETWORK_EMPTY, 0); is(HTMLVideoElement.prototype.NETWORK_IDLE, 1); is(HTMLVideoElement.prototype.NETWORK_LOADING, 2); -is(HTMLVideoElement.prototype.NETWORK_LOADED, 3); -is(HTMLVideoElement.prototype.NETWORK_NO_SOURCE, 4); +is(HTMLVideoElement.prototype.NETWORK_NO_SOURCE, 3); is(HTMLVideoElement.prototype.HAVE_NOTHING, 0); is(HTMLVideoElement.prototype.HAVE_METADATA, 1); is(HTMLVideoElement.prototype.HAVE_CURRENT_DATA, 2); @@ -198,8 +186,7 @@ is(HTMLVideoElement.prototype.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined); is(HTMLAudioElement.prototype.NETWORK_EMPTY, 0); is(HTMLAudioElement.prototype.NETWORK_IDLE, 1); is(HTMLAudioElement.prototype.NETWORK_LOADING, 2); -is(HTMLAudioElement.prototype.NETWORK_LOADED, 3); -is(HTMLAudioElement.prototype.NETWORK_NO_SOURCE, 4); +is(HTMLAudioElement.prototype.NETWORK_NO_SOURCE, 3); is(HTMLAudioElement.prototype.HAVE_NOTHING, 0); is(HTMLAudioElement.prototype.HAVE_METADATA, 1); is(HTMLAudioElement.prototype.HAVE_CURRENT_DATA, 2); @@ -212,7 +199,6 @@ is(HTMLAudioElement.prototype.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined); is(HTMLSourceElement.prototype.NETWORK_EMPTY, undefined); is(HTMLSourceElement.prototype.NETWORK_IDLE, undefined); is(HTMLSourceElement.prototype.NETWORK_LOADING, undefined); -is(HTMLSourceElement.prototype.NETWORK_LOADED, undefined); is(HTMLSourceElement.prototype.NETWORK_NO_SOURCE, undefined); is(HTMLSourceElement.prototype.HAVE_NOTHING, undefined); is(HTMLSourceElement.prototype.HAVE_METADATA, undefined); @@ -226,7 +212,6 @@ is(HTMLSourceElement.prototype.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined); is(MediaError.prototype.NETWORK_EMPTY, undefined); is(MediaError.prototype.NETWORK_IDLE, undefined); is(MediaError.prototype.NETWORK_LOADING, undefined); -is(MediaError.prototype.NETWORK_LOADED, undefined); is(MediaError.prototype.NETWORK_NO_SOURCE, undefined); is(MediaError.prototype.HAVE_NOTHING, undefined); is(MediaError.prototype.HAVE_METADATA, undefined); diff --git a/content/media/test/test_decode_error.html b/content/media/test/test_decode_error.html index 8c75b664216b..e2324cf8daf7 100644 --- a/content/media/test/test_decode_error.html +++ b/content/media/test/test_decode_error.html @@ -43,8 +43,7 @@ function startTest(test, token) { ok(false, "Unexpected ended event"); }, false); - v.src = test.name; - v.load(); + v.src = test.name; // implicitly starts a load. } manager.runTests(gDecodeErrorTests, startTest); diff --git a/content/media/test/test_decoder_disable.html b/content/media/test/test_decoder_disable.html index 0eb2715fd3d0..7967036e0102 100644 --- a/content/media/test/test_decoder_disable.html +++ b/content/media/test/test_decoder_disable.html @@ -18,6 +18,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=448600
 
 
 
diff --git a/content/media/wave/nsWaveDecoder.cpp b/content/media/wave/nsWaveDecoder.cpp
index b54376fd4a04..91e1088c6562 100644
--- a/content/media/wave/nsWaveDecoder.cpp
+++ b/content/media/wave/nsWaveDecoder.cpp
@@ -1466,7 +1466,6 @@ nsWaveDecoder::ResourceLoaded()
 
   if (mElement) {
     // Ensure the final progress event gets fired
-    mElement->DispatchAsyncProgressEvent(NS_LITERAL_STRING("progress"));
     mElement->ResourceLoaded();
   }
 
@@ -1533,8 +1532,10 @@ nsWaveDecoder::NotifyDownloadEnded(nsresult aStatus)
 {
   if (NS_SUCCEEDED(aStatus)) {
     ResourceLoaded();
-  } else if (aStatus != NS_BASE_STREAM_CLOSED &&
-             aStatus != NS_BINDING_ABORTED) {
+  } else if (aStatus == NS_BINDING_ABORTED) {
+    // Download has been cancelled by user.
+    mElement->LoadAborted();
+  } else if (aStatus != NS_BASE_STREAM_CLOSED) {
     NetworkError();
   }
   UpdateReadyStateForData();
diff --git a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl
index d9a5cb05a0f6..0a1280421eb6 100644
--- a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl
@@ -57,7 +57,7 @@
 #endif
 %}
 
-[scriptable, uuid(4355cfdb-0d70-4e5b-bb48-3ae8111ee72b)]
+[scriptable, uuid(c8b1423f-1321-4324-b6b7-8548d2fdc3da)]
 interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement
 {
   // error state
@@ -69,8 +69,7 @@ interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement
   const unsigned short NETWORK_EMPTY = 0;
   const unsigned short NETWORK_IDLE = 1;
   const unsigned short NETWORK_LOADING = 2;
-  const unsigned short NETWORK_LOADED = 3;
-  const unsigned short NETWORK_NO_SOURCE = 4;
+  const unsigned short NETWORK_NO_SOURCE = 3;
   readonly attribute unsigned short networkState;
            attribute DOMString preload;  
   readonly attribute nsIDOMTimeRanges buffered;
diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h
index 1f4311eb8dae..2e49a61cc2d4 100644
--- a/parser/html/nsHtml5TreeBuilderCppSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -515,9 +515,7 @@ nsHtml5TreeBuilder::elementPopped(PRInt32 aNamespace, nsIAtom* aName, nsIContent
   // Some HTML nodes need DoneAddingChildren() called to initialize
   // properly (e.g. form state restoration).
   // XXX expose ElementName group here and do switch
-  if (aName == nsHtml5Atoms::video ||
-      aName == nsHtml5Atoms::audio ||
-      aName == nsHtml5Atoms::object ||
+  if (aName == nsHtml5Atoms::object ||
       aName == nsHtml5Atoms::applet) {
     nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     NS_ASSERTION(treeOp, "Tree op allocation failed.");
diff --git a/widget/public/nsIAppShell.idl b/widget/public/nsIAppShell.idl
index d02278314073..ec4abec74ddc 100644
--- a/widget/public/nsIAppShell.idl
+++ b/widget/public/nsIAppShell.idl
@@ -38,12 +38,13 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
+#include "nsIRunnable.idl"
 
 /**
  * Interface for the native event system layer.  This interface is designed
  * to be used on the main application thread only.
  */
-[uuid(501403e9-a091-4780-ba55-cfd1e21287a1)]
+[uuid(40bc6280-ad83-471e-b197-80ab90e2065e)]
 interface nsIAppShell : nsISupports
 {
   /**
@@ -101,4 +102,15 @@ interface nsIAppShell : nsISupports
    * The current event loop nesting level.
    */
   readonly attribute unsigned long eventloopNestingLevel;
+  
+  /**
+   * Allows running of a "synchronous section", in the form of an nsIRunnable
+   * once the event loop has reached a "stable state". We've reached a stable
+   * state when the currently executing task/event has finished, see:
+   * http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#synchronous-section
+   * In practice this runs aRunnable once the currently executing event
+   * finishes. If called multiple times per task/event, all the runnables will
+   * be executed, in the order in which runInStableState() was called.
+   */
+  void runInStableState(in nsIRunnable aRunnable);
 };
diff --git a/widget/src/xpwidgets/nsBaseAppShell.cpp b/widget/src/xpwidgets/nsBaseAppShell.cpp
index 1320eefb403a..fe489d8e8c25 100644
--- a/widget/src/xpwidgets/nsBaseAppShell.cpp
+++ b/widget/src/xpwidgets/nsBaseAppShell.cpp
@@ -324,14 +324,36 @@ nsBaseAppShell::OnProcessNextEvent(nsIThreadInternal *thr, PRBool mayWait,
     thr->Dispatch(mDummyEvent, NS_DISPATCH_NORMAL);
   }
 
+  // We're about to run an event, so we're in a stable state. 
+  RunSyncSections();
+
   return NS_OK;
 }
 
+void
+nsBaseAppShell::RunSyncSections()
+{
+  if (mSyncSections.Count() == 0) {
+    return;
+  }
+  // We've got synchronous sections awaiting a stable state. Run
+  // all the synchronous sections. Note that a synchronous section could
+  // add another synchronous section, so we don't remove elements from
+  // mSyncSections until all sections have been run, else we'll screw up
+  // our iteration.
+  for (PRUint32 i=0; iRun();
+  }
+  mSyncSections.Clear();
+}
+
 // Called from the main thread
 NS_IMETHODIMP
 nsBaseAppShell::AfterProcessNextEvent(nsIThreadInternal *thr,
                                       PRUint32 recursionDepth)
 {
+  // We've just finished running an event, so we're in a stable state. 
+  RunSyncSections();
   return NS_OK;
 }
 
@@ -343,3 +365,18 @@ nsBaseAppShell::Observe(nsISupports *subject, const char *topic,
   Exit();
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsBaseAppShell::RunInStableState(nsIRunnable* aRunnable)
+{
+  if (!mRunning) {
+    // We're not running a "task"/event, so we're already in a "stable state",
+    // so we can run the synchronous section immediately.
+    aRunnable->Run();
+    return NS_OK;
+  }
+  // Else we're running a "task"/event, record the synchronous section, and
+  // run it with any others once we reach a stable state.
+  mSyncSections.AppendObject(aRunnable);
+  return NS_OK;
+}
diff --git a/widget/src/xpwidgets/nsBaseAppShell.h b/widget/src/xpwidgets/nsBaseAppShell.h
index bb991e77204c..6924ab8e098c 100644
--- a/widget/src/xpwidgets/nsBaseAppShell.h
+++ b/widget/src/xpwidgets/nsBaseAppShell.h
@@ -42,6 +42,7 @@
 #include "nsIThreadInternal.h"
 #include "nsIObserver.h"
 #include "nsIRunnable.h"
+#include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "prinrval.h"
 
@@ -99,6 +100,11 @@ protected:
 private:
   PRBool DoProcessNextNativeEvent(PRBool mayWait);
 
+  /**
+   * Runs all synchronous sections which are queued up in mSyncSections.
+   */
+  void RunSyncSections();
+
   nsCOMPtr mDummyEvent;
   /**
    * mBlockedWait points back to a slot that controls the wait loop in
@@ -119,6 +125,7 @@ private:
     eEventloopOther  // innermost native event loop is a native library/plugin etc
   };
   EventloopNestingState mEventloopNestingState;
+  nsCOMArray mSyncSections;
   PRPackedBool mRunning;
   PRPackedBool mExiting;
   /**

From 126937b6af827c52d322548d5e468a27369ee6a0 Mon Sep 17 00:00:00 2001
From: Chris Pearce 
Date: Fri, 3 Sep 2010 12:03:03 +1200
Subject: [PATCH 071/222] Bug 528523 - Ensure sync sections run in between
 events. r=roc a=blocking2.0

---
 widget/src/xpwidgets/nsBaseAppShell.cpp | 27 +++++++++++++++++--------
 widget/src/xpwidgets/nsBaseAppShell.h   |  2 +-
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/widget/src/xpwidgets/nsBaseAppShell.cpp b/widget/src/xpwidgets/nsBaseAppShell.cpp
index fe489d8e8c25..c8e0a41da701 100644
--- a/widget/src/xpwidgets/nsBaseAppShell.cpp
+++ b/widget/src/xpwidgets/nsBaseAppShell.cpp
@@ -70,6 +70,11 @@ nsBaseAppShell::nsBaseAppShell()
 {
 }
 
+nsBaseAppShell::~nsBaseAppShell()
+{
+  NS_ASSERTION(mSyncSections.Count() == 0, "Must have run all sync sections");
+}
+
 nsresult
 nsBaseAppShell::Init()
 {
@@ -369,14 +374,20 @@ nsBaseAppShell::Observe(nsISupports *subject, const char *topic,
 NS_IMETHODIMP
 nsBaseAppShell::RunInStableState(nsIRunnable* aRunnable)
 {
-  if (!mRunning) {
-    // We're not running a "task"/event, so we're already in a "stable state",
-    // so we can run the synchronous section immediately.
-    aRunnable->Run();
-    return NS_OK;
-  }
-  // Else we're running a "task"/event, record the synchronous section, and
-  // run it with any others once we reach a stable state.
+  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
+  // Record the synchronous section, and run it with any others once
+  // we reach a stable state.
   mSyncSections.AppendObject(aRunnable);
+
+  // Ensure we've got a pending event, else the callbacks will never run.
+  nsIThread* thread = NS_GetCurrentThread(); 
+  if (!NS_HasPendingEvents(thread) &&
+       NS_FAILED(thread->Dispatch(new nsRunnable(), NS_DISPATCH_NORMAL)))
+  {
+    // Failed to dispatch dummy event to cause sync sections to run, thread
+    // is probably done processing events, just run the sync sections now.
+    RunSyncSections();
+  }
   return NS_OK;
 }
+
diff --git a/widget/src/xpwidgets/nsBaseAppShell.h b/widget/src/xpwidgets/nsBaseAppShell.h
index 6924ab8e098c..3a8a1fe63215 100644
--- a/widget/src/xpwidgets/nsBaseAppShell.h
+++ b/widget/src/xpwidgets/nsBaseAppShell.h
@@ -62,7 +62,7 @@ public:
   nsBaseAppShell();
 
 protected:
-  virtual ~nsBaseAppShell() {}
+  virtual ~nsBaseAppShell();
 
   /**
    * This method is called by subclasses when the app shell singleton is

From 39524be8153861aa91f692cf6e0baabc24a71d50 Mon Sep 17 00:00:00 2001
From: Chris Pearce 
Date: Fri, 3 Sep 2010 12:03:03 +1200
Subject: [PATCH 072/222] Bug 485288 - Ensure video context menu doesn't show
 when video's source children don't contain a resource. r=dolske a=blocking2.0

---
 browser/base/content/nsContextMenu.js   | 3 ++-
 content/media/test/test_audiowrite.html | 1 -
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js
index 977678017fda..eadc5b04f1d2 100644
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -404,7 +404,8 @@ nsContextMenu.prototype = {
     this.showItem("context-video-fullscreen", this.onVideo);
     // Disable them when there isn't a valid media source loaded.
     if (onMedia) {
-      var hasError = (this.target.error != null);
+      var hasError = this.target.error != null ||
+                     this.target.networkState == this.target.NETWORK_NO_SOURCE;
       this.setItemAttr("context-media-play",  "disabled", hasError);
       this.setItemAttr("context-media-pause", "disabled", hasError);
       this.setItemAttr("context-media-mute",   "disabled", hasError);
diff --git a/content/media/test/test_audiowrite.html b/content/media/test/test_audiowrite.html
index be1dfb75bc84..50227091a2aa 100644
--- a/content/media/test/test_audiowrite.html
+++ b/content/media/test/test_audiowrite.html
@@ -60,7 +60,6 @@ function runTests() {
     writeArgsOK = true;
   }
   ok(writeArgsOK, "mozWriteAudio args test failed.");
-
   SimpleTest.finish();
 }
 

From b26c5c69d642c9e75dda1cebf4b8d7f49c57a932 Mon Sep 17 00:00:00 2001
From: Chris Pearce 
Date: Fri, 3 Sep 2010 12:03:03 +1200
Subject: [PATCH 073/222] Bug 485288 - Don't process video controls events
 after bindings detached. r=dolske a=blocking2.0

---
 toolkit/content/widgets/videocontrols.xml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/toolkit/content/widgets/videocontrols.xml b/toolkit/content/widgets/videocontrols.xml
index d0f5fed53bad..bff881f57d05 100644
--- a/toolkit/content/widgets/videocontrols.xml
+++ b/toolkit/content/widgets/videocontrols.xml
@@ -404,8 +404,10 @@
 
                     // If the binding is detached (or has been replaced by a
                     // newer instance of the binding), nuke our event-listeners.
-                    if (this.videocontrols.randomID != this.randomID)
+                    if (this.videocontrols.randomID != this.randomID) {
                         this.terminateEventListeners();
+                        return;
+                    }
 
                     switch (aEvent.type) {
                         case "play":

From be2bfe2038717c18dd05f68c03b46451e4578246 Mon Sep 17 00:00:00 2001
From: Chris Pearce 
Date: Fri, 3 Sep 2010 12:03:03 +1200
Subject: [PATCH 074/222] Bug 593074 - Prevent multiple test finish from
 causing errors. a=test-fix

---
 content/media/test/test_preload_actions.html | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/content/media/test/test_preload_actions.html b/content/media/test/test_preload_actions.html
index 3b3cbb742bd8..4172c4cfa9ae 100644
--- a/content/media/test/test_preload_actions.html
+++ b/content/media/test/test_preload_actions.html
@@ -46,7 +46,9 @@ function log(m) {
 
 function maybeFinish(v, n) {
   log(n + ",");
-  v.parentNode.removeChild(v);
+  if (v.parentNode) {
+    v.parentNode.removeChild(v);
+  }
   manager.finished(v.token);
 }
 

From 0f27aac7094be5a1baccf295a8cb6034d18cb408 Mon Sep 17 00:00:00 2001
From: Frank Yan 
Date: Thu, 2 Sep 2010 19:20:12 -0700
Subject: [PATCH 075/222] Bug 544816 - Attach combined Stop/Go/Refresh button
 to the Location Bar.  r=dolske, ui-r=shorlander, a=dolske

---
 browser/base/content/browser.css              |  13 +++-
 browser/base/content/browser.js               |  28 +++++---
 browser/base/content/browser.xul              |  36 ++++++----
 browser/components/nsBrowserGlue.js           |  29 ++++++--
 .../themes/gnomestripe/browser/browser.css    |  64 +++++++++++++++++-
 browser/themes/gnomestripe/browser/jar.mn     |   1 +
 .../gnomestripe/browser/reload-stop-go.png    | Bin 0 -> 1608 bytes
 browser/themes/pinstripe/browser/browser.css  |  58 +++++++++++++++-
 browser/themes/pinstripe/browser/jar.mn       |   1 +
 .../pinstripe/browser/reload-stop-go.png      | Bin 0 -> 1516 bytes
 browser/themes/winstripe/browser/browser.css  |  63 ++++++++++++++++-
 browser/themes/winstripe/browser/jar.mn       |   2 +
 .../winstripe/browser/reload-stop-go.png      | Bin 0 -> 1590 bytes
 toolkit/content/widgets/autocomplete.xml      |   2 +
 14 files changed, 263 insertions(+), 34 deletions(-)
 create mode 100644 browser/themes/gnomestripe/browser/reload-stop-go.png
 create mode 100644 browser/themes/pinstripe/browser/reload-stop-go.png
 create mode 100644 browser/themes/winstripe/browser/reload-stop-go.png

diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css
index 3331daf75dca..3b2e3831fd78 100644
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -100,6 +100,13 @@ toolbarpaletteitem[place="palette"] > toolbaritem > hbox[type="places"] {
   display: none;
 }
 
+#wrapper-urlbar-container #urlbar-container > #urlbar > toolbarbutton,
+#urlbar-container:not([combined]) > #urlbar > toolbarbutton,
+#urlbar-container[combined] + #reload-button + #stop-button,
+#urlbar-container[combined] + #reload-button,
+toolbar:not([mode="icons"]) > #urlbar-container > #urlbar > toolbarbutton,
+toolbar[mode="icons"] > #urlbar-container > #urlbar > #urlbar-reload-button:not([displaystop]) + #urlbar-stop-button,
+toolbar[mode="icons"] > #urlbar-container > #urlbar > #urlbar-reload-button[displaystop],
 toolbar[mode="icons"] > #reload-button:not([displaystop]) + #stop-button,
 toolbar[mode="icons"] > #reload-button[displaystop] {
   visibility: collapse;
@@ -178,8 +185,12 @@ richlistitem[type~="action"]:-moz-locale-dir(rtl) > .ac-url-box {
   direction: rtl;
 }
 
+#urlbar-container[combined] > #urlbar > #urlbar-icons > #go-button,
 #urlbar[pageproxystate="invalid"] > #urlbar-icons > .urlbar-icon:not(#go-button),
-#urlbar[pageproxystate="valid"] > #urlbar-icons > #go-button {
+#urlbar[pageproxystate="valid"] > #urlbar-icons > #go-button,
+#urlbar[pageproxystate="invalid"][focused="true"] > #urlbar-go-button ~ toolbarbutton,
+#urlbar[pageproxystate="valid"] > #urlbar-go-button,
+#urlbar:not([focused="true"]) > #urlbar-go-button {
   visibility: collapse;
 }
 
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index debad768d3ad..a47bc1f1d4a3 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2360,10 +2360,13 @@ function UpdateUrlbarSearchSplitterState()
   var splitter = document.getElementById("urlbar-search-splitter");
   var urlbar = document.getElementById("urlbar-container");
   var searchbar = document.getElementById("search-container");
+  var stop = document.getElementById("stop-button");
 
   var ibefore = null;
   if (urlbar && searchbar) {
-    if (urlbar.nextSibling == searchbar)
+    if (urlbar.nextSibling == searchbar ||
+        urlbar.getAttribute("combined") &&
+        stop && stop.nextSibling == searchbar)
       ibefore = searchbar;
     else if (searchbar.nextSibling == urlbar)
       ibefore = urlbar;
@@ -4456,23 +4459,30 @@ var CombinedStopReload = {
     if (this._initialized)
       return;
 
-    var stop = document.getElementById("stop-button");
-    if (!stop)
-      return;
-
+    var urlbar = document.getElementById("urlbar-container");
     var reload = document.getElementById("reload-button");
-    if (!reload)
-      return;
+    var stop = document.getElementById("stop-button");
 
-    if (!(reload.nextSibling == stop))
+    if (urlbar) {
+      if (urlbar.parentNode.getAttribute("mode") != "icons" ||
+          !reload || urlbar.nextSibling != reload ||
+          !stop || reload.nextSibling != stop)
+        urlbar.removeAttribute("combined");
+      else {
+        urlbar.setAttribute("combined", "true");
+        reload = document.getElementById("urlbar-reload-button");
+        stop = document.getElementById("urlbar-stop-button");
+      }
+    }
+    if (!stop || !reload || reload.nextSibling != stop)
       return;
 
     this._initialized = true;
     if (XULBrowserWindow.stopCommand.getAttribute("disabled") != "true")
       reload.setAttribute("displaystop", "true");
     stop.addEventListener("click", this, false);
-    this.stop = stop;
     this.reload = reload;
+    this.stop = stop;
   },
 
   uninit: function () {
diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul
index 386237ca5ea9..ecf93407570c 100644
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -790,10 +790,10 @@
              fullscreentoolbar="true" mode="icons" customizable="true"
 #ifdef WINCE
              iconsize="small" defaulticonsize="small"
-             defaultset="unified-back-forward-button,reload-button,stop-button,home-button,urlbar-container,search-container,bookmarks-menu-button-container,navigator-throbber,fullscreenflex,window-controls"
+             defaultset="unified-back-forward-button,home-button,urlbar-container,reload-button,stop-button,search-container,bookmarks-menu-button-container,navigator-throbber,fullscreenflex,window-controls"
 #else
              iconsize="large"
-             defaultset="unified-back-forward-button,reload-button,stop-button,home-button,urlbar-container,search-container,bookmarks-menu-button-container,fullscreenflex,window-controls"
+             defaultset="unified-back-forward-button,home-button,urlbar-container,reload-button,stop-button,search-container,bookmarks-menu-button-container,fullscreenflex,window-controls"
 #endif
              context="toolbar-context-menu">
 
@@ -827,17 +827,6 @@
         
       
 
-      
-
-      
-
       
           
+          
+          
+          
         
       
 
+      
+
+      
+
       
diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js
index 8ad446463adb..5df106cfad57 100644
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -589,7 +589,7 @@ BrowserGlue.prototype = {
     var buttonAccessKey  = rightsBundle.GetStringFromName("buttonAccessKey");
     var productName      = brandBundle.GetStringFromName("brandFullName");
     var notifyRightsText = rightsBundle.formatStringFromName("notifyRightsText", [productName], 1);
-    
+
     var buttons = [
                     {
                       label:     buttonLabel,
@@ -995,7 +995,7 @@ BrowserGlue.prototype = {
   },
 
   _migrateUI: function BG__migrateUI() {
-    const UI_VERSION = 2;
+    const UI_VERSION = 3;
     let currentUIVersion = 0;
     try {
       currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
@@ -1053,6 +1053,25 @@ BrowserGlue.prototype = {
       }
     }
 
+    if (currentUIVersion < 3) {
+      // This code merges the reload/stop/go button into the url bar.
+      let currentsetResource = this._rdf.GetResource("currentset");
+      let toolbarResource = this._rdf.GetResource("chrome://browser/content/browser.xul#nav-bar");
+      let currentset = this._getPersist(toolbarResource, currentsetResource);
+      // Need to migrate only if toolbar is customized and all 3 elements are found.
+      if (currentset &&
+          currentset.indexOf("reload-button") != -1 &&
+          currentset.indexOf("stop-button") != -1 &&
+          currentset.indexOf("urlbar-container") != -1 &&
+          currentset.indexOf("urlbar-container,reload-button,stop-button") == -1) {
+        currentset = currentset.replace(/(^|,)reload-button($|,)/, "$1$2").
+                                replace(/(^|,)stop-button($|,)/, "$1$2").
+                                replace(/(^|,)urlbar-container($|,)/,
+                                        "$1urlbar-container,reload-button,stop-button$2");
+        this._setPersist(toolbarResource, currentsetResource, currentset);
+      }
+    }
+
     if (this._dirty)
       this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
 
@@ -1090,7 +1109,7 @@ BrowserGlue.prototype = {
   // ------------------------------
   // public nsIBrowserGlue members
   // ------------------------------
-  
+
   sanitize: function BG_sanitize(aParentWindow) {
     this._sanitizer.sanitize(aParentWindow);
   },
@@ -1229,7 +1248,7 @@ BrowserGlue.prototype = {
                                     SMART_BOOKMARKS_ANNO, smartBookmark.queryId,
                                     0, annosvc.EXPIRE_NEVER);
         }
-        
+
         // If we are creating all Smart Bookmarks from ground up, add a
         // separator below them in the bookmarks menu.
         if (smartBookmarksCurrentVersion == 0 &&
@@ -1324,7 +1343,7 @@ GeolocationPrompt.prototype = {
       request.allow();
       return;
     }
-    
+
     if (result == Ci.nsIPermissionManager.DENY_ACTION) {
       request.cancel();
       return;
diff --git a/browser/themes/gnomestripe/browser/browser.css b/browser/themes/gnomestripe/browser/browser.css
index f6a882867aa6..c684a32c73dc 100644
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -701,7 +701,7 @@ toolbar[iconsize="small"] #reload-button[disabled="true"] {
   list-style-image: url("moz-icon://stock/gtk-refresh?size=menu&state=disabled");
 }
 
-toolbar[iconsize="small"] #home-button ,
+toolbar[iconsize="small"] #home-button,
 #home-button.bookmark-item {
   list-style-image: url("moz-icon://stock/gtk-home?size=menu");
 }
@@ -787,6 +787,7 @@ toolbar[iconsize="small"] #fullscreen-button {
   width: 7em;
   min-width: 7em;
   -moz-appearance: textfield;
+  padding: 0;
 }
 
 #urlbar > .autocomplete-textbox-container {
@@ -1113,11 +1114,72 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
 }
 
 /* Go button */
+
 #go-button {
   padding: 3px 2px 2px 2px;
   list-style-image: url("chrome://browser/skin/Go-arrow.png");
 }
 
+/* Combined go/reload/stop button in location bar */
+
+#urlbar > toolbarbutton {
+  -moz-appearance: none;
+  list-style-image: url("chrome://browser/skin/reload-stop-go.png");
+  margin: -1px;
+  -moz-margin-start: 0;
+  padding: 0 3px;
+  background-origin: border-box;
+  border: none;
+  border-left: 1px solid rgba(0,0,0,.35);
+  -moz-border-radius-topright: 2px;
+  -moz-border-radius-bottomright: 2px;
+}
+
+#urlbar > toolbarbutton:active:hover {
+  padding-left: 4px;
+  border-left: none;
+  -moz-box-shadow: 0 0 9px rgba(0,0,0,.4) inset,
+                   0 0 3px rgba(0,0,0,.4) inset;
+}
+
+#urlbar-go-button {
+  -moz-image-region: rect(0px, 56px, 14px, 42px);
+  background-image: -moz-linear-gradient(rgb(143,219,69), rgb(115,177,57));
+  -moz-box-shadow: 0 1px 0 rgba(0,0,0,.1) inset,
+                   -1px -1px 0 rgba(255,255,255,.2) inset;
+}
+
+#urlbar-go-button:hover {
+  background-image: -moz-linear-gradient(rgb(163,232,92), rgb(137,196,81));
+}
+
+#urlbar-reload-button {
+  -moz-image-region: rect(0px, 14px, 14px, 0px);
+}
+
+#urlbar-reload-button:hover {
+  -moz-image-region: rect(0px, 28px, 14px, 14px);
+  background-image: -moz-linear-gradient(rgb(137,183,233), rgb(79,130,195));
+  -moz-box-shadow: 0 1px 0 rgba(0,0,0,.1) inset,
+                   -1px -1px 0 rgba(255,255,255,.2) inset;
+}
+
+#urlbar-stop-button {
+  -moz-image-region: rect(0px, 42px, 14px, 28px);
+  background-image: -moz-linear-gradient(rgb(226,99,99), rgb(199,68,68));
+  -moz-box-shadow: 0 1px 0 rgba(0,0,0,.1) inset,
+                   -1px -1px 0 rgba(255,255,255,.2) inset;
+}
+
+#urlbar-stop-button:hover {
+  background-image: -moz-linear-gradient(rgb(237,120,120), rgb(216,92,92));
+}
+
+
+#urlbar-stop-button[disabled="true"] > .toolbarbutton-icon {
+  opacity: .5;
+}
+
 /* Star button */
 #star-button {
   padding: 1px;
diff --git a/browser/themes/gnomestripe/browser/jar.mn b/browser/themes/gnomestripe/browser/jar.mn
index 9acbfb90a0cd..1baff47933a4 100644
--- a/browser/themes/gnomestripe/browser/jar.mn
+++ b/browser/themes/gnomestripe/browser/jar.mn
@@ -26,6 +26,7 @@ browser.jar:
   skin/classic/browser/page-livemarks.png
   skin/classic/browser/Privacy-16.png
   skin/classic/browser/Privacy-48.png
+  skin/classic/browser/reload-stop-go.png
   skin/classic/browser/searchbar.css                  (searchbar.css)
   skin/classic/browser/section_collapsed.png
   skin/classic/browser/section_collapsed-rtl.png
diff --git a/browser/themes/gnomestripe/browser/reload-stop-go.png b/browser/themes/gnomestripe/browser/reload-stop-go.png
new file mode 100644
index 0000000000000000000000000000000000000000..922a4c4c62e8ecd1bd380a62673dbc0b429b1756
GIT binary patch
literal 1608
zcmV-O2DkZ%P)PbXFRCwCdR%>h(MHHUd*~fjh_x3@N
zVik}A)f5wHYl}t1z9>*=A-0jCqyz}iVzy?b{&gN58~Zy`1Dhnsvmd(NDhGvAyua~4xd(f{>%F^N<{v#jBi
z*FKO9H<$_2k|wSHHwz(QG5P-V<1sc2M&EB<0gd7%ymv$ji5$oV`$jNh>f7PGz;80>
zbr~4rK&sN49!2>Xx;B8k5^NWhSNvq|Pat*(!Z;rzoPaPgB8u)HL@z?u4w!u&A>3@a
zu`1Db%&QnLgC-S_cbU>=AAJZkI{`;QU-~qHV`lQz9FG*Qf<1~$wbdQ>Uewy~k3TY}
zr=$g0E#*3$q_$$Mt`p{r&
zduv;#WPi}a2u;Lb!trU8RZ4|t)_}@w@D!#HAnM#9AgZJ?m$7eWD@YXi<;4MI-K#47f|sV+Rm+G6*`<1G1CX;eruKB)1PiNhIke
zlj&M=YWf}!+nFvmd&Xz7?6S4CwjjIRj_h~uqNb*%KC4s_9Ul=MR&QIFeG0@LrW3*^
z&PS9cQK}NEdPRT)GVzmP@`Nc<&Mw}#u~H(WRl@ioYnjaStiRul$Rjrqu?yfNjF^B~
zin<=@cwSK!n69yK6(A6Z{!kB4;6th
z2ZV{o!I8Piwr`7f8sAvST&1aXerN6nTqwTn(gOR7}ims7K1iLx+yM5+7g1(wwzSX8Neu
z*qb%|)0ExPe?ErC0g-edNp%R^;*7%GALf;u1bv6ULN6UC+g)(_#E}9Bw$ABtU+{R8
z%Pf-^TrPKq!EBzocmEGn8izvRrqXvl`C`v(MNtHp>MsZ^6nQin5DCORA=bc^_pY6|
z>hDkMPHpY*7a}7sXf6~H^s%6~`#H;fp3&*TF`Z7=u_CuxE>&k8
zIlu<-n{?86V-dE$pabuEx-T<{bG<=UxnWQ0000 #urlbar {
   -moz-padding-end: 3px;
 }
 
@@ -899,15 +902,64 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
 
 #go-button {
   list-style-image: url("chrome://browser/skin/Go-arrow.png");
-  -moz-image-region: rect(0px, 16px, 16px, 0px);  
+  -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 
 #go-button:hover {
-  -moz-image-region: rect(0px, 32px, 16px, 16px);  
+  -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 #go-button:hover:active {
-  -moz-image-region: rect(0px, 48px, 16px, 32px);  
+  -moz-image-region: rect(0px, 48px, 16px, 32px);
+}
+
+/* ----- COMBINED GO/RELOAD/STOP BUTTON IN LOCATION BAR ----- */
+
+#urlbar > toolbarbutton {
+  list-style-image: url("chrome://browser/skin/reload-stop-go.png");
+  margin: 0;
+  -moz-margin-start: 2px;
+  padding: 0 3px;
+  background-origin: border-box;
+  border: none;
+  border-left: 1px solid rgba(0,0,0,.25);
+  -moz-border-radius-topright: 2px;
+  -moz-border-radius-bottomright: 2px;
+}
+
+#urlbar > toolbarbutton:active:hover {
+  -moz-box-shadow: @toolbarbuttonPressedInnerShadow@;
+  padding-left: 4px;
+  border-left: none;
+}
+
+#urlbar-go-button {
+  -moz-image-region: rect(0px, 56px, 14px, 42px);
+  background-image: -moz-linear-gradient(rgb(184,221,142), rgb(154,201,111) 49%, rgb(130,187,92) 51%, rgb(114,171,79));
+  -moz-box-shadow: 0 1px 0 rgba(0,0,0,.1) inset,
+                   -1px -1px 1px rgba(255,255,255,.15) inset;
+}
+
+#urlbar-reload-button {
+  -moz-image-region: rect(0px, 14px, 14px, 0px);
+}
+
+#urlbar-reload-button:hover {
+  -moz-image-region: rect(0px, 28px, 14px, 14px);
+  background-image: -moz-linear-gradient(rgb(162,207,241), rgb(111,178,225) 49%, rgb(91,159,217) 51%, rgb(62,138,200));
+  -moz-box-shadow: 0 1px 0 rgba(0,0,0,.1) inset,
+                   -1px -1px 1px rgba(255,255,255,.15) inset;
+}
+
+#urlbar-stop-button {
+  -moz-image-region: rect(0px, 42px, 14px, 28px);
+  background-image: -moz-linear-gradient(rgb(231,162,140), rgb(209,119,100) 49%, rgb(193,92,78) 51%, rgb(173,72,58));
+  -moz-box-shadow: 0 1px 0 rgba(0,0,0,.1) inset,
+                   -1px -1px 1px rgba(255,255,255,.15) inset;
+}
+
+#urlbar-stop-button[disabled="true"] > .toolbarbutton-icon {
+  opacity: .4;
 }
 
 /* STAR BUTTON */
diff --git a/browser/themes/pinstripe/browser/jar.mn b/browser/themes/pinstripe/browser/jar.mn
index ba19934e32ca..31435d1b4b57 100644
--- a/browser/themes/pinstripe/browser/jar.mn
+++ b/browser/themes/pinstripe/browser/jar.mn
@@ -41,6 +41,7 @@ browser.jar:
   skin/classic/browser/Popup-blocked.png
   skin/classic/browser/Privacy-16.png
   skin/classic/browser/Privacy-48.png
+  skin/classic/browser/reload-stop-go.png
   skin/classic/browser/searchbar-dropmarker.png
   skin/classic/browser/searchbar.css
   skin/classic/browser/Search.png
diff --git a/browser/themes/pinstripe/browser/reload-stop-go.png b/browser/themes/pinstripe/browser/reload-stop-go.png
new file mode 100644
index 0000000000000000000000000000000000000000..0406477f52e20d343d5d7903aee28d6d05bcbc63
GIT binary patch
literal 1516
zcmVCB$F@1A$|-t)WXch7l9mSyVyEcBf?8w`f2
zce4rRN6+{-gVv?6YeDU|wlmfm@{t02_r+
z9z~&%FpZ)R)k?|o5qK^K9S`pcU@TMqZy1LjgJJ*o0l8gax4@7M_Rmzaf~X8cqs{sh
zb`$XLqwbS}5Dp;frKs6#9>%ilA`OVuYHe{i9KW@+wDk3OJdR*6C^8_#4{VQyfQuhJ
z64Cf|SPCcdj%&&NdEdE}zw(8i%$ElpDaSRYHW{F5wEtGZ4K$HHdNVzF5Ddi~3hk&*uS^XG3V
zC@820b08G$ex%yb(a0?FC1qt*z})Z_wey?+G2SNMx(LI
z>-Aa`>s;>9uwphD0?og8l-W7ZqqmfF4w)GSFGr$ijEaeY46yRgjhBpHZY+E4b9d>y
zT19oeiJ~&Y(K1aVs4+4v2{MzJmesN1`QoFl*u*MuIT}LIgoK28pU;;JG)=mbeso{z
zpteiRtud@??4UdCWdt0{;I%+YKFZ+?tl71vX7!HhgLXbX0Jd224t)Bk1BBdR8p{Z2
ztbH8Jx`iJ!ZeFwfQvgTqF=o~CO|cP3ED#lNSn=;WVhR=M@L7Slp7W0
zPpa0ijLdTE61aOIAjzC{WfkItF=n+OO=feBEQ(3}?2h1DReSfxB@cARBn~KBy>s`z
z=r~@0cm2%~5fj2RHx912_VIDgw12(v_<;#olh%QCo7$c2?Sopk+da9Wq9XU|)vHWr
zXXjbyeNE8%;X)3Xd1)+mM%+cPKM6lN1iMJK;KU>iqO&
zZ*LlK;P8(oZ&$a@q}Td0M-1`4^4wGPX+x4Xflou2{YQYFQ8{@%=si7jQxo#ZNbcIT
zTU`aD_}JEh#)9@EEF(n`^jFX;puT@tCjvABl+fGQ6EOK$sJWdW{!95&fB^vXVi?_!
SEg&=i0000 .ac-url-box > .ac-action-
 
 #go-button {
   list-style-image: url("chrome://browser/skin/Go-arrow.png");
-  -moz-image-region: rect(0px 16px 16px 0px);
+  -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 
 #go-button:hover {
-  -moz-image-region: rect(16px 16px 32px 0px);
+  -moz-image-region: rect(16px, 16px, 32px, 0px);
+}
+
+/* combined go/reload/stop button in location bar */
+
+#urlbar > toolbarbutton {
+  -moz-appearance: none;
+  list-style-image: url("chrome://browser/skin/reload-stop-go.png");
+  margin: -2px;
+  -moz-margin-start: 0;
+  padding: 0 3px;
+  background-origin: border-box;
+  border: none;
+  border-left: 1px solid rgba(0,0,0,.25);
+  -moz-border-radius-topright: 2px;
+  -moz-border-radius-bottomright: 2px;
+}
+
+#urlbar > toolbarbutton:active:hover {
+  padding-left: 4px;
+  border-left: none;
+  -moz-box-shadow: 0 0 9px rgba(0,0,0,.4) inset,
+                   0 0 3px rgba(0,0,0,.4) inset;
+}
+
+#urlbar-go-button {
+  -moz-image-region: rect(0px, 56px, 14px, 42px);
+  background-image: -moz-linear-gradient(rgb(115,213,115), rgb(96,190,96) 49%, rgb(82,174,82) 51%, rgb(79,155,79));
+  -moz-box-shadow: 0 1px 0 rgba(0,0,0,.1) inset,
+                   -1px -1px 1px rgba(255,255,255,.25) inset;
+}
+
+#urlbar-go-button:hover {
+  background-image: -moz-linear-gradient(rgb(96,221,96), rgb(71,191,71) 49%, rgb(54,171,54) 51%, rgb(50,147,50));
+}
+
+#urlbar-reload-button {
+  -moz-image-region: rect(0px, 14px, 14px, 0px);
+}
+
+#urlbar-reload-button:hover {
+  -moz-image-region: rect(0px, 28px, 14px, 14px);
+  background-image: -moz-linear-gradient(rgb(162,207,241), rgb(111,178,225) 49%, rgb(91,159,217) 51%, rgb(62,138,200));
+  -moz-box-shadow: 0 1px 0 rgba(0,0,0,.1) inset,
+                   -1px -1px 1px rgba(255,255,255,.25) inset;
+}
+
+#urlbar-stop-button {
+  -moz-image-region: rect(0px, 42px, 14px, 28px);
+  background-image: -moz-linear-gradient(rgb(231,162,140), rgb(209,119,100) 49%, rgb(193,92,78) 51%, rgb(173,72,58));
+  -moz-box-shadow: 0 1px 0 rgba(0,0,0,.1) inset,
+                   -1px -1px 1px rgba(255,255,255,.25) inset;
+}
+
+#urlbar-stop-button:hover {
+  background-image: -moz-linear-gradient(rgb(244,156,128), rgb(215,101,77) 49%, rgb(194,66,48) 51%, rgb(170,41,23));
+}
+
+#urlbar-stop-button[disabled="true"] > .toolbarbutton-icon {
+  opacity: .5;
 }
 
 /* star button */
diff --git a/browser/themes/winstripe/browser/jar.mn b/browser/themes/winstripe/browser/jar.mn
index a6b030584d53..27978100b484 100644
--- a/browser/themes/winstripe/browser/jar.mn
+++ b/browser/themes/winstripe/browser/jar.mn
@@ -32,6 +32,7 @@ browser.jar:
         skin/classic/browser/livemark-folder.png                     (livemark-folder.png)
         skin/classic/browser/Privacy-16.png
         skin/classic/browser/Privacy-48.png
+        skin/classic/browser/reload-stop-go.png
         skin/classic/browser/Secure.png                              (Secure.png)
         skin/classic/browser/Secure24.png                            (Secure24.png)
         skin/classic/browser/Security-broken.png                     (Security-broken.png)
@@ -147,6 +148,7 @@ browser.jar:
         skin/classic/aero/browser/livemark-folder.png                (livemark-folder-aero.png)
         skin/classic/aero/browser/Privacy-16.png                     (Privacy-16-aero.png)
         skin/classic/aero/browser/Privacy-48.png                     (Privacy-48-aero.png)
+        skin/classic/aero/browser/reload-stop-go.png
         skin/classic/aero/browser/Secure.png                         (Secure-aero.png)
         skin/classic/aero/browser/Secure24.png                       (Secure24-aero.png)
         skin/classic/aero/browser/Security-broken.png                (Security-broken-aero.png)
diff --git a/browser/themes/winstripe/browser/reload-stop-go.png b/browser/themes/winstripe/browser/reload-stop-go.png
new file mode 100644
index 0000000000000000000000000000000000000000..e070eb424b03f8bedf69aaeab810f398cc3b28ec
GIT binary patch
literal 1590
zcmV-62Fdw}P)%Hl!*BEU^*ArivgKYOP641+1d7h+@EqRhw9w
z0P$57QH#|0U|G1!?wy`X7YfTRtxf#VxjC7cbLY;S@18Sf1`|Ti|Fz&iY8g~x$aOK#
z)fnnUCQMqqB^jM7u
zkzAHx(>R{bhG98Q06Y=Kuow=3?r4Nj8zST~w7&(J3-3OFy2SCjH#qzbRCT{t$P)*>
z8&tDEU*XE|pn#w$&9|B@(3B(!AVu)x4wrxc7b}y=D|k*Omn-DW8nya(XIGb>V6hk&
zicVvBo)d)bq2BQe55YA31;Ekcbly+(0lItFZnbbXTOQ1W=nn%p8i_Wu6S!oI&<6OC
zH>PlS)fGD=wB2Z$-YeQ{dKkk4^V-|#XmSK?1YITJ3q!}h>q??;inwQx;H)ci?
zs2@pQT(D|mSY_=+6@Wtk5bS7R(aBTo*((iC+gk691)zdAIlLOwHmMD8x=~(U&o&j7
zv=0-d$Bz{rMM-Ou6DrPB$NQYfMSR!D!}ausCg$IFzW*K#f8_(4gWG3nh$Q@b_k3JXYC4(rn?Up>^k(>
z?n2Yh)CuNe!ayxTOA>-O@E!O7JSX;!uo4m*GW+q7T@?@e0eO~tX0=+p9HzTt7nen&
zR$5wrZ+G-g{XhMfz7on|4a3m6*k)6W_VqP0EK45Vxve^0TC(NG;-Ym84%wA7i9_Z!
zdYfE9{!GjT#5Ro91=a*M;EO)g(L^T>sJ-iKDW>^{gB4<(X2mMVZk@~LcI
z=sW^&Cjjn<^gsFmBf>)qD2fu)YRwNHW_&yd((uum;M5iATi;7HjC3^eljTX(Jj)Q4
zV>iLx8w4r!S^wyC`qfB{GeEUQ6HjcmKo2i(>ki}TI<5Y-V&8G&OSYdpRXawj>w$Lx
z8h7_Zmj`_aHb96*1DFUYMn31fH9fTY3dYgww~mDdv;ejtmA&5+_)iQHV|$gpj1Yjzi=`3OkG_{SGOe;LiQDad#vF3hM1^`gJCnK*T9%3PS*0j
z(s&~^`>Xxq>o5MQ?l5=B)e4yqF>O*u*4nh|Qzz;7!jAX*R)DWTb~L4QbI0qGuQF?WzKkU;5jU^nb
oFY&$|1tMMRDxJYen+a07*qoM6N<$f*HQzl>h($

literal 0
HcmV?d00001

diff --git a/toolkit/content/widgets/autocomplete.xml b/toolkit/content/widgets/autocomplete.xml
index ce1bc8c6f563..46c626e8ce1a 100644
--- a/toolkit/content/widgets/autocomplete.xml
+++ b/toolkit/content/widgets/autocomplete.xml
@@ -79,6 +79,8 @@
                       xbl:inherits="open,enablehistory,parentfocused=focused"/>
 
       
+
+      
     
 
     

From 849e25849e01de54a532861e7057d31293322957 Mon Sep 17 00:00:00 2001
From: Justin Dolske 
Date: Thu, 2 Sep 2010 19:20:14 -0700
Subject: [PATCH 076/222] Bug 544816 - Attach combined Stop/Go/Refresh button
 to the Location Bar.  Perffix patch #1. a=blocker

---
 browser/base/content/browser.xul | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul
index ecf93407570c..32b7fdddf6ad 100644
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -836,7 +836,7 @@
                      ondragleave="homeButtonObserver.onDragLeave(event)"
                      onclick="BrowserGoHome(event);"/>
 
-      
         
Date: Fri, 3 Sep 2010 14:27:06 +1200
Subject: [PATCH 077/222] followup test only fix for SeaMonkey and Thunderbird
 for bug 583408. r=dtownsend, a=test bustage fix

---
 toolkit/mozapps/update/test/chrome/utils.js | 3 ---
 toolkit/mozapps/update/test/shared.js       | 3 +++
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/toolkit/mozapps/update/test/chrome/utils.js b/toolkit/mozapps/update/test/chrome/utils.js
index e5121d086eac..69a3ed1b5f47 100644
--- a/toolkit/mozapps/update/test/chrome/utils.js
+++ b/toolkit/mozapps/update/test/chrome/utils.js
@@ -143,9 +143,6 @@ const URI_UPDATE_PROMPT_DIALOG  = "chrome://mozapps/content/update/updates.xul";
 
 const CRC_ERROR = 4;
 
-const PREF_APP_UPDATE_CERT_INVALID_ATTR_NAME = PREF_APP_UPDATE_CERTS_BRANCH +
-                                               "1.invalidName";
-
 const ADDON_ID_SUFFIX = "@appupdatetest.mozilla.org";
 const ADDON_PREP_DIR = "appupdateprep";
 // Preference for storing add-ons that are disabled by the tests to prevent them
diff --git a/toolkit/mozapps/update/test/shared.js b/toolkit/mozapps/update/test/shared.js
index d1b43d5bf8ad..5c82782c75f3 100644
--- a/toolkit/mozapps/update/test/shared.js
+++ b/toolkit/mozapps/update/test/shared.js
@@ -59,6 +59,9 @@ const PREF_APP_UPDATE_URL                 = "app.update.url";
 const PREF_APP_UPDATE_URL_DETAILS         = "app.update.url.details";
 const PREF_APP_UPDATE_URL_OVERRIDE        = "app.update.url.override";
 
+const PREF_APP_UPDATE_CERT_INVALID_ATTR_NAME = PREF_APP_UPDATE_CERTS_BRANCH +
+                                               "1.invalidName";
+
 const PREF_APP_PARTNER_BRANCH             = "app.partner.";
 const PREF_DISTRIBUTION_ID                = "distribution.id";
 const PREF_DISTRIBUTION_VERSION           = "distribution.version";

From c64900878901d5b66e6ea42870ea460495ddeb53 Mon Sep 17 00:00:00 2001
From: Robert O'Callahan 
Date: Thu, 2 Sep 2010 21:18:39 +1200
Subject: [PATCH 078/222] Bug 579276. Part 1: Change layer/layermanager user
 data API to use keys and values. r=cjones,sr=vlad

---
 content/canvas/src/WebGLContext.cpp           |   4 +-
 .../canvas/src/nsCanvasRenderingContext2D.cpp |   4 +-
 gfx/layers/Layers.h                           | 113 ++++++++++++++++--
 layout/base/FrameLayerBuilder.cpp             |  59 +++++----
 4 files changed, 140 insertions(+), 40 deletions(-)

diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp
index 5882206473e4..c35058635638 100644
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -514,7 +514,7 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer,
                              LayerManager *aManager)
 {
     if (!mResetLayer && aOldLayer &&
-        aOldLayer->GetUserData() == &gWebGLLayerUserData) {
+        aOldLayer->HasUserData(&gWebGLLayerUserData)) {
         NS_ADDREF(aOldLayer);
         if (mInvalidated) {
             aOldLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
@@ -528,7 +528,7 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer,
         NS_WARNING("CreateCanvasLayer returned null!");
         return nsnull;
     }
-    canvasLayer->SetUserData(&gWebGLLayerUserData);
+    canvasLayer->SetUserData(&gWebGLLayerUserData, nsnull);
 
     CanvasLayer::Data data;
 
diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp
index c0a9f753d196..d76eee6f82e8 100644
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -4154,7 +4154,7 @@ nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer,
         return nsnull;
 
     if (!mResetLayer && aOldLayer &&
-        aOldLayer->GetUserData() == &g2DContextLayerUserData) {
+        aOldLayer->HasUserData(&g2DContextLayerUserData)) {
         NS_ADDREF(aOldLayer);
         // XXX Need to just update the changed area here
         aOldLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
@@ -4166,7 +4166,7 @@ nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer,
         NS_WARNING("CreateCanvasLayer returned null!");
         return nsnull;
     }
-    canvasLayer->SetUserData(&g2DContextLayerUserData);
+    canvasLayer->SetUserData(&g2DContextLayerUserData, nsnull);
 
     CanvasLayer::Data data;
 
diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h
index 47a9baab9b75..6643d60f0062 100644
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -83,6 +83,14 @@ class SpecificLayerAttributes;
   virtual const char* Name() const { return n; }            \
   virtual LayerType GetType() const { return e; }
 
+/**
+ * Base class for userdata objects attached to layers and layer managers.
+ */
+class THEBES_API LayerUserData {
+public:
+  virtual ~LayerUserData() {}
+};
+
 /*
  * Motivation: For truly smooth animation and video playback, we need to
  * be able to compose frames and render them on a dedicated thread (i.e.
@@ -109,6 +117,52 @@ class SpecificLayerAttributes;
  * BasicLayerManager for such an implementation.
  */
 
+/**
+ * Helper class to manage user data for layers and LayerManagers.
+ */
+class THEBES_API LayerUserDataSet {
+public:
+  LayerUserDataSet() : mKey(nsnull) {}
+
+  void Set(void* aKey, LayerUserData* aValue)
+  {
+    NS_ASSERTION(!mKey || mKey == aKey,
+                 "Multiple LayerUserData objects not supported");
+    mKey = aKey;
+    mValue = aValue;
+  }
+  /**
+   * This can be used anytime. Ownership passes to the caller!
+   */
+  LayerUserData* Remove(void* aKey)
+  {
+    if (mKey == aKey) {
+      mKey = nsnull;
+      LayerUserData* d = mValue.forget();
+      return d;
+    }
+    return nsnull;
+  }
+  /**
+   * This getter can be used anytime.
+   */
+  PRBool Has(void* aKey)
+  {
+    return mKey == aKey;
+  }
+  /**
+   * This getter can be used anytime. Ownership is retained by this object.
+   */
+  LayerUserData* Get(void* aKey)
+  {
+    return mKey == aKey ? mValue.get() : nsnull;
+  }
+
+private:
+  void* mKey;
+  nsAutoPtr mValue;
+};
+
 /**
  * A LayerManager controls a tree of layers. All layers in the tree
  * must use the same LayerManager.
@@ -142,7 +196,7 @@ public:
     LAYERS_D3D9
   };
 
-  LayerManager() : mUserData(nsnull), mDestroyed(PR_FALSE)
+  LayerManager() : mDestroyed(PR_FALSE)
   {
     InitLog();
   }
@@ -267,10 +321,28 @@ public:
    */
   virtual LayersBackend GetBackendType() = 0;
 
-  // This setter and getter can be used anytime. The user data is initially
-  // null.
-  void SetUserData(void* aData) { mUserData = aData; }
-  void* GetUserData() { return mUserData; }
+  /**
+   * This setter can be used anytime. The user data for all keys is
+   * initially null. Ownership pases to the layer manager.
+   */
+  void SetUserData(void* aKey, LayerUserData* aData)
+  { mUserData.Set(aKey, aData); }
+  /**
+   * This can be used anytime. Ownership passes to the caller!
+   */
+  nsAutoPtr RemoveUserData(void* aKey)
+  { nsAutoPtr d(mUserData.Remove(aKey)); return d; }
+  /**
+   * This getter can be used anytime.
+   */
+  PRBool HasUserData(void* aKey)
+  { return mUserData.Has(aKey); }
+  /**
+   * This getter can be used anytime. Ownership is retained by the layer
+   * manager.
+   */
+  LayerUserData* GetUserData(void* aKey)
+  { return mUserData.Get(aKey); }
 
   // We always declare the following logging symbols, because it's
   // extremely tricky to conditionally declare them.  However, for
@@ -305,7 +377,7 @@ public:
 
 protected:
   nsRefPtr mRoot;
-  void* mUserData;
+  LayerUserDataSet mUserData;
   PRPackedBool mDestroyed;
 
   // Print interesting information about this into aTo.  Internally
@@ -460,10 +532,28 @@ public:
   // quality.
   PRBool CanUseOpaqueSurface();
 
-  // This setter and getter can be used anytime. The user data is initially
-  // null.
-  void SetUserData(void* aData) { mUserData = aData; }
-  void* GetUserData() { return mUserData; }
+  /**
+   * This setter can be used anytime. The user data for all keys is
+   * initially null. Ownership pases to the layer manager.
+   */
+  void SetUserData(void* aKey, LayerUserData* aData)
+  { mUserData.Set(aKey, aData); }
+  /**
+   * This can be used anytime. Ownership passes to the caller!
+   */
+  nsAutoPtr RemoveUserData(void* aKey)
+  { nsAutoPtr d(mUserData.Remove(aKey)); return d; }
+  /**
+   * This getter can be used anytime.
+   */
+  PRBool HasUserData(void* aKey)
+  { return mUserData.Has(aKey); }
+  /**
+   * This getter can be used anytime. Ownership is retained by the layer
+   * manager.
+   */
+  LayerUserData* GetUserData(void* aKey)
+  { return mUserData.Get(aKey); }
 
   /**
    * Dynamic downcast to a Thebes layer. Returns null if this is not
@@ -519,7 +609,6 @@ protected:
     mNextSibling(nsnull),
     mPrevSibling(nsnull),
     mImplData(aImplData),
-    mUserData(nsnull),
     mOpacity(1.0),
     mUseClipRect(PR_FALSE),
     mIsOpaqueContent(PR_FALSE)
@@ -539,7 +628,7 @@ protected:
   Layer* mNextSibling;
   Layer* mPrevSibling;
   void* mImplData;
-  void* mUserData;
+  LayerUserDataSet mUserData;
   nsIntRegion mVisibleRegion;
   gfx3DMatrix mTransform;
   float mOpacity;
diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp
index 01c9797f776b..df505c492ba5 100644
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -57,14 +57,19 @@ namespace {
 /**
  * This is the userdata we associate with a layer manager.
  */
-class LayerManagerData {
+class LayerManagerData : public LayerUserData {
 public:
   LayerManagerData() :
     mInvalidateAllThebesContent(PR_FALSE),
     mInvalidateAllLayers(PR_FALSE)
   {
+    MOZ_COUNT_CTOR(LayerManagerData);
+
     mFramesWithLayers.Init();
   }
+  ~LayerManagerData() {
+    MOZ_COUNT_DTOR(LayerManagerData);
+  }
 
   /**
    * Tracks which frames have layers associated with them.
@@ -304,18 +309,26 @@ protected:
 
 /**
  * The address of gThebesDisplayItemLayerUserData is used as the user
- * data pointer for ThebesLayers created by FrameLayerBuilder.
+ * data key for ThebesLayers created by FrameLayerBuilder.
  * It identifies ThebesLayers used to draw non-layer content, which are
  * therefore eligible for recycling. We want display items to be able to
  * create their own dedicated ThebesLayers in BuildLayer, if necessary,
  * and we wouldn't want to accidentally recycle those.
+ * The user data is null.
  */
-static PRUint8 gThebesDisplayItemLayerUserData;
+PRUint8 gThebesDisplayItemLayerUserData;
 /**
  * The address of gColorLayerUserData is used as the user
- * data pointer for ColorLayers
+ * data key for ColorLayers created by FrameLayerBuilder.
+ * The user data is null.
  */
-static PRUint8 gColorLayerUserData;
+PRUint8 gColorLayerUserData;
+/**
+ * The address of gLayerManagerUserData is used as the user
+ * data key for retained LayerManagers managed by FrameLayerBuilder.
+ * The user data is a LayerManagerData.
+ */
+PRUint8 gLayerManagerUserData;
 
 } // anonymous namespace
 
@@ -342,12 +355,11 @@ FrameLayerBuilder::InternalDestroyDisplayItemData(nsIFrame* aFrame,
   if (aRemoveFromFramesWithLayers) {
     LayerManager* manager = array->ElementAt(0).mLayer->Manager();
     LayerManagerData* data = static_cast
-      (manager->GetUserData());
+      (manager->GetUserData(&gLayerManagerUserData));
     NS_ASSERTION(data, "Frame with layer should have been recorded");
     data->mFramesWithLayers.RemoveEntry(aFrame);
     if (data->mFramesWithLayers.Count() == 0) {
-      delete data;
-      manager->SetUserData(nsnull);
+      manager->RemoveUserData(&gLayerManagerUserData);
       // Consume the reference we added when we set the user data
       // in DidEndTransaction. But don't actually release until we've
       // released all the layers in the DisplayItemData array below!
@@ -371,7 +383,7 @@ FrameLayerBuilder::WillBeginRetainedLayerTransaction(LayerManager* aManager)
 {
   mRetainingManager = aManager;
   LayerManagerData* data = static_cast
-    (aManager->GetUserData());
+    (aManager->GetUserData(&gLayerManagerUserData));
   if (data) {
     mInvalidateAllThebesContent = data->mInvalidateAllThebesContent;
     mInvalidateAllLayers = data->mInvalidateAllLayers;
@@ -420,13 +432,13 @@ FrameLayerBuilder::WillEndTransaction(LayerManager* aManager)
   // correctly and the NS_FRAME_HAS_CONTAINER_LAYER bits will be set
   // correctly.
   LayerManagerData* data = static_cast
-    (mRetainingManager->GetUserData());
+    (mRetainingManager->GetUserData(&gLayerManagerUserData));
   if (data) {
     // Update all the frames that used to have layers.
     data->mFramesWithLayers.EnumerateEntries(UpdateDisplayItemDataForFrame, this);
   } else {
     data = new LayerManagerData();
-    mRetainingManager->SetUserData(data);
+    mRetainingManager->SetUserData(&gLayerManagerUserData, data);
     // Addref mRetainingManager. We'll release it when 'data' is
     // removed.
     NS_ADDREF(mRetainingManager);
@@ -595,7 +607,7 @@ ContainerState::CreateOrRecycleColorLayer()
     if (!layer)
       return nsnull;
     // Mark this layer as being used for Thebes-painting display items
-    layer->SetUserData(&gColorLayerUserData);
+    layer->SetUserData(&gColorLayerUserData, nsnull);
   }
   return layer.forget();
 }
@@ -637,7 +649,7 @@ ContainerState::CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot)
     if (!layer)
       return nsnull;
     // Mark this layer as being used for Thebes-painting display items
-    layer->SetUserData(&gThebesDisplayItemLayerUserData);
+    layer->SetUserData(&gThebesDisplayItemLayerUserData, nsnull);
   }
 
   // Set up transform so that 0,0 in the Thebes layer corresponds to the
@@ -965,7 +977,7 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
 
       // Update that layer's clip and visible rects.
       NS_ASSERTION(ownLayer->Manager() == mManager, "Wrong manager");
-      NS_ASSERTION(ownLayer->GetUserData() != &gThebesDisplayItemLayerUserData,
+      NS_ASSERTION(!ownLayer->HasUserData(&gLayerManagerUserData),
                    "We shouldn't have a FrameLayerBuilder-managed layer here!");
       // It has its own layer. Update that layer's clip and visible rects.
       if (aClipRect) {
@@ -1119,10 +1131,9 @@ ContainerState::CollectOldLayers()
 {
   for (Layer* layer = mContainerLayer->GetFirstChild(); layer;
        layer = layer->GetNextSibling()) {
-    void* data = layer->GetUserData();
-    if (data == &gColorLayerUserData) {
+    if (layer->HasUserData(&gColorLayerUserData)) {
       mRecycledColorLayers.AppendElement(static_cast(layer));
-    } else if (data == &gThebesDisplayItemLayerUserData) {
+    } else if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
       NS_ASSERTION(layer->AsThebesLayer(), "Wrong layer type");
       mRecycledThebesLayers.AppendElement(static_cast(layer));
     }
@@ -1203,7 +1214,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
     Layer* oldLayer = GetOldLayerFor(aContainerFrame, containerDisplayItemKey);
     if (oldLayer) {
       NS_ASSERTION(oldLayer->Manager() == aManager, "Wrong manager");
-      if (oldLayer->GetUserData() == &gThebesDisplayItemLayerUserData) {
+      if (oldLayer->HasUserData(&gThebesDisplayItemLayerUserData)) {
         // The old layer for this item is actually our ThebesLayer
         // because we rendered its layer into that ThebesLayer. So we
         // don't actually have a retained container layer.
@@ -1276,7 +1287,7 @@ FrameLayerBuilder::GetLeafLayerFor(nsDisplayListBuilder* aBuilder,
   Layer* layer = GetOldLayerFor(f, aItem->GetPerFrameKey());
   if (!layer)
     return nsnull;
-  if (layer->GetUserData() == &gThebesDisplayItemLayerUserData) {
+  if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
     // This layer was created to render Thebes-rendered content for this
     // display item. The display item should not use it for its own
     // layer rendering.
@@ -1352,7 +1363,7 @@ FrameLayerBuilder::InvalidateThebesLayersInSubtree(nsIFrame* aFrame)
 FrameLayerBuilder::InvalidateAllThebesLayerContents(LayerManager* aManager)
 {
   LayerManagerData* data = static_cast
-    (aManager->GetUserData());
+    (aManager->GetUserData(&gLayerManagerUserData));
   if (data) {
     data->mInvalidateAllThebesContent = PR_TRUE;
   }
@@ -1362,7 +1373,7 @@ FrameLayerBuilder::InvalidateAllThebesLayerContents(LayerManager* aManager)
 FrameLayerBuilder::InvalidateAllLayers(LayerManager* aManager)
 {
   LayerManagerData* data = static_cast
-    (aManager->GetUserData());
+    (aManager->GetUserData(&gLayerManagerUserData));
   if (data) {
     data->mInvalidateAllLayers = PR_TRUE;
   }
@@ -1380,9 +1391,9 @@ FrameLayerBuilder::HasDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
     (reinterpret_cast*>(&propValue));
   for (PRUint32 i = 0; i < array->Length(); ++i) {
     if (array->ElementAt(i).mDisplayItemKey == aDisplayItemKey) {
-      void* layerUserData = array->ElementAt(i).mLayer->GetUserData();
-      if (layerUserData != &gColorLayerUserData &&
-          layerUserData != &gThebesDisplayItemLayerUserData)
+      Layer* layer = array->ElementAt(i).mLayer;
+      if (!layer->HasUserData(&gColorLayerUserData) &&
+          !layer->HasUserData(&gThebesDisplayItemLayerUserData))
         return PR_TRUE;
     }
   }

From add75cf1da0244be69b76b21b92f5192976d30a1 Mon Sep 17 00:00:00 2001
From: Robert O'Callahan 
Date: Thu, 2 Sep 2010 21:18:39 +1200
Subject: [PATCH 079/222] Bug 579276. Part 2: If a transparent layer is over a
 solid background color, hoist that color into the layer to make it opaque.
 r=tnikkel

---
 layout/base/FrameLayerBuilder.cpp | 148 ++++++++++++++++++++++++++----
 layout/base/FrameLayerBuilder.h   |  20 ++++
 2 files changed, 148 insertions(+), 20 deletions(-)

diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp
index df505c492ba5..3949bef8d325 100644
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -64,10 +64,13 @@ public:
     mInvalidateAllLayers(PR_FALSE)
   {
     MOZ_COUNT_CTOR(LayerManagerData);
-
     mFramesWithLayers.Init();
   }
   ~LayerManagerData() {
+    // Remove display item data properties now, since we won't be able
+    // to find these frames again without mFramesWithLayers.
+    mFramesWithLayers.EnumerateEntries(
+        FrameLayerBuilder::RemoveDisplayItemDataForFrame, nsnull);
     MOZ_COUNT_DTOR(LayerManagerData);
   }
 
@@ -250,6 +253,12 @@ protected:
    * aItem in that layer.
    */
   void InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer);
+  /**
+   * Try to determine whether the ThebesLayer at aThebesLayerIndex
+   * has an opaque single color covering the visible area behind it.
+   * If successful, return that color, otherwise return NS_RGBA(0,0,0,0).
+   */
+  nscolor FindOpaqueBackgroundColorFor(PRInt32 aThebesLayerIndex);
   /**
    * Indicate that we are done adding items to the ThebesLayer at the top of
    * mThebesLayerDataStack. Set the final visible region and opaque-content
@@ -307,6 +316,15 @@ protected:
   PRPackedBool                     mInvalidateAllThebesContent;
 };
 
+class ThebesDisplayItemLayerUserData : public LayerUserData
+{
+public:
+  ThebesDisplayItemLayerUserData() :
+    mForcedBackgroundColor(NS_RGBA(0,0,0,0)) {}
+
+  nscolor mForcedBackgroundColor;
+};
+
 /**
  * The address of gThebesDisplayItemLayerUserData is used as the user
  * data key for ThebesLayers created by FrameLayerBuilder.
@@ -314,7 +332,7 @@ protected:
  * therefore eligible for recycling. We want display items to be able to
  * create their own dedicated ThebesLayers in BuildLayer, if necessary,
  * and we wouldn't want to accidentally recycle those.
- * The user data is null.
+ * The user data is a ThebesDisplayItemLayerUserData.
  */
 PRUint8 gThebesDisplayItemLayerUserData;
 /**
@@ -462,7 +480,7 @@ FrameLayerBuilder::UpdateDisplayItemDataForFrame(nsPtrHashKey* aEntry,
   nsIFrame* f = aEntry->GetKey();
   FrameProperties props = f->Properties();
   DisplayItemDataEntry* newDisplayItems =
-    builder->mNewDisplayItemData.GetEntry(f);
+    builder ? builder->mNewDisplayItemData.GetEntry(f) : nsnull;
   if (!newDisplayItems) {
     // This frame was visible, but isn't anymore.
     PRBool found;
@@ -649,7 +667,8 @@ ContainerState::CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot)
     if (!layer)
       return nsnull;
     // Mark this layer as being used for Thebes-painting display items
-    layer->SetUserData(&gThebesDisplayItemLayerUserData, nsnull);
+    layer->SetUserData(&gThebesDisplayItemLayerUserData,
+        new ThebesDisplayItemLayerUserData());
   }
 
   // Set up transform so that 0,0 in the Thebes layer corresponds to the
@@ -709,6 +728,39 @@ SetVisibleRectForLayer(Layer* aLayer, const nsIntRect& aRect)
   }
 }
 
+nscolor
+ContainerState::FindOpaqueBackgroundColorFor(PRInt32 aThebesLayerIndex)
+{
+  ThebesLayerData* target = mThebesLayerDataStack[aThebesLayerIndex];
+  for (PRInt32 i = aThebesLayerIndex - 1; i >= 0; --i) {
+    ThebesLayerData* candidate = mThebesLayerDataStack[i];
+    nsIntRegion visibleAboveIntersection;
+    visibleAboveIntersection.And(candidate->mVisibleAboveRegion, target->mVisibleRegion);
+    if (!visibleAboveIntersection.IsEmpty()) {
+      // Some non-Thebes content between target and candidate; this is
+      // hopeless
+      break;
+    }
+
+    nsIntRegion intersection;
+    intersection.And(candidate->mVisibleRegion, target->mVisibleRegion);
+    if (intersection.IsEmpty()) {
+      // The layer doesn't intersect our target, ignore it and move on
+      continue;
+    }
+ 
+    // The candidate intersects our target. If any layer has a solid-color
+    // area behind our target, this must be it. Scan its display items.
+    nsPresContext* presContext = mContainerFrame->PresContext();
+    nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
+    nsRect rect =
+      target->mVisibleRegion.GetBounds().ToAppUnits(appUnitsPerDevPixel);
+    return mBuilder->LayerBuilder()->
+      FindOpaqueColorCovering(mBuilder, candidate->mLayer, rect);
+  }
+  return NS_RGBA(0,0,0,0);
+}
+
 void
 ContainerState::PopThebesLayerData()
 {
@@ -717,21 +769,6 @@ ContainerState::PopThebesLayerData()
   PRInt32 lastIndex = mThebesLayerDataStack.Length() - 1;
   ThebesLayerData* data = mThebesLayerDataStack[lastIndex];
 
-  if (lastIndex > 0) {
-    // Since we're going to pop off the last ThebesLayerData, the
-    // mVisibleAboveRegion of the second-to-last item will need to include
-    // the regions of the last item.
-    ThebesLayerData* nextData = mThebesLayerDataStack[lastIndex - 1];
-    nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion,
-                                     data->mVisibleAboveRegion);
-    nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion,
-                                     data->mVisibleRegion);
-    nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion,
-                                     data->mDrawAboveRegion);
-    nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion,
-                                     data->mDrawRegion);
-  }
-
   Layer* layer;
   if (data->mIsSolidColorInVisibleRegion) {
     nsRefPtr colorLayer = CreateOrRecycleColorLayer();
@@ -778,7 +815,47 @@ ContainerState::PopThebesLayerData()
 
   nsIntRegion transparentRegion;
   transparentRegion.Sub(data->mVisibleRegion, data->mOpaqueRegion);
-  layer->SetIsOpaqueContent(transparentRegion.IsEmpty());
+  PRBool isOpaque = transparentRegion.IsEmpty();
+  // For translucent ThebesLayers, try to find an opaque background
+  // color that covers the entire area beneath it so we can pull that
+  // color into this layer to make it opaque.
+  if (layer == data->mLayer) {
+    nscolor backgroundColor = NS_RGBA(0,0,0,0);
+    if (!isOpaque) {
+      backgroundColor = FindOpaqueBackgroundColorFor(lastIndex);
+      if (NS_GET_A(backgroundColor) == 255) {
+        isOpaque = PR_TRUE;
+      }
+    }
+
+    // Store the background color
+    ThebesDisplayItemLayerUserData* userData =
+      static_cast
+        (data->mLayer->GetUserData(&gThebesDisplayItemLayerUserData));
+    NS_ASSERTION(userData, "where did our user data go?");
+    if (userData->mForcedBackgroundColor != backgroundColor) {
+      // Invalidate the entire target ThebesLayer since we're changing
+      // the background color
+      data->mLayer->InvalidateRegion(data->mLayer->GetValidRegion());
+    }
+    userData->mForcedBackgroundColor = backgroundColor;
+  }
+  layer->SetIsOpaqueContent(isOpaque);
+
+  if (lastIndex > 0) {
+    // Since we're going to pop off the last ThebesLayerData, the
+    // mVisibleAboveRegion of the second-to-last item will need to include
+    // the regions of the last item.
+    ThebesLayerData* nextData = mThebesLayerDataStack[lastIndex - 1];
+    nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion,
+                                     data->mVisibleAboveRegion);
+    nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion,
+                                     data->mVisibleRegion);
+    nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion,
+                                     data->mDrawAboveRegion);
+    nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion,
+                                     data->mDrawRegion);
+  }
 
   mThebesLayerDataStack.RemoveElementAt(lastIndex);
 }
@@ -1126,6 +1203,28 @@ FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
   }
 }
 
+nscolor
+FrameLayerBuilder::FindOpaqueColorCovering(nsDisplayListBuilder* aBuilder,
+                                           ThebesLayer* aLayer,
+                                           const nsRect& aRect)
+{
+  ThebesLayerItemsEntry* entry = mThebesLayerItems.GetEntry(aLayer);
+  NS_ASSERTION(entry, "Must know about this layer!");
+  for (PRInt32 i = entry->mItems.Length() - 1; i >= 0; --i) {
+    nsDisplayItem* item = entry->mItems[i].mItem;
+    const nsRect& visible = item->GetVisibleRect();
+    if (!visible.Intersects(aRect))
+      continue;
+
+    nscolor color;
+    if (visible.Contains(aRect) && item->IsUniform(aBuilder, &color) &&
+        NS_GET_A(color) == 255)
+      return color;
+    break;
+  }
+  return NS_RGBA(0,0,0,0);
+}
+
 void
 ContainerState::CollectOldLayers()
 {
@@ -1422,6 +1521,15 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
     // so 'entry' could become invalid.
   }
 
+  ThebesDisplayItemLayerUserData* userData =
+    static_cast
+      (aLayer->GetUserData(&gThebesDisplayItemLayerUserData));
+  NS_ASSERTION(userData, "where did our user data go?");
+  if (NS_GET_A(userData->mForcedBackgroundColor) > 0) {
+    aContext->SetColor(gfxRGBA(userData->mForcedBackgroundColor));
+    aContext->Paint();
+  }
+
   gfxMatrix transform;
   if (!aLayer->GetTransform().Is2D(&transform)) {
     NS_ERROR("non-2D transform in our Thebes layer!");
diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h
index e3e082068994..4cce9ebbcb70 100644
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -243,6 +243,26 @@ public:
    */
   Layer* GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey);
 
+  /**
+   * A useful hashtable iteration function that removes the
+   * DisplayItemData property for the frame, clears its
+   * NS_FRAME_HAS_CONTAINER_LAYER bit and returns PL_DHASH_REMOVE.
+   * aClosure is ignored.
+   */
+  static PLDHashOperator RemoveDisplayItemDataForFrame(nsPtrHashKey* aEntry,
+                                                       void* aClosure)
+  {
+    return UpdateDisplayItemDataForFrame(aEntry, nsnull);
+  }
+
+  /**
+   * Try to determine whether the ThebesLayer aLayer paints an opaque
+   * single color everywhere it's visible in aRect.
+   * If successful, return that color, otherwise return NS_RGBA(0,0,0,0).
+   */
+  nscolor FindOpaqueColorCovering(nsDisplayListBuilder* aBuilder,
+                                  ThebesLayer* aLayer, const nsRect& aRect);
+
 protected:
   /**
    * We store an array of these for each frame that is associated with

From 8f85c65afc57393eaf712a71c92806f900e4da53 Mon Sep 17 00:00:00 2001
From: Robert O'Callahan 
Date: Thu, 2 Sep 2010 21:18:39 +1200
Subject: [PATCH 080/222] Bug 579276. Part 8: Bump scroll timeout up a lot.
 r=tnikkel

---
 layout/generic/nsGfxScrollFrame.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp
index df8ff01b4f95..364bf10385b5 100644
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -1251,9 +1251,9 @@ IsSmoothScrollingEnabled()
 
 class ScrollFrameActivityTracker : public nsExpirationTracker {
 public:
-  // Wait for 75-100ms between scrolls before we switch the appearance back to
-  // subpixel AA. That's 4 generations of 25ms each.
-  enum { TIMEOUT_MS = 25 };
+  // Wait for 3-4s between scrolls before we remove our layers.
+  // That's 4 generations of 1s each.
+  enum { TIMEOUT_MS = 1000 };
   ScrollFrameActivityTracker()
     : nsExpirationTracker(TIMEOUT_MS) {}
   ~ScrollFrameActivityTracker() {

From 61c4b7a2c44d5102ac3618fad98298ee0f38d625 Mon Sep 17 00:00:00 2001
From: Robert O'Callahan 
Date: Thu, 2 Sep 2010 21:18:39 +1200
Subject: [PATCH 081/222] Bug 579276. Part 4: Move nsDisplayItem parameter down
 to ThebesLayerData::Accumulate. r=tnikkel

---
 layout/base/FrameLayerBuilder.cpp | 56 +++++++++++++------------------
 1 file changed, 24 insertions(+), 32 deletions(-)

diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp
index 3949bef8d325..1932ea1a5127 100644
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -173,10 +173,10 @@ protected:
      * @param aSolidColor if non-null, the visible area of the item is
      * a constant color given by *aSolidColor
      */
-    void Accumulate(const nsIntRect& aVisibleRect,
-                    const nsIntRect& aDrawRect,
-                    const nsIntRect* aOpaqueRect,
-                    nscolor* aSolidColor);
+    void Accumulate(nsDisplayListBuilder* aBuilder,
+                    nsDisplayItem* aItem,
+                    const nsIntRect& aVisibleRect,
+                    const nsIntRect& aDrawRect);
     nsIFrame* GetActiveScrolledRoot() { return mActiveScrolledRoot; }
 
     /**
@@ -282,11 +282,10 @@ protected:
    * @param aSolidColor if non-null, indicates that every pixel in aVisibleRect
    * will be painted with aSolidColor by the item
    */
-  already_AddRefed FindThebesLayerFor(const nsIntRect& aVisibleRect,
+  already_AddRefed FindThebesLayerFor(nsDisplayItem* aItem,
+                                                   const nsIntRect& aVisibleRect,
                                                    const nsIntRect& aDrawRect,
-                                                   nsIFrame* aActiveScrolledRoot,
-                                                   const nsIntRect* aOpaqueRect,
-                                                   nscolor* aSolidColor);
+                                                   nsIFrame* aActiveScrolledRoot);
   ThebesLayerData* GetTopThebesLayerData()
   {
     return mThebesLayerDataStack.IsEmpty() ? nsnull
@@ -861,20 +860,21 @@ ContainerState::PopThebesLayerData()
 }
 
 void
-ContainerState::ThebesLayerData::Accumulate(const nsIntRect& aVisibleRect,
-                                            const nsIntRect& aDrawRect,
-                                            const nsIntRect* aOpaqueRect,
-                                            nscolor* aSolidColor)
+ContainerState::ThebesLayerData::Accumulate(nsDisplayListBuilder* aBuilder,
+                                            nsDisplayItem* aItem,
+                                            const nsIntRect& aVisibleRect,
+                                            const nsIntRect& aDrawRect)
 {
-  if (aSolidColor) {
+  nscolor uniformColor;
+  if (aItem->IsUniform(aBuilder, &uniformColor)) {
     if (mVisibleRegion.IsEmpty()) {
       // This color is all we have
-      mSolidColor = *aSolidColor;
+      mSolidColor = uniformColor;
       mIsSolidColorInVisibleRegion = PR_TRUE;
     } else if (mIsSolidColorInVisibleRegion &&
                mVisibleRegion.IsEqual(nsIntRegion(aVisibleRect))) {
       // we can just blend the colors together
-      mSolidColor = NS_ComposeColors(mSolidColor, *aSolidColor);
+      mSolidColor = NS_ComposeColors(mSolidColor, uniformColor);
     } else {
       mIsSolidColorInVisibleRegion = PR_FALSE;
     }
@@ -886,14 +886,15 @@ ContainerState::ThebesLayerData::Accumulate(const nsIntRect& aVisibleRect,
   mVisibleRegion.SimplifyOutward(4);
   mDrawRegion.Or(mDrawRegion, aDrawRect);
   mDrawRegion.SimplifyOutward(4);
-  if (aOpaqueRect) {
+
+  if (aItem->IsOpaque(aBuilder)) {
     // We don't use SimplifyInward here since it's not defined exactly
     // what it will discard. For our purposes the most important case
     // is a large opaque background at the bottom of z-order (e.g.,
     // a canvas background), so we need to make sure that the first rect
     // we see doesn't get discarded.
     nsIntRegion tmp;
-    tmp.Or(mOpaqueRegion, *aOpaqueRect);
+    tmp.Or(mOpaqueRegion, aDrawRect);
     if (tmp.GetNumRects() <= 4) {
       mOpaqueRegion = tmp;
     }
@@ -901,11 +902,10 @@ ContainerState::ThebesLayerData::Accumulate(const nsIntRect& aVisibleRect,
 }
 
 already_AddRefed
-ContainerState::FindThebesLayerFor(const nsIntRect& aVisibleRect,
+ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
+                                   const nsIntRect& aVisibleRect,
                                    const nsIntRect& aDrawRect,
-                                   nsIFrame* aActiveScrolledRoot,
-                                   const nsIntRect* aOpaqueRect,
-                                   nscolor* aSolidColor)
+                                   nsIFrame* aActiveScrolledRoot)
 {
   PRInt32 i;
   PRInt32 lowestUsableLayerWithScrolledRoot = -1;
@@ -959,7 +959,7 @@ ContainerState::FindThebesLayerFor(const nsIntRect& aVisibleRect,
     layer = thebesLayerData->mLayer;
   }
 
-  thebesLayerData->Accumulate(aVisibleRect, aDrawRect, aOpaqueRect, aSolidColor);
+  thebesLayerData->Accumulate(mBuilder, aItem, aVisibleRect, aDrawRect);
   return layer.forget();
 }
 
@@ -1105,17 +1105,9 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
           nsLayoutUtils::GetActiveScrolledRootFor(viewportFrame, mBuilder->ReferenceFrame());
       }
 
-      nscolor uniformColor;
-      PRBool isUniform = item->IsUniform(mBuilder, &uniformColor);
-      PRBool isOpaque = item->IsOpaque(mBuilder);
-      nsIntRect opaqueRect;
-      if (isOpaque) {
-        opaqueRect = item->GetBounds(mBuilder).ToNearestPixels(appUnitsPerDevPixel);
-      }
       nsRefPtr thebesLayer =
-        FindThebesLayerFor(itemVisibleRect, itemDrawRect, activeScrolledRoot,
-                           isOpaque ? &opaqueRect : nsnull,
-                           isUniform ? &uniformColor : nsnull);
+        FindThebesLayerFor(item, itemVisibleRect, itemDrawRect,
+                           activeScrolledRoot);
 
       InvalidateForLayerChange(item, thebesLayer);
 

From be2d05f9a8a96a08be8e3159b4a744d7a6fc3305 Mon Sep 17 00:00:00 2001
From: Robert O'Callahan 
Date: Thu, 2 Sep 2010 21:18:40 +1200
Subject: [PATCH 082/222] Bug 579276. Part 3: Change Set/IsOpaqueContent API to
 a more generic Get/SetContentFlags API. r=cjones,sr=vlad

---
 content/canvas/src/WebGLContext.cpp           |  4 +-
 .../canvas/src/nsCanvasRenderingContext2D.cpp |  3 +-
 gfx/layers/Layers.cpp                         | 20 ++++++---
 gfx/layers/Layers.h                           | 42 ++++++++++++++-----
 gfx/layers/basic/BasicLayers.cpp              |  4 +-
 gfx/layers/d3d9/ThebesLayerD3D9.cpp           | 36 ++++------------
 gfx/layers/ipc/PLayers.ipdl                   |  2 +-
 gfx/layers/ipc/ShadowLayers.cpp               |  2 +-
 gfx/layers/ipc/ShadowLayersParent.cpp         |  2 +-
 layout/base/FrameLayerBuilder.cpp             |  6 ++-
 10 files changed, 68 insertions(+), 53 deletions(-)

diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp
index c35058635638..89bb9d15f40e 100644
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -63,6 +63,7 @@
 
 using namespace mozilla;
 using namespace mozilla::gl;
+using namespace mozilla::layers;
 
 nsresult NS_NewCanvasRenderingContextWebGL(nsICanvasRenderingContextWebGL** aResult);
 
@@ -548,7 +549,8 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer,
     data.mGLBufferIsPremultiplied = PR_FALSE;
 
     canvasLayer->Initialize(data);
-    canvasLayer->SetIsOpaqueContent(gl->CreationFormat().alpha == 0 ? PR_TRUE : PR_FALSE);
+    PRUint32 flags = gl->CreationFormat().alpha == 0 ? Layer::CONTENT_OPAQUE : 0;
+    canvasLayer->SetContentFlags(flags);
     canvasLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
 
     mInvalidated = PR_FALSE;
diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp
index d76eee6f82e8..49a9e52f909a 100644
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -4174,7 +4174,8 @@ nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer,
     data.mSize = nsIntSize(mWidth, mHeight);
 
     canvasLayer->Initialize(data);
-    canvasLayer->SetIsOpaqueContent(mOpaque);
+    PRUint32 flags = mOpaque ? Layer::CONTENT_OPAQUE : 0;
+    canvasLayer->SetContentFlags(flags);
     canvasLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
 
     mResetLayer = PR_FALSE;
diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp
index cccbd3d76a4d..d622b01a5e9e 100644
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -147,7 +147,7 @@ Layer::CanUseOpaqueSurface()
 {
   // If the visible content in the layer is opaque, there is no need
   // for an alpha channel.
-  if (IsOpaqueContent())
+  if (GetContentFlags() & CONTENT_OPAQUE)
     return PR_TRUE;
   // Also, if this layer is the bottommost layer in a container which
   // doesn't need an alpha channel, we can use an opaque surface for this
@@ -221,14 +221,24 @@ Layer::PrintInfo(nsACString& aTo, const char* aPrefix)
   if (mUseClipRect) {
     AppendToString(aTo, mClipRect, " [clip=", "]");
   }
-  if (!mTransform.IsIdentity())
+  if (!mTransform.IsIdentity()) {
     AppendToString(aTo, mTransform, " [transform=", "]");
-  if (!mVisibleRegion.IsEmpty())
+  }
+  if (!mVisibleRegion.IsEmpty()) {
     AppendToString(aTo, mVisibleRegion, " [visible=", "]");
-  if (1.0 != mOpacity)
+  }
+  if (1.0 != mOpacity) {
     aTo.AppendPrintf(" [opacity=%g]", mOpacity);
-  if (IsOpaqueContent())
+  }
+  if (GetContentFlags() & CONTENT_OPAQUE) {
     aTo += " [opaqueContent]";
+  }
+  if (GetContentFlags() & CONTENT_NO_TEXT) {
+    aTo += " [noText]";
+  }
+  if (GetContentFlags() & CONTENT_NO_TEXT_OVER_TRANSPARENT) {
+    aTo += " [noTextOverTransparent]";
+  }
 
   return aTo;
 }
diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h
index 6643d60f0062..fe1e996f2979 100644
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -416,17 +416,37 @@ public:
    */
   LayerManager* Manager() { return mManager; }
 
+  enum {
+    /**
+     * If this is set, the caller is promising that by the end of this
+     * transaction the entire visible region (as specified by
+     * SetVisibleRegion) will be filled with opaque content.
+     */
+    CONTENT_OPAQUE = 0x01,
+    /**
+     * ThebesLayers only!
+     * If this is set, the caller is promising that the visible region
+     * contains no text at all. If this is set,
+     * CONTENT_NO_TEXT_OVER_TRANSPARENT will also be set.
+     */
+    CONTENT_NO_TEXT = 0x02,
+    /**
+     * ThebesLayers only!
+     * If this is set, the caller is promising that the visible region
+     * contains no text over transparent pixels (any text, if present,
+     * is over fully opaque pixels).
+     */
+    CONTENT_NO_TEXT_OVER_TRANSPARENT = 0x04
+  };
   /**
    * CONSTRUCTION PHASE ONLY
-   * If this is called with aOpaque set to true, the caller is promising
-   * that by the end of this transaction the entire visible region
-   * (as specified by SetVisibleRegion) will be filled with opaque
-   * content. This enables some internal quality and performance
-   * optimizations.
+   * This lets layout make some promises about what will be drawn into the
+   * visible region of the ThebesLayer. This enables internal quality
+   * and performance optimizations.
    */
-  void SetIsOpaqueContent(PRBool aOpaque)
+  void SetContentFlags(PRUint32 aFlags)
   {
-    mIsOpaqueContent = aOpaque;
+    mContentFlags = aFlags;
     Mutated();
   }
   /**
@@ -509,7 +529,7 @@ public:
   // These getters can be used anytime.
   float GetOpacity() { return mOpacity; }
   const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nsnull; }
-  PRBool IsOpaqueContent() { return mIsOpaqueContent; }
+  PRUint32 GetContentFlags() { return mContentFlags; }
   const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; }
   ContainerLayer* GetParent() { return mParent; }
   Layer* GetNextSibling() { return mNextSibling; }
@@ -610,8 +630,8 @@ protected:
     mPrevSibling(nsnull),
     mImplData(aImplData),
     mOpacity(1.0),
-    mUseClipRect(PR_FALSE),
-    mIsOpaqueContent(PR_FALSE)
+    mContentFlags(0),
+    mUseClipRect(PR_FALSE)
     {}
 
   void Mutated() { mManager->Mutated(this); }
@@ -633,8 +653,8 @@ protected:
   gfx3DMatrix mTransform;
   float mOpacity;
   nsIntRect mClipRect;
+  PRUint32 mContentFlags;
   PRPackedBool mUseClipRect;
-  PRPackedBool mIsOpaqueContent;
 };
 
 /**
diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp
index 217ad5926375..1cbac945e8a8 100644
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -682,7 +682,7 @@ BasicCanvasLayer::Updated(const nsIntRect& aRect)
   if (mGLContext) {
     nsRefPtr isurf =
       new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height),
-                          IsOpaqueContent()
+                          (GetContentFlags() & CONTENT_OPAQUE)
                             ? gfxASurface::ImageFormatRGB24
                             : gfxASurface::ImageFormatARGB32);
     if (!isurf || isurf->CairoStatus() != 0) {
@@ -793,7 +793,7 @@ MayHaveOverlappingOrTransparentLayers(Layer* aLayer,
                                       const nsIntRect& aBounds,
                                       nsIntRegion* aDirtyVisibleRegionInContainer)
 {
-  if (!aLayer->IsOpaqueContent()) {
+  if (!(aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE)) {
     return PR_TRUE;
   }
 
diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.cpp b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
index 438e73f0eea3..8e7092a4f08d 100644
--- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
@@ -46,27 +46,6 @@
 namespace mozilla {
 namespace layers {
 
-// Returns true if it's OK to save the contents of aLayer in an
-// opaque surface (a surface without an alpha channel).
-// If we can use a surface without an alpha channel, we should, because
-// it will often make painting of antialiased text faster and higher
-// quality.
-static PRBool
-UseOpaqueSurface(Layer* aLayer)
-{
-  // If the visible content in the layer is opaque, there is no need
-  // for an alpha channel.
-  if (aLayer->IsOpaqueContent())
-    return PR_TRUE;
-  // Also, if this layer is the bottommost layer in a container which
-  // doesn't need an alpha channel, we can use an opaque surface for this
-  // layer too. Any transparent areas must be covered by something else
-  // in the container.
-  ContainerLayer* parent = aLayer->GetParent();
-  return parent && parent->GetFirstChild() == aLayer &&
-         UseOpaqueSurface(parent);
-}
-
 ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager)
   : ThebesLayer(aManager, NULL)
   , LayerD3D9(aManager)
@@ -105,7 +84,7 @@ ThebesLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion)
     return;
   }
 
-  D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ?
+  D3DFORMAT fmt = (CanUseOpaqueSurface() && !mD2DSurface) ?
                     D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
 
   D3DSURFACE_DESC desc;
@@ -199,7 +178,7 @@ ThebesLayerD3D9::RenderLayer()
 
   // We differentiate between these formats since D3D9 will only allow us to
   // call GetDC on an opaque surface.
-  D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ?
+  D3DFORMAT fmt = (CanUseOpaqueSurface() && !mD2DSurface) ?
                     D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
 
   if (mTexture) {
@@ -319,7 +298,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion)
   }
 #endif
 
-  D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
+  D3DFORMAT fmt = CanUseOpaqueSurface() ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
   nsIntRect bounds = aRegion.GetBounds();
 
   gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32;
@@ -332,7 +311,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion)
 
   nsRefPtr surf;
   HDC dc;
-  if (UseOpaqueSurface(this)) {
+  if (CanUseOpaqueSurface()) {
     hr = tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surf));
 
     if (FAILED(hr)) {
@@ -365,7 +344,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion)
   LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
   cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
 
-  if (UseOpaqueSurface(this)) {
+  if (CanUseOpaqueSurface()) {
     surf->ReleaseDC(dc);
   } else {
     D3DLOCKED_RECT r;
@@ -418,6 +397,7 @@ ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize)
   }
 
   mTexture = nsnull;
+  PRBool canUseOpaqueSurface = CanUseOpaqueSurface();
 #ifdef CAIRO_HAS_D2D_SURFACE
   if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
       gfxWindowsPlatform::RENDER_DIRECT2D) {
@@ -429,7 +409,7 @@ ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize)
                                   D3DPOOL_DEFAULT, getter_AddRefs(mTexture), &sharedHandle);
 
           mD2DSurfaceInitialized = false;
-          mD2DSurface = new gfxD2DSurface(sharedHandle, UseOpaqueSurface(this) ?
+          mD2DSurface = new gfxD2DSurface(sharedHandle, canUseOpaqueSurface ?
             gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA);
 
           // If there's an error, go on and do what we always do.
@@ -442,7 +422,7 @@ ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize)
 #endif
   if (!mTexture) {
     device()->CreateTexture(aSize.width, aSize.height, 1,
-                            D3DUSAGE_RENDERTARGET, UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
+                            D3DUSAGE_RENDERTARGET, canUseOpaqueSurface ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
                             D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
   }
 }
diff --git a/gfx/layers/ipc/PLayers.ipdl b/gfx/layers/ipc/PLayers.ipdl
index 7f90abff46c9..fdde16ca6893 100644
--- a/gfx/layers/ipc/PLayers.ipdl
+++ b/gfx/layers/ipc/PLayers.ipdl
@@ -93,7 +93,7 @@ struct OpCreateImageBuffer {
 struct CommonLayerAttributes {
   nsIntRegion visibleRegion;
   gfx3DMatrix transform;
-  bool isOpaqueContent;
+  PRUint32 contentFlags;
   float opacity;
   bool useClipRect;
   nsIntRect clipRect;
diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp
index f0222eb63c08..dc6b1ea6de32 100644
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -271,7 +271,7 @@ ShadowLayerForwarder::EndTransaction(nsTArray* aReplies)
     CommonLayerAttributes& common = attrs.common();
     common.visibleRegion() = mutant->GetVisibleRegion();
     common.transform() = mutant->GetTransform();
-    common.isOpaqueContent() = mutant->IsOpaqueContent();
+    common.contentFlags() = mutant->GetContentFlags();
     common.opacity() = mutant->GetOpacity();
     common.useClipRect() = !!mutant->GetClipRect();
     common.clipRect() = (common.useClipRect() ?
diff --git a/gfx/layers/ipc/ShadowLayersParent.cpp b/gfx/layers/ipc/ShadowLayersParent.cpp
index 9b4b71428132..e61d886bce39 100644
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -229,7 +229,7 @@ ShadowLayersParent::RecvUpdate(const nsTArray& cset,
 
       const CommonLayerAttributes& common = attrs.common();
       layer->SetVisibleRegion(common.visibleRegion());
-      layer->SetIsOpaqueContent(common.isOpaqueContent());
+      layer->SetContentFlags(common.contentFlags());
       layer->SetOpacity(common.opacity());
       layer->SetClipRect(common.useClipRect() ? &common.clipRect() : NULL);
       layer->SetTransform(common.transform());
diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp
index 1932ea1a5127..d35fa352770d 100644
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -839,7 +839,8 @@ ContainerState::PopThebesLayerData()
     }
     userData->mForcedBackgroundColor = backgroundColor;
   }
-  layer->SetIsOpaqueContent(isOpaque);
+  PRUint32 flags = isOpaque ? Layer::CONTENT_OPAQUE : 0;
+  layer->SetContentFlags(flags);
 
   if (lastIndex > 0) {
     // Since we're going to pop off the last ThebesLayerData, the
@@ -1361,7 +1362,8 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
   state.ProcessDisplayItems(aChildren, nsnull);
   state.Finish();
 
-  containerLayer->SetIsOpaqueContent(aChildren.IsOpaque());
+  PRUint32 flags = aChildren.IsOpaque() ? Layer::CONTENT_OPAQUE : 0;
+  containerLayer->SetContentFlags(flags);
   return containerLayer.forget();
 }
 

From b9aeeda471579934431940a72db2fdfb17ebd31d Mon Sep 17 00:00:00 2001
From: Robert O'Callahan 
Date: Thu, 2 Sep 2010 21:18:40 +1200
Subject: [PATCH 083/222] Bug 579276. Part 5: Set CONTENT_NO_TEXT and
 CONTENT_NO_TEXT_OVER_TRANSPARENT flags. r=tnikkel

---
 layout/base/FrameLayerBuilder.cpp | 38 +++++++++++++++++++++++++++++--
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp
index d35fa352770d..b0dcb3c1bcec 100644
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -159,7 +159,8 @@ protected:
   public:
     ThebesLayerData() :
       mActiveScrolledRoot(nsnull), mLayer(nsnull),
-      mIsSolidColorInVisibleRegion(PR_FALSE) {}
+      mIsSolidColorInVisibleRegion(PR_FALSE),
+      mHasText(PR_FALSE), mHasTextOverTransparent(PR_FALSE) {}
     /**
      * Record that an item has been added to the ThebesLayer, so we
      * need to update our regions.
@@ -228,6 +229,15 @@ protected:
      * True if every pixel in mVisibleRegion will have color mSolidColor.
      */
     PRPackedBool mIsSolidColorInVisibleRegion;
+    /**
+     * True if there is any text visible in the layer.
+     */
+    PRPackedBool mHasText;
+    /**
+     * True if there is any text visible in the layer that's over
+     * transparent pixels in the layer.
+     */
+    PRPackedBool mHasTextOverTransparent;
   };
 
   /**
@@ -839,7 +849,10 @@ ContainerState::PopThebesLayerData()
     }
     userData->mForcedBackgroundColor = backgroundColor;
   }
-  PRUint32 flags = isOpaque ? Layer::CONTENT_OPAQUE : 0;
+  PRUint32 flags =
+    (isOpaque ? Layer::CONTENT_OPAQUE : 0) |
+    (data->mHasText ? 0 : Layer::CONTENT_NO_TEXT) |
+    (data->mHasTextOverTransparent ? 0 : Layer::CONTENT_NO_TEXT_OVER_TRANSPARENT);
   layer->SetContentFlags(flags);
 
   if (lastIndex > 0) {
@@ -860,6 +873,22 @@ ContainerState::PopThebesLayerData()
   mThebesLayerDataStack.RemoveElementAt(lastIndex);
 }
 
+static PRBool
+IsText(nsDisplayItem* aItem) {
+  switch (aItem->GetType()) {
+  case nsDisplayItem::TYPE_TEXT:
+  case nsDisplayItem::TYPE_BULLET:
+  case nsDisplayItem::TYPE_HEADER_FOOTER:
+  case nsDisplayItem::TYPE_MATHML_CHAR_FOREGROUND:
+#ifdef MOZ_XUL
+  case nsDisplayItem::TYPE_XUL_TEXT_BOX:
+#endif
+    return PR_TRUE;
+  default:
+    return PR_FALSE;
+  }
+}
+
 void
 ContainerState::ThebesLayerData::Accumulate(nsDisplayListBuilder* aBuilder,
                                             nsDisplayItem* aItem,
@@ -899,6 +928,11 @@ ContainerState::ThebesLayerData::Accumulate(nsDisplayListBuilder* aBuilder,
     if (tmp.GetNumRects() <= 4) {
       mOpaqueRegion = tmp;
     }
+  } else if (IsText(aItem)) {
+    mHasText = PR_TRUE;
+    if (!mOpaqueRegion.Contains(aVisibleRect)) {
+      mHasTextOverTransparent = PR_TRUE;
+    }
   }
 }
 

From 4251c4b8a97d323f3b03b846aefa469aeb083945 Mon Sep 17 00:00:00 2001
From: Robert O'Callahan 
Date: Thu, 2 Sep 2010 21:18:41 +1200
Subject: [PATCH 084/222] Bug 579276. Part 6: Add
 gfxASurface::GetTextQualityInTransparentSurfaces API. r=jrmuizel,sr=vlad

---
 gfx/thebes/gfxASurface.h       | 35 +++++++++++++++++++++++++++++++++-
 gfx/thebes/gfxD2DSurface.h     |  6 ++++++
 gfx/thebes/gfxQuartzSurface.h  |  4 ++++
 gfx/thebes/gfxWindowsSurface.h |  5 +++++
 gfx/thebes/gfxXlibSurface.h    |  5 +++++
 5 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/gfx/thebes/gfxASurface.h b/gfx/thebes/gfxASurface.h
index 9ee195608ad0..4a746f717d2b 100644
--- a/gfx/thebes/gfxASurface.h
+++ b/gfx/thebes/gfxASurface.h
@@ -153,7 +153,40 @@ public:
      */
     virtual PRBool AreSimilarSurfacesSensitiveToContentType()
     {
-      return PR_TRUE;
+        return PR_TRUE;
+    }
+
+    enum TextQuality {
+        /**
+         * TEXT_QUALITY_OK means that text is always rendered to a
+         * transparent surface just as well as it would be rendered to an
+         * opaque surface. This would normally only be true if
+         * subpixel antialiasing is disabled or if the platform's
+         * transparent surfaces support component alpha.
+         */
+        TEXT_QUALITY_OK,
+        /**
+         * TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS means that text is rendered
+         * to a transparent surface just as well as it would be rendered to an
+         * opaque surface, but only if all the pixels the text is drawn
+         * over already have opaque alpha values.
+         */
+        TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS,
+        /**
+         * TEXT_QUALITY_BAD means that text is rendered
+         * to a transparent surface worse than it would be rendered to an
+         * opaque surface, even if all the pixels the text is drawn
+         * over already have opaque alpha values.
+         */
+        TEXT_QUALITY_BAD
+    };
+    /**
+     * Determine how well text would be rendered in transparent surfaces that
+     * are similar to this surface.
+     */
+    virtual TextQuality GetTextQualityInTransparentSurfaces()
+    {
+        return TEXT_QUALITY_BAD;
     }
 
     int CairoStatus();
diff --git a/gfx/thebes/gfxD2DSurface.h b/gfx/thebes/gfxD2DSurface.h
index 1a3d641fdc57..3a08ffc5e103 100644
--- a/gfx/thebes/gfxD2DSurface.h
+++ b/gfx/thebes/gfxD2DSurface.h
@@ -57,6 +57,12 @@ public:
 
     virtual ~gfxD2DSurface();
 
+    virtual TextQuality GetTextQualityInTransparentSurfaces()
+    {
+      // D2D always draws text in transparent surfaces with grayscale-AA,
+      // even if the text is over opaque pixels.
+      return TEXT_QUALITY_BAD;
+    }
 
     void Present();
     void Scroll(const nsIntPoint &aDelta, const nsIntRect &aClip);
diff --git a/gfx/thebes/gfxQuartzSurface.h b/gfx/thebes/gfxQuartzSurface.h
index 5fbbe4040865..1fd5fd773175 100644
--- a/gfx/thebes/gfxQuartzSurface.h
+++ b/gfx/thebes/gfxQuartzSurface.h
@@ -60,6 +60,10 @@ public:
     {
       return PR_FALSE;
     }
+    virtual TextQuality GetTextQualityInTransparentSurfaces()
+    {
+      return TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS;
+    }
 
     const gfxSize& GetSize() const { return mSize; }
 
diff --git a/gfx/thebes/gfxWindowsSurface.h b/gfx/thebes/gfxWindowsSurface.h
index 20230ec799b6..0da4fe3d1f77 100644
--- a/gfx/thebes/gfxWindowsSurface.h
+++ b/gfx/thebes/gfxWindowsSurface.h
@@ -81,6 +81,11 @@ public:
                                                       const gfxIntSize& size,
                                                       gfxImageFormat format);
 
+    virtual TextQuality GetTextQualityInTransparentSurfaces()
+    {
+      return TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS;
+    }
+
     nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName);
     nsresult EndPrinting();
     nsresult AbortPrinting();
diff --git a/gfx/thebes/gfxXlibSurface.h b/gfx/thebes/gfxXlibSurface.h
index ad07f74d1efe..e3b1d1f0b613 100644
--- a/gfx/thebes/gfxXlibSurface.h
+++ b/gfx/thebes/gfxXlibSurface.h
@@ -77,6 +77,11 @@ public:
     virtual already_AddRefed
     CreateSimilarSurface(gfxContentType aType, const gfxIntSize& aSize);
 
+    virtual TextQuality GetTextQualityInTransparentSurfaces()
+    {
+      return TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS;
+    }
+
     const gfxIntSize& GetSize() { return mSize; }
 
     Display* XDisplay() { return mDisplay; }

From c4801219d756eccfa1592d852d32ea30e5dba290 Mon Sep 17 00:00:00 2001
From: Robert O'Callahan 
Date: Thu, 2 Sep 2010 21:18:41 +1200
Subject: [PATCH 085/222] Bug 579276. Part 7: Don't retain transparent layers
 that would hurt text rendering. r=cjones

---
 gfx/layers/basic/BasicLayers.cpp | 41 +++++++++++++++++++++++---------
 1 file changed, 30 insertions(+), 11 deletions(-)

diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp
index 1cbac945e8a8..1bb1a8e539a9 100644
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -367,6 +367,23 @@ InheritContextFlags(gfxContext* aSource, gfxContext* aDest)
   }
 }
 
+static PRBool
+ShouldRetainTransparentSurface(PRUint32 aContentFlags,
+                               gfxASurface* aTargetSurface)
+{
+  if (aContentFlags & Layer::CONTENT_NO_TEXT)
+    return PR_TRUE;
+
+  switch (aTargetSurface->GetTextQualityInTransparentSurfaces()) {
+  case gfxASurface::TEXT_QUALITY_OK:
+    return PR_TRUE;
+  case gfxASurface::TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS:
+    return (aContentFlags & Layer::CONTENT_NO_TEXT_OVER_TRANSPARENT) != 0;
+  default:
+    return PR_FALSE;
+  }
+}
+
 void
 BasicThebesLayer::Paint(gfxContext* aContext,
                         LayerManager::DrawThebesLayerCallback aCallback,
@@ -377,15 +394,20 @@ BasicThebesLayer::Paint(gfxContext* aContext,
                "Can only draw in drawing phase");
   gfxContext* target = BasicManager()->GetTarget();
   NS_ASSERTION(target, "We shouldn't be called if there's no target");
+  nsRefPtr targetSurface = aContext->CurrentSurface();
+
+  PRBool canUseOpaqueSurface = CanUseOpaqueSurface();
+  if (!BasicManager()->IsRetained() ||
+      (aOpacity == 1.0 && !canUseOpaqueSurface &&
+       !ShouldRetainTransparentSurface(mContentFlags, targetSurface))) {
+    mValidRegion.SetEmpty();
+    mBuffer.Clear();
 
-  if (!BasicManager()->IsRetained()) {
     if (aOpacity != 1.0) {
       target->Save();
       ClipToContain(target, mVisibleRegion.GetBounds());
       target->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
     }
-    mValidRegion.SetEmpty();
-    mBuffer.Clear();
     aCallback(this, target, mVisibleRegion, nsIntRegion(), aCallbackData);
     if (aOpacity != 1.0) {
       target->PopGroupToSource();
@@ -395,15 +417,12 @@ BasicThebesLayer::Paint(gfxContext* aContext,
     return;
   }
 
-  nsRefPtr targetSurface = aContext->CurrentSurface();
-  PRBool isOpaqueContent =
-    (targetSurface->AreSimilarSurfacesSensitiveToContentType() &&
-     aOpacity == 1.0 &&
-     CanUseOpaqueSurface());
   {
+    PRBool opaqueBuffer = canUseOpaqueSurface &&
+      targetSurface->AreSimilarSurfacesSensitiveToContentType();
     Buffer::ContentType contentType =
-      isOpaqueContent ? gfxASurface::CONTENT_COLOR :
-                        gfxASurface::CONTENT_COLOR_ALPHA;
+      opaqueBuffer ? gfxASurface::CONTENT_COLOR :
+                     gfxASurface::CONTENT_COLOR_ALPHA;
     Buffer::PaintState state = mBuffer.BeginPaint(this, contentType);
     mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
 
@@ -425,7 +444,7 @@ BasicThebesLayer::Paint(gfxContext* aContext,
     }
   }
 
-  mBuffer.DrawTo(this, isOpaqueContent, target, aOpacity);
+  mBuffer.DrawTo(this, canUseOpaqueSurface, target, aOpacity);
 }
 
 void

From c46464ab7b27562600b5a67c3b4253b4ccd3fabf Mon Sep 17 00:00:00 2001
From: Robert O'Callahan 
Date: Thu, 2 Sep 2010 21:18:41 +1200
Subject: [PATCH 086/222] Bug 579276. Part 9: Backout 4d1dc2ea47fd since we no
 longer need those test changes

---
 layout/reftests/bidi/logicalmarquee.html  | 2 +-
 layout/reftests/bidi/marquee-ref.html     | 2 +-
 layout/reftests/bidi/visualmarquee.html   | 2 +-
 layout/reftests/marquee/413027-4-ref.html | 2 +-
 layout/reftests/marquee/413027-4.html     | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/layout/reftests/bidi/logicalmarquee.html b/layout/reftests/bidi/logicalmarquee.html
index 9ba9d6306cf4..cb13827dec7b 100644
--- a/layout/reftests/bidi/logicalmarquee.html
+++ b/layout/reftests/bidi/logicalmarquee.html
@@ -6,6 +6,6 @@
   
 
   
-    עד שיפוח היום ונסו הצלילים
+    עד שיפוח היום ונסו הצלילים
  
 
diff --git a/layout/reftests/bidi/marquee-ref.html b/layout/reftests/bidi/marquee-ref.html
index 724e4f8559d2..d8778dc88063 100644
--- a/layout/reftests/bidi/marquee-ref.html
+++ b/layout/reftests/bidi/marquee-ref.html
@@ -6,6 +6,6 @@
   
 
   
-    
עד שיפוח היום ונסו הצלילים
+
עד שיפוח היום ונסו הצלילים
diff --git a/layout/reftests/bidi/visualmarquee.html b/layout/reftests/bidi/visualmarquee.html index 51a559469124..932fd775a191 100644 --- a/layout/reftests/bidi/visualmarquee.html +++ b/layout/reftests/bidi/visualmarquee.html @@ -6,6 +6,6 @@ - םילילצה וסנו םויה חופיש דע + םילילצה וסנו םויה חופיש דע diff --git a/layout/reftests/marquee/413027-4-ref.html b/layout/reftests/marquee/413027-4-ref.html index fbe705e414da..22fdd42e6016 100644 --- a/layout/reftests/marquee/413027-4-ref.html +++ b/layout/reftests/marquee/413027-4-ref.html @@ -4,7 +4,7 @@
-
text
+
text
diff --git a/layout/reftests/marquee/413027-4.html b/layout/reftests/marquee/413027-4.html index beb15e6f752a..d57f2f121517 100644 --- a/layout/reftests/marquee/413027-4.html +++ b/layout/reftests/marquee/413027-4.html @@ -8,7 +8,7 @@ -
text
+
text
From 0a8fad86d1503859eb431da48a90e4a36c83ad59 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 21:19:24 +1200 Subject: [PATCH 087/222] Bug 579276. Part 10: add a couple of scrolling tests to ensure that text looks good when scrolled in an overflow:auto div. a=blocking --- layout/reftests/scrolling/fixed-text-1.html | 7 +++++++ layout/reftests/scrolling/reftest.list | 2 ++ layout/reftests/scrolling/text-1.html | 10 ++++++++++ 3 files changed, 19 insertions(+) create mode 100644 layout/reftests/scrolling/fixed-text-1.html create mode 100644 layout/reftests/scrolling/text-1.html diff --git a/layout/reftests/scrolling/fixed-text-1.html b/layout/reftests/scrolling/fixed-text-1.html new file mode 100644 index 000000000000..d470a7c6415d --- /dev/null +++ b/layout/reftests/scrolling/fixed-text-1.html @@ -0,0 +1,7 @@ + + + + +

Hello Kitty + + diff --git a/layout/reftests/scrolling/reftest.list b/layout/reftests/scrolling/reftest.list index bfdc32a7ad77..e227cefd356b 100644 --- a/layout/reftests/scrolling/reftest.list +++ b/layout/reftests/scrolling/reftest.list @@ -1,5 +1,7 @@ HTTP == fixed-1.html fixed-1.html?ref +HTTP == fixed-text-1.html fixed-text-1.html?ref HTTP == opacity-mixed-scrolling-1.html opacity-mixed-scrolling-1.html?ref HTTP == simple-1.html simple-1.html?ref +HTTP == text-1.html text-1.html?ref == uncovering-1.html uncovering-1-ref.html == uncovering-2.html uncovering-2-ref.html diff --git a/layout/reftests/scrolling/text-1.html b/layout/reftests/scrolling/text-1.html new file mode 100644 index 000000000000..0ede92a6fa28 --- /dev/null +++ b/layout/reftests/scrolling/text-1.html @@ -0,0 +1,10 @@ + + + + +

+
Hello Kitty
+
+
+ + From dc9e28789b4d3e46726fb22f9f67131165e24a23 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 3 Sep 2010 14:31:42 +1200 Subject: [PATCH 088/222] Bug 579276. Part 11: Move ClipToRegion to gfxUtils. r=vlad --- gfx/layers/ThebesLayerBuffer.cpp | 16 ++-------------- gfx/layers/ThebesLayerBuffer.h | 3 --- gfx/layers/basic/BasicLayers.cpp | 2 +- gfx/thebes/gfxUtils.cpp | 25 +++++++++++++++++++++++++ gfx/thebes/gfxUtils.h | 11 +++++++++++ 5 files changed, 39 insertions(+), 18 deletions(-) diff --git a/gfx/layers/ThebesLayerBuffer.cpp b/gfx/layers/ThebesLayerBuffer.cpp index 49da164e96c8..4e1949e8c0c0 100644 --- a/gfx/layers/ThebesLayerBuffer.cpp +++ b/gfx/layers/ThebesLayerBuffer.cpp @@ -39,23 +39,11 @@ #include "Layers.h" #include "gfxContext.h" #include "gfxPlatform.h" +#include "gfxUtils.h" namespace mozilla { namespace layers { -/*static*/ void -ThebesLayerBuffer::ClipToRegion(gfxContext* aContext, - const nsIntRegion& aRegion) -{ - aContext->NewPath(); - nsIntRegionRectIterator iter(aRegion); - const nsIntRect* r; - while ((r = iter.Next()) != nsnull) { - aContext->Rectangle(gfxRect(r->x, r->y, r->width, r->height)); - } - aContext->Clip(); -} - nsIntRect ThebesLayerBuffer::GetQuadrantRectangle(XSide aXSide, YSide aYSide) { @@ -238,7 +226,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType) NS_ASSERTION(quadrantRect.Contains(drawBounds), "Messed up quadrants"); result.mContext->Translate(-gfxPoint(quadrantRect.x, quadrantRect.y)); - ClipToRegion(result.mContext, result.mRegionToDraw); + gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw); if (aContentType == gfxASurface::CONTENT_COLOR_ALPHA && !isClear) { result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR); result.mContext->Paint(); diff --git a/gfx/layers/ThebesLayerBuffer.h b/gfx/layers/ThebesLayerBuffer.h index 936e1c3c2067..b1353b71e4a8 100644 --- a/gfx/layers/ThebesLayerBuffer.h +++ b/gfx/layers/ThebesLayerBuffer.h @@ -140,9 +140,6 @@ public: gfxASurface* GetBuffer() { return mBuffer; } protected: - // XXX make me a general utility - static void ClipToRegion(gfxContext* aContext, const nsIntRegion& aRegion); - enum XSide { LEFT, RIGHT }; diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index 1bb1a8e539a9..480de49e58af 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -454,7 +454,7 @@ BasicThebesLayerBuffer::DrawTo(ThebesLayer* aLayer, float aOpacity) { aTarget->Save(); - ClipToRegion(aTarget, aLayer->GetVisibleRegion()); + gfxUtils::ClipToRegion(aTarget, aLayer->GetVisibleRegion()); if (aIsOpaqueContent) { aTarget->SetOperator(gfxContext::OPERATOR_SOURCE); } diff --git a/gfx/thebes/gfxUtils.cpp b/gfx/thebes/gfxUtils.cpp index 01f9d83ccaca..bbe7a43e7866 100644 --- a/gfx/thebes/gfxUtils.cpp +++ b/gfx/thebes/gfxUtils.cpp @@ -39,6 +39,7 @@ #include "gfxContext.h" #include "gfxPlatform.h" #include "gfxDrawable.h" +#include "nsRegion.h" #if defined(XP_WIN) || defined(WINCE) #include "gfxWindowsPlatform.h" @@ -418,3 +419,27 @@ gfxUtils::DrawPixelSnapped(gfxContext* aContext, aContext->SetOperator(op); } +static void +ClipToRegionInternal(gfxContext* aContext, const nsIntRegion& aRegion, + PRBool aSnap) +{ + aContext->NewPath(); + nsIntRegionRectIterator iter(aRegion); + const nsIntRect* r; + while ((r = iter.Next()) != nsnull) { + aContext->Rectangle(gfxRect(r->x, r->y, r->width, r->height), aSnap); + } + aContext->Clip(); +} + +/*static*/ void +gfxUtils::ClipToRegion(gfxContext* aContext, const nsIntRegion& aRegion) +{ + ClipToRegionInternal(aContext, aRegion, PR_FALSE); +} + +/*static*/ void +gfxUtils::ClipToRegionSnapped(gfxContext* aContext, const nsIntRegion& aRegion) +{ + ClipToRegionInternal(aContext, aRegion, PR_TRUE); +} diff --git a/gfx/thebes/gfxUtils.h b/gfx/thebes/gfxUtils.h index 1a024a6448c0..9854b5e0769a 100644 --- a/gfx/thebes/gfxUtils.h +++ b/gfx/thebes/gfxUtils.h @@ -43,6 +43,7 @@ #include "gfxImageSurface.h" class gfxDrawable; +class nsIntRegion; class THEBES_API gfxUtils { public: @@ -83,6 +84,16 @@ public: const gfxRect& aFill, const gfxImageSurface::gfxImageFormat aFormat, const gfxPattern::GraphicsFilter& aFilter); + + /** + * Clip aContext to the region aRegion. + */ + static void ClipToRegion(gfxContext* aContext, const nsIntRegion& aRegion); + + /** + * Clip aContext to the region aRegion, snapping the rectangles. + */ + static void ClipToRegionSnapped(gfxContext* aContext, const nsIntRegion& aRegion); }; #endif From ef6a01f479b1ee1b9d4914dcb29c2c7f6cdcde59 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 3 Sep 2010 14:31:42 +1200 Subject: [PATCH 089/222] Bug 579276. Part 12: Clip all drawing to the visible region on the nonretained path. r=cjones --- gfx/layers/basic/BasicLayers.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index 480de49e58af..e8ed254579c3 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -403,17 +403,17 @@ BasicThebesLayer::Paint(gfxContext* aContext, mValidRegion.SetEmpty(); mBuffer.Clear(); + target->Save(); + gfxUtils::ClipToRegionSnapped(target, mVisibleRegion); if (aOpacity != 1.0) { - target->Save(); - ClipToContain(target, mVisibleRegion.GetBounds()); target->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA); } aCallback(this, target, mVisibleRegion, nsIntRegion(), aCallbackData); if (aOpacity != 1.0) { target->PopGroupToSource(); target->Paint(aOpacity); - target->Restore(); } + target->Restore(); return; } From d070f2c342b10698d9b79369ef5a97e7c5643d69 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 3 Sep 2010 14:31:42 +1200 Subject: [PATCH 090/222] Bug 579276. Part 13: Use CONTENT_COLOR for temporary surface in nonretained path, if possible. r=cjones --- gfx/layers/basic/BasicLayers.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index e8ed254579c3..a56a93c20403 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -397,6 +397,12 @@ BasicThebesLayer::Paint(gfxContext* aContext, nsRefPtr targetSurface = aContext->CurrentSurface(); PRBool canUseOpaqueSurface = CanUseOpaqueSurface(); + PRBool opaqueBuffer = canUseOpaqueSurface && + targetSurface->AreSimilarSurfacesSensitiveToContentType(); + Buffer::ContentType contentType = + opaqueBuffer ? gfxASurface::CONTENT_COLOR : + gfxASurface::CONTENT_COLOR_ALPHA; + if (!BasicManager()->IsRetained() || (aOpacity == 1.0 && !canUseOpaqueSurface && !ShouldRetainTransparentSurface(mContentFlags, targetSurface))) { @@ -406,7 +412,7 @@ BasicThebesLayer::Paint(gfxContext* aContext, target->Save(); gfxUtils::ClipToRegionSnapped(target, mVisibleRegion); if (aOpacity != 1.0) { - target->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA); + target->PushGroup(contentType); } aCallback(this, target, mVisibleRegion, nsIntRegion(), aCallbackData); if (aOpacity != 1.0) { @@ -418,11 +424,6 @@ BasicThebesLayer::Paint(gfxContext* aContext, } { - PRBool opaqueBuffer = canUseOpaqueSurface && - targetSurface->AreSimilarSurfacesSensitiveToContentType(); - Buffer::ContentType contentType = - opaqueBuffer ? gfxASurface::CONTENT_COLOR : - gfxASurface::CONTENT_COLOR_ALPHA; Buffer::PaintState state = mBuffer.BeginPaint(this, contentType); mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate); From c6e8dab10dbd286643794dd62a16c368a38eb2a9 Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Fri, 3 Sep 2010 14:56:04 +1200 Subject: [PATCH 091/222] Bug 589175 - Comment out binary-component entries, r=bsmedberg a=blocking2.0 --- toolkit/mozapps/installer/packager.mk | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/toolkit/mozapps/installer/packager.mk b/toolkit/mozapps/installer/packager.mk index c5b6d7c5b405..01814fbcc579 100644 --- a/toolkit/mozapps/installer/packager.mk +++ b/toolkit/mozapps/installer/packager.mk @@ -237,12 +237,18 @@ NON_OMNIJAR_FILES = \ PACK_OMNIJAR = \ rm -f omni.jar components/binary.manifest && \ grep -h '^binary-component' components/*.manifest > binary.manifest ; \ + sed -e 's/^binary-component/\#binary-component/' components/components.manifest > components.manifest && \ + mv components.manifest components && \ find . | xargs touch -t 201001010000 && \ zip -r9mX omni.jar $(OMNIJAR_FILES) -x $(NON_OMNIJAR_FILES) && \ $(OPTIMIZE_JARS_CMD) $(DIST)/jarlog/ ./ ./ && \ mv binary.manifest components && \ printf "manifest components/binary.manifest\n" > chrome.manifest -UNPACK_OMNIJAR = unzip -o omni.jar && rm -f components/binary.manifest +UNPACK_OMNIJAR = \ + unzip -o omni.jar && \ + rm -f components/binary.manifest && \ + sed -e 's/^\#binary-component/binary-component/' components/components.manifest > components.manifest && \ + mv components.manifest components MAKE_PACKAGE = (cd $(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH) && $(PACK_OMNIJAR)) && $(INNER_MAKE_PACKAGE) UNMAKE_PACKAGE = $(INNER_UNMAKE_PACKAGE) && (cd $(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH) && $(UNPACK_OMNIJAR)) From 47a5284310c9b4e0b1ea2d0bb17f9aeab86cbc38 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Fri, 3 Sep 2010 15:50:29 +1200 Subject: [PATCH 092/222] Bug 589632 - Fix LayerManagerD3D9 debug output r=Bas, a=blocking2.0 --- gfx/layers/Layers.cpp | 8 ++++---- gfx/layers/d3d9/LayerManagerD3D9.cpp | 8 ++++---- gfx/layers/d3d9/LayerManagerD3D9.h | 7 ++++--- gfx/layers/opengl/LayerManagerOGL.h | 4 ++++ 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index d622b01a5e9e..35b2b4f80631 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -291,12 +291,12 @@ LayerManager::Dump(FILE* aFile, const char* aPrefix) nsCAutoString pfx(aPrefix); pfx += " "; - if (!mRoot) { + if (!GetRoot()) { fprintf(file, "%s(null)", pfx.get()); return; } - mRoot->Dump(file, pfx.get()); + GetRoot()->Dump(file, pfx.get()); } void @@ -317,12 +317,12 @@ LayerManager::Log(const char* aPrefix) nsCAutoString pfx(aPrefix); pfx += " "; - if (!mRoot) { + if (!GetRoot()) { MOZ_LAYERS_LOG(("%s(null)", pfx.get())); return; } - mRoot->Log(pfx.get()); + GetRoot()->Log(pfx.get()); } void diff --git a/gfx/layers/d3d9/LayerManagerD3D9.cpp b/gfx/layers/d3d9/LayerManagerD3D9.cpp index 1ba30089bc62..130c5ac57a35 100644 --- a/gfx/layers/d3d9/LayerManagerD3D9.cpp +++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp @@ -137,7 +137,7 @@ LayerManagerD3D9::EndTransaction(DrawThebesLayerCallback aCallback, void LayerManagerD3D9::SetRoot(Layer *aLayer) { - mRootLayer = static_cast(aLayer->ImplData()); + mRoot = aLayer; } already_AddRefed @@ -198,8 +198,8 @@ LayerManagerD3D9::Render() device()->BeginScene(); - if (mRootLayer) { - const nsIntRect *clipRect = mRootLayer->GetLayer()->GetClipRect(); + if (mRoot) { + const nsIntRect *clipRect = mRoot->GetClipRect(); RECT r; if (clipRect) { r.left = (LONG)clipRect->x; @@ -213,7 +213,7 @@ LayerManagerD3D9::Render() } device()->SetScissorRect(&r); - mRootLayer->RenderLayer(); + static_cast(mRoot->ImplData())->RenderLayer(); } device()->EndScene(); diff --git a/gfx/layers/d3d9/LayerManagerD3D9.h b/gfx/layers/d3d9/LayerManagerD3D9.h index d481f3fcf0f1..f9a3e5b7661b 100644 --- a/gfx/layers/d3d9/LayerManagerD3D9.h +++ b/gfx/layers/d3d9/LayerManagerD3D9.h @@ -145,6 +145,10 @@ public: mDeviceManager = nsnull; } +#ifdef MOZ_LAYERS_HAVE_LOG + virtual const char* Name() const { return "D3D9"; } +#endif // MOZ_LAYERS_HAVE_LOG + private: /* Device manager instance */ static DeviceManagerD3D9 *mDeviceManager; @@ -160,9 +164,6 @@ private: */ nsRefPtr mTarget; - /* Current root layer. */ - LayerD3D9 *mRootLayer; - /* Callback info for current transaction */ CallbackInfo mCurrentCallbackInfo; diff --git a/gfx/layers/opengl/LayerManagerOGL.h b/gfx/layers/opengl/LayerManagerOGL.h index dd054edafa43..e7d731ac5ba3 100644 --- a/gfx/layers/opengl/LayerManagerOGL.h +++ b/gfx/layers/opengl/LayerManagerOGL.h @@ -293,6 +293,10 @@ public: aFlipped); } +#ifdef MOZ_LAYERS_HAVE_LOG + virtual const char* Name() const { return "OGL"; } +#endif // MOZ_LAYERS_HAVE_LOG + private: /** Widget associated with this layer manager */ nsIWidget *mWidget; From b5fb6a703c4b79d6261d4a6b7d55fb2100fff507 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Fri, 3 Sep 2010 15:50:42 +1200 Subject: [PATCH 093/222] Bug 590735 - D3D9/OGL Image layers need to round up on uneven sized YCbCr images r=joe, a=blocking2.0 --- gfx/layers/d3d9/ImageLayerD3D9.cpp | 14 +++++++++++++- gfx/layers/d3d9/ImageLayerD3D9.h | 1 + gfx/layers/opengl/ImageLayerOGL.cpp | 12 ++++++++++++ gfx/layers/opengl/ImageLayerOGL.h | 2 ++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/gfx/layers/d3d9/ImageLayerD3D9.cpp b/gfx/layers/d3d9/ImageLayerD3D9.cpp index f10f87c7171e..eef6c6bf235c 100644 --- a/gfx/layers/d3d9/ImageLayerD3D9.cpp +++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp @@ -269,23 +269,35 @@ PlanarYCbCrImageD3D9::SetData(const PlanarYCbCrImage::Data &aData) // YV24 format width_shift = 0; height_shift = 0; + mType = gfx::YV24; } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width && aData.mYSize.height == aData.mCbCrSize.height) { // YV16 format width_shift = 1; height_shift = 0; + mType = gfx::YV16; } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width && aData.mYSize.height / 2 == aData.mCbCrSize.height ) { // YV12 format width_shift = 1; height_shift = 1; + mType = gfx::YV12; } else { NS_ERROR("YCbCr format not supported"); } mData = aData; mData.mCbCrStride = mData.mCbCrSize.width = aData.mPicSize.width >> width_shift; + // Round up the values for width and height to make sure we sample enough data + // for the last pixel - See bug 590735 + if (width_shift && (aData.mPicSize.width & 1)) { + mData.mCbCrStride++; + mData.mCbCrSize.width++; + } mData.mCbCrSize.height = aData.mPicSize.height >> height_shift; + if (height_shift && (aData.mPicSize.height & 1)) { + mData.mCbCrSize.height++; + } mData.mYSize = aData.mPicSize; mData.mYStride = mData.mYSize.width; @@ -458,7 +470,7 @@ PlanarYCbCrImageD3D9::GetAsSurface() mData.mYStride, mData.mCbCrStride, imageSurface->Stride(), - gfx::YV12); + mType); return imageSurface.forget().get(); } diff --git a/gfx/layers/d3d9/ImageLayerD3D9.h b/gfx/layers/d3d9/ImageLayerD3D9.h index a21776519607..0ce25c147fba 100644 --- a/gfx/layers/d3d9/ImageLayerD3D9.h +++ b/gfx/layers/d3d9/ImageLayerD3D9.h @@ -129,6 +129,7 @@ public: nsRefPtr mCrTexture; nsRefPtr mCbTexture; PRPackedBool mHasData; + gfx::YUVType mType; }; diff --git a/gfx/layers/opengl/ImageLayerOGL.cpp b/gfx/layers/opengl/ImageLayerOGL.cpp index e9658b6427d8..405132cb7232 100644 --- a/gfx/layers/opengl/ImageLayerOGL.cpp +++ b/gfx/layers/opengl/ImageLayerOGL.cpp @@ -489,23 +489,35 @@ PlanarYCbCrImageOGL::SetData(const PlanarYCbCrImage::Data &aData) // YV24 format width_shift = 0; height_shift = 0; + mType = gfx::YV24; } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width && aData.mYSize.height == aData.mCbCrSize.height) { // YV16 format width_shift = 1; height_shift = 0; + mType = gfx::YV16; } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width && aData.mYSize.height / 2 == aData.mCbCrSize.height ) { // YV12 format width_shift = 1; height_shift = 1; + mType = gfx::YV16; } else { NS_ERROR("YCbCr format not supported"); } mData = aData; mData.mCbCrStride = mData.mCbCrSize.width = aData.mPicSize.width >> width_shift; + // Round up the values for width and height to make sure we sample enough data + // for the last pixel - See bug 590735 + if (width_shift && (aData.mPicSize.width & 1)) { + mData.mCbCrStride++; + mData.mCbCrSize.width++; + } mData.mCbCrSize.height = aData.mPicSize.height >> height_shift; + if (height_shift && (aData.mPicSize.height & 1)) { + mData.mCbCrSize.height++; + } mData.mYSize = aData.mPicSize; mData.mYStride = mData.mYSize.width; diff --git a/gfx/layers/opengl/ImageLayerOGL.h b/gfx/layers/opengl/ImageLayerOGL.h index e0d5b49d1226..287f72f4d3c5 100644 --- a/gfx/layers/opengl/ImageLayerOGL.h +++ b/gfx/layers/opengl/ImageLayerOGL.h @@ -40,6 +40,7 @@ #include "LayerManagerOGL.h" #include "ImageLayers.h" +#include "yuv_convert.h" #include "mozilla/Mutex.h" namespace mozilla { @@ -213,6 +214,7 @@ public: Data mData; gfxIntSize mSize; PRPackedBool mHasData; + gfx::YUVType mType; }; From e4a9dac062be882cf19f52af4e55ae4fe6a6e6f7 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Fri, 3 Sep 2010 15:50:53 +1200 Subject: [PATCH 094/222] Bug 593224 - ContainerLayerD3D9 can reset the clip rect r=Bas, a=blocking2.0 --- gfx/layers/d3d9/ContainerLayerD3D9.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gfx/layers/d3d9/ContainerLayerD3D9.cpp b/gfx/layers/d3d9/ContainerLayerD3D9.cpp index 5ed9eee70f38..3e6a21d39c9d 100644 --- a/gfx/layers/d3d9/ContainerLayerD3D9.cpp +++ b/gfx/layers/d3d9/ContainerLayerD3D9.cpp @@ -141,6 +141,7 @@ ContainerLayerD3D9::RenderLayer() nsRefPtr previousRenderTarget; nsRefPtr renderTexture; float previousRenderTargetOffset[4]; + RECT oldClipRect; float renderTargetOffset[] = { 0, 0, 0, 0 }; float oldViewMatrix[4][4]; @@ -149,6 +150,7 @@ ContainerLayerD3D9::RenderLayer() if (useIntermediate) { device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget)); + device()->GetScissorRect(&oldClipRect); device()->CreateTexture(visibleRect.width, visibleRect.height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, getter_AddRefs(renderTexture), @@ -224,6 +226,7 @@ ContainerLayerD3D9::RenderLayer() if (useIntermediate) { device()->SetRenderTarget(0, previousRenderTarget); + device()->SetScissorRect(&oldClipRect); device()->SetVertexShaderConstantF(12, previousRenderTargetOffset, 1); device()->SetVertexShaderConstantF(8, &oldViewMatrix[0][0], 4); From 0fe2dd0835db31fb7bf5843bb897285a5a36345c Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Fri, 3 Sep 2010 15:51:04 +1200 Subject: [PATCH 095/222] Bug 590367 - Render RGB d2d layers with a RGBA surface and shader r=Bas, a=blocking2.0 --- gfx/layers/d3d9/CanvasLayerD3D9.cpp | 2 +- gfx/layers/d3d9/ContainerLayerD3D9.cpp | 2 +- gfx/layers/d3d9/DeviceManagerD3D9.cpp | 11 ++ gfx/layers/d3d9/DeviceManagerD3D9.h | 4 + gfx/layers/d3d9/ImageLayerD3D9.cpp | 2 +- gfx/layers/d3d9/LayerManagerD3D9Shaders.h | 119 ++++++++++++++++--- gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl | 10 +- gfx/layers/d3d9/ThebesLayerD3D9.cpp | 7 +- gfx/layers/d3d9/genshaders.sh | 2 + 9 files changed, 138 insertions(+), 21 deletions(-) diff --git a/gfx/layers/d3d9/CanvasLayerD3D9.cpp b/gfx/layers/d3d9/CanvasLayerD3D9.cpp index b34a45ed4968..7bfdff061925 100644 --- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp +++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp @@ -239,7 +239,7 @@ CanvasLayerD3D9::RenderLayer() opacity[0] = GetOpacity(); device()->SetPixelShaderConstantF(0, opacity, 1); - mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER); + mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER); if (!mDataIsPremultiplied) { device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); diff --git a/gfx/layers/d3d9/ContainerLayerD3D9.cpp b/gfx/layers/d3d9/ContainerLayerD3D9.cpp index 3e6a21d39c9d..97815aefbf7d 100644 --- a/gfx/layers/d3d9/ContainerLayerD3D9.cpp +++ b/gfx/layers/d3d9/ContainerLayerD3D9.cpp @@ -257,7 +257,7 @@ ContainerLayerD3D9::RenderLayer() opacityVector[0] = opacity; device()->SetPixelShaderConstantF(0, opacityVector, 1); - mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER); + mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER); device()->SetTexture(0, renderTexture); device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); diff --git a/gfx/layers/d3d9/DeviceManagerD3D9.cpp b/gfx/layers/d3d9/DeviceManagerD3D9.cpp index 7c00fe308a7d..228fe9adcb86 100644 --- a/gfx/layers/d3d9/DeviceManagerD3D9.cpp +++ b/gfx/layers/d3d9/DeviceManagerD3D9.cpp @@ -338,6 +338,13 @@ DeviceManagerD3D9::Init() return false; } + hr = mDevice->CreatePixelShader((DWORD*)RGBAShaderPS, + getter_AddRefs(mRGBAPS)); + + if (FAILED(hr)) { + return false; + } + hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS, getter_AddRefs(mYCbCrPS)); @@ -459,6 +466,10 @@ DeviceManagerD3D9::SetShaderMode(ShaderMode aMode) mDevice->SetVertexShader(mLayerVS); mDevice->SetPixelShader(mRGBPS); break; + case RGBALAYER: + mDevice->SetVertexShader(mLayerVS); + mDevice->SetPixelShader(mRGBAPS); + break; case YCBCRLAYER: mDevice->SetVertexShader(mLayerVS); mDevice->SetPixelShader(mYCbCrPS); diff --git a/gfx/layers/d3d9/DeviceManagerD3D9.h b/gfx/layers/d3d9/DeviceManagerD3D9.h index 8be99987efe2..095a5c3423a0 100644 --- a/gfx/layers/d3d9/DeviceManagerD3D9.h +++ b/gfx/layers/d3d9/DeviceManagerD3D9.h @@ -129,6 +129,7 @@ public: enum ShaderMode { RGBLAYER, + RGBALAYER, YCBCRLAYER, SOLIDCOLORLAYER }; @@ -178,6 +179,9 @@ private: /* Pixel shader used for RGB textures */ nsRefPtr mRGBPS; + /* Pixel shader used for RGBA textures */ + nsRefPtr mRGBAPS; + /* Pixel shader used for RGB textures */ nsRefPtr mYCbCrPS; diff --git a/gfx/layers/d3d9/ImageLayerD3D9.cpp b/gfx/layers/d3d9/ImageLayerD3D9.cpp index eef6c6bf235c..f204eed0c06e 100644 --- a/gfx/layers/d3d9/ImageLayerD3D9.cpp +++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp @@ -243,7 +243,7 @@ ImageLayerD3D9::RenderLayer() opacity[0] = GetOpacity(); device()->SetPixelShaderConstantF(0, opacity, 1); - mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER); + mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER); device()->SetTexture(0, cairoImage->mTexture); device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); diff --git a/gfx/layers/d3d9/LayerManagerD3D9Shaders.h b/gfx/layers/d3d9/LayerManagerD3D9Shaders.h index 7201f070f275..4d22b6f8c6c5 100644 --- a/gfx/layers/d3d9/LayerManagerD3D9Shaders.h +++ b/gfx/layers/d3d9/LayerManagerD3D9Shaders.h @@ -1,6 +1,6 @@ #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022 // // fxc LayerManagerD3D9Shaders.hlsl -ELayerQuadVS -nologo -FhtmpShaderHeader // -VnLayerQuadVS @@ -92,8 +92,8 @@ const BYTE LayerQuadVS[] = 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 57, 46, - 50, 57, 46, 57, 53, 50, - 46, 51, 49, 49, 49, 0, + 50, 55, 46, 57, 53, 50, + 46, 51, 48, 50, 50, 0, 81, 0, 0, 5, 13, 0, 15, 160, 0, 0, 0, 191, 0, 0, 0, 0, 0, 0, @@ -149,10 +149,10 @@ const BYTE LayerQuadVS[] = }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022 // -// fxc LayerManagerD3D9Shaders.hlsl -ERGBShader -nologo -Tps_2_0 -// -FhtmpShaderHeader -VnRGBShaderPS +// fxc LayerManagerD3D9Shaders.hlsl -ERGBAShader -nologo -Tps_2_0 +// -FhtmpShaderHeader -VnRGBAShaderPS // // // Parameters: @@ -179,6 +179,87 @@ const BYTE LayerQuadVS[] = // approximately 3 instruction slots used (1 texture, 2 arithmetic) #endif +const BYTE RGBAShaderPS[] = +{ + 0, 2, 255, 255, 254, 255, + 45, 0, 67, 84, 65, 66, + 28, 0, 0, 0, 127, 0, + 0, 0, 0, 2, 255, 255, + 2, 0, 0, 0, 28, 0, + 0, 0, 0, 1, 0, 0, + 120, 0, 0, 0, 68, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 0, 0, 0, 0, + 100, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 0, 0, 0, + 0, 0, 102, 76, 97, 121, + 101, 114, 79, 112, 97, 99, + 105, 116, 121, 0, 171, 171, + 0, 0, 3, 0, 1, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 115, 50, + 68, 0, 4, 0, 12, 0, + 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 112, 115, 95, 50, 95, 48, + 0, 77, 105, 99, 114, 111, + 115, 111, 102, 116, 32, 40, + 82, 41, 32, 72, 76, 83, + 76, 32, 83, 104, 97, 100, + 101, 114, 32, 67, 111, 109, + 112, 105, 108, 101, 114, 32, + 57, 46, 50, 55, 46, 57, + 53, 50, 46, 51, 48, 50, + 50, 0, 31, 0, 0, 2, + 0, 0, 0, 128, 0, 0, + 3, 176, 31, 0, 0, 2, + 0, 0, 0, 144, 0, 8, + 15, 160, 66, 0, 0, 3, + 0, 0, 15, 128, 0, 0, + 228, 176, 0, 8, 228, 160, + 5, 0, 0, 3, 0, 0, + 15, 128, 0, 0, 228, 128, + 0, 0, 0, 160, 1, 0, + 0, 2, 0, 8, 15, 128, + 0, 0, 228, 128, 255, 255, + 0, 0 +}; +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022 +// +// fxc LayerManagerD3D9Shaders.hlsl -ERGBShader -nologo -Tps_2_0 +// -FhtmpShaderHeader -VnRGBShaderPS +// +// +// Parameters: +// +// float fLayerOpacity; +// sampler2D s2D; +// +// +// Registers: +// +// Name Reg Size +// ------------- ----- ---- +// fLayerOpacity c0 1 +// s2D s0 1 +// + + ps_2_0 + def c1, 1, 0, 0, 0 + dcl t0.xy + dcl_2d s0 + texld r0, t0, s0 + mul r0.xyz, r0, c0.x + mov r0.w, c1.x + mov oC0, r0 + +// approximately 4 instruction slots used (1 texture, 3 arithmetic) +#endif + const BYTE RGBShaderPS[] = { 0, 2, 255, 255, 254, 255, @@ -210,9 +291,13 @@ const BYTE RGBShaderPS[] = 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, - 57, 46, 50, 57, 46, 57, - 53, 50, 46, 51, 49, 49, - 49, 0, 31, 0, 0, 2, + 57, 46, 50, 55, 46, 57, + 53, 50, 46, 51, 48, 50, + 50, 0, 81, 0, 0, 5, + 1, 0, 15, 160, 0, 0, + 128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, @@ -220,15 +305,17 @@ const BYTE RGBShaderPS[] = 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228, 160, 5, 0, 0, 3, 0, 0, - 15, 128, 0, 0, 228, 128, + 7, 128, 0, 0, 228, 128, 0, 0, 0, 160, 1, 0, + 0, 2, 0, 0, 8, 128, + 1, 0, 0, 160, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255, 255, 0, 0 }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022 // // fxc LayerManagerD3D9Shaders.hlsl -EYCbCrShader -nologo -Tps_2_0 // -FhtmpShaderHeader -VnYCbCrShaderPS @@ -323,9 +410,9 @@ const BYTE YCbCrShaderPS[] = 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, - 114, 32, 57, 46, 50, 57, + 114, 32, 57, 46, 50, 55, 46, 57, 53, 50, 46, 51, - 49, 49, 49, 0, 81, 0, + 48, 50, 50, 0, 81, 0, 0, 5, 1, 0, 15, 160, 0, 0, 0, 191, 0, 0, 128, 189, 244, 253, 148, 63, @@ -384,7 +471,7 @@ const BYTE YCbCrShaderPS[] = }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022 // // fxc LayerManagerD3D9Shaders.hlsl -ESolidColorShader -nologo -Tps_2_0 // -FhtmpShaderHeader -VnSolidColorShaderPS @@ -432,8 +519,8 @@ const BYTE SolidColorShaderPS[] = 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 57, 46, - 50, 57, 46, 57, 53, 50, - 46, 51, 49, 49, 49, 0, + 50, 55, 46, 57, 53, 50, + 46, 51, 48, 50, 50, 0, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 160, 255, 255, 0, 0 diff --git a/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl b/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl index 0bbba3c216ed..4b01ec50ec6c 100644 --- a/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl +++ b/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl @@ -39,11 +39,19 @@ VS_OUTPUT LayerQuadVS(const VS_INPUT aVertex) return outp; } -float4 RGBShader(const VS_OUTPUT aVertex) : COLOR +float4 RGBAShader(const VS_OUTPUT aVertex) : COLOR { return tex2D(s2D, aVertex.vTexCoords) * fLayerOpacity; } +float4 RGBShader(const VS_OUTPUT aVertex) : COLOR +{ + float4 result; + result = tex2D(s2D, aVertex.vTexCoords) * fLayerOpacity; + result.a = 1.0; + return result; +} + float4 YCbCrShader(const VS_OUTPUT aVertex) : COLOR { float4 yuv; diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.cpp b/gfx/layers/d3d9/ThebesLayerD3D9.cpp index 8e7092a4f08d..a532e46cf35b 100644 --- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp +++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp @@ -234,7 +234,12 @@ ThebesLayerD3D9::RenderLayer() opacity[0] = GetOpacity(); device()->SetPixelShaderConstantF(0, opacity, 1); - mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER); +#ifdef CAIRO_HAS_D2D_SURFACE + if (mD2DSurface && UseOpaqueSurface(this)) { + mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER); + } else +#endif + mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER); device()->SetTexture(0, mTexture); device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); diff --git a/gfx/layers/d3d9/genshaders.sh b/gfx/layers/d3d9/genshaders.sh index bf6bd8355665..383041ad03df 100644 --- a/gfx/layers/d3d9/genshaders.sh +++ b/gfx/layers/d3d9/genshaders.sh @@ -2,6 +2,8 @@ tempfile=tmpShaderHeader rm LayerManagerD3D9Shaders.h fxc LayerManagerD3D9Shaders.hlsl -ELayerQuadVS -nologo -Fh$tempfile -VnLayerQuadVS cat $tempfile >> LayerManagerD3D9Shaders.h +fxc LayerManagerD3D9Shaders.hlsl -ERGBAShader -nologo -Tps_2_0 -Fh$tempfile -VnRGBAShaderPS +cat $tempfile >> LayerManagerD3D9Shaders.h fxc LayerManagerD3D9Shaders.hlsl -ERGBShader -nologo -Tps_2_0 -Fh$tempfile -VnRGBShaderPS cat $tempfile >> LayerManagerD3D9Shaders.h fxc LayerManagerD3D9Shaders.hlsl -EYCbCrShader -nologo -Tps_2_0 -Fh$tempfile -VnYCbCrShaderPS From d55c0df3ede5ae362639cfb2ab6ce4ccd4b30c6f Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Fri, 3 Sep 2010 15:51:15 +1200 Subject: [PATCH 096/222] Bug 592985 - Free global shared CGL context on shutdown r=vlad, a=blocking2.0 --- gfx/thebes/GLContextProviderCGL.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx/thebes/GLContextProviderCGL.mm b/gfx/thebes/GLContextProviderCGL.mm index 934ef4118ea3..a2fd984e6c7e 100644 --- a/gfx/thebes/GLContextProviderCGL.mm +++ b/gfx/thebes/GLContextProviderCGL.mm @@ -530,6 +530,7 @@ GLContextProviderCGL::GetGlobalContext() void GLContextProviderCGL::Shutdown() { + gGlobalContext = nsnull; } } /* namespace gl */ From 418edf53e3ae9bd82621b3d4104a572da679d151 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 3 Sep 2010 16:20:23 +1200 Subject: [PATCH 097/222] Fixing bustage, a=me --- gfx/layers/d3d9/ImageLayerD3D9.h | 1 + gfx/layers/d3d9/ThebesLayerD3D9.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx/layers/d3d9/ImageLayerD3D9.h b/gfx/layers/d3d9/ImageLayerD3D9.h index 0ce25c147fba..687d5d6fa0d6 100644 --- a/gfx/layers/d3d9/ImageLayerD3D9.h +++ b/gfx/layers/d3d9/ImageLayerD3D9.h @@ -40,6 +40,7 @@ #include "LayerManagerD3D9.h" #include "ImageLayers.h" +#include "yuv_convert.h" #include "mozilla/Mutex.h" namespace mozilla { diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.cpp b/gfx/layers/d3d9/ThebesLayerD3D9.cpp index a532e46cf35b..a82c1880c5d2 100644 --- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp +++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp @@ -235,7 +235,7 @@ ThebesLayerD3D9::RenderLayer() device()->SetPixelShaderConstantF(0, opacity, 1); #ifdef CAIRO_HAS_D2D_SURFACE - if (mD2DSurface && UseOpaqueSurface(this)) { + if (mD2DSurface && CanUseOpaqueSurface()) { mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER); } else #endif From 559a6b92cf904725d0cec4cba57e37991f2a436d Mon Sep 17 00:00:00 2001 From: Timothy Nikkel Date: Fri, 3 Sep 2010 00:43:26 -0500 Subject: [PATCH 098/222] Bug 593262. The stop/reload button is chasing me. Keep running from it. r=roc a=fix a test --HG-- rename : layout/style/test/hover_helper.html => layout/style/test/chrome/hover_helper.html rename : layout/style/test/test_hover.html => layout/style/test/chrome/test_hover.html --- layout/style/test/Makefile.in | 2 - layout/style/test/chrome/Makefile.in | 2 + .../style/test/{ => chrome}/hover_helper.html | 39 +++++++++---------- .../style/test/{ => chrome}/test_hover.html | 8 ++-- 4 files changed, 25 insertions(+), 26 deletions(-) rename layout/style/test/{ => chrome}/hover_helper.html (89%) rename layout/style/test/{ => chrome}/test_hover.html (60%) diff --git a/layout/style/test/Makefile.in b/layout/style/test/Makefile.in index 2752dff78a9e..9815d73d837d 100644 --- a/layout/style/test/Makefile.in +++ b/layout/style/test/Makefile.in @@ -145,8 +145,6 @@ _TEST_FILES = test_acid3_test46.html \ test_dont_use_document_colors.html \ test_font_face_parser.html \ test_garbage_at_end_of_declarations.html \ - test_hover.html \ - hover_helper.html \ test_ident_escaping.html \ test_inherit_computation.html \ test_inherit_storage.html \ diff --git a/layout/style/test/chrome/Makefile.in b/layout/style/test/chrome/Makefile.in index e17e3329def8..735e0c029310 100644 --- a/layout/style/test/chrome/Makefile.in +++ b/layout/style/test/chrome/Makefile.in @@ -48,6 +48,8 @@ _CHROME_FILES = \ bug535806-css.css \ bug535806-html.html \ bug535806-xul.xul \ + test_hover.html \ + hover_helper.html \ $(NULL) libs:: $(_CHROME_FILES) diff --git a/layout/style/test/hover_helper.html b/layout/style/test/chrome/hover_helper.html similarity index 89% rename from layout/style/test/hover_helper.html rename to layout/style/test/chrome/hover_helper.html index 549bd534b637..5b0fb9830fa9 100644 --- a/layout/style/test/hover_helper.html +++ b/layout/style/test/chrome/hover_helper.html @@ -2,10 +2,7 @@ Test for :hover - - - - + + + + +

Inspector tree panel test.

+ +
+ +

hello world!

+
+
+ +
test
+ + + + + + diff --git a/browser/base/content/test/browser_inspector_treePanel_output.js b/browser/base/content/test/browser_inspector_treePanel_output.js new file mode 100644 index 000000000000..e2b729950d7e --- /dev/null +++ b/browser/base/content/test/browser_inspector_treePanel_output.js @@ -0,0 +1,123 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Inspector iframe Tests. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mihai Șucan + * Rob Campbell + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +let doc = null; +let xhr = null; +let expectedResult = ""; + +const TEST_URI = "http://mochi.test:8888/browser/browser/base/content/test/browser_inspector_treePanel_input.html"; +const RESULT_URI = "http://mochi.test:8888/browser/browser/base/content/test/browser_inspector_treePanel_result.html"; + +function tabFocused() +{ + xhr = new XMLHttpRequest(); + xhr.onreadystatechange = xhr_onReadyStateChange; + xhr.open("GET", RESULT_URI, true); + xhr.send(null); +} + +function xhr_onReadyStateChange() { + if (xhr.readyState != 4) { + return; + } + + is(xhr.status, 200, "xhr.status is 200"); + ok(!!xhr.responseText, "xhr.responseText is available"); + expectedResult = xhr.responseText.replace(/^\s+|\s+$/mg, ''); + xhr = null; + + Services.obs.addObserver(inspectorOpened, "inspector-opened", false); + InspectorUI.openInspectorUI(); +} + +function inspectorOpened() +{ + Services.obs.removeObserver(inspectorOpened, "inspector-opened", false); + + ok(InspectorUI.inspecting, "Inspector is highlighting"); + ok(InspectorUI.isTreePanelOpen, "Inspector Tree Panel is open"); + InspectorUI.stopInspecting(); + ok(!InspectorUI.inspecting, "Inspector is not highlighting"); + + let elements = doc.querySelectorAll("meta, script, style, p[unknownAttribute]"); + for (let i = 0; i < elements.length; i++) { + InspectorUI.inspectNode(elements[i]); + } + + let iframe = doc.querySelector("iframe"); + ok(iframe, "Found the iframe tag"); + ok(iframe.contentDocument, "Found the iframe.contentDocument"); + + let iframeDiv = iframe.contentDocument.querySelector("div"); + ok(iframeDiv, "Found the div element inside the iframe"); + InspectorUI.inspectNode(iframeDiv); + + ok(InspectorUI.treePanelDiv, "InspectorUI.treePanelDiv is available"); + is(InspectorUI.treePanelDiv.innerHTML.replace(/^\s+|\s+$/mg, ''), + expectedResult, "treePanelDiv.innerHTML is correct"); + expectedResult = null; + + Services.obs.addObserver(inspectorClosed, "inspector-closed", false); + InspectorUI.closeInspectorUI(); +} + +function inspectorClosed() +{ + Services.obs.removeObserver(inspectorClosed, "inspector-closed", false); + + ok(!InspectorUI.inspecting, "Inspector is not highlighting"); + ok(!InspectorUI.isTreePanelOpen, "Inspector Tree Panel is not open"); + + gBrowser.removeCurrentTab(); + finish(); +} + +function test() +{ + waitForExplicitFinish(); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.selectedBrowser.addEventListener("load", function(evt) { + gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true); + doc = content.document; + waitForFocus(tabFocused, content); + }, true); + + content.location = TEST_URI; +} diff --git a/browser/base/content/test/browser_inspector_treePanel_result.html b/browser/base/content/test/browser_inspector_treePanel_result.html new file mode 100644 index 000000000000..1156a1f251ed --- /dev/null +++ b/browser/base/content/test/browser_inspector_treePanel_result.html @@ -0,0 +1,8 @@ + diff --git a/browser/base/content/test/browser_inspector_treeSelection.js b/browser/base/content/test/browser_inspector_treeSelection.js index 6da08547f307..9f328d69e29f 100644 --- a/browser/base/content/test/browser_inspector_treeSelection.js +++ b/browser/base/content/test/browser_inspector_treeSelection.js @@ -68,18 +68,16 @@ function setupSelectionTests() { h1 = doc.querySelectorAll("h1")[0]; ok(h1, "we have the header node"); - document.addEventListener("popupshown", runSelectionTests, false); + Services.obs.addObserver(runSelectionTests, "inspector-opened", false); InspectorUI.openInspectorUI(); } -function runSelectionTests(evt) +function runSelectionTests() { - if (evt.target.id != "inspector-panel") - return true; - document.removeEventListener("popupshown", runSelectionTests, false); + Services.obs.removeObserver(runSelectionTests, "inspector-opened", false); InspectorUI.stopInspecting(); document.addEventListener("popupshown", performTestComparisons, false); - InspectorUI.treeView.selectedNode = h1; + InspectorUI.inspectNode(h1); } function performTestComparisons(evt) @@ -87,7 +85,7 @@ function performTestComparisons(evt) if (evt.target.id != "highlighter-panel") return true; document.removeEventListener("popupshown", performTestComparisons, false); - is(h1, InspectorUI.treeView.selectedNode, "selection matches node"); + is(h1, InspectorUI.selection, "selection matches node"); ok(InspectorUI.highlighter.isHighlighting, "panel is highlighting"); is(h1, InspectorUI.highlighter.highlitNode, "highlighter highlighting correct node"); finishUp(); diff --git a/browser/base/content/test/domplate_test.js b/browser/base/content/test/domplate_test.js new file mode 100644 index 000000000000..282a7edceb5f --- /dev/null +++ b/browser/base/content/test/domplate_test.js @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Domplate Test. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Rob Campbell + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +let doc; +let div; +let plate; + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource:///modules/domplate.jsm"); + +function createDocument() +{ + doc.body.innerHTML = '
no
'; + doc.title = "Domplate Test"; + setupDomplateTests(); +} + +function setupDomplateTests() +{ + ok(domplate, "domplate is defined"); + plate = domplate({tag: domplate.DIV("Hello!")}); + ok(plate, "template is defined"); + div = doc.getElementById("first"); + ok(div, "we have our div"); + plate.tag.replace({}, div, template); + is(div.innerText, "Hello!", "Is the div's innerText replaced?"); + finishUp(); +} + +function finishUp() +{ + gBrowser.removeCurrentTab(); + finish(); +} + +function test() +{ + waitForExplicitFinish(); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.selectedBrowser.addEventListener("load", function() { + gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true); + doc = content.document; + waitForFocus(createDocument, content); + }, true); + + content.location = "data:text/html,basic domplate tests"; +} + diff --git a/browser/base/jar.mn b/browser/base/jar.mn index 3e38a94ecbd7..4335d3b049db 100644 --- a/browser/base/jar.mn +++ b/browser/base/jar.mn @@ -30,6 +30,7 @@ browser.jar: * content/browser/browser-tabPreviews.xml (content/browser-tabPreviews.xml) * content/browser/credits.xhtml (content/credits.xhtml) * content/browser/fullscreen-video.xhtml (content/fullscreen-video.xhtml) +* content/browser/inspector.html (content/inspector.html) * content/browser/pageinfo/pageInfo.xul (content/pageinfo/pageInfo.xul) * content/browser/pageinfo/pageInfo.js (content/pageinfo/pageInfo.js) * content/browser/pageinfo/pageInfo.css (content/pageinfo/pageInfo.css) diff --git a/browser/themes/gnomestripe/browser/inspector.css b/browser/themes/gnomestripe/browser/inspector.css new file mode 100644 index 000000000000..c2764611e21a --- /dev/null +++ b/browser/themes/gnomestripe/browser/inspector.css @@ -0,0 +1,377 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2007, Parakey Inc. + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * * Neither the name of Parakey Inc. nor the names of its + * contributors may be used to endorse or promote products + * derived from this software without specific prior + * written permission of Parakey Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Creator: + * Joe Hewitt + * Contributors + * John J. Barton (IBM Almaden) + * Jan Odvarko (Mozilla Corp.) + * Max Stepanov (Aptana Inc.) + * Rob Campbell (Mozilla Corp.) + * Hans Hillen (Paciello Group, Mozilla) + * Curtis Bartley (Mozilla Corp.) + * Mike Collins (IBM Almaden) + * Kevin Decker + * Mike Ratcliffe (Comartis AG) + * Hernan Rodríguez Colmeiro + * Austin Andrews + * Christoph Dorn + * Steven Roussey (AppCenter Inc, Network54) + */ + +html { + background-color: -moz-dialog; +} + +body { + margin: 0; + overflow: auto; + font-family: Lucida Grande, sans-serif; + font-size: 11px; + border-top: 1px solid #BBB9BA; +} + +h1 { + font-size: 17px; + border-bottom: 1px solid threedlightshadow; +} + +a { + color: #0000ff; +} + +pre { + margin: 0; + font: inherit; +} + +code { + display: block; + white-space: pre; +} + +/* DOMPlate */ + +.objectLink-element, +.objectLink-textNode, +.objectLink-function, +.objectBox-stackTrace, +.objectLink-profile { + font-family: Menlo, Andale Mono, monospace; +} + +.objectLink-textNode { + white-space: pre-wrap; +} + +.objectLink-styleRule, +.objectLink-element, +.objectLink-textNode { + color: #000088; +} + +.selectorTag, +.selectorId, +.selectorClass { + font-family: Menlo, Andale Mono, monospace; + font-weight: normal; +} + +.selectorTag { + color: #0000FF; +} + +.selectorId { + color: DarkBlue; +} + +.selectorClass { + color: red; +} + +.selectorHidden > .selectorTag { + color: #5F82D9; +} + +.selectorHidden > .selectorId { + color: #888888; +} + +.selectorHidden > .selectorClass { + color: #D86060; +} + +.selectorValue { + font-family: Menlo, Andale Mono, monospace; + font-style: italic; + color: #555555; +} + +.panelNode-html { + -moz-box-sizing: padding-box; + padding: 4px 0 0 2px; +} + +.nodeBox { + position: relative; + font-family: Menlo, Andale Mono, monospace; + padding-left: 13px; + -moz-user-select: -moz-none; +} + +.nodeBox.search-selection { + -moz-user-select: text; +} + +.twisty { + position: absolute; + left: 0px; + top: 0px; + width: 14px; + height: 14px; +} + +.nodeChildBox { + margin-left: 12px; + display: none; +} + +.nodeLabel, +.nodeCloseLabel { + margin: -2px 2px 0 2px; + border: 2px solid transparent; + -moz-border-radius: 3px; + padding: 0 2px; + color: #000088; +} + +.nodeCloseLabel { + display: none; +} + +.nodeTag { + cursor: pointer; + color: blue; +} + +.nodeValue { + color: #FF0000; + font-weight: normal; +} + +.nodeText, +.nodeComment { + margin: 0 2px; + vertical-align: top; +} + +.nodeText { + color: #333333; +} + +.docType { + position: absolute; + top: -16px; + font-family: Menlo, Andale Mono, monospace; + padding-left: 8px; + color: #999; + white-space: nowrap; + font-style: italic; +} + +.htmlNodeBox { + top: 16px; +} + +.nodeWhiteSpace { + border: 1px solid LightGray; + white-space: pre; /* otherwise the border will be collapsed around zero pixels */ + margin-left: 1px; + color: gray; +} + +.nodeWhiteSpace_Space { + border: 1px solid #ddd; +} + +.nodeTextEntity { + border: 1px solid gray; + white-space: pre; /* otherwise the border will be collapsed around zero pixels */ + margin-left: 1px; +} + +.nodeComment { + color: DarkGreen; +} + +.nodeBox.highlightOpen > .nodeLabel { + background-color: #EEEEEE; +} + +.nodeBox.highlightOpen > .nodeCloseLabel, +.nodeBox.highlightOpen > .nodeChildBox, +.nodeBox.open > .nodeCloseLabel, +.nodeBox.open > .nodeChildBox { + display: block; +} + +.nodeBox.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel { + border-color: Highlight; + background-color: Highlight; + color: HighlightText !important; +} + +.nodeBox.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeTag, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText { + color: inherit !important; +} + +.nodeBox.highlighted > .nodeLabel { + border-color: Highlight !important; + background-color: cyan !important; + color: #000000 !important; +} + +.nodeBox.highlighted > .nodeLabel > .nodeLabelBox, +.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeTag, +.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue, +.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeText { + color: #000000 !important; +} + +.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox, +.nodeBox.nodeHidden .nodeCloseLabel, +.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeText, +.nodeBox.nodeHidden .nodeText { + color: #888888; +} + +.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeTag, +.nodeBox.nodeHidden .nodeCloseLabel > .nodeCloseLabelBox > .nodeTag { + color: #5F82D9; +} + +.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue { + color: #D86060; +} + +.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeTag, +.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue, +.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText { + color: SkyBlue !important; +} + +.nodeBox.mutated > .nodeLabel, +.nodeAttr.mutated, +.nodeValue.mutated, +.nodeText.mutated, +.nodeBox.mutated > .nodeText { + background-color: #EFFF79; + color: #FF0000 !important; +} + +.nodeBox.selected.mutated > .nodeLabel, +.nodeBox.selected.mutated > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr.mutated > .nodeValue, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue.mutated, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText.mutated { + background-color: #EFFF79; + border-color: #EFFF79; + color: #FF0000 !important; +} + +.logRow-dirxml { + padding-left: 0; +} + +.soloElement > .nodeBox { + padding-left: 0; +} + +.useA11y .nodeLabel.focused { + outline: 2px solid #FF9933; + -moz-outline-radius: 3px; + outline-offset: -2px; +} + +.useA11y .nodeLabelBox:focus { + outline: none; +} + +/* from panel.css */ + +/* HTML panel */ + +.nodeBox.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel { + border-color: #3875d7; + background-color: #3875d7; + color: #FFFFFF !important; +} + +.nodeBox.highlighted > .nodeLabel { + border-color: #3875d7 !important; +} + +/************************************************************************************************/ +/* Twisties */ + +.twisty +{ + -moz-appearance: treetwisty; +} + +.nodeBox.highlightOpen > .nodeLabel > .twisty, +.nodeBox.open > .nodeLabel > .twisty +{ + -moz-appearance: treetwistyopen; +} + +/************************************************************************************************/ +/* HTML panel */ + +.nodeBox.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel { + border-color: #3875d7; + background-color: #3875d7; + color: #FFFFFF !important; +} + +.nodeBox.highlighted > .nodeLabel { + border-color: #3875d7 !important; +} diff --git a/browser/themes/gnomestripe/browser/jar.mn b/browser/themes/gnomestripe/browser/jar.mn index 1baff47933a4..6fb08700dcb0 100644 --- a/browser/themes/gnomestripe/browser/jar.mn +++ b/browser/themes/gnomestripe/browser/jar.mn @@ -13,6 +13,7 @@ browser.jar: * skin/classic/browser/browser.css (browser.css) * skin/classic/browser/engineManager.css (engineManager.css) skin/classic/browser/fullscreen-video.css + skin/classic/browser/inspector.css skin/classic/browser/Geolocation-16.png skin/classic/browser/Geolocation-64.png skin/classic/browser/Go-arrow.png diff --git a/browser/themes/pinstripe/browser/inspector.css b/browser/themes/pinstripe/browser/inspector.css new file mode 100644 index 000000000000..539a11f2ea44 --- /dev/null +++ b/browser/themes/pinstripe/browser/inspector.css @@ -0,0 +1,365 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2007, Parakey Inc. + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * * Neither the name of Parakey Inc. nor the names of its + * contributors may be used to endorse or promote products + * derived from this software without specific prior + * written permission of Parakey Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Creator: + * Joe Hewitt + * Contributors + * John J. Barton (IBM Almaden) + * Jan Odvarko (Mozilla Corp.) + * Max Stepanov (Aptana Inc.) + * Rob Campbell (Mozilla Corp.) + * Hans Hillen (Paciello Group, Mozilla) + * Curtis Bartley (Mozilla Corp.) + * Mike Collins (IBM Almaden) + * Kevin Decker + * Mike Ratcliffe (Comartis AG) + * Hernan Rodríguez Colmeiro + * Austin Andrews + * Christoph Dorn + * Steven Roussey (AppCenter Inc, Network54) + */ + +html { + background-color: -moz-dialog; +} + +body { + margin: 0; + overflow: auto; + font-family: Lucida Grande, sans-serif; + font-size: 11px; + border-top: 1px solid #BBB9BA; +} + +h1 { + font-size: 17px; + border-bottom: 1px solid threedlightshadow; +} + +a { + color: #0000ff; +} + +pre { + margin: 0; + font: inherit; +} + +code { + display: block; + white-space: pre; +} + +/* DOMPlate */ + +.objectLink-element, +.objectLink-textNode, +.objectLink-function, +.objectBox-stackTrace, +.objectLink-profile { + font-family: Menlo, Andale Mono, monospace; +} + +.objectLink-textNode { + white-space: pre-wrap; +} + +.objectLink-styleRule, +.objectLink-element, +.objectLink-textNode { + color: #000088; +} + +.selectorTag, +.selectorId, +.selectorClass { + font-family: Menlo, Andale Mono, monospace; + font-weight: normal; +} + +.selectorTag { + color: #0000FF; +} + +.selectorId { + color: DarkBlue; +} + +.selectorClass { + color: red; +} + +.selectorHidden > .selectorTag { + color: #5F82D9; +} + +.selectorHidden > .selectorId { + color: #888888; +} + +.selectorHidden > .selectorClass { + color: #D86060; +} + +.selectorValue { + font-family: Menlo, Andale Mono, monospace; + font-style: italic; + color: #555555; +} + +.panelNode-html { + -moz-box-sizing: padding-box; + padding: 4px 0 0 2px; +} + +.nodeBox { + position: relative; + font-family: Menlo, Andale Mono, monospace; + padding-left: 13px; + -moz-user-select: -moz-none; +} + +.nodeBox.search-selection { + -moz-user-select: text; +} + +.twisty { + position: absolute; + left: 0px; + top: 0px; + width: 14px; + height: 14px; +} + +.nodeChildBox { + margin-left: 12px; + display: none; +} + +.nodeLabel, +.nodeCloseLabel { + margin: -2px 2px 0 2px; + border: 2px solid transparent; + -moz-border-radius: 3px; + padding: 0 2px; + color: #000088; +} + +.nodeCloseLabel { + display: none; +} + +.nodeTag { + cursor: pointer; + color: blue; +} + +.nodeValue { + color: #FF0000; + font-weight: normal; +} + +.nodeText, +.nodeComment { + margin: 0 2px; + vertical-align: top; +} + +.nodeText { + color: #333333; +} + +.docType { + position: absolute; + top: -16px; + font-family: Menlo, Andale Mono, monospace; + padding-left: 8px; + color: #999; + white-space: nowrap; + font-style: italic; +} + +.htmlNodeBox { + top: 16px; +} + +.nodeWhiteSpace { + border: 1px solid LightGray; + white-space: pre; /* otherwise the border will be collapsed around zero pixels */ + margin-left: 1px; + color: gray; +} + +.nodeWhiteSpace_Space { + border: 1px solid #ddd; +} + +.nodeTextEntity { + border: 1px solid gray; + white-space: pre; /* otherwise the border will be collapsed around zero pixels */ + margin-left: 1px; +} + +.nodeComment { + color: DarkGreen; +} + +.nodeBox.highlightOpen > .nodeLabel { + background-color: #EEEEEE; +} + +.nodeBox.highlightOpen > .nodeCloseLabel, +.nodeBox.highlightOpen > .nodeChildBox, +.nodeBox.open > .nodeCloseLabel, +.nodeBox.open > .nodeChildBox { + display: block; +} + +.nodeBox.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel { + border-color: Highlight; + background-color: Highlight; + color: HighlightText !important; +} + +.nodeBox.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeTag, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText { + color: inherit !important; +} + +.nodeBox.highlighted > .nodeLabel { + border-color: Highlight !important; + background-color: cyan !important; + color: #000000 !important; +} + +.nodeBox.highlighted > .nodeLabel > .nodeLabelBox, +.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeTag, +.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue, +.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeText { + color: #000000 !important; +} + +.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox, +.nodeBox.nodeHidden .nodeCloseLabel, +.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeText, +.nodeBox.nodeHidden .nodeText { + color: #888888; +} + +.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeTag, +.nodeBox.nodeHidden .nodeCloseLabel > .nodeCloseLabelBox > .nodeTag { + color: #5F82D9; +} + +.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue { + color: #D86060; +} + +.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeTag, +.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue, +.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText { + color: SkyBlue !important; +} + +.nodeBox.mutated > .nodeLabel, +.nodeAttr.mutated, +.nodeValue.mutated, +.nodeText.mutated, +.nodeBox.mutated > .nodeText { + background-color: #EFFF79; + color: #FF0000 !important; +} + +.nodeBox.selected.mutated > .nodeLabel, +.nodeBox.selected.mutated > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr.mutated > .nodeValue, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue.mutated, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText.mutated { + background-color: #EFFF79; + border-color: #EFFF79; + color: #FF0000 !important; +} + +.logRow-dirxml { + padding-left: 0; +} + +.soloElement > .nodeBox { + padding-left: 0; +} + +.nodeBox.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel { + border-color: #3875d7; + background-color: #3875d7; + color: #FFFFFF !important; +} + +.nodeBox.highlighted > .nodeLabel { + border-color: #3875d7 !important; +} + +/************************************************************************************************/ +/* Twisties */ + +.twisty +{ + -moz-appearance: treetwisty; +} + +.nodeBox.highlightOpen > .nodeLabel > .twisty, +.nodeBox.open > .nodeLabel > .twisty +{ + -moz-appearance: treetwistyopen; +} + +.memberRow.hasChildren > .memberLabelCell > .memberLabel, +.hasHeaders .netHrefLabel { + background-position: 2px 2px; +} + +.nodeBox.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel { + border-color: #3875d7; + background-color: #3875d7; + color: #FFFFFF !important; +} + +.nodeBox.highlighted > .nodeLabel { + border-color: #3875d7 !important; +} diff --git a/browser/themes/pinstripe/browser/jar.mn b/browser/themes/pinstripe/browser/jar.mn index 31435d1b4b57..3a5fc1e5277d 100644 --- a/browser/themes/pinstripe/browser/jar.mn +++ b/browser/themes/pinstripe/browser/jar.mn @@ -65,6 +65,7 @@ browser.jar: skin/classic/browser/feeds/audioFeedIcon.png (feeds/audioFeedIcon.png) skin/classic/browser/feeds/audioFeedIcon16.png (feeds/audioFeedIcon16.png) skin/classic/browser/setDesktopBackground.css + skin/classic/browser/inspector.css skin/classic/browser/monitor.png skin/classic/browser/monitor_16-10.png skin/classic/browser/places/allBookmarks.png (places/allBookmarks.png) diff --git a/browser/themes/winstripe/browser/inspector.css b/browser/themes/winstripe/browser/inspector.css new file mode 100644 index 000000000000..f04bd6c86654 --- /dev/null +++ b/browser/themes/winstripe/browser/inspector.css @@ -0,0 +1,350 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2007, Parakey Inc. + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * * Neither the name of Parakey Inc. nor the names of its + * contributors may be used to endorse or promote products + * derived from this software without specific prior + * written permission of Parakey Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Creator: + * Joe Hewitt + * Contributors + * John J. Barton (IBM Almaden) + * Jan Odvarko (Mozilla Corp.) + * Max Stepanov (Aptana Inc.) + * Rob Campbell (Mozilla Corp.) + * Hans Hillen (Paciello Group, Mozilla) + * Curtis Bartley (Mozilla Corp.) + * Mike Collins (IBM Almaden) + * Kevin Decker + * Mike Ratcliffe (Comartis AG) + * Hernan Rodríguez Colmeiro + * Austin Andrews + * Christoph Dorn + * Steven Roussey (AppCenter Inc, Network54) + */ + +html { + background-color: -moz-dialog; +} + +body { + margin: 0; + overflow: auto; + font-family: Lucida Grande, sans-serif; + font-size: 11px; +} + +h1 { + font-size: 17px; + border-bottom: 1px solid threedlightshadow; +} + +a { + color: #0000ff; +} + +pre { + margin: 0; + font: inherit; +} + +code { + display: block; + white-space: pre; +} + +/* DOMPlate */ + +.objectLink-element, +.objectLink-textNode, +.objectLink-function, +.objectBox-stackTrace, +.objectLink-profile { + font-family: Menlo, Andale Mono, monospace; +} + +.objectLink-textNode { + white-space: pre-wrap; +} + +.objectLink-styleRule, +.objectLink-element, +.objectLink-textNode { + color: #000088; +} + +.selectorTag, +.selectorId, +.selectorClass { + font-family: Menlo, Andale Mono, monospace; + font-weight: normal; +} + +.selectorTag { + color: #0000FF; +} + +.selectorId { + color: DarkBlue; +} + +.selectorClass { + color: red; +} + +.selectorHidden > .selectorTag { + color: #5F82D9; +} + +.selectorHidden > .selectorId { + color: #888888; +} + +.selectorHidden > .selectorClass { + color: #D86060; +} + +.selectorValue { + font-family: Menlo, Andale Mono, monospace; + font-style: italic; + color: #555555; +} + +.panelNode-html { + -moz-box-sizing: padding-box; + padding: 4px 0 0 2px; +} + +.nodeBox { + position: relative; + font-family: Menlo, Andale Mono, monospace; + padding-left: 13px; + -moz-user-select: -moz-none; +} + +.nodeBox.search-selection { + -moz-user-select: text; +} + +.twisty { + position: absolute; + left: 0px; + top: 0px; + width: 14px; + height: 14px; +} + +.nodeChildBox { + margin-left: 12px; + display: none; +} + +.nodeLabel, +.nodeCloseLabel { + margin: -2px 2px 0 2px; + border: 2px solid transparent; + -moz-border-radius: 3px; + padding: 0 2px; + color: #000088; +} + +.nodeCloseLabel { + display: none; +} + +.nodeTag { + cursor: pointer; + color: blue; +} + +.nodeValue { + color: #FF0000; + font-weight: normal; +} + +.nodeText, +.nodeComment { + margin: 0 2px; + vertical-align: top; +} + +.nodeText { + color: #333333; +} + +.docType { + position: absolute; + top: -16px; + font-family: Menlo, Andale Mono, monospace; + padding-left: 8px; + color: #999; + white-space: nowrap; + font-style: italic; +} + +.htmlNodeBox { + top: 16px; +} + +.nodeWhiteSpace { + border: 1px solid LightGray; + white-space: pre; + margin-left: 1px; + color: gray; +} + +.nodeWhiteSpace_Space { + border: 1px solid #ddd; +} + +.nodeTextEntity { + border: 1px solid gray; + white-space: pre; + margin-left: 1px; +} + +.nodeComment { + color: DarkGreen; +} + +.nodeBox.highlightOpen > .nodeLabel { + background-color: #EEEEEE; +} + +.nodeBox.highlightOpen > .nodeCloseLabel, +.nodeBox.highlightOpen > .nodeChildBox, +.nodeBox.open > .nodeCloseLabel, +.nodeBox.open > .nodeChildBox { + display: block; +} + +.nodeBox.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel { + border-color: Highlight; + background-color: Highlight; + color: HighlightText !important; +} + +.nodeBox.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeTag, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText { + color: inherit !important; +} + +.nodeBox.highlighted > .nodeLabel { + border-color: Highlight !important; + background-color: cyan !important; + color: #000000 !important; +} + +.nodeBox.highlighted > .nodeLabel > .nodeLabelBox, +.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeTag, +.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue, +.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeText { + color: #000000 !important; +} + +.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox, +.nodeBox.nodeHidden .nodeCloseLabel, +.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeText, +.nodeBox.nodeHidden .nodeText { + color: #888888; +} + +.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeTag, +.nodeBox.nodeHidden .nodeCloseLabel > .nodeCloseLabelBox > .nodeTag { + color: #5F82D9; +} + +.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue { + color: #D86060; +} + +.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeTag, +.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue, +.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText { + color: SkyBlue !important; +} + +.nodeBox.mutated > .nodeLabel, +.nodeAttr.mutated, +.nodeValue.mutated, +.nodeText.mutated, +.nodeBox.mutated > .nodeText { + background-color: #EFFF79; + color: #FF0000 !important; +} + +.nodeBox.selected.mutated > .nodeLabel, +.nodeBox.selected.mutated > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr.mutated > .nodeValue, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue.mutated, +.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText.mutated { + background-color: #EFFF79; + border-color: #EFFF79; + color: #FF0000 !important; +} + +.logRow-dirxml { + padding-left: 0; +} + +.soloElement > .nodeBox { + padding-left: 0; +} + +.nodeBox.selected > .nodeLabel > .nodeLabelBox, +.nodeBox.selected > .nodeLabel { + border-color: #3875d7; + background-color: #3875d7; + color: #FFFFFF !important; +} + +.nodeBox.highlighted > .nodeLabel { + border-color: #3875d7 !important; +} + +/* Twisties */ + +.twisty +{ + background-repeat: no-repeat; + background-position: center; + background-image: url("chrome://global/skin/tree/twisty-clsd.png") !important; +} + +.nodeBox.highlightOpen > .nodeLabel > .twisty, +.nodeBox.open > .nodeLabel > .twisty +{ + background-image: url("chrome://global/skin/tree/twisty-open.png") !important; +} + diff --git a/browser/themes/winstripe/browser/jar.mn b/browser/themes/winstripe/browser/jar.mn index 27978100b484..7e2309f6baff 100644 --- a/browser/themes/winstripe/browser/jar.mn +++ b/browser/themes/winstripe/browser/jar.mn @@ -58,6 +58,7 @@ browser.jar: skin/classic/browser/feeds/videoFeedIcon16.png (feeds/videoFeedIcon16.png) skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css) skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css) + skin/classic/browser/inspector.css skin/classic/browser/places/places.css (places/places.css) * skin/classic/browser/places/organizer.css (places/organizer.css) skin/classic/browser/places/bookmark.png (places/bookmark.png) From 2ae5984b1e4f0b2bd3056539c90477cfe3f4fc9b Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Fri, 3 Sep 2010 13:16:01 -0400 Subject: [PATCH 112/222] Bug 588351 - Add missing interface reference to ExternalHelperAppParent. r=dwitte a=blocking-fennec --- uriloader/exthandler/ExternalHelperAppParent.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/uriloader/exthandler/ExternalHelperAppParent.cpp b/uriloader/exthandler/ExternalHelperAppParent.cpp index 7ec82177286a..95565977375c 100644 --- a/uriloader/exthandler/ExternalHelperAppParent.cpp +++ b/uriloader/exthandler/ExternalHelperAppParent.cpp @@ -50,10 +50,11 @@ namespace mozilla { namespace dom { -NS_IMPL_ISUPPORTS_INHERITED2(ExternalHelperAppParent, +NS_IMPL_ISUPPORTS_INHERITED3(ExternalHelperAppParent, nsHashPropertyBag, nsIRequest, - nsIChannel) + nsIChannel, + nsIResumableChannel) ExternalHelperAppParent::ExternalHelperAppParent( const IPC::URI& uri, From 8eb36f1ade46a91b1dad42501861135e2b6cbfaa Mon Sep 17 00:00:00 2001 From: Ben Turner Date: Fri, 3 Sep 2010 09:12:27 -0700 Subject: [PATCH 113/222] Bug 593045 - 'Add SQLite file size quota management to mozStorage'. Missed a comment change. r=ted+asuth, a=blocking2.0+. --- storage/src/mozStorageConnection.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/storage/src/mozStorageConnection.h b/storage/src/mozStorageConnection.h index e8194cdfd2f1..9394de97301b 100644 --- a/storage/src/mozStorageConnection.h +++ b/storage/src/mozStorageConnection.h @@ -100,6 +100,9 @@ public: * The nsIFile of the location of the database to open, or create if it * does not exist. Passing in nsnull here creates an in-memory * database. + * @param aVFSName + * The VFS that SQLite will use when opening this database. NULL means + * "default". */ nsresult initialize(nsIFile *aDatabaseFile, const char* aVFSName = NULL); From 5e2fdc8e1fb38dcb735df118ec9ec65fd3edc80f Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Fri, 3 Sep 2010 17:11:50 -0400 Subject: [PATCH 114/222] Bug 593438. d3d9: Don't use an accelerated layer manager for transparent windows. r=vlad Transparent windows require a more complicated dance to get transparency to work correctly. For now, we'll just not accelerate them. --- widget/src/windows/nsWindow.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 5db06086cdc0..853ad99136ce 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -3168,6 +3168,14 @@ nsWindow::GetLayerManager() return nsBaseWidget::GetLayerManager(); } + /* We don't currently support using an accelerated layer manager with + * transparent windows so don't even try. I'm also not sure if we even + * want to support this case. See bug #593471 */ + if (eTransparencyTransparent == mTransparencyMode) { + mUseAcceleratedRendering = PR_FALSE; + return nsBaseWidget::GetLayerManager(); + } + if (topWindow->GetAcceleratedRendering() != mUseAcceleratedRendering) { mLayerManager = NULL; mUseAcceleratedRendering = topWindow->GetAcceleratedRendering(); From 4b23d63e316d4938985bff31bb6451269cab0dcf Mon Sep 17 00:00:00 2001 From: Joe Drew Date: Fri, 3 Sep 2010 17:14:44 -0400 Subject: [PATCH 115/222] Bug 593272. d3d9: Don't try to sync parent/child acceleration status. r=vlad It doesn't make a ton of sense to make child widgets have the same acceleration status as their parent now that we have (mostly - see bug 593440) only one widget per window. (It might never have made sense.) This fixes dialog boxes (which currently have child windows) not displaying any content. --- widget/src/windows/nsWindow.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 853ad99136ce..12e2f6017aa5 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -3176,11 +3176,6 @@ nsWindow::GetLayerManager() return nsBaseWidget::GetLayerManager(); } - if (topWindow->GetAcceleratedRendering() != mUseAcceleratedRendering) { - mLayerManager = NULL; - mUseAcceleratedRendering = topWindow->GetAcceleratedRendering(); - } - #ifndef WINCE if (!mLayerManager) { nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); From 3535a09d4bcb3ab8f0ab6832fecef39b0c490c9f Mon Sep 17 00:00:00 2001 From: Joe Drew Date: Fri, 3 Sep 2010 17:15:10 -0400 Subject: [PATCH 116/222] Bug 590844. reftest: fix the condition setting layersGPUAccelerated. r=vlad, a=b Frig. I accidentally reversed the condition here. --- layout/tools/reftest/reftest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/tools/reftest/reftest.js b/layout/tools/reftest/reftest.js index 8bd2c47285b6..adfead48dc3d 100644 --- a/layout/tools/reftest/reftest.js +++ b/layout/tools/reftest/reftest.js @@ -343,7 +343,7 @@ function BuildConditionSandbox(aURL) { sandbox.d2d = false; } - if (gWindowUtils && gWindowUtils.layerManagerType == "Basic") + if (gWindowUtils && gWindowUtils.layerManagerType != "Basic") sandbox.layersGPUAccelerated = true; else sandbox.layersGPUAccelerated = false; From 072da93f46aca2cbde804876d519a9ff0261e6c7 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Sat, 4 Sep 2010 00:39:29 +0200 Subject: [PATCH 117/222] Bug 575462 - Crash [@ nsDocument::AddToIdTable] with mutation events. r=sicking a2.0=blocking --- content/base/crashtests/575462.svg | 27 +++++++++++++++++++++++++ content/base/crashtests/crashtests.list | 1 + content/base/src/nsStyledElement.cpp | 21 +++++++++++-------- content/base/src/nsStyledElement.h | 2 ++ 4 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 content/base/crashtests/575462.svg diff --git a/content/base/crashtests/575462.svg b/content/base/crashtests/575462.svg new file mode 100644 index 000000000000..8131d5f1fd0b --- /dev/null +++ b/content/base/crashtests/575462.svg @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/content/base/crashtests/crashtests.list b/content/base/crashtests/crashtests.list index fd79e993735f..35cbba5c02ab 100644 --- a/content/base/crashtests/crashtests.list +++ b/content/base/crashtests/crashtests.list @@ -69,3 +69,4 @@ load 564079-1.html load 564114.html load 565125-1.html load 582601.html +load 575462.svg diff --git a/content/base/src/nsStyledElement.cpp b/content/base/src/nsStyledElement.cpp index 81a92723ada3..d8d72c770a24 100644 --- a/content/base/src/nsStyledElement.cpp +++ b/content/base/src/nsStyledElement.cpp @@ -131,23 +131,28 @@ nsresult nsStyledElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRBool aNotify) { - PRBool isId = PR_FALSE; if (aAttribute == nsGkAtoms::id && aNameSpaceID == kNameSpaceID_None) { // Have to do this before clearing flag. See RemoveFromIdTable RemoveFromIdTable(); - isId = PR_TRUE; } - nsMutationGuard guard; - - nsresult rv = nsGenericElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify); + return nsGenericElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify); +} - if (isId && - (!guard.Mutated(0) || !HasAttr(kNameSpaceID_None, nsGkAtoms::id))) { +nsresult +nsStyledElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aAttribute, + const nsAString* aValue, PRBool aNotify) +{ + if (aNamespaceID == kNameSpaceID_None && !aValue && + aAttribute == nsGkAtoms::id) { + // The id has been removed when calling UnsetAttr but we kept it because + // the id is used for some layout stuff between UnsetAttr and AfterSetAttr. + // Now. the id is really removed so it would not be safe to keep this flag. UnsetFlags(NODE_HAS_ID); } - return rv; + return nsGenericElement::AfterSetAttr(aNamespaceID, aAttribute, aValue, + aNotify); } NS_IMETHODIMP diff --git a/content/base/src/nsStyledElement.h b/content/base/src/nsStyledElement.h index abece792698f..9aaf0eae46ca 100644 --- a/content/base/src/nsStyledElement.h +++ b/content/base/src/nsStyledElement.h @@ -80,6 +80,8 @@ public: virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRBool aNotify); + virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, + const nsAString* aValue, PRBool aNotify); nsIDOMCSSStyleDeclaration* GetStyle(nsresult* retval); From f92bf942a3831fe6bc8432fa755363817c84069b Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 4 Sep 2010 00:40:10 +0200 Subject: [PATCH 118/222] Bug 591864 - Convert nsCOMPtr to nsRefPtr for mImageElement in nsIdentifierMapEntry. r=sicking a2.0=jst --- content/base/src/nsDocument.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 3c277c6ab3e0..763e38737658 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -264,7 +264,7 @@ private: nsBaseContentList *mNameContentList; nsRefPtr mDocAllList; nsAutoPtr > mChangeCallbacks; - nsCOMPtr mImageElement; + nsRefPtr mImageElement; }; class nsDocHeaderData From 3e387d5361ddc33c091581e8130e60555588c8f8 Mon Sep 17 00:00:00 2001 From: Jonas Sicking Date: Fri, 3 Sep 2010 15:53:28 -0700 Subject: [PATCH 119/222] Bug 582176: Only send content-document-global-created (and its chrome counter part) when a new window was actually created. Not when we fast-backed to one. r=jst a=blocker --- docshell/test/chrome/582176_dummy.html | 1 + docshell/test/chrome/Makefile.in | 3 + docshell/test/chrome/bug582176_window.xul | 83 +++++++++++++++++++++++ docshell/test/chrome/docshell_helpers.js | 3 +- docshell/test/chrome/test_bug582176.xul | 43 ++++++++++++ dom/base/nsGlobalWindow.cpp | 29 ++++---- 6 files changed, 144 insertions(+), 18 deletions(-) create mode 100644 docshell/test/chrome/582176_dummy.html create mode 100644 docshell/test/chrome/bug582176_window.xul create mode 100644 docshell/test/chrome/test_bug582176.xul diff --git a/docshell/test/chrome/582176_dummy.html b/docshell/test/chrome/582176_dummy.html new file mode 100644 index 000000000000..3b18e512dba7 --- /dev/null +++ b/docshell/test/chrome/582176_dummy.html @@ -0,0 +1 @@ +hello world diff --git a/docshell/test/chrome/Makefile.in b/docshell/test/chrome/Makefile.in index b8e7d92027ca..58d3efc4136a 100644 --- a/docshell/test/chrome/Makefile.in +++ b/docshell/test/chrome/Makefile.in @@ -52,6 +52,7 @@ _HTTP_FILES = \ 215405_nostore.html^headers^ \ 215405_nocache.html \ 215405_nocache.html^headers^ \ + 582176_dummy.html \ $(NULL) _TEST_FILES = \ @@ -94,6 +95,8 @@ _TEST_FILES = \ bug396519_window.xul \ test_bug396649.xul \ bug396649_window.xul \ + test_bug582176.xul \ + bug582176_window.xul \ test_bug428288.html \ test_bug449778.xul \ bug449778_window.xul \ diff --git a/docshell/test/chrome/bug582176_window.xul b/docshell/test/chrome/bug582176_window.xul new file mode 100644 index 000000000000..7c39f3c09c9d --- /dev/null +++ b/docshell/test/chrome/bug582176_window.xul @@ -0,0 +1,83 @@ + + + + + + + + + diff --git a/docshell/test/chrome/docshell_helpers.js b/docshell/test/chrome/docshell_helpers.js index 94e511e0362a..167bfe2eef8a 100755 --- a/docshell/test/chrome/docshell_helpers.js +++ b/docshell/test/chrome/docshell_helpers.js @@ -321,8 +321,9 @@ function finish() { } // Close the test window and signal the framework that the test is done. + let opener = window.opener; window.close(); - window.opener.wrappedJSObject.SimpleTest.finish(); + opener.wrappedJSObject.SimpleTest.finish(); } /** diff --git a/docshell/test/chrome/test_bug582176.xul b/docshell/test/chrome/test_bug582176.xul new file mode 100644 index 000000000000..41090c4a30c2 --- /dev/null +++ b/docshell/test/chrome/test_bug582176.xul @@ -0,0 +1,43 @@ + + + + + + + Test for Bug 582176 + + + + + + Mozilla Bug 582176 +

+ +
+
+ + + + +
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index dcb67c5fab66..d687ed70689a 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -1757,6 +1757,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, if (aState) { newInnerWindow = wsh->GetInnerWindow(); mInnerWindowHolder = wsh->GetInnerWindowHolder(); + + NS_ASSERTION(newInnerWindow, "Got a state without inner window"); // These assignments addref. mNavigator = wsh->GetNavigator(); @@ -1766,22 +1768,13 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, mNavigator->SetDocShell(mDocShell); mNavigator->LoadingNewDocument(); } + } else if (thisChrome) { + newInnerWindow = new nsGlobalChromeWindow(this); + isChrome = PR_TRUE; + } else if (mIsModalContentWindow) { + newInnerWindow = new nsGlobalModalWindow(this); } else { - if (thisChrome) { - newInnerWindow = new nsGlobalChromeWindow(this); - - isChrome = PR_TRUE; - } else { - if (mIsModalContentWindow) { - newInnerWindow = new nsGlobalModalWindow(this); - } else { - newInnerWindow = new nsGlobalWindow(this); - } - } - } - - if (!newInnerWindow) { - return NS_ERROR_OUT_OF_MEMORY; + newInnerWindow = new nsGlobalWindow(this); } if (currentInner && currentInner->mJSObject) { @@ -2047,8 +2040,10 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, wrapper, nsIXPConnect::XPC_XOW_NAVIGATED); NS_ENSURE_SUCCESS(rv, rv); - nsContentUtils::AddScriptRunner( - NS_NewRunnableMethod(this, &nsGlobalWindow::DispatchDOMWindowCreated)); + if (!aState && !reUseInnerWindow) { + nsContentUtils::AddScriptRunner( + NS_NewRunnableMethod(this, &nsGlobalWindow::DispatchDOMWindowCreated)); + } return NS_OK; } From ec1a4a941c58c159ae5b622b692c9a9e2037f619 Mon Sep 17 00:00:00 2001 From: Jonas Sicking Date: Fri, 3 Sep 2010 15:53:28 -0700 Subject: [PATCH 120/222] Bug 590870: Allow mochitest domains that don't support XUL/XBL. r=ted a=test-only --- build/automation.py.in | 8 ++++---- build/pgo/server-locations.txt | 1 + layout/tools/reftest/runreftest.py | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/build/automation.py.in b/build/automation.py.in index 088d72b4a795..b706474bf0af 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -307,10 +307,10 @@ class Automation(object): # Insert desired permissions c = 0 for perm in permissions.keys(): - for host in permissions[perm]: + for host,allow in permissions[perm]: c += 1 - cursor.execute("INSERT INTO moz_hosts values(?, ?, ?, 1, 0, 0)", - (c, host, perm)) + cursor.execute("INSERT INTO moz_hosts values(?, ?, ?, ?, 0, 0)", + (c, host, perm, 1 if allow else 2)) # Commit and close permDB.commit() @@ -327,7 +327,7 @@ class Automation(object): # Set up permissions database locations = self.readLocations() self.setupPermissionsDatabase(profileDir, - {'allowXULXBL':map(lambda l: l.host, locations)}); + {'allowXULXBL':[(l.host, 'noxul' not in l.options) for l in locations]}); part = """\ user_pref("browser.dom.window.dump.enabled", true); diff --git a/build/pgo/server-locations.txt b/build/pgo/server-locations.txt index 12190aa32ea6..a340b91df2d3 100644 --- a/build/pgo/server-locations.txt +++ b/build/pgo/server-locations.txt @@ -106,6 +106,7 @@ http://sub1.test1.example.com:80 privileged http://sub1.test2.example.com:80 privileged http://sub2.test1.example.com:80 privileged http://sub2.test2.example.com:80 privileged +http://noxul.example.com:80 privileged,noxul https://example.com:443 privileged https://test1.example.com:443 privileged diff --git a/layout/tools/reftest/runreftest.py b/layout/tools/reftest/runreftest.py index b8d6ae1d35c6..f2273bb13223 100644 --- a/layout/tools/reftest/runreftest.py +++ b/layout/tools/reftest/runreftest.py @@ -69,7 +69,7 @@ class RefTest(object): "Sets up a profile for reftest." self.automation.setupPermissionsDatabase(profileDir, - {'allowXULXBL': ['localhost', '']}) + {'allowXULXBL': [('localhost', True), ('', True)]}) # Set preferences. prefsFile = open(os.path.join(profileDir, "user.js"), "w") From a38d3a7e8dc4439e8745bbede0488a824ab95c06 Mon Sep 17 00:00:00 2001 From: Jonas Sicking Date: Fri, 3 Sep 2010 15:53:28 -0700 Subject: [PATCH 121/222] Test for bug 590870. r=jst a=test-only --- content/base/test/Makefile.in | 2 ++ content/base/test/file_bug590870.html | 16 +++++++++++ content/base/test/test_bug590870.html | 38 +++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 content/base/test/file_bug590870.html create mode 100644 content/base/test/test_bug590870.html diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index 8b19f0979cfb..6034132f5cda 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -245,6 +245,8 @@ _TEST_FILES1 = test_bug5141.html \ test_bug454325.html \ file_bug391728_2.html \ test_bug456262.html \ + test_bug590870.html \ + file_bug590870.html \ test_bug368972.html \ test_bug448993.html \ test_bug450160.html \ diff --git a/content/base/test/file_bug590870.html b/content/base/test/file_bug590870.html new file mode 100644 index 000000000000..4432b01d3cbb --- /dev/null +++ b/content/base/test/file_bug590870.html @@ -0,0 +1,16 @@ + + + + + + Here be dragons! + + diff --git a/content/base/test/test_bug590870.html b/content/base/test/test_bug590870.html new file mode 100644 index 000000000000..4b24718f1fd2 --- /dev/null +++ b/content/base/test/test_bug590870.html @@ -0,0 +1,38 @@ + + + + + Test for creating XUL elements, bug 590870 + + + + + +Mozilla Bug 590870 +

+ +
+
+
+ + From 1a2c535e49d74a40790e85d9a0dfdfc281f02182 Mon Sep 17 00:00:00 2001 From: Jonas Sicking Date: Fri, 3 Sep 2010 15:53:28 -0700 Subject: [PATCH 122/222] Test for bug 590812. r=jst a=test-only --- content/base/test/Makefile.in | 3 ++ content/base/test/file_bug590812-ref.xhtml | 3 ++ content/base/test/file_bug590812.xml | 1 + content/base/test/test_bug590812.html | 37 +++++++++++++++++++ .../tests/SimpleTest/WindowSnapshot.js | 7 ++-- 5 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 content/base/test/file_bug590812-ref.xhtml create mode 100644 content/base/test/file_bug590812.xml create mode 100644 content/base/test/test_bug590812.html diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index 6034132f5cda..9e7cc91ca35c 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -247,6 +247,9 @@ _TEST_FILES1 = test_bug5141.html \ test_bug456262.html \ test_bug590870.html \ file_bug590870.html \ + test_bug590812.html \ + file_bug590812.xml \ + file_bug590812-ref.xhtml \ test_bug368972.html \ test_bug448993.html \ test_bug450160.html \ diff --git a/content/base/test/file_bug590812-ref.xhtml b/content/base/test/file_bug590812-ref.xhtml new file mode 100644 index 000000000000..85375f831759 --- /dev/null +++ b/content/base/test/file_bug590812-ref.xhtml @@ -0,0 +1,3 @@ +
<out>Here be sea hags</out>
diff --git a/content/base/test/file_bug590812.xml b/content/base/test/file_bug590812.xml new file mode 100644 index 000000000000..759d5066cf0f --- /dev/null +++ b/content/base/test/file_bug590812.xml @@ -0,0 +1 @@ +Here be sea hags diff --git a/content/base/test/test_bug590812.html b/content/base/test/test_bug590812.html new file mode 100644 index 000000000000..c7965c321f23 --- /dev/null +++ b/content/base/test/test_bug590812.html @@ -0,0 +1,37 @@ + + + + Test for XML pretty printing, bug 590812 + + + + + + +Mozilla Bug 590812 +

+ + + +
+
+
+ + diff --git a/testing/mochitest/tests/SimpleTest/WindowSnapshot.js b/testing/mochitest/tests/SimpleTest/WindowSnapshot.js index e55c59bc25f9..f0c46b4472e0 100644 --- a/testing/mochitest/tests/SimpleTest/WindowSnapshot.js +++ b/testing/mochitest/tests/SimpleTest/WindowSnapshot.js @@ -11,13 +11,14 @@ try { } function snapshotWindow(win, withCaret) { + // drawWindow requires privileges, as might innerWidth/innerHeight if it's + // a cross domain window + netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); + var el = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); el.width = win.innerWidth; el.height = win.innerHeight; - // drawWindow requires privileges - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - var ctx = el.getContext("2d"); ctx.drawWindow(win, win.scrollX, win.scrollY, win.innerWidth, win.innerHeight, From 6c4013865874ece5b1e511b1dda6e24d50afb73b Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Sat, 4 Sep 2010 09:32:13 +0900 Subject: [PATCH 123/222] Bug 574588 - nsAccessible::GetRole() should avoid a11y tree traversal, r=davidb, a=davidb --- accessible/src/base/nsAccessible.cpp | 4 +--- accessible/src/xul/nsXULColorPickerAccessible.cpp | 2 -- accessible/src/xul/nsXULFormControlAccessible.cpp | 2 -- accessible/src/xul/nsXULMenuAccessible.cpp | 11 ++++++----- 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/accessible/src/base/nsAccessible.cpp b/accessible/src/base/nsAccessible.cpp index 8808c98aa77c..3a32c796a2d5 100644 --- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -2785,9 +2785,7 @@ nsAccessible::GetParent() // XXX: mParent can be null randomly because supposedly we get layout // notification and invalidate parent-child relations, this accessible stays - // unattached. This should gone after bug 572951. Other reason is bug 574588 - // since CacheChildren() implementation calls nsAccessible::GetRole() what - // can need to get a parent and we are here as result. + // unattached. This should gone after bug 572951. NS_WARNING("Bad accessible tree!"); #ifdef DEBUG diff --git a/accessible/src/xul/nsXULColorPickerAccessible.cpp b/accessible/src/xul/nsXULColorPickerAccessible.cpp index ca88fc865b1d..ad21ff216009 100644 --- a/accessible/src/xul/nsXULColorPickerAccessible.cpp +++ b/accessible/src/xul/nsXULColorPickerAccessible.cpp @@ -166,8 +166,6 @@ nsXULColorPickerAccessible::CacheChildren() nsRefPtr child; while ((child = walker.GetNextChild())) { - // XXX: do not call nsAccessible::GetRole() while accessible not in tree - // (bug 574588). PRUint32 role = nsAccUtils::Role(child); // Get an accessbile for menupopup or panel elements. diff --git a/accessible/src/xul/nsXULFormControlAccessible.cpp b/accessible/src/xul/nsXULFormControlAccessible.cpp index 975052aadbc8..237c3bcfee6c 100644 --- a/accessible/src/xul/nsXULFormControlAccessible.cpp +++ b/accessible/src/xul/nsXULFormControlAccessible.cpp @@ -212,8 +212,6 @@ nsXULButtonAccessible::CacheChildren() nsRefPtr child; while ((child = walker.GetNextChild())) { - // XXX: do not call nsAccessible::GetRole() while accessible not in tree - // (bug 574588). PRUint32 role = nsAccUtils::Role(child); if (role == nsIAccessibleRole::ROLE_MENUPOPUP) { diff --git a/accessible/src/xul/nsXULMenuAccessible.cpp b/accessible/src/xul/nsXULMenuAccessible.cpp index 116f02a90898..8fdc59e9a894 100644 --- a/accessible/src/xul/nsXULMenuAccessible.cpp +++ b/accessible/src/xul/nsXULMenuAccessible.cpp @@ -488,7 +488,7 @@ nsXULMenuitemAccessible::GetRoleInternal(PRUint32 *aRole) return NS_OK; } - if (nsAccUtils::Role(GetParent()) == nsIAccessibleRole::ROLE_COMBOBOX_LIST) { + if (nsAccUtils::Role(mParent) == nsIAccessibleRole::ROLE_COMBOBOX_LIST) { *aRole = nsIAccessibleRole::ROLE_COMBOBOX_OPTION; return NS_OK; } @@ -670,9 +670,10 @@ nsXULMenupopupAccessible::GetNameInternal(nsAString& aName) nsresult nsXULMenupopupAccessible::GetRoleInternal(PRUint32 *aRole) { - nsAccessible *parent = GetParent(); - if (parent) { - PRUint32 role = nsAccUtils::Role(parent); + // If accessible is not bound to the tree (this happens while children are + // cached) return general role. + if (mParent) { + PRUint32 role = nsAccUtils::Role(mParent); if (role == nsIAccessibleRole::ROLE_COMBOBOX || role == nsIAccessibleRole::ROLE_AUTOCOMPLETE) { *aRole = nsIAccessibleRole::ROLE_COMBOBOX_LIST; @@ -680,7 +681,7 @@ nsXULMenupopupAccessible::GetRoleInternal(PRUint32 *aRole) } else if (role == nsIAccessibleRole::ROLE_PUSHBUTTON) { // Some widgets like the search bar have several popups, owned by buttons. - nsAccessible *grandParent = parent->GetParent(); + nsAccessible* grandParent = mParent->GetParent(); if (nsAccUtils::Role(grandParent) == nsIAccessibleRole::ROLE_AUTOCOMPLETE) { *aRole = nsIAccessibleRole::ROLE_COMBOBOX_LIST; return NS_OK; From 761a179dc15e20e7b2dcf67c0754b41fbf30afef Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 3 Sep 2010 19:04:05 -0700 Subject: [PATCH 124/222] Bug 591052 - MessageManager wakeup service. r=mfinkle,smaug a=blocking-fennec2.0b1 --- .../base/public/nsIMessageWakeupService.idl | 74 ++++++++++++ content/base/src/Makefile.in | 2 + content/base/src/messageWakeupService.js | 110 ++++++++++++++++++ .../base/src/messageWakeupService.manifest | 4 + 4 files changed, 190 insertions(+) create mode 100644 content/base/public/nsIMessageWakeupService.idl create mode 100644 content/base/src/messageWakeupService.js create mode 100644 content/base/src/messageWakeupService.manifest diff --git a/content/base/public/nsIMessageWakeupService.idl b/content/base/public/nsIMessageWakeupService.idl new file mode 100644 index 000000000000..bd16ee8eb329 --- /dev/null +++ b/content/base/public/nsIMessageWakeupService.idl @@ -0,0 +1,74 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is the Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alon Zakai + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +/** + * This service lets other components be woken up when particular + * messageManager messages arrive. By using this wakeup service, + * those components do not need to be started until they are + * needed. + * + * The parentprocessmessagemanager is used for this, so messages + * send from childprocessmessagemanagers will be heard. + * + * Components can request wakeups using the .manifest files, or + * by someone else calling requestWakeup. For .manifest files, + * the line should look something like + * + * category wakeup-request nsComponent @mozilla.org/myservice;1, + * nsIMyInterface,getService,myMessage1,myMessage2[,..] + * + * Currently we require services to expose wrappedJSObject, but + * that will be cleaned up in bug 593407, at which point the + * service that will be woken up must implement + * nsIFrameMessageListener. + */ +[scriptable, uuid(968e31b6-b859-42f3-8140-014378fe1783)] +interface nsIMessageWakeupService : nsISupports +{ + /** + * Requests that the wakeup service wake us up when a particular + * message arrives. At that time the service will be woken up + * and subscribed to receive further messages of that name as + * well. + */ + boolean requestWakeup(in AString aMessageName, + in AString aCid, + in AString aIid, + in AString aMethod); +}; + diff --git a/content/base/src/Makefile.in b/content/base/src/Makefile.in index f9018dc089a7..94b983561ab0 100644 --- a/content/base/src/Makefile.in +++ b/content/base/src/Makefile.in @@ -163,6 +163,8 @@ EXTRA_COMPONENTS = \ contentSecurityPolicy.manifest \ contentAreaDropListener.js \ contentAreaDropListener.manifest \ + messageWakeupService.js \ + messageWakeupService.manifest \ $(NULL) EXTRA_JS_MODULES = \ diff --git a/content/base/src/messageWakeupService.js b/content/base/src/messageWakeupService.js new file mode 100644 index 000000000000..f4a0b6e2350b --- /dev/null +++ b/content/base/src/messageWakeupService.js @@ -0,0 +1,110 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is the Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alon Zakai + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); + +const Cc = Components.classes; +const Ci = Components.interfaces; + +const CATEGORY_WAKEUP_REQUEST = "wakeup-request"; + +function MessageWakeupService() { }; + +MessageWakeupService.prototype = +{ + classID: Components.ID("{f9798742-4f7b-4188-86ba-48b116412b29}"), + QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageWakeupService, Ci.nsISupports, Ci.nsIObserver]), + + messagesData: [], + + get messageManager() { + if (!this._messageManager) + this._messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"]. + getService(Ci.nsIFrameMessageManager); + return this._messageManager; + }, + + requestWakeup: function(aMessageName, aCid, aIid, aMethod) { + this.messagesData[aMessageName] = { + cid: aCid, + iid: aIid, + method: aMethod, + }; + + this.messageManager.addMessageListener(aMessageName, this); + }, + + receiveMessage: function(aMessage) { + var data = this.messagesData[aMessage.name]; + delete this.messagesData[aMessage.name]; + var service = Cc[data.cid][data.method](Ci[data.iid]). + wrappedJSObject; +// TODO: When bug 593407 is ready, stop doing the wrappedJSObject hack +// and use the line below instead +// QueryInterface(Ci.nsIFrameMessageListener); + this.messageManager.addMessageListener(aMessage.name, service); + this.messageManager.removeMessageListener(aMessage.name, this); + service.receiveMessage(aMessage); + }, + + observe: function TM_observe(aSubject, aTopic, aData) { + switch (aTopic) { + case "profile-after-change": + { + var catMan = Cc["@mozilla.org/categorymanager;1"]. + getService(Ci.nsICategoryManager); + var entries = catMan.enumerateCategory(CATEGORY_WAKEUP_REQUEST); + while (entries.hasMoreElements()) { + var entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data; + var value = catMan.getCategoryEntry(CATEGORY_WAKEUP_REQUEST, entry); + var parts = value.split(","); + var cid = parts[0]; + var iid = parts[1]; + var method = parts[2]; + var messages = parts.slice(3); + messages.forEach(function(messageName) { + this.requestWakeup(messageName, cid, iid, method); + }, this); + } + } + break; + } + }, +}; + +var components = [MessageWakeupService]; +const NSGetFactory = XPCOMUtils.generateNSGetFactory(components); + diff --git a/content/base/src/messageWakeupService.manifest b/content/base/src/messageWakeupService.manifest new file mode 100644 index 000000000000..271e7b8f5413 --- /dev/null +++ b/content/base/src/messageWakeupService.manifest @@ -0,0 +1,4 @@ +component {f9798742-4f7b-4188-86ba-48b116412b29} messageWakeupService.js +contract @mozilla.org/content/messagewakeupservice;1 {f9798742-4f7b-4188-86ba-48b116412b29} +category profile-after-change messageWakeupService @mozilla.org/content/messagewakeupservice;1 + From 27845c2ea101f03f98aab3d751be35ae96810f11 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Sat, 4 Sep 2010 11:20:09 +0900 Subject: [PATCH 125/222] Bug 593377 bug 585922 killed all tests in dom/tests/browser r=bzbarsky, a=blocking2.0 final+ --- dom/tests/Makefile.in | 2 +- dom/tests/browser/Makefile.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dom/tests/Makefile.in b/dom/tests/Makefile.in index d972533afcdb..96e9e5e0514a 100644 --- a/dom/tests/Makefile.in +++ b/dom/tests/Makefile.in @@ -50,7 +50,7 @@ DIRS += mochitest \ XPCSHELL_TESTS = unit ifneq (mobile,$(MOZ_BUILD_APP)) - dirs += browser + DIRS += browser endif include $(topsrcdir)/config/rules.mk diff --git a/dom/tests/browser/Makefile.in b/dom/tests/browser/Makefile.in index 0bb5381acd2c..00eff1777c9f 100644 --- a/dom/tests/browser/Makefile.in +++ b/dom/tests/browser/Makefile.in @@ -46,7 +46,7 @@ include $(topsrcdir)/config/rules.mk _BROWSER_FILES = \ browser_focus_steal_from_chrome.js \ - browser_autofocus_background.js \ + $(warning browser_autofocus_background.js temporarily disabled, see bug 593378) \ $(NULL) libs:: $(_BROWSER_FILES) From 9c2950db18930d52175881dea1651ebc73947eea Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 3 Sep 2010 23:21:14 -0400 Subject: [PATCH 126/222] Bug 593275. Take reftest snapshots by painting the toplevel window. r=dbaron --- layout/tools/reftest/reftest.js | 59 ++++++++++----------------------- 1 file changed, 18 insertions(+), 41 deletions(-) diff --git a/layout/tools/reftest/reftest.js b/layout/tools/reftest/reftest.js index adfead48dc3d..80633757e3b1 100644 --- a/layout/tools/reftest/reftest.js +++ b/layout/tools/reftest/reftest.js @@ -880,21 +880,21 @@ function OnDocumentLoad(event) } function WhenMozAfterPaintFlushed(continuation) { - if (utils.isMozAfterPaintPending) { + if (gWindowUtils.isMozAfterPaintPending) { function handler() { - gBrowser.removeEventListener("MozAfterPaint", handler, false); + window.removeEventListener("MozAfterPaint", handler, false); continuation(); } - gBrowser.addEventListener("MozAfterPaint", handler, false); + window.addEventListener("MozAfterPaint", handler, false); } else { continuation(); } } function AfterPaintListener(event) { - if (event.target.document != currentDoc) { + if (event.target.document != document) { // ignore paint events for subframes or old documents in the window. - // Invalidation in subframes will cause invalidation in the main document anyway. + // Invalidation in subframes will cause invalidation in the toplevel document anyway. return; } @@ -903,13 +903,13 @@ function OnDocumentLoad(event) // When stopAfteraintReceived is set, we can stop --- but we should keep going as long // as there are paint events coming (there probably shouldn't be any, but it doesn't // hurt to process them) - if (stopAfterPaintReceived && !utils.isMozAfterPaintPending) { + if (stopAfterPaintReceived && !gWindowUtils.isMozAfterPaintPending) { FinishWaitingForTestEnd(); } } function FinishWaitingForTestEnd() { - gBrowser.removeEventListener("MozAfterPaint", AfterPaintListener, false); + window.removeEventListener("MozAfterPaint", AfterPaintListener, false); setTimeout(DocumentLoaded, 0); } @@ -931,7 +931,7 @@ function OnDocumentLoad(event) setupPrintMode(); FlushRendering(); - if (utils.isMozAfterPaintPending) { + if (gWindowUtils.isMozAfterPaintPending) { // Wait for the last invalidation to have happened and been snapshotted before // we stop the test stopAfterPaintReceived = true; @@ -945,7 +945,7 @@ function OnDocumentLoad(event) FlushRendering(); function continuation() { - gBrowser.addEventListener("MozAfterPaint", AfterPaintListener, false); + window.addEventListener("MozAfterPaint", AfterPaintListener, false); contentRootElement.addEventListener("DOMAttrModified", AttrModifiedListener, false); // Take a snapshot of the window in its current state @@ -1002,7 +1002,7 @@ function UpdateCanvasCache(url, canvas) // Compute drawWindow flags lazily so the window is set up and can be // measured accurately -function DoDrawWindow(ctx, win, x, y, w, h) +function DoDrawWindow(ctx, x, y, w, h) { if (typeof gDrawWindowFlags == "undefined") { gDrawWindowFlags = ctx.DRAWWINDOW_DRAW_CARET | @@ -1021,13 +1021,7 @@ function DoDrawWindow(ctx, win, x, y, w, h) r.width + "," + r.height + "\n"); } - var scrollX = 0; - var scrollY = 0; - if (!(gDrawWindowFlags & ctx.DRAWWINDOW_DRAW_VIEW)) { - scrollX = win.scrollX; - scrollY = win.scrollY; - } - ctx.drawWindow(win, scrollX + x, scrollY + y, w, h, "rgb(255,255,255)", + ctx.drawWindow(window, x, y, w, h, "rgb(255,255,255)", gDrawWindowFlags); } @@ -1040,21 +1034,8 @@ function InitCurrentCanvasWithSnapshot() gCurrentCanvas = AllocateCanvas(); - /* XXX This needs to be rgb(255,255,255) because otherwise we get - * black bars at the bottom of every test that are different size - * for the first test and the rest (scrollbar-related??) */ - var win = gBrowser.contentWindow; var ctx = gCurrentCanvas.getContext("2d"); - var scale = gBrowser.markupDocumentViewer.fullZoom; - ctx.save(); - // drawWindow always draws one canvas pixel for each CSS pixel in the source - // window, so scale the drawing to show the zoom (making each canvas pixel be one - // device pixel instead) - ctx.scale(scale, scale); - DoDrawWindow(ctx, win, 0, 0, - Math.ceil(gCurrentCanvas.width / scale), - Math.ceil(gCurrentCanvas.height / scale)); - ctx.restore(); + DoDrawWindow(ctx, 0, 0, gCurrentCanvas.width, gCurrentCanvas.height); } function roundTo(x, fraction) @@ -1067,23 +1048,19 @@ function UpdateCurrentCanvasForEvent(event) if (!gCurrentCanvas) return; - var win = gBrowser.contentWindow; var ctx = gCurrentCanvas.getContext("2d"); - var scale = gBrowser.markupDocumentViewer.fullZoom; - var rectList = event.clientRects; for (var i = 0; i < rectList.length; ++i) { var r = rectList[i]; - // Set left/top/right/bottom to "device pixel" boundaries - var left = Math.floor(roundTo(r.left*scale, 0.001))/scale; - var top = Math.floor(roundTo(r.top*scale, 0.001))/scale; - var right = Math.ceil(roundTo(r.right*scale, 0.001))/scale; - var bottom = Math.ceil(roundTo(r.bottom*scale, 0.001))/scale; + // Set left/top/right/bottom to pixel boundaries + var left = Math.floor(r.left); + var top = Math.floor(r.top); + var right = Math.ceil(r.right); + var bottom = Math.ceil(r.bottom); ctx.save(); - ctx.scale(scale, scale); ctx.translate(left, top); - DoDrawWindow(ctx, win, left, top, right - left, bottom - top); + DoDrawWindow(ctx, left, top, right - left, bottom - top); ctx.restore(); } } From a851698e78c5ba564f3e74f7873b660930b0b5e4 Mon Sep 17 00:00:00 2001 From: Felipe Gomes Date: Fri, 3 Sep 2010 23:21:26 -0400 Subject: [PATCH 127/222] Bug 592870 - Make caption buttons work with D3D9-accelerated layers. r=jrmuizel a=blocking2.0:beta6+ --- widget/src/windows/nsWindowGfx.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/widget/src/windows/nsWindowGfx.cpp b/widget/src/windows/nsWindowGfx.cpp index db3d527f7563..4b9d616e3a72 100644 --- a/widget/src/windows/nsWindowGfx.cpp +++ b/widget/src/windows/nsWindowGfx.cpp @@ -756,6 +756,23 @@ DDRAW_FAILED: } } +#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN + if(event.region.Intersects(mCaptionButtons)) { + // Temporary workaround to make the captions buttons visible for D3D9 + const nsIntRect* r; + RECT rect; + HBRUSH blackBrush = (HBRUSH)GetStockObject(BLACK_BRUSH); + for (nsIntRegionRectIterator iter(mCaptionButtonsRoundedRegion); + (r = iter.Next()) != nsnull;) { + rect.top = r->y; + rect.left = r->x; + rect.right = r->XMost(); + rect.bottom = r->YMost(); + FillRect(hDC, &rect, blackBrush); + } + } +#endif + if (!aDC) { ::EndPaint(mWnd, &ps); } From aaa21a504a588ffe05f1d0c55f17b51224a9f124 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Fri, 3 Sep 2010 23:27:04 -0400 Subject: [PATCH 128/222] Bug 587678 - Implement ImageLayerOGL::GetCurrentAsSurface for YUV surfaces. r=bas a=blocking2.0:beta6+ --- gfx/layers/opengl/ImageLayerOGL.cpp | 31 ++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/gfx/layers/opengl/ImageLayerOGL.cpp b/gfx/layers/opengl/ImageLayerOGL.cpp index 405132cb7232..42d5aa51a190 100644 --- a/gfx/layers/opengl/ImageLayerOGL.cpp +++ b/gfx/layers/opengl/ImageLayerOGL.cpp @@ -38,6 +38,7 @@ #include "ImageLayerOGL.h" #include "gfxImageSurface.h" +#include "yuv_convert.h" #include "GLContextProvider.h" using namespace mozilla::gl; @@ -253,22 +254,37 @@ ImageContainerOGL::GetCurrentAsSurface(gfxIntSize *aSize) GLContext *gl = nsnull; // tex1 will be RGBA or Y, tex2 will Cb, tex3 will be Cr - GLuint tex1 = 0, tex2 = 0, tex3 = 0; + GLuint tex1 = 0; gfxIntSize size; if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) { PlanarYCbCrImageOGL *yuvImage = static_cast(mActiveImage.get()); - if (!yuvImage->HasData() || !yuvImage->HasTextures()) { + if (!yuvImage->HasData()) { *aSize = gfxIntSize(0, 0); return nsnull; } size = yuvImage->mSize; - gl = yuvImage->mTextures[0].GetGLContext(); - tex1 = yuvImage->mTextures[0].GetTextureID(); - tex2 = yuvImage->mTextures[1].GetTextureID(); - tex3 = yuvImage->mTextures[2].GetTextureID(); + + nsRefPtr imageSurface = + new gfxImageSurface(size, gfxASurface::ImageFormatRGB24); + + gfx::ConvertYCbCrToRGB32(yuvImage->mData.mYChannel, + yuvImage->mData.mCbChannel, + yuvImage->mData.mCrChannel, + imageSurface->Data(), + 0, + 0, + size.width, + size.height, + yuvImage->mData.mYStride, + yuvImage->mData.mCbCrStride, + imageSurface->Stride(), + yuvImage->mType); + + *aSize = size; + return imageSurface.forget().get(); } if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) { @@ -279,9 +295,6 @@ ImageContainerOGL::GetCurrentAsSurface(gfxIntSize *aSize) tex1 = cairoImage->mTexture.GetTextureID(); } - // XXX TODO: read all textures in YCbCr case and convert to RGB - // XXX Or maybe add a ReadYCbCrTextureImage that will take 3 textures - // and return RGB, since we can render YCbCr to the temporary framebuffer. nsRefPtr s = gl->ReadTextureImage(tex1, size, LOCAL_GL_RGBA); *aSize = size; return s.forget(); From 1f4350abad0021d71a7c3da6f0a6983bdd65db7c Mon Sep 17 00:00:00 2001 From: Joe Drew Date: Fri, 3 Sep 2010 23:27:07 -0400 Subject: [PATCH 129/222] Bug 581212 - turn on Direct3D accelerated layers on Windows. r=vlad a=blocking2.0:beta6+ --- modules/libpref/src/init/all.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 5b2f4765842a..dc571919a164 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -3182,7 +3182,11 @@ pref("gfx.color_management.mode", 0); pref("mozilla.widget.render-mode", -1); // Default value of acceleration for all widgets. +#ifdef XP_WIN +pref("layers.accelerate-all", true); +#else pref("layers.accelerate-all", false); +#endif // Whether to allow acceleration on layers at all. pref("layers.accelerate-none", false); From 95b6aeb65f7153df2c38d497cebec0bd8cee3807 Mon Sep 17 00:00:00 2001 From: Joe Drew Date: Sat, 4 Sep 2010 00:32:36 -0400 Subject: [PATCH 130/222] Back out roc's reftest patch, which broke reftests on non-accelerated layer managers. --- layout/tools/reftest/reftest.js | 59 +++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/layout/tools/reftest/reftest.js b/layout/tools/reftest/reftest.js index 80633757e3b1..adfead48dc3d 100644 --- a/layout/tools/reftest/reftest.js +++ b/layout/tools/reftest/reftest.js @@ -880,21 +880,21 @@ function OnDocumentLoad(event) } function WhenMozAfterPaintFlushed(continuation) { - if (gWindowUtils.isMozAfterPaintPending) { + if (utils.isMozAfterPaintPending) { function handler() { - window.removeEventListener("MozAfterPaint", handler, false); + gBrowser.removeEventListener("MozAfterPaint", handler, false); continuation(); } - window.addEventListener("MozAfterPaint", handler, false); + gBrowser.addEventListener("MozAfterPaint", handler, false); } else { continuation(); } } function AfterPaintListener(event) { - if (event.target.document != document) { + if (event.target.document != currentDoc) { // ignore paint events for subframes or old documents in the window. - // Invalidation in subframes will cause invalidation in the toplevel document anyway. + // Invalidation in subframes will cause invalidation in the main document anyway. return; } @@ -903,13 +903,13 @@ function OnDocumentLoad(event) // When stopAfteraintReceived is set, we can stop --- but we should keep going as long // as there are paint events coming (there probably shouldn't be any, but it doesn't // hurt to process them) - if (stopAfterPaintReceived && !gWindowUtils.isMozAfterPaintPending) { + if (stopAfterPaintReceived && !utils.isMozAfterPaintPending) { FinishWaitingForTestEnd(); } } function FinishWaitingForTestEnd() { - window.removeEventListener("MozAfterPaint", AfterPaintListener, false); + gBrowser.removeEventListener("MozAfterPaint", AfterPaintListener, false); setTimeout(DocumentLoaded, 0); } @@ -931,7 +931,7 @@ function OnDocumentLoad(event) setupPrintMode(); FlushRendering(); - if (gWindowUtils.isMozAfterPaintPending) { + if (utils.isMozAfterPaintPending) { // Wait for the last invalidation to have happened and been snapshotted before // we stop the test stopAfterPaintReceived = true; @@ -945,7 +945,7 @@ function OnDocumentLoad(event) FlushRendering(); function continuation() { - window.addEventListener("MozAfterPaint", AfterPaintListener, false); + gBrowser.addEventListener("MozAfterPaint", AfterPaintListener, false); contentRootElement.addEventListener("DOMAttrModified", AttrModifiedListener, false); // Take a snapshot of the window in its current state @@ -1002,7 +1002,7 @@ function UpdateCanvasCache(url, canvas) // Compute drawWindow flags lazily so the window is set up and can be // measured accurately -function DoDrawWindow(ctx, x, y, w, h) +function DoDrawWindow(ctx, win, x, y, w, h) { if (typeof gDrawWindowFlags == "undefined") { gDrawWindowFlags = ctx.DRAWWINDOW_DRAW_CARET | @@ -1021,7 +1021,13 @@ function DoDrawWindow(ctx, x, y, w, h) r.width + "," + r.height + "\n"); } - ctx.drawWindow(window, x, y, w, h, "rgb(255,255,255)", + var scrollX = 0; + var scrollY = 0; + if (!(gDrawWindowFlags & ctx.DRAWWINDOW_DRAW_VIEW)) { + scrollX = win.scrollX; + scrollY = win.scrollY; + } + ctx.drawWindow(win, scrollX + x, scrollY + y, w, h, "rgb(255,255,255)", gDrawWindowFlags); } @@ -1034,8 +1040,21 @@ function InitCurrentCanvasWithSnapshot() gCurrentCanvas = AllocateCanvas(); + /* XXX This needs to be rgb(255,255,255) because otherwise we get + * black bars at the bottom of every test that are different size + * for the first test and the rest (scrollbar-related??) */ + var win = gBrowser.contentWindow; var ctx = gCurrentCanvas.getContext("2d"); - DoDrawWindow(ctx, 0, 0, gCurrentCanvas.width, gCurrentCanvas.height); + var scale = gBrowser.markupDocumentViewer.fullZoom; + ctx.save(); + // drawWindow always draws one canvas pixel for each CSS pixel in the source + // window, so scale the drawing to show the zoom (making each canvas pixel be one + // device pixel instead) + ctx.scale(scale, scale); + DoDrawWindow(ctx, win, 0, 0, + Math.ceil(gCurrentCanvas.width / scale), + Math.ceil(gCurrentCanvas.height / scale)); + ctx.restore(); } function roundTo(x, fraction) @@ -1048,19 +1067,23 @@ function UpdateCurrentCanvasForEvent(event) if (!gCurrentCanvas) return; + var win = gBrowser.contentWindow; var ctx = gCurrentCanvas.getContext("2d"); + var scale = gBrowser.markupDocumentViewer.fullZoom; + var rectList = event.clientRects; for (var i = 0; i < rectList.length; ++i) { var r = rectList[i]; - // Set left/top/right/bottom to pixel boundaries - var left = Math.floor(r.left); - var top = Math.floor(r.top); - var right = Math.ceil(r.right); - var bottom = Math.ceil(r.bottom); + // Set left/top/right/bottom to "device pixel" boundaries + var left = Math.floor(roundTo(r.left*scale, 0.001))/scale; + var top = Math.floor(roundTo(r.top*scale, 0.001))/scale; + var right = Math.ceil(roundTo(r.right*scale, 0.001))/scale; + var bottom = Math.ceil(roundTo(r.bottom*scale, 0.001))/scale; ctx.save(); + ctx.scale(scale, scale); ctx.translate(left, top); - DoDrawWindow(ctx, left, top, right - left, bottom - top); + DoDrawWindow(ctx, win, left, top, right - left, bottom - top); ctx.restore(); } } From 2b37d991aed97f96b9e92c1f0abb824261a2309e Mon Sep 17 00:00:00 2001 From: Joe Drew Date: Sat, 4 Sep 2010 00:34:05 -0400 Subject: [PATCH 131/222] Without roc's reftest patch, we can't turn on D3D9, because we don't have reftest coverage. Back out the on-by-default patch. --- modules/libpref/src/init/all.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index dc571919a164..5b2f4765842a 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -3182,11 +3182,7 @@ pref("gfx.color_management.mode", 0); pref("mozilla.widget.render-mode", -1); // Default value of acceleration for all widgets. -#ifdef XP_WIN -pref("layers.accelerate-all", true); -#else pref("layers.accelerate-all", false); -#endif // Whether to allow acceleration on layers at all. pref("layers.accelerate-none", false); From c0d7f645a099b5818e1657446336d54014e6e709 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 3 Sep 2010 21:48:17 -0700 Subject: [PATCH 132/222] 584842 - E10s nsIContentPrefService remoting implementation r=myk, a=blocking-fennec --- dom/interfaces/base/nsIContentPrefService.idl | 6 + .../contentprefs/src/nsContentPrefService.js | 165 ++++++++++++------ .../src/nsContentPrefService.manifest | 2 + .../tests/unit/head_contentPrefs.js | 14 +- .../tests/unit/test_contentPrefs_childipc.js | 39 +++++ .../tests/unit/test_contentPrefs_parentipc.js | 54 ++++++ 6 files changed, 223 insertions(+), 57 deletions(-) create mode 100644 toolkit/components/contentprefs/tests/unit/test_contentPrefs_childipc.js create mode 100644 toolkit/components/contentprefs/tests/unit/test_contentPrefs_parentipc.js diff --git a/dom/interfaces/base/nsIContentPrefService.idl b/dom/interfaces/base/nsIContentPrefService.idl index 278a54fca815..1c0834263041 100644 --- a/dom/interfaces/base/nsIContentPrefService.idl +++ b/dom/interfaces/base/nsIContentPrefService.idl @@ -82,6 +82,9 @@ interface nsIContentPrefService : nsISupports * to NULL in the database, as well as undefined (nsIDataType::VTYPE_VOID), * which means there is no record for this pref in the database. * + * This method can be called from content processes in electrolysis builds. + * We have a whitelist of values that can be read in such a way. + * * @param aGroup the group for which to get the pref, as an nsIURI * from which the hostname will be used, a string * (typically in the format of a hostname), or null @@ -101,6 +104,9 @@ interface nsIContentPrefService : nsISupports /** * Set a pref. * + * This method can be called from content processes in electrolysis builds. + * We have a whitelist of values that can be set in such a way. + * * @param aGroup the group for which to set the pref, as an nsIURI * from which the hostname will be used, a string * (typically in the format of a hostname), or null diff --git a/toolkit/components/contentprefs/src/nsContentPrefService.js b/toolkit/components/contentprefs/src/nsContentPrefService.js index de39372ffdb2..292efd37842b 100644 --- a/toolkit/components/contentprefs/src/nsContentPrefService.js +++ b/toolkit/components/contentprefs/src/nsContentPrefService.js @@ -43,7 +43,88 @@ const Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +/** + * Remotes the service. All the remoting/electrolysis code is in here, + * so the regular service code below remains uncluttered and maintainable. + */ +function electrolify(service) { + // FIXME: For now, use the wrappedJSObject hack, until bug + // 593407 which will clean that up. + service.wrappedJSObject = service; + + var appInfo = Cc["@mozilla.org/xre/app-info;1"]; + if (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == + Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { + // Parent process + + // Setup listener for child messages. We don't need to call + // addMessageListener as the wakeup service will do that for us. + service.receiveMessage = function(aMessage) { + var json = aMessage.json; + // We have a whitelist for getting/setting. This is because + // there are potential privacy issues with a compromised + // content process checking the user's content preferences + // and using that to discover all the websites visited, etc. + // Also there are both potential race conditions (if two processes + // set more than one value in succession, and the values + // only make sense together), as well as security issues, if + // a compromised content process can send arbitrary setPref + // messages. The whitelist contains only those settings that + // are not at risk for either. + // We currently whitelist saving/reading the last directory of file + // uploads, which is so far the only need we have identified. + + const NAME_WHITELIST = ["browser.upload.lastDir"]; + if (NAME_WHITELIST.indexOf(json.name) == -1) + return { succeeded: false }; + + switch (aMessage.name) { + case "ContentPref:getPref": + return { succeeded: true, + value: service.getPref(json.group, json.name, json.value) }; + + case "ContentPref:setPref": + service.setPref(json.group, json.name, json.value); + return { succeeded: true }; + } + }; + } else { + // Child process + + service._dbInit = function(){}; // No local DB + + service.messageManager = Cc["@mozilla.org/childprocessmessagemanager;1"]. + getService(Ci.nsISyncMessageSender); + + // Child method remoting + [ + ['getPref', ['group', 'name'], ['_parseGroupParam']], + ['setPref', ['group', 'name', 'value'], ['_parseGroupParam']], + ].forEach(function(data) { + var method = data[0]; + var params = data[1]; + var parsers = data[2]; + service[method] = function __remoted__() { + var json = {}; + for (var i = 0; i < params.length; i++) { + if (params[i]) { + json[params[i]] = arguments[i]; + if (parsers[i]) + json[params[i]] = this[parsers[i]](json[params[i]]); + } + } + var ret = service.messageManager.sendSyncMessage('ContentPref:' + method, json)[0]; + if (!ret.succeeded) + throw "ContentPrefs remoting failed to pass whitelist"; + return ret.value; + }; + }); + } +} + function ContentPrefService() { + electrolify(this); + // If this throws an exception, it causes the getService call to fail, // but the next time a consumer tries to retrieve the service, we'll try // to initialize the database again, which might work if the failure @@ -59,7 +140,8 @@ ContentPrefService.prototype = { // XPCOM Plumbing classID: Components.ID("{e6a3f533-4ffa-4615-8eb4-d4e72d883fa7}"), - QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPrefService]), + QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPrefService, + Ci.nsIFrameMessageListener]), //**************************************************************************// @@ -137,15 +219,10 @@ ContentPrefService.prototype = { throw Components.Exception("aName cannot be null or an empty string", Cr.NS_ERROR_ILLEGAL_VALUE); - if (aGroup == null) + var group = this._parseGroupParam(aGroup); + if (group == null) return this._selectGlobalPref(aName, aCallback); - if (aGroup.constructor.name == "String") - return this._selectPref(aGroup.toString(), aName, aCallback); - if (aGroup instanceof Ci.nsIURI) - return this._selectPref(this.grouper.group(aGroup), aName, aCallback); - - throw Components.Exception("aGroup is not a string, nsIURI or null", - Cr.NS_ERROR_ILLEGAL_VALUE); + return this._selectPref(group, aName, aCallback); }, setPref: function ContentPrefService_setPref(aGroup, aName, aValue) { @@ -168,26 +245,15 @@ ContentPrefService.prototype = { } var settingID = this._selectSettingID(aName) || this._insertSetting(aName); - var group, groupID, prefID; - if (aGroup == null) { - group = null; + var group = this._parseGroupParam(aGroup); + var groupID, prefID; + if (group == null) { groupID = null; prefID = this._selectGlobalPrefID(settingID); } - else if (aGroup.constructor.name == "String") { - group = aGroup.toString(); - groupID = this._selectGroupID(group) || this._insertGroup(group); - prefID = this._selectPrefID(groupID, settingID); - } - else if (aGroup instanceof Ci.nsIURI) { - group = this.grouper.group(aGroup); - groupID = this._selectGroupID(group) || this._insertGroup(group); - prefID = this._selectPrefID(groupID, settingID); - } else { - // Should never get here, due to earlier getPref call - throw Components.Exception("aGroup is not a string, nsIURI or null", - Cr.NS_ERROR_ILLEGAL_VALUE); + groupID = this._selectGroupID(group) || this._insertGroup(group); + prefID = this._selectPrefID(groupID, settingID); } // Update the existing record, if any, or create a new one. @@ -217,27 +283,17 @@ ContentPrefService.prototype = { if (!this.hasPref(aGroup, aName)) return; + var settingID = this._selectSettingID(aName); - var group, groupID, prefID; - if (aGroup == null) { - group = null; + var group = this._parseGroupParam(aGroup); + var groupID, prefID; + if (group == null) { groupID = null; prefID = this._selectGlobalPrefID(settingID); } - else if (aGroup.constructor.name == "String") { - group = aGroup.toString(); - groupID = this._selectGroupID(group); - prefID = this._selectPrefID(groupID, settingID); - } - else if (aGroup instanceof Ci.nsIURI) { - group = this.grouper.group(aGroup); - groupID = this._selectGroupID(group); - prefID = this._selectPrefID(groupID, settingID); - } else { - // Should never get here, due to earlier hasPref call - throw Components.Exception("aGroup is not a string, nsIURI or null", - Cr.NS_ERROR_ILLEGAL_VALUE); + groupID = this._selectGroupID(group); + prefID = this._selectPrefID(groupID, settingID); } this._deletePref(prefID); @@ -312,18 +368,10 @@ ContentPrefService.prototype = { }, getPrefs: function ContentPrefService_getPrefs(aGroup) { - if (aGroup == null) + var group = this._parseGroupParam(aGroup); + if (group == null) return this._selectGlobalPrefs(); - if (aGroup.constructor.name == "String") { - group = aGroup.toString(); - return this._selectPrefs(group); - } - if (aGroup instanceof Ci.nsIURI) { - var group = this.grouper.group(aGroup); - return this._selectPrefs(group); - } - throw Components.Exception("aGroup is not a string, nsIURI or null", - Cr.NS_ERROR_ILLEGAL_VALUE); + return this._selectPrefs(group); }, getPrefsByName: function ContentPrefService_getPrefsByName(aName) { @@ -1011,8 +1059,19 @@ ContentPrefService.prototype = { _dbMigrate2To3: function ContentPrefService__dbMigrate2To3(aDBConnection) { this._dbCreateIndices(aDBConnection); - } + }, + _parseGroupParam: function ContentPrefService__parseGroupParam(aGroup) { + if (aGroup == null) + return null; + if (aGroup.constructor.name == "String") + return aGroup.toString(); + if (aGroup instanceof Ci.nsIURI) + return this.grouper.group(aGroup); + + throw Components.Exception("aGroup is not a string, nsIURI or null", + Cr.NS_ERROR_ILLEGAL_VALUE); + }, }; diff --git a/toolkit/components/contentprefs/src/nsContentPrefService.manifest b/toolkit/components/contentprefs/src/nsContentPrefService.manifest index 28bfc4807e77..04007510a4f0 100644 --- a/toolkit/components/contentprefs/src/nsContentPrefService.manifest +++ b/toolkit/components/contentprefs/src/nsContentPrefService.manifest @@ -2,3 +2,5 @@ component {e6a3f533-4ffa-4615-8eb4-d4e72d883fa7} nsContentPrefService.js contract @mozilla.org/content-pref/service;1 {e6a3f533-4ffa-4615-8eb4-d4e72d883fa7} component {8df290ae-dcaa-4c11-98a5-2429a4dc97bb} nsContentPrefService.js contract @mozilla.org/content-pref/hostname-grouper;1 {8df290ae-dcaa-4c11-98a5-2429a4dc97bb} +category wakeup-request nsContentPrefService @mozilla.org/content-pref/service;1,nsIContentPrefService,getService,ContentPref:getPref,ContentPref:setPref + diff --git a/toolkit/components/contentprefs/tests/unit/head_contentPrefs.js b/toolkit/components/contentprefs/tests/unit/head_contentPrefs.js index 289676dbbd7d..7a3dcb5db360 100644 --- a/toolkit/components/contentprefs/tests/unit/head_contentPrefs.js +++ b/toolkit/components/contentprefs/tests/unit/head_contentPrefs.js @@ -167,7 +167,13 @@ var ContentPrefTest = { ContentPrefTest.deleteDatabase(); // Turn on logging for the content preferences service so we can troubleshoot -// problems with the tests. -var prefBranch = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefBranch); -prefBranch.setBoolPref("browser.preferences.content.log", true); +// problems with the tests. This is only useful in regular (parent) +// processes - child processes are not able to do that and will crash. +var appInfo = Cc["@mozilla.org/xre/app-info;1"]; +if (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == + Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { + var prefBranch = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + prefBranch.setBoolPref("browser.preferences.content.log", true); +} + diff --git a/toolkit/components/contentprefs/tests/unit/test_contentPrefs_childipc.js b/toolkit/components/contentprefs/tests/unit/test_contentPrefs_childipc.js new file mode 100644 index 000000000000..2e228196c0fc --- /dev/null +++ b/toolkit/components/contentprefs/tests/unit/test_contentPrefs_childipc.js @@ -0,0 +1,39 @@ +function run_test() { + var appInfo = Cc["@mozilla.org/xre/app-info;1"]; + if (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == + Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { + return; // test harness also calls us in the parent process - ignore that + } + + let cps = Cc["@mozilla.org/content-pref/service;1"]. + createInstance(Ci.nsIContentPrefService); + + // Cannot get general values + try { + cps.getPref("group", "name") + do_check_false(true, "Must have thrown exception on getting general value"); + } + catch(e) { } + + // Cannot set general values + try { + cps.setPref("group", "name", "someValue2"); + do_check_false(true, "Must have thrown exception on setting general value"); + } + catch(e) { } + + // Can set&get whitelisted values + cps.setPref("group", "browser.upload.lastDir", "childValue"); + do_check_eq(cps.getPref("group", "browser.upload.lastDir"), "childValue"); + + // Test sending URI + var ioSvc = Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService); + var uri = ioSvc.newURI("http://mozilla.org", null, null); + cps.setPref(uri, "browser.upload.lastDir", "childValue2"); + do_check_eq(cps.getPref(uri, "browser.upload.lastDir"), "childValue2"); + + // Previous value + do_check_eq(cps.getPref("group", "browser.upload.lastDir"), "childValue"); +} + diff --git a/toolkit/components/contentprefs/tests/unit/test_contentPrefs_parentipc.js b/toolkit/components/contentprefs/tests/unit/test_contentPrefs_parentipc.js new file mode 100644 index 000000000000..9d874863fd32 --- /dev/null +++ b/toolkit/components/contentprefs/tests/unit/test_contentPrefs_parentipc.js @@ -0,0 +1,54 @@ + +function run_test() { + let cps = Cc["@mozilla.org/content-pref/service;1"]. + createInstance(Ci.nsIContentPrefService); + + // Check received messages + + let messageHandler = cps; + // FIXME: For now, use the wrappedJSObject hack, until bug + // 593407 which will clean that up. After that, use + // the commented out line below it. + messageHandler = cps.wrappedJSObject; + //messageHandler = cps.QueryInterface(Ci.nsIFrameMessageListener); + + // Cannot get values + do_check_false(messageHandler.receiveMessage({ + name: "ContentPref:getPref", + json: { group: 'group2', name: 'name' } }).succeeded); + + // Cannot set general values + messageHandler.receiveMessage({ name: "ContentPref:setPref", + json: { group: 'group2', name: 'name', value: 'someValue' } }); + do_check_eq(cps.getPref('group', 'name'), undefined); + + // Can set whitelisted values + do_check_true(messageHandler.receiveMessage({ name: "ContentPref:setPref", + json: { group: 'group2', name: 'browser.upload.lastDir', + value: 'someValue' } }).succeeded); + do_check_eq(cps.getPref('group2', 'browser.upload.lastDir'), 'someValue'); + + // Prepare for child tests + + // Mock construction for set/get for child. This is necessary because + // the IPC xpcshell setup doens't do well with the normal storage + // engine. But even with this mock interface, we are testing + // the whitelisting functionality properly, which is all we need here. + var mockStorage = {}; + cps.wrappedJSObject.setPref = function(aGroup, aName, aValue) { + mockStorage[aGroup+':'+aName] = aValue; + } + cps.wrappedJSObject.getPref = function(aGroup, aName) { + return mockStorage[aGroup+':'+aName]; + } + + // Manually listen to messages - the wakeup manager should do this + // for us, but it doens't run in xpcshell tests + var mM = Cc["@mozilla.org/parentprocessmessagemanager;1"]. + getService(Ci.nsIFrameMessageManager); + mM.addMessageListener("ContentPref:setPref", messageHandler); + mM.addMessageListener("ContentPref:getPref", messageHandler); + + run_test_in_child("test_contentPrefs_childipc.js"); +} + From 8b0852baf74db2d57c74b88da289d6bccb683295 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Fri, 3 Sep 2010 22:56:49 -0700 Subject: [PATCH 133/222] Backed out changeset 38b763292cb1. MacOS doesn't support E10S tests. a=bah --- dom/interfaces/base/nsIContentPrefService.idl | 6 - .../contentprefs/src/nsContentPrefService.js | 161 ++++++------------ .../src/nsContentPrefService.manifest | 2 - .../tests/unit/head_contentPrefs.js | 14 +- .../tests/unit/test_contentPrefs_childipc.js | 39 ----- .../tests/unit/test_contentPrefs_parentipc.js | 54 ------ 6 files changed, 55 insertions(+), 221 deletions(-) delete mode 100644 toolkit/components/contentprefs/tests/unit/test_contentPrefs_childipc.js delete mode 100644 toolkit/components/contentprefs/tests/unit/test_contentPrefs_parentipc.js diff --git a/dom/interfaces/base/nsIContentPrefService.idl b/dom/interfaces/base/nsIContentPrefService.idl index 1c0834263041..278a54fca815 100644 --- a/dom/interfaces/base/nsIContentPrefService.idl +++ b/dom/interfaces/base/nsIContentPrefService.idl @@ -82,9 +82,6 @@ interface nsIContentPrefService : nsISupports * to NULL in the database, as well as undefined (nsIDataType::VTYPE_VOID), * which means there is no record for this pref in the database. * - * This method can be called from content processes in electrolysis builds. - * We have a whitelist of values that can be read in such a way. - * * @param aGroup the group for which to get the pref, as an nsIURI * from which the hostname will be used, a string * (typically in the format of a hostname), or null @@ -104,9 +101,6 @@ interface nsIContentPrefService : nsISupports /** * Set a pref. * - * This method can be called from content processes in electrolysis builds. - * We have a whitelist of values that can be set in such a way. - * * @param aGroup the group for which to set the pref, as an nsIURI * from which the hostname will be used, a string * (typically in the format of a hostname), or null diff --git a/toolkit/components/contentprefs/src/nsContentPrefService.js b/toolkit/components/contentprefs/src/nsContentPrefService.js index 292efd37842b..de39372ffdb2 100644 --- a/toolkit/components/contentprefs/src/nsContentPrefService.js +++ b/toolkit/components/contentprefs/src/nsContentPrefService.js @@ -43,88 +43,7 @@ const Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -/** - * Remotes the service. All the remoting/electrolysis code is in here, - * so the regular service code below remains uncluttered and maintainable. - */ -function electrolify(service) { - // FIXME: For now, use the wrappedJSObject hack, until bug - // 593407 which will clean that up. - service.wrappedJSObject = service; - - var appInfo = Cc["@mozilla.org/xre/app-info;1"]; - if (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == - Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { - // Parent process - - // Setup listener for child messages. We don't need to call - // addMessageListener as the wakeup service will do that for us. - service.receiveMessage = function(aMessage) { - var json = aMessage.json; - // We have a whitelist for getting/setting. This is because - // there are potential privacy issues with a compromised - // content process checking the user's content preferences - // and using that to discover all the websites visited, etc. - // Also there are both potential race conditions (if two processes - // set more than one value in succession, and the values - // only make sense together), as well as security issues, if - // a compromised content process can send arbitrary setPref - // messages. The whitelist contains only those settings that - // are not at risk for either. - // We currently whitelist saving/reading the last directory of file - // uploads, which is so far the only need we have identified. - - const NAME_WHITELIST = ["browser.upload.lastDir"]; - if (NAME_WHITELIST.indexOf(json.name) == -1) - return { succeeded: false }; - - switch (aMessage.name) { - case "ContentPref:getPref": - return { succeeded: true, - value: service.getPref(json.group, json.name, json.value) }; - - case "ContentPref:setPref": - service.setPref(json.group, json.name, json.value); - return { succeeded: true }; - } - }; - } else { - // Child process - - service._dbInit = function(){}; // No local DB - - service.messageManager = Cc["@mozilla.org/childprocessmessagemanager;1"]. - getService(Ci.nsISyncMessageSender); - - // Child method remoting - [ - ['getPref', ['group', 'name'], ['_parseGroupParam']], - ['setPref', ['group', 'name', 'value'], ['_parseGroupParam']], - ].forEach(function(data) { - var method = data[0]; - var params = data[1]; - var parsers = data[2]; - service[method] = function __remoted__() { - var json = {}; - for (var i = 0; i < params.length; i++) { - if (params[i]) { - json[params[i]] = arguments[i]; - if (parsers[i]) - json[params[i]] = this[parsers[i]](json[params[i]]); - } - } - var ret = service.messageManager.sendSyncMessage('ContentPref:' + method, json)[0]; - if (!ret.succeeded) - throw "ContentPrefs remoting failed to pass whitelist"; - return ret.value; - }; - }); - } -} - function ContentPrefService() { - electrolify(this); - // If this throws an exception, it causes the getService call to fail, // but the next time a consumer tries to retrieve the service, we'll try // to initialize the database again, which might work if the failure @@ -140,8 +59,7 @@ ContentPrefService.prototype = { // XPCOM Plumbing classID: Components.ID("{e6a3f533-4ffa-4615-8eb4-d4e72d883fa7}"), - QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPrefService, - Ci.nsIFrameMessageListener]), + QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPrefService]), //**************************************************************************// @@ -219,10 +137,15 @@ ContentPrefService.prototype = { throw Components.Exception("aName cannot be null or an empty string", Cr.NS_ERROR_ILLEGAL_VALUE); - var group = this._parseGroupParam(aGroup); - if (group == null) + if (aGroup == null) return this._selectGlobalPref(aName, aCallback); - return this._selectPref(group, aName, aCallback); + if (aGroup.constructor.name == "String") + return this._selectPref(aGroup.toString(), aName, aCallback); + if (aGroup instanceof Ci.nsIURI) + return this._selectPref(this.grouper.group(aGroup), aName, aCallback); + + throw Components.Exception("aGroup is not a string, nsIURI or null", + Cr.NS_ERROR_ILLEGAL_VALUE); }, setPref: function ContentPrefService_setPref(aGroup, aName, aValue) { @@ -245,16 +168,27 @@ ContentPrefService.prototype = { } var settingID = this._selectSettingID(aName) || this._insertSetting(aName); - var group = this._parseGroupParam(aGroup); - var groupID, prefID; - if (group == null) { + var group, groupID, prefID; + if (aGroup == null) { + group = null; groupID = null; prefID = this._selectGlobalPrefID(settingID); } - else { + else if (aGroup.constructor.name == "String") { + group = aGroup.toString(); groupID = this._selectGroupID(group) || this._insertGroup(group); prefID = this._selectPrefID(groupID, settingID); } + else if (aGroup instanceof Ci.nsIURI) { + group = this.grouper.group(aGroup); + groupID = this._selectGroupID(group) || this._insertGroup(group); + prefID = this._selectPrefID(groupID, settingID); + } + else { + // Should never get here, due to earlier getPref call + throw Components.Exception("aGroup is not a string, nsIURI or null", + Cr.NS_ERROR_ILLEGAL_VALUE); + } // Update the existing record, if any, or create a new one. if (prefID) @@ -283,18 +217,28 @@ ContentPrefService.prototype = { if (!this.hasPref(aGroup, aName)) return; - var settingID = this._selectSettingID(aName); - var group = this._parseGroupParam(aGroup); - var groupID, prefID; - if (group == null) { + var group, groupID, prefID; + if (aGroup == null) { + group = null; groupID = null; prefID = this._selectGlobalPrefID(settingID); } - else { + else if (aGroup.constructor.name == "String") { + group = aGroup.toString(); groupID = this._selectGroupID(group); prefID = this._selectPrefID(groupID, settingID); } + else if (aGroup instanceof Ci.nsIURI) { + group = this.grouper.group(aGroup); + groupID = this._selectGroupID(group); + prefID = this._selectPrefID(groupID, settingID); + } + else { + // Should never get here, due to earlier hasPref call + throw Components.Exception("aGroup is not a string, nsIURI or null", + Cr.NS_ERROR_ILLEGAL_VALUE); + } this._deletePref(prefID); @@ -368,10 +312,18 @@ ContentPrefService.prototype = { }, getPrefs: function ContentPrefService_getPrefs(aGroup) { - var group = this._parseGroupParam(aGroup); - if (group == null) + if (aGroup == null) return this._selectGlobalPrefs(); - return this._selectPrefs(group); + if (aGroup.constructor.name == "String") { + group = aGroup.toString(); + return this._selectPrefs(group); + } + if (aGroup instanceof Ci.nsIURI) { + var group = this.grouper.group(aGroup); + return this._selectPrefs(group); + } + throw Components.Exception("aGroup is not a string, nsIURI or null", + Cr.NS_ERROR_ILLEGAL_VALUE); }, getPrefsByName: function ContentPrefService_getPrefsByName(aName) { @@ -1059,19 +1011,8 @@ ContentPrefService.prototype = { _dbMigrate2To3: function ContentPrefService__dbMigrate2To3(aDBConnection) { this._dbCreateIndices(aDBConnection); - }, + } - _parseGroupParam: function ContentPrefService__parseGroupParam(aGroup) { - if (aGroup == null) - return null; - if (aGroup.constructor.name == "String") - return aGroup.toString(); - if (aGroup instanceof Ci.nsIURI) - return this.grouper.group(aGroup); - - throw Components.Exception("aGroup is not a string, nsIURI or null", - Cr.NS_ERROR_ILLEGAL_VALUE); - }, }; diff --git a/toolkit/components/contentprefs/src/nsContentPrefService.manifest b/toolkit/components/contentprefs/src/nsContentPrefService.manifest index 04007510a4f0..28bfc4807e77 100644 --- a/toolkit/components/contentprefs/src/nsContentPrefService.manifest +++ b/toolkit/components/contentprefs/src/nsContentPrefService.manifest @@ -2,5 +2,3 @@ component {e6a3f533-4ffa-4615-8eb4-d4e72d883fa7} nsContentPrefService.js contract @mozilla.org/content-pref/service;1 {e6a3f533-4ffa-4615-8eb4-d4e72d883fa7} component {8df290ae-dcaa-4c11-98a5-2429a4dc97bb} nsContentPrefService.js contract @mozilla.org/content-pref/hostname-grouper;1 {8df290ae-dcaa-4c11-98a5-2429a4dc97bb} -category wakeup-request nsContentPrefService @mozilla.org/content-pref/service;1,nsIContentPrefService,getService,ContentPref:getPref,ContentPref:setPref - diff --git a/toolkit/components/contentprefs/tests/unit/head_contentPrefs.js b/toolkit/components/contentprefs/tests/unit/head_contentPrefs.js index 7a3dcb5db360..289676dbbd7d 100644 --- a/toolkit/components/contentprefs/tests/unit/head_contentPrefs.js +++ b/toolkit/components/contentprefs/tests/unit/head_contentPrefs.js @@ -167,13 +167,7 @@ var ContentPrefTest = { ContentPrefTest.deleteDatabase(); // Turn on logging for the content preferences service so we can troubleshoot -// problems with the tests. This is only useful in regular (parent) -// processes - child processes are not able to do that and will crash. -var appInfo = Cc["@mozilla.org/xre/app-info;1"]; -if (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == - Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { - var prefBranch = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefBranch); - prefBranch.setBoolPref("browser.preferences.content.log", true); -} - +// problems with the tests. +var prefBranch = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); +prefBranch.setBoolPref("browser.preferences.content.log", true); diff --git a/toolkit/components/contentprefs/tests/unit/test_contentPrefs_childipc.js b/toolkit/components/contentprefs/tests/unit/test_contentPrefs_childipc.js deleted file mode 100644 index 2e228196c0fc..000000000000 --- a/toolkit/components/contentprefs/tests/unit/test_contentPrefs_childipc.js +++ /dev/null @@ -1,39 +0,0 @@ -function run_test() { - var appInfo = Cc["@mozilla.org/xre/app-info;1"]; - if (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == - Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { - return; // test harness also calls us in the parent process - ignore that - } - - let cps = Cc["@mozilla.org/content-pref/service;1"]. - createInstance(Ci.nsIContentPrefService); - - // Cannot get general values - try { - cps.getPref("group", "name") - do_check_false(true, "Must have thrown exception on getting general value"); - } - catch(e) { } - - // Cannot set general values - try { - cps.setPref("group", "name", "someValue2"); - do_check_false(true, "Must have thrown exception on setting general value"); - } - catch(e) { } - - // Can set&get whitelisted values - cps.setPref("group", "browser.upload.lastDir", "childValue"); - do_check_eq(cps.getPref("group", "browser.upload.lastDir"), "childValue"); - - // Test sending URI - var ioSvc = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - var uri = ioSvc.newURI("http://mozilla.org", null, null); - cps.setPref(uri, "browser.upload.lastDir", "childValue2"); - do_check_eq(cps.getPref(uri, "browser.upload.lastDir"), "childValue2"); - - // Previous value - do_check_eq(cps.getPref("group", "browser.upload.lastDir"), "childValue"); -} - diff --git a/toolkit/components/contentprefs/tests/unit/test_contentPrefs_parentipc.js b/toolkit/components/contentprefs/tests/unit/test_contentPrefs_parentipc.js deleted file mode 100644 index 9d874863fd32..000000000000 --- a/toolkit/components/contentprefs/tests/unit/test_contentPrefs_parentipc.js +++ /dev/null @@ -1,54 +0,0 @@ - -function run_test() { - let cps = Cc["@mozilla.org/content-pref/service;1"]. - createInstance(Ci.nsIContentPrefService); - - // Check received messages - - let messageHandler = cps; - // FIXME: For now, use the wrappedJSObject hack, until bug - // 593407 which will clean that up. After that, use - // the commented out line below it. - messageHandler = cps.wrappedJSObject; - //messageHandler = cps.QueryInterface(Ci.nsIFrameMessageListener); - - // Cannot get values - do_check_false(messageHandler.receiveMessage({ - name: "ContentPref:getPref", - json: { group: 'group2', name: 'name' } }).succeeded); - - // Cannot set general values - messageHandler.receiveMessage({ name: "ContentPref:setPref", - json: { group: 'group2', name: 'name', value: 'someValue' } }); - do_check_eq(cps.getPref('group', 'name'), undefined); - - // Can set whitelisted values - do_check_true(messageHandler.receiveMessage({ name: "ContentPref:setPref", - json: { group: 'group2', name: 'browser.upload.lastDir', - value: 'someValue' } }).succeeded); - do_check_eq(cps.getPref('group2', 'browser.upload.lastDir'), 'someValue'); - - // Prepare for child tests - - // Mock construction for set/get for child. This is necessary because - // the IPC xpcshell setup doens't do well with the normal storage - // engine. But even with this mock interface, we are testing - // the whitelisting functionality properly, which is all we need here. - var mockStorage = {}; - cps.wrappedJSObject.setPref = function(aGroup, aName, aValue) { - mockStorage[aGroup+':'+aName] = aValue; - } - cps.wrappedJSObject.getPref = function(aGroup, aName) { - return mockStorage[aGroup+':'+aName]; - } - - // Manually listen to messages - the wakeup manager should do this - // for us, but it doens't run in xpcshell tests - var mM = Cc["@mozilla.org/parentprocessmessagemanager;1"]. - getService(Ci.nsIFrameMessageManager); - mM.addMessageListener("ContentPref:setPref", messageHandler); - mM.addMessageListener("ContentPref:getPref", messageHandler); - - run_test_in_child("test_contentPrefs_childipc.js"); -} - From c662cb6d9df4bd4fe8030e20249961710157a09a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Sat, 4 Sep 2010 10:46:14 +0200 Subject: [PATCH 134/222] Bug 591853 - Optimize chrome layer size with lightweight themes with transparent or no footer images. r=enn --- browser/themes/gnomestripe/browser/browser.css | 2 +- toolkit/content/LightweightThemeConsumer.jsm | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/browser/themes/gnomestripe/browser/browser.css b/browser/themes/gnomestripe/browser/browser.css index c684a32c73dc..a8dc14ada94e 100644 --- a/browser/themes/gnomestripe/browser/browser.css +++ b/browser/themes/gnomestripe/browser/browser.css @@ -68,7 +68,7 @@ padding-top: 0; } -#browser-bottombox:not([lwthemefooter="true"]) { +#browser-bottombox { /* opaque for layers optimization */ background-color: -moz-Dialog; } diff --git a/toolkit/content/LightweightThemeConsumer.jsm b/toolkit/content/LightweightThemeConsumer.jsm index 24a46c384e17..18481b73dcf1 100644 --- a/toolkit/content/LightweightThemeConsumer.jsm +++ b/toolkit/content/LightweightThemeConsumer.jsm @@ -89,6 +89,7 @@ LightweightThemeConsumer.prototype = { _setImage(root, active, aData.headerURL); if (this._footerId) { let footer = this._doc.getElementById(this._footerId); + footer.style.backgroundColor = active ? aData.accentcolor || "white" : ""; _setImage(footer, active, aData.footerURL); if (active && aData.footerURL) footer.setAttribute("lwthemefooter", "true"); From 6cd35b9b2edc86e244c67da3df96ecca3d489ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Sat, 4 Sep 2010 10:46:24 +0200 Subject: [PATCH 135/222] Bug 572488 - New tab and toolbar style for Linux. r=gavin --- .../themes/gnomestripe/browser/browser.css | 163 +++++++++++++----- browser/themes/gnomestripe/browser/jar.mn | 1 + .../gnomestripe/browser/tabbrowser/tab.png | Bin 0 -> 411 bytes 3 files changed, 121 insertions(+), 43 deletions(-) create mode 100644 browser/themes/gnomestripe/browser/tabbrowser/tab.png diff --git a/browser/themes/gnomestripe/browser/browser.css b/browser/themes/gnomestripe/browser/browser.css index a8dc14ada94e..5a17a47a8a00 100644 --- a/browser/themes/gnomestripe/browser/browser.css +++ b/browser/themes/gnomestripe/browser/browser.css @@ -49,6 +49,8 @@ @namespace html url("http://www.w3.org/1999/xhtml"); %include ../../browserShared.inc +%filter substitution +%define toolbarHighlight rgba(255,255,255,.3) #menubar-items { -moz-box-orient: vertical; /* for flex hack */ @@ -58,14 +60,41 @@ -moz-box-flex: 1; /* make menu items expand to fill toolbar height */ } -#personal-bookmarks { - min-height: 29px; +#navigator-toolbox { + -moz-appearance: none; + background-color: transparent; + border-top: none; + border-bottom: 1px solid ThreeDShadow; } -#navigator-toolbox[inFullscreen="true"], -#navigator-toolbox[inFullscreen="true"] > #nav-bar { - border-top: none; - padding-top: 0; +#navigator-toolbox > toolbar:not(:-moz-lwtheme):not(#toolbar-menubar) { + -moz-appearance: none; + border-style: none; + background-color: -moz-Dialog; +} + +#navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar) { + padding-top: 1px; + padding-bottom: 1px; +} + +#nav-bar:not(:-moz-lwtheme), +#nav-bar[collapsed="true"] + toolbar:not(:-moz-lwtheme), +#nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme), +#navigator-toolbox[tabsontop="true"] > #nav-bar, +#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + toolbar, +#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar { + background-image: -moz-linear-gradient(@toolbarHighlight@, rgba(255,255,255,0)); +} + +#navigator-toolbox[tabsontop="true"] > #nav-bar:not(:-moz-lwtheme), +#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + toolbar:not(:-moz-lwtheme), +#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme) { + border-top: 1px solid ThreeDShadow; +} + +#personal-bookmarks { + min-height: 29px; } #browser-bottombox { @@ -74,15 +103,10 @@ } #urlbar:-moz-lwtheme:not([focused="true"]), -.searchbar-textbox:-moz-lwtheme:not([focused="true"]), -.tabbrowser-tab:-moz-lwtheme:not([selected="true"]) { +.searchbar-textbox:-moz-lwtheme:not([focused="true"]) { opacity: .85; } -.tabbrowser-tab:-moz-lwtheme { - text-shadow: none; -} - /* Places toolbar */ toolbarbutton.bookmark-item { margin: 0; @@ -1262,55 +1286,113 @@ statusbarpanel#statusbar-display { list-style-image: url("chrome://global/skin/icons/notloading_16.png"); } -/* Tabs */ +/* Tabstrip */ #TabsToolbar { - -moz-appearance: none; min-height: 0; padding: 0; - -moz-box-shadow: ThreeDShadow 0 -1px inset; } -#TabsToolbar > toolbarbutton, -#TabsToolbar > toolbarpaletteitem > toolbarbutton, -#TabsToolbar > #bookmarks-menu-button-container > #bookmarks-menu-button { - margin-bottom: 1px; +#TabsToolbar:not(:-moz-lwtheme), +#TabsToolbar[tabsontop="false"] { + background-image: -moz-linear-gradient(transparent, transparent 50%, + rgba(0,0,0,.05) 90%, rgba(0,0,0,.1)); } -.tabbrowser-tab { - padding: 0 2px 2px; - margin-bottom: 1px; - min-height: 25px; /* reserve space for the sometimes hidden close button */ +#tabbrowser-tabs[tabsontop="true"] > .tabbrowser-arrowscrollbox > scrollbox:not(:-moz-lwtheme) { + padding-bottom: 1px; + margin-bottom: -1px; + position: relative; +} + +#tabbrowser-tabs[tabsontop="true"] > .tabbrowser-tab[selected="true"]:not(:-moz-lwtheme) { + margin-bottom: -1px; + padding-bottom: 1px; +} + +.tabbrowser-tab, +.tabs-newtab-button { + position: static; + -moz-appearance: none; + background: -moz-linear-gradient(hsla(0,0%,100%,.3), hsla(0,0%,50%,.1) 2px, hsla(0,0%,37%,.1) 50%); + background-position: -5px -2px; + background-repeat: no-repeat; + background-size: 200%; + margin: 0; + padding: 0; + -moz-border-image: url(tabbrowser/tab.png) 4 5 3 6 / 4px 5px 3px 6px; + -moz-border-radius: 10px 8px 0 0; + min-height: 27px; /* reserve space for the sometimes hidden close button */ +} + +.tabbrowser-tab:hover, +.tabs-newtab-button:hover { + background-image: -moz-linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.4) 2px, hsla(0,0%,75%,.4) 50%); } .tabbrowser-tab[selected="true"] { - margin-bottom: 0; - padding-top: 2px; /* compensates the top margin of background tabs */ - padding-bottom: 3px; /* compensates the bottom margin of background tabs */ - min-height: 28px; + background-image: -moz-linear-gradient(rgba(255,255,255,.8), rgba(255,255,255,.5) 2px, @toolbarHighlight@ 20%), + -moz-linear-gradient(-moz-dialog, -moz-dialog); +} + +.tabbrowser-tab:-moz-lwtheme { + color: inherit; +} + +.tabbrowser-tab[selected="true"]:-moz-lwtheme { + background-image: -moz-linear-gradient(rgba(255,255,255,.8), rgba(255,255,255,.5) 2px, @toolbarHighlight@ 20%); +} + +.tabbrowser-tab:-moz-lwtheme-brighttext:not([selected="true"]), +.tabs-newtab-button:-moz-lwtheme-brighttext { + background-image: -moz-linear-gradient(hsla(0,0%,60%,.6), hsla(0,0%,40%,.6) 2px, hsla(0,0%,30%,.6) 50%); +} + +.tabbrowser-tab:-moz-lwtheme-brighttext:not([selected="true"]):hover, +.tabs-newtab-button:-moz-lwtheme-brighttext:hover { + background-image: -moz-linear-gradient(hsla(0,0%,80%,.6), hsla(0,0%,60%,.6) 2px, hsla(0,0%,45%,.6) 50%); +} + +.tabbrowser-tab:-moz-lwtheme-darktext:not([selected="true"]), +.tabs-newtab-button:-moz-lwtheme-darktext { + background-image: -moz-linear-gradient(hsla(0,0%,100%,.5), hsla(0,0%,60%,.5) 2px, hsla(0,0%,45%,.5) 50%); +} + +.tabbrowser-tab:-moz-lwtheme-darktext:not([selected="true"]):hover, +.tabs-newtab-button:-moz-lwtheme-darktext:hover { + background-image: -moz-linear-gradient(hsla(0,0%,100%,.5), hsla(0,0%,80%,.5) 2px, hsla(0,0%,60%,.5) 50%); +} + +.tabbrowser-tab[pinned][titlechanged]:not([selected="true"]) { + background-image: -moz-linear-gradient(rgba(255,0,0,.5), rgba(255,0,0,.5)) !important; } .tabbrowser-tab[pinned] { min-height: 20px; /* corresponds to the max. height of non-textual tab contents, i.e. the tab close button */ } -.tabbrowser-tab[pinned] + .tabbrowser-tab:not([pinned]) { - -moz-margin-start: 0; +.tabbrowser-tab > .tab-text { + border: 1px dotted transparent; + margin: -1px !important; /* let the border not consume any space, like outline */ } -.tabbrowser-tab[pinned][titlechanged]:not([selected="true"]) { - -moz-box-shadow: 0 0 0 1em rgba(255,0,0,.5) inset; +.tabbrowser-tab:focus > .tab-text { + border: 1px dotted -moz-DialogText; +} + +.tabbrowser-tab[pinned]:focus > .tab-icon-image { + outline: 1px dotted; } .tab-icon-image { width: 16px; height: 16px; - -moz-margin-start: 1px; - -moz-margin-end: 4px; + -moz-margin-end: 3px; list-style-image: url("chrome://global/skin/icons/folder-item.png"); -moz-image-region: rect(0px, 16px, 16px, 0px); } -.tabbrowser-tab[pinned] > .tab-icon-image { +.tabbrowser-tab[pinned] > .tab-icon-image, +.tabs-newtab-button > .toolbarbutton-icon { -moz-margin-start: 2px; -moz-margin-end: 2px; } @@ -1390,24 +1472,19 @@ statusbarpanel#statusbar-display { -moz-user-focus: normal; } -.tab-close-button:focus { - outline: none !important; -} - /* Tabstrip new tab button */ .tabs-newtab-button, #TabsToolbar > #new-tab-button , #TabsToolbar > #wrapper-new-tab-button > #new-tab-button { list-style-image: url("moz-icon://stock/gtk-add?size=menu"); -moz-image-region: auto; +} + +#TabsToolbar > #new-tab-button, +#TabsToolbar > #wrapper-new-tab-button > #new-tab-button { margin-bottom: 1px; } -.tabs-newtab-button { - width: 32px; -} - -.tabs-newtab-button > .toolbarbutton-icon, #TabsToolbar > #new-tab-button > .toolbarbutton-icon, #TabsToolbar > #wrapper-new-tab-button > #new-tab-button > .toolbarbutton-icon { margin-top: -2px; diff --git a/browser/themes/gnomestripe/browser/jar.mn b/browser/themes/gnomestripe/browser/jar.mn index 6fb08700dcb0..0b3516bab4f1 100644 --- a/browser/themes/gnomestripe/browser/jar.mn +++ b/browser/themes/gnomestripe/browser/jar.mn @@ -74,6 +74,7 @@ browser.jar: skin/classic/browser/tabbrowser/alltabs.png (tabbrowser/alltabs.png) skin/classic/browser/tabbrowser/progress.png (tabbrowser/progress.png) skin/classic/browser/tabbrowser/progress-pulsing.png (tabbrowser/progress-pulsing.png) + skin/classic/browser/tabbrowser/tab.png (tabbrowser/tab.png) skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png) skin/classic/browser/tabview/edit-light.png (tabview/edit-light.png) skin/classic/browser/tabview/edit.png (tabview/edit.png) diff --git a/browser/themes/gnomestripe/browser/tabbrowser/tab.png b/browser/themes/gnomestripe/browser/tabbrowser/tab.png new file mode 100644 index 0000000000000000000000000000000000000000..48bcf03d41a520846715c614358f56234be5c676 GIT binary patch literal 411 zcmV;M0c8G(P)&cJ=1=TE-x&y`@+3}mrA&zni^h>749YpeZkElMSyDU~j*xP_aH{Bq17Ie43( z8wEPIwr4gO`3$wBy)#S^{4K*c9yBxc76HAwA(WD)*gp!yM1c^>PfyNZ>?5GIo=Pe8 zDba`<9_+?(oNC7$4YP!}SBT^+ilT=duROdo;vRnl7yyJzWY2X`E`$I8002ovPDHLk FV1lLGt(E`) literal 0 HcmV?d00001 From 734ad7fda89ad158f597ab29fc869ee1afeca5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Sat, 4 Sep 2010 10:59:43 +0200 Subject: [PATCH 136/222] Bug 575056 - Background tabs should be more opaque. r=gavin a=blocking --- browser/themes/winstripe/browser/browser-aero.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/themes/winstripe/browser/browser-aero.css b/browser/themes/winstripe/browser/browser-aero.css index a71dff297223..6c278dd62730 100644 --- a/browser/themes/winstripe/browser/browser-aero.css +++ b/browser/themes/winstripe/browser/browser-aero.css @@ -88,13 +88,13 @@ .tabbrowser-tab:not(:-moz-lwtheme):not([selected="true"]), .tabs-newtab-button:not(:-moz-lwtheme) { - background-image: -moz-linear-gradient(hsla(0,0%,100%,.4), hsla(0,0%,75%,.4) 50%); + background-image: -moz-linear-gradient(hsla(214,15%,80%,.8), hsla(214,15%,65%,.8) 50%); text-shadow: 0 1px 0 rgba(255,255,255,.4); } .tabbrowser-tab:not(:-moz-lwtheme):not([selected="true"]):hover, .tabs-newtab-button:not(:-moz-lwtheme):hover { - background-image: -moz-linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,75%,.6) 50%); + background-image: -moz-linear-gradient(hsla(214,15%,90%,.8), hsla(214,15%,75%,.8) 50%); } #allTabs-panel, From 295632f66ae242bef0b5f851762f16fc117ac5eb Mon Sep 17 00:00:00 2001 From: Kurt Schultz Date: Fri, 3 Sep 2010 06:09:46 -0400 Subject: [PATCH 137/222] Bug 592908 - Update the text 'Organize Bookmarks' in the Firefox menu. r=dao --- browser/base/content/browser-menubar.inc | 2 +- browser/base/content/browser.xul | 6 +++--- browser/locales/en-US/chrome/browser/browser.dtd | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/browser/base/content/browser-menubar.inc b/browser/base/content/browser-menubar.inc index 50958acac2d5..09fd85e022d3 100644 --- a/browser/base/content/browser-menubar.inc +++ b/browser/base/content/browser-menubar.inc @@ -573,7 +573,7 @@ command="Browser:BookmarkAllTabs" key="bookmarkAllTabsKb"/> diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index 540a67827275..01a64566a9dd 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -593,8 +593,8 @@ label="&appMenuUnsorted.label;" oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');" class="menuitem-iconic"/> - @@ -959,7 +959,7 @@ command="Browser:BookmarkAllTabs" key="bookmarkAllTabsKb"/> diff --git a/browser/locales/en-US/chrome/browser/browser.dtd b/browser/locales/en-US/chrome/browser/browser.dtd index f578283db14a..57b6974e1afa 100644 --- a/browser/locales/en-US/chrome/browser/browser.dtd +++ b/browser/locales/en-US/chrome/browser/browser.dtd @@ -97,7 +97,7 @@ - + From 3d65ece5086364122326d92870aacff908fa9d34 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sat, 4 Sep 2010 13:38:07 +0200 Subject: [PATCH 138/222] Bug 592827 - Implement DOMImplementation.createHTMLDocument; r=jonas approval2.0=jonas --- content/base/src/nsDocument.cpp | 83 +++++++++++++++++++ content/base/test/Makefile.in | 1 + .../base/test/test_createHTMLDocument.html | 48 +++++++++++ .../core/nsIDOMDOMImplementation.idl | 12 ++- js/src/xpconnect/src/dom_quickstubs.qsconf | 1 + 5 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 content/base/test/test_createHTMLDocument.html diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index dab8ac14b72d..1b84f1a27f5d 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -201,6 +201,8 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID); #include "nsHTMLCSSStyleSheet.h" #include "mozilla/dom/Link.h" +#include "nsIHTMLDocument.h" + using namespace mozilla::dom; @@ -1435,6 +1437,87 @@ nsDOMImplementation::CreateDocument(const nsAString& aNamespaceURI, scriptHandlingObject, aReturn); } +NS_IMETHODIMP +nsDOMImplementation::CreateHTMLDocument(const nsAString& aTitle, + nsIDOMDocument** aReturn) +{ + *aReturn = NULL; + + nsCOMPtr doc; + nsresult rv = NS_NewHTMLDocument(getter_AddRefs(doc)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr HTMLdoc = do_QueryInterface(doc); + HTMLdoc->SetCompatibilityMode(eCompatibility_FullStandards); + + nsCOMPtr doctype; + // Indicate that there is no internal subset (not just an empty one) + nsAutoString voidString; + voidString.SetIsVoid(true); + rv = NS_NewDOMDocumentType(getter_AddRefs(doctype), + NULL, // aNodeInfoManager + mPrincipal, // aPrincipal + nsGkAtoms::html, // aName + NULL, // aEntities + NULL, // aNotations + EmptyString(), // aPublicId + EmptyString(), // aSystemId + voidString); // aInternalSubset + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr doctypeAsContent = do_QueryInterface(doctype); + rv = doc->AppendChildTo(doctypeAsContent, false); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr root; + rv = doc->CreateElem(NS_LITERAL_STRING("html"), NULL, kNameSpaceID_XHTML, + false, getter_AddRefs(root)); + NS_ENSURE_SUCCESS(rv, rv); + rv = doc->AppendChildTo(root, false); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr head; + rv = doc->CreateElem(NS_LITERAL_STRING("head"), NULL, kNameSpaceID_XHTML, + false, getter_AddRefs(head)); + NS_ENSURE_SUCCESS(rv, rv); + rv = root->AppendChildTo(head, false); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr title; + rv = doc->CreateElem(NS_LITERAL_STRING("title"), NULL, kNameSpaceID_XHTML, + false, getter_AddRefs(title)); + NS_ENSURE_SUCCESS(rv, rv); + rv = head->AppendChildTo(title, false); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr titleText; + rv = NS_NewTextNode(getter_AddRefs(titleText), doc->NodeInfoManager()); + NS_ENSURE_SUCCESS(rv, rv); + rv = titleText->SetText(aTitle, false); + NS_ENSURE_SUCCESS(rv, rv); + rv = title->AppendChildTo(titleText, false); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr body; + rv = doc->CreateElem(NS_LITERAL_STRING("body"), NULL, kNameSpaceID_XHTML, + false, getter_AddRefs(body)); + NS_ENSURE_SUCCESS(rv, rv); + rv = root->AppendChildTo(body, false); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr scriptHandlingObject = + do_QueryReferent(mScriptObject); + doc->SetScriptHandlingObject(scriptHandlingObject); + + // created documents are immediately "complete" (ready to use) + doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); + + nsCOMPtr document = do_QueryInterface(doc); + document.forget(aReturn); + + return NS_OK; +} + // ================================================================== // = // ================================================================== diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index 9e7cc91ca35c..e94dd36b44b5 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -413,6 +413,7 @@ _TEST_FILES2 = \ test_x-frame-options.html \ file_x-frame-options_main.html \ file_x-frame-options_page.sjs \ + test_createHTMLDocument.html \ $(NULL) # This test fails on the Mac for some reason diff --git a/content/base/test/test_createHTMLDocument.html b/content/base/test/test_createHTMLDocument.html new file mode 100644 index 000000000000..6e81eeef59f0 --- /dev/null +++ b/content/base/test/test_createHTMLDocument.html @@ -0,0 +1,48 @@ + +createHTMLDocument + + + + + + + + + diff --git a/dom/interfaces/core/nsIDOMDOMImplementation.idl b/dom/interfaces/core/nsIDOMDOMImplementation.idl index 2a26a8e80d7f..529f81b4576d 100644 --- a/dom/interfaces/core/nsIDOMDOMImplementation.idl +++ b/dom/interfaces/core/nsIDOMDOMImplementation.idl @@ -48,7 +48,7 @@ * http://www.w3.org/TR/DOM-Level-2-Core/ */ -[scriptable, uuid(a6cf9074-15b3-11d2-932e-00805f8add32)] +[scriptable, uuid(03a6f574-99ec-42f8-9e6c-812a4a9bcbf7)] interface nsIDOMDOMImplementation : nsISupports { boolean hasFeature(in DOMString feature, @@ -63,4 +63,14 @@ interface nsIDOMDOMImplementation : nsISupports in DOMString qualifiedName, in nsIDOMDocumentType doctype) raises(DOMException); + + /** + * Returns an HTML document with a basic DOM already constructed and with an + * appropriate title element. + * + * @param title the title of the Document + * @see + */ + nsIDOMDocument createHTMLDocument([Null(Stringify)] + in DOMString title); }; diff --git a/js/src/xpconnect/src/dom_quickstubs.qsconf b/js/src/xpconnect/src/dom_quickstubs.qsconf index e70e973b616c..7a17ad23ce2d 100644 --- a/js/src/xpconnect/src/dom_quickstubs.qsconf +++ b/js/src/xpconnect/src/dom_quickstubs.qsconf @@ -148,6 +148,7 @@ members = [ 'nsIDOM3Document.adoptNode', 'nsIDOM3Document.renameNode', 'nsIDOM3Node.*', + 'nsIDOMDOMImplementation.*', 'nsIDOMDOMStringList.*', 'nsIDOMDOMTokenList.*', 'nsIDOMDOMSettableTokenList.*', From 5b41ca7297f7a9112ef5006a15bd3d87b57f9245 Mon Sep 17 00:00:00 2001 From: Blair McBride Date: Sat, 28 Aug 2010 14:45:11 +1200 Subject: [PATCH 139/222] Bug 581076 - No "See all results" link present when searching for add-ons and not all are displayed (extensions.getAddons.maxResults). r=dtownsend, a=blocking-beta6 --- browser/app/profile/firefox.js | 5 +- .../mozapps/extensions/extensions.properties | 3 + .../mozapps/extensions/content/extensions.css | 3 +- .../mozapps/extensions/content/extensions.js | 39 +++++- .../mozapps/extensions/content/extensions.xul | 19 +-- .../extensions/test/browser/Makefile.in | 1 + .../test/browser/browser_bug581076.js | 121 ++++++++++++++++++ .../test/xpcshell/test_AddonRepository.js | 2 +- .../mozapps/extensions/extensions.css | 5 + .../mozapps/extensions/extensions.css | 5 + .../mozapps/extensions/extensions.css | 5 + 11 files changed, 189 insertions(+), 19 deletions(-) create mode 100644 toolkit/mozapps/extensions/test/browser/browser_bug581076.js diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 1e87d4b0c061..5e9be6cb28f2 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -56,13 +56,12 @@ pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindow.xul // Enables some extra Extension System Logging (can reduce performance) pref("extensions.logging.enabled", false); -// Preferences for the Addon Repository +// Preferences for AMO integration pref("extensions.getAddons.cache.enabled", true); pref("extensions.getAddons.maxResults", 15); pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/guid:%IDS%"); +pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/%APP%/search?q=%TERMS%"); pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%"); - -// Preferences for AMO integration pref("extensions.webservice.discoverURL", "https://services.addons.mozilla.org/%LOCALE%/%APP%/discovery/%VERSION%/%OS%"); // Blocklist preferences diff --git a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties index 236e9e7e00af..87e0ef424460 100644 --- a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties +++ b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties @@ -81,3 +81,6 @@ enableAddonTooltip=Enable this add-on enableAddonRestartRequiredTooltip=Enable this add-on (restart required) disableAddonTooltip=Disable this add-on disableAddonRestartRequiredTooltip=Disable this add-on (restart required) + +#LOCALIZATION NOTE (showAllSearchResults) #1 is the total number of search results +showAllSearchResults=See one result;See all #1 results diff --git a/toolkit/mozapps/extensions/content/extensions.css b/toolkit/mozapps/extensions/content/extensions.css index e1eedb3a4f8c..29d4b9cdf2b6 100644 --- a/toolkit/mozapps/extensions/content/extensions.css +++ b/toolkit/mozapps/extensions/content/extensions.css @@ -115,7 +115,8 @@ xhtml|link { #detail-view:not([upgrade="true"]) .update-postfix, #detail-view[active="true"] .disabled-postfix, #detail-view[loading] > .detail-view-container, -.detail-row:not([value]) { +.detail-row:not([value]), +#search-list[remote="false"] #search-allresults-link { display: none; } diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js index fb081a164160..5ecbe0ded0ad 100644 --- a/toolkit/mozapps/extensions/content/extensions.js +++ b/toolkit/mozapps/extensions/content/extensions.js @@ -1201,7 +1201,9 @@ var gSearchView = { _sorters: null, _listBox: null, _emptyNotice: null, + _allResultsLink: null, _lastQuery: null, + _lastRemoteTotal: 0, _pendingSearches: 0, initialize: function() { @@ -1211,6 +1213,7 @@ var gSearchView = { this._sorters.handler = this; this._listBox = document.getElementById("search-list"); this._emptyNotice = document.getElementById("search-list-empty"); + this._allResultsLink = document.getElementById("search-allresults-link"); var self = this; this._listBox.addEventListener("keydown", function(aEvent) { @@ -1237,6 +1240,7 @@ var gSearchView = { show: function(aQuery, aRequest) { gHeader.isSearching = true; this.showEmptyNotice(false); + this.showAllResultsLink(0); gHeader.searchQuery = aQuery; aQuery = aQuery.trim().toLocaleLowerCase(); @@ -1250,8 +1254,8 @@ var gSearchView = { if (AddonRepository.isSearching) AddonRepository.cancelSearch(); - while (this._listBox.lastChild.localName == "richlistitem") - this._listBox.removeChild(this._listBox.lastChild); + while (this._listBox.firstChild.localName == "richlistitem") + this._listBox.removeChild(this._listBox.firstChild); var self = this; gCachedAddons = {}; @@ -1273,7 +1277,7 @@ var gSearchView = { if (aIsRemote) gCachedAddons[aObj.id] = aObj; - self._listBox.appendChild(item); + self._listBox.insertBefore(item, self._listBox.lastChild); createdCount++; }); @@ -1315,6 +1319,8 @@ var gSearchView = { if (gViewController && aRequest != gViewController.currentViewRequest) return; + self._lastRemoteTotal = 0; + // XXXunf Better handling of AMO search failure. See bug 579502 finishSearch(0); // Silently fail }, @@ -1323,6 +1329,11 @@ var gSearchView = { if (gViewController && aRequest != gViewController.currentViewRequest) return; + if (aTotalResults > maxRemoteResults) + self._lastRemoteTotal = aTotalResults; + else + self._lastRemoteTotal = 0; + var createdCount = createSearchResults(aAddonsList, false, true); finishSearch(createdCount); } @@ -1347,6 +1358,7 @@ var gSearchView = { } this.showEmptyNotice(isEmpty); + this.showAllResultsLink(this._lastRemoteTotal); } gViewController.updateCommands(); @@ -1407,9 +1419,24 @@ var gSearchView = { this._emptyNotice.hidden = !aShow; }, + showAllResultsLink: function(aTotalResults) { + if (aTotalResults == 0) { + this._allResultsLink.hidden = true; + return; + } + + var linkStr = gStrings.ext.GetStringFromName("showAllSearchResults"); + linkStr = PluralForm.get(aTotalResults, linkStr); + linkStr = linkStr.replace("#1", aTotalResults); + this._allResultsLink.value = linkStr; + + this._allResultsLink.href = AddonRepository.getSearchURL(this._lastQuery); + this._allResultsLink.hidden = false; + }, + onSortChanged: function(aSortBy, aAscending) { - var header = this._listBox.firstChild; - this._listBox.removeChild(header); + var footer = this._listBox.lastChild; + this._listBox.removeChild(footer); var hints = aAscending ? "ascending" : "descending"; if (INTEGER_FIELDS.indexOf(aSortBy) >= 0) @@ -1419,7 +1446,7 @@ var gSearchView = { getService(Ci.nsIXULSortService); sortService.sort(this._listBox, aSortBy, hints); - this._listBox.insertBefore(header, this._listBox.firstChild); + this._listBox.appendChild(footer); }, getSelectedAddon: function() { diff --git a/toolkit/mozapps/extensions/content/extensions.xul b/toolkit/mozapps/extensions/content/extensions.xul index 5ab0bc60d40e..0734c5ea4e1e 100644 --- a/toolkit/mozapps/extensions/content/extensions.xul +++ b/toolkit/mozapps/extensions/content/extensions.xul @@ -238,15 +238,18 @@ +