From baaa3050408f745d276cfd9c83a7d4d820e8b439 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Mon, 26 Aug 2013 14:50:16 +0200 Subject: [PATCH 01/85] Bug 907745 - Prepare for texture locking support. r=mattwodrow --- gfx/layers/client/TextureClient.cpp | 2 +- gfx/layers/client/TextureClient.h | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index f7969c873ac8..3335f602ab38 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -183,7 +183,7 @@ BufferTextureClient::UpdateSurface(gfxASurface* aSurface) tmpCtx->DrawSurface(aSurface, gfxSize(serializer.GetSize().width, serializer.GetSize().height)); - if (TextureRequiresLocking(mFlags)) { + if (TextureRequiresLocking(mFlags) && !ImplementsLocking()) { // We don't have support for proper locking yet, so we'll // have to be immutable instead. MarkImmutable(); diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h index 3b75639b711f..4750020a514b 100644 --- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -111,6 +111,16 @@ public: virtual void Unlock() {} + /** + * Returns true if this texture has a lock/unlock mechanism. + * Textures that do not implement locking should be immutable or should + * use immediate uploads (see TextureFlags in CompositorTypes.h) + */ + virtual bool ImplementsLocking() const + { + return false; + } + void SetID(uint64_t aID) { MOZ_ASSERT(mID == 0 || aID == 0); From ea8a7bdc6c678832b4152caf15e8d75c7d05ef7b Mon Sep 17 00:00:00 2001 From: Douglas Crosher Date: Sat, 24 Aug 2013 13:35:08 +1000 Subject: [PATCH 02/85] Bug 908971 - jemalloc: fix uninitialized 'mapped' variable. r=jlebar --- memory/mozjemalloc/jemalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/memory/mozjemalloc/jemalloc.c b/memory/mozjemalloc/jemalloc.c index 38bf2d0d23d9..9fb7ece2e933 100644 --- a/memory/mozjemalloc/jemalloc.c +++ b/memory/mozjemalloc/jemalloc.c @@ -5515,7 +5515,7 @@ malloc_print_stats(void) #ifdef MALLOC_STATS { - size_t allocated, mapped; + size_t allocated, mapped = 0; #ifdef MALLOC_BALANCE uint64_t nbalance = 0; #endif From a3c2a0f45516ebdae27d4ffc41c47efcbcc259ca Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Mon, 26 Aug 2013 11:07:34 -0400 Subject: [PATCH 03/85] Bug 908637 - Add bootstrap support for FreeBSD. r=gps --- python/mozboot/bin/bootstrap.py | 1 + python/mozboot/mozboot/base.py | 5 ++- python/mozboot/mozboot/bootstrap.py | 5 +++ python/mozboot/mozboot/freebsd.py | 48 +++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 python/mozboot/mozboot/freebsd.py diff --git a/python/mozboot/bin/bootstrap.py b/python/mozboot/bin/bootstrap.py index 55cb033667c1..38658acfe7bc 100755 --- a/python/mozboot/bin/bootstrap.py +++ b/python/mozboot/bin/bootstrap.py @@ -37,6 +37,7 @@ REPOSITORY_PATHS = [ 'mozboot/centos.py', 'mozboot/debian.py', 'mozboot/fedora.py', + 'mozboot/freebsd.py', 'mozboot/gentoo.py', 'mozboot/mint.py', 'mozboot/openbsd.py', diff --git a/python/mozboot/mozboot/base.py b/python/mozboot/mozboot/base.py index 7f2b915e8690..70044bb12534 100644 --- a/python/mozboot/mozboot/base.py +++ b/python/mozboot/mozboot/base.py @@ -96,7 +96,10 @@ class BaseBootstrapper(object): def run_as_root(self, command): if os.geteuid() != 0: - command.insert(0, 'sudo') + if self.which('sudo'): + command.insert(0, 'sudo') + else: + command = ['su', 'root', '-c', ' '.join(command)] print('Executing as root:', subprocess.list2cmdline(command)) diff --git a/python/mozboot/mozboot/bootstrap.py b/python/mozboot/mozboot/bootstrap.py index e6d1279704d1..e99c1b75f8b3 100644 --- a/python/mozboot/mozboot/bootstrap.py +++ b/python/mozboot/mozboot/bootstrap.py @@ -11,6 +11,7 @@ import sys from mozboot.centos import CentOSBootstrapper from mozboot.debian import DebianBootstrapper from mozboot.fedora import FedoraBootstrapper +from mozboot.freebsd import FreeBSDBootstrapper from mozboot.gentoo import GentooBootstrapper from mozboot.mint import MintBootstrapper from mozboot.osx import OSXBootstrapper @@ -70,6 +71,10 @@ class Bootstrapper(object): cls = OpenBSDBootstrapper args['version'] = platform.uname()[2] + elif sys.platform.startswith('freebsd'): + cls = FreeBSDBootstrapper + args['version'] = platform.release() + if cls is None: raise NotImplementedError('Bootstrap support is not yet available ' 'for your OS.') diff --git a/python/mozboot/mozboot/freebsd.py b/python/mozboot/mozboot/freebsd.py new file mode 100644 index 000000000000..4e81e8c47120 --- /dev/null +++ b/python/mozboot/mozboot/freebsd.py @@ -0,0 +1,48 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + +from __future__ import print_function + +import os +import subprocess +import sys + +from mozboot.base import BaseBootstrapper + +class FreeBSDBootstrapper(BaseBootstrapper): + def __init__(self, version): + BaseBootstrapper.__init__(self) + self.version = int(version.split('.')[0]) + + def pkg_install(self, *packages): + if self.which('pkg'): + command = ['pkg', 'install', '-x'] + command.extend([i[0] for i in packages]) + else: + command = ['pkg_add', '-Fr'] + command.extend([i[-1] for i in packages]) + + self.run_as_root(command) + + def install_system_packages(self): + # using clang since 9.0 + if self.version < 9: + self.pkg_install(('gcc',)) + + self.pkg_install( + ('autoconf-2.13', 'autoconf213'), + ('dbus-glib',), + ('gmake',), + ('gstreamer-plugins',), + ('gtk-2', 'gtk20'), + ('libGL',), + ('libIDL',), + ('libv4l',), + ('mercurial',), + ('pulseaudio',), + ('yasm',), + ('zip',)) + + def upgrade_mercurial(self, current): + self.pkg_install('mercurial') From e577d20fc20d89338e2175974be6196b8aa3a81b Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 26 Aug 2013 11:08:29 -0400 Subject: [PATCH 04/85] Bug 897404 - Port GTK2 to GTK3 - treeview rendering, don't use treeview flags. r=karlt --- widget/gtk2/gtk3drawing.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/widget/gtk2/gtk3drawing.c b/widget/gtk2/gtk3drawing.c index 2b9d6eacd68b..77c3a807c399 100644 --- a/widget/gtk2/gtk3drawing.c +++ b/widget/gtk2/gtk3drawing.c @@ -1588,12 +1588,14 @@ moz_gtk_treeview_expander_paint(cairo_t *cr, GdkRectangle* rect, gtk_style_context_save(style); gtk_style_context_add_class(style, GTK_STYLE_CLASS_EXPANDER); - state_flags = GetStateFlagsFromGtkWidgetState(state); + /* Because the frame we get is of the entire treeview, we can't get the precise + * event state of one expander, thus rendering hover and active feedback useless. */ + state_flags = state->disabled ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL; /* GTK_STATE_FLAG_ACTIVE controls expanded/colapsed state rendering * in gtk_render_expander() */ - if (expander_state == GTK_EXPANDER_EXPANDED) + if (expander_state == GTK_EXPANDER_EXPANDED) state_flags |= GTK_STATE_FLAG_ACTIVE; else state_flags &= ~(GTK_STATE_FLAG_ACTIVE); From 999cb2239a2e34f1baf6ed90b060d46c982bb53c Mon Sep 17 00:00:00 2001 From: Alexandre BM Date: Mon, 26 Aug 2013 11:08:51 -0400 Subject: [PATCH 05/85] Bug 761064 - Remove an unnecessary mTreeView null check. r=surkov --- accessible/src/xul/XULTreeAccessible.cpp | 12 ++---------- accessible/src/xul/XULTreeGridAccessible.cpp | 4 ---- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/accessible/src/xul/XULTreeAccessible.cpp b/accessible/src/xul/XULTreeAccessible.cpp index 5d686c90aea3..61a613f44c7c 100644 --- a/accessible/src/xul/XULTreeAccessible.cpp +++ b/accessible/src/xul/XULTreeAccessible.cpp @@ -779,7 +779,7 @@ XULTreeItemAccessibleBase::GetBounds(int32_t* aX, int32_t* aY, NS_IMETHODIMP XULTreeItemAccessibleBase::SetSelected(bool aSelect) { - if (IsDefunct() || !mTreeView) + if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr selection; @@ -797,7 +797,7 @@ XULTreeItemAccessibleBase::SetSelected(bool aSelect) NS_IMETHODIMP XULTreeItemAccessibleBase::TakeFocus() { - if (IsDefunct() || !mTreeView) + if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr selection; @@ -812,8 +812,6 @@ XULTreeItemAccessibleBase::TakeFocus() Relation XULTreeItemAccessibleBase::RelationByType(uint32_t aType) { - if (!mTreeView) - return Relation(); switch (aType) { case nsIAccessibleRelation::RELATION_NODE_CHILD_OF: { @@ -956,8 +954,6 @@ XULTreeItemAccessibleBase::GroupPosition() uint64_t XULTreeItemAccessibleBase::NativeState() { - if (!mTreeView) - return states::DEFUNCT; // focusable and selectable states uint64_t state = NativeInteractiveState(); @@ -1062,8 +1058,6 @@ XULTreeItemAccessibleBase::GetSiblingAtOffset(int32_t aOffset, bool XULTreeItemAccessibleBase::IsExpandable() { - if (!mTreeView) - return false; bool isContainer = false; mTreeView->IsContainer(mRow, &isContainer); @@ -1089,8 +1083,6 @@ XULTreeItemAccessibleBase::IsExpandable() void XULTreeItemAccessibleBase::GetCellName(nsITreeColumn* aColumn, nsAString& aName) { - if (!mTreeView) - return; mTreeView->GetCellText(mRow, aColumn, aName); diff --git a/accessible/src/xul/XULTreeGridAccessible.cpp b/accessible/src/xul/XULTreeGridAccessible.cpp index f0a46a057b47..86bdd4d61cbf 100644 --- a/accessible/src/xul/XULTreeGridAccessible.cpp +++ b/accessible/src/xul/XULTreeGridAccessible.cpp @@ -778,8 +778,6 @@ XULTreeGridCellAccessible::RelationByType(uint32_t aType) void XULTreeGridCellAccessible::CellInvalidated() { - if (!mTreeView) - return; nsAutoString textEquiv; @@ -852,8 +850,6 @@ XULTreeGridCellAccessible::DispatchClickEvent(nsIContent* aContent, bool XULTreeGridCellAccessible::IsEditable() const { - if (!mTreeView) - return false; // XXX: logic corresponds to tree.xml, it's preferable to have interface // method to check it. From ed907121713644c555c2895c06127d31fe293bcb Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Mon, 26 Aug 2013 02:07:17 -0400 Subject: [PATCH 06/85] Bug 909187: Part 1-Refactor MediaStreamTrack disabling so we can call it directly and access from other threads r=roc (reland) --- content/media/MediaSegment.h | 13 +++++++++++++ content/media/MediaStreamGraph.cpp | 28 +++++++++------------------- content/media/MediaStreamGraph.h | 7 ++++++- content/media/VideoSegment.h | 8 ++++++++ 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/content/media/MediaSegment.h b/content/media/MediaSegment.h index 0fb72a92f64f..814d6065a3f7 100644 --- a/content/media/MediaSegment.h +++ b/content/media/MediaSegment.h @@ -100,6 +100,10 @@ public: * Insert aDuration of null data at the end of the segment. */ virtual void AppendNullData(TrackTicks aDuration) = 0; + /** + * Replace contents with disabled data of the same duration + */ + virtual void ReplaceWithDisabled() = 0; /** * Remove all contents, setting duration to 0. */ @@ -190,6 +194,15 @@ public: } mDuration += aDuration; } + virtual void ReplaceWithDisabled() + { + if (GetType() != AUDIO) { + MOZ_CRASH("Disabling unknown segment type"); + } + TrackTicks duration = GetDuration(); + Clear(); + AppendNullData(duration); + } virtual void Clear() { mDuration = 0; diff --git a/content/media/MediaStreamGraph.cpp b/content/media/MediaStreamGraph.cpp index d32be208cbf4..707a505d2ac6 100644 --- a/content/media/MediaStreamGraph.cpp +++ b/content/media/MediaStreamGraph.cpp @@ -1912,29 +1912,15 @@ MediaStream::SetTrackEnabled(TrackID aTrackID, bool aEnabled) } void -MediaStream::ApplyTrackDisabling(TrackID aTrackID, MediaSegment* aSegment) +MediaStream::ApplyTrackDisabling(TrackID aTrackID, MediaSegment* aSegment, MediaSegment* aRawSegment) { + // mMutex must be owned here if this is a SourceMediaStream if (!mDisabledTrackIDs.Contains(aTrackID)) { return; } - - switch (aSegment->GetType()) { - case MediaSegment::AUDIO: { - TrackTicks duration = aSegment->GetDuration(); - aSegment->Clear(); - aSegment->AppendNullData(duration); - break; - } - case MediaSegment::VIDEO: { - for (VideoSegment::ChunkIterator i(*static_cast(aSegment)); - !i.IsEnded(); i.Next()) { - VideoChunk& chunk = *i; - chunk.SetForceBlack(true); - } - break; - } - default: - MOZ_CRASH("Unknown track type"); + aSegment->ReplaceWithDisabled(); + if (aRawSegment) { + aRawSegment->ReplaceWithDisabled(); } } @@ -1990,6 +1976,10 @@ SourceMediaStream::AppendToTrack(TrackID aID, MediaSegment* aSegment, MediaSegme // Indirect listeners (via subsequent TrackUnion nodes) are synced to // playout time, and so can be delayed by buffering. + // Apply track disabling before notifying any consumers directly + // or inserting into the graph + ApplyTrackDisabling(aID, aSegment, aRawSegment); + // Must notify first, since AppendFrom() will empty out aSegment NotifyDirectConsumers(track, aRawSegment ? aRawSegment : aSegment); track->mData->AppendFrom(aSegment); // note: aSegment is now dead diff --git a/content/media/MediaStreamGraph.h b/content/media/MediaStreamGraph.h index 86adb59f9527..d66fb2b1fe19 100644 --- a/content/media/MediaStreamGraph.h +++ b/content/media/MediaStreamGraph.h @@ -459,7 +459,7 @@ public: StreamBuffer::Track* EnsureTrack(TrackID aTrack, TrackRate aSampleRate); - void ApplyTrackDisabling(TrackID aTrackID, MediaSegment* aSegment); + void ApplyTrackDisabling(TrackID aTrackID, MediaSegment* aSegment, MediaSegment* aRawSegment = nullptr); DOMMediaStream* GetWrapper() { @@ -679,6 +679,11 @@ public: FinishWithLockHeld(); } + // Overriding allows us to hold the mMutex lock while changing the track enable status + void SetTrackEnabledImpl(TrackID aTrackID, bool aEnabled) { + MutexAutoLock lock(mMutex); + MediaStream::SetTrackEnabledImpl(aTrackID, aEnabled); + } /** * End all tracks and Finish() this stream. Used to voluntarily revoke access diff --git a/content/media/VideoSegment.h b/content/media/VideoSegment.h index 000a4721d9c1..5a16400f98e4 100644 --- a/content/media/VideoSegment.h +++ b/content/media/VideoSegment.h @@ -107,6 +107,14 @@ public: } return &c->mFrame; } + // Override default impl + virtual void ReplaceWithDisabled() MOZ_OVERRIDE { + for (ChunkIterator i(*this); + !i.IsEnded(); i.Next()) { + VideoChunk& chunk = *i; + chunk.SetForceBlack(true); + } + } // Segment-generic methods not in MediaSegmentBase static Type StaticType() { return VIDEO; } From d093043b4d0fa7fe4fcb27904f1601357d2844bf Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Mon, 26 Aug 2013 02:07:19 -0400 Subject: [PATCH 07/85] Bug 909187: Part 2 - Allow DOM MediaStreams to intercept SetTrackEnabled calls r=roc (reland) --- content/media/DOMMediaStream.cpp | 8 ++++++++ content/media/DOMMediaStream.h | 6 ++++++ content/media/MediaStreamGraph.h | 5 +++++ content/media/MediaStreamTrack.cpp | 5 +---- content/media/TrackUnionStream.h | 11 +++++++++++ dom/media/MediaManager.cpp | 11 +++++++++++ 6 files changed, 42 insertions(+), 4 deletions(-) diff --git a/content/media/DOMMediaStream.cpp b/content/media/DOMMediaStream.cpp index 4b8f7a615626..2e5f7b404026 100644 --- a/content/media/DOMMediaStream.cpp +++ b/content/media/DOMMediaStream.cpp @@ -240,6 +240,14 @@ DOMMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHi return stream.forget(); } +void +DOMMediaStream::SetTrackEnabled(TrackID aTrackID, bool aEnabled) +{ + if (mStream) { + mStream->SetTrackEnabled(aTrackID, aEnabled); + } +} + bool DOMMediaStream::CombineWithPrincipal(nsIPrincipal* aPrincipal) { diff --git a/content/media/DOMMediaStream.h b/content/media/DOMMediaStream.h index d8874181c830..78a3fd789ca1 100644 --- a/content/media/DOMMediaStream.h +++ b/content/media/DOMMediaStream.h @@ -84,6 +84,12 @@ public: virtual bool AddDirectListener(MediaStreamDirectListener *aListener) { return false; } virtual void RemoveDirectListener(MediaStreamDirectListener *aListener) {} + /** + * Overridden in DOMLocalMediaStreams to allow getUserMedia to disable + * media at the SourceMediaStream. + */ + virtual void SetTrackEnabled(TrackID aTrackID, bool aEnabled); + bool IsFinished(); /** * Returns a principal indicating who may access this stream. The stream contents diff --git a/content/media/MediaStreamGraph.h b/content/media/MediaStreamGraph.h index d66fb2b1fe19..6231074d0bf3 100644 --- a/content/media/MediaStreamGraph.h +++ b/content/media/MediaStreamGraph.h @@ -942,6 +942,11 @@ public: virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo) = 0; void SetAutofinishImpl(bool aAutofinish) { mAutofinish = aAutofinish; } + /** + * Forward SetTrackEnabled() to the input MediaStream(s) and translate the ID + */ + virtual void ForwardTrackEnabled(TrackID aOutputID, bool aEnabled) {}; + protected: // This state is all accessed only on the media graph thread. diff --git a/content/media/MediaStreamTrack.cpp b/content/media/MediaStreamTrack.cpp index 212f4070a9f3..7583e11206c6 100644 --- a/content/media/MediaStreamTrack.cpp +++ b/content/media/MediaStreamTrack.cpp @@ -52,10 +52,7 @@ void MediaStreamTrack::SetEnabled(bool aEnabled) { mEnabled = aEnabled; - MediaStream* stream = mStream->GetStream(); - if (stream) { - stream->SetTrackEnabled(mTrackID, aEnabled); - } + mStream->SetTrackEnabled(mTrackID, aEnabled); } } diff --git a/content/media/TrackUnionStream.h b/content/media/TrackUnionStream.h index 22d4c563dfae..ff0881fc3ecb 100644 --- a/content/media/TrackUnionStream.h +++ b/content/media/TrackUnionStream.h @@ -115,6 +115,17 @@ public: mFilterCallback = aCallback; } + // Forward SetTrackEnabled(output_track_id, enabled) to the Source MediaStream, + // translating the output track ID into the correct ID in the source. + virtual void ForwardTrackEnabled(TrackID aOutputID, bool aEnabled) { + for (int32_t i = mTrackMap.Length() - 1; i >= 0; --i) { + if (mTrackMap[i].mOutputTrackID == aOutputID) { + mTrackMap[i].mInputPort->GetSource()-> + SetTrackEnabled(mTrackMap[i].mInputTrackID, aEnabled); + } + } + } + protected: TrackIDFilterCallback mFilterCallback; diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index e38504614e89..8870a523b7dc 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -312,6 +312,17 @@ public: } } + // let us intervene for direct listeners when someone does track.enabled = false + virtual void SetTrackEnabled(TrackID aID, bool aEnabled) MOZ_OVERRIDE + { + // We encapsulate the SourceMediaStream and TrackUnion into one entity, so + // we can handle the disabling at the SourceMediaStream + + // We need to find the input track ID for output ID aID, so we let the TrackUnion + // forward the request to the source and translate the ID + GetStream()->AsProcessedStream()->ForwardTrackEnabled(aID, aEnabled); + } + // The actual MediaStream is a TrackUnionStream. But these resources need to be // explicitly destroyed too. nsRefPtr mSourceStream; From cc1485b44fc0faf3150b4e01e8690e01beab932c Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Mon, 26 Aug 2013 11:26:27 -0400 Subject: [PATCH 08/85] Bug 783674 - WebGLContext::Render to use ReadScreen* and mark its surfaces as dirty. r=bjacob --- content/canvas/src/WebGLContext.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index 7e507aea2217..1aa957498383 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -615,6 +615,7 @@ WebGLContext::Render(gfxContext *ctx, gfxPattern::GraphicsFilter f, uint32_t aFl } else if (srcPremultAlpha && !dstPremultAlpha) { gfxUtils::UnpremultiplyImageSurface(surf); } + surf->MarkDirty(); nsRefPtr pat = new gfxPattern(surf); pat->SetFilter(f); From 9c65c918b9cb0b8a5bf46765502d4f0a4af60be1 Mon Sep 17 00:00:00 2001 From: Ivan Alagenchev Date: Mon, 26 Aug 2013 11:26:43 -0400 Subject: [PATCH 09/85] Bug 875456 - DEVTOOLS patch. Adds logic for logging Mixed Content messages to the security console. r=msucan --- browser/devtools/webconsole/test/Makefile.in | 3 + ...nsole_allow_mixedcontent_securityerrors.js | 69 ++++++++++++ ...nsole_block_mixedcontent_securityerrors.js | 104 ++++++++++++++++++ browser/devtools/webconsole/test/head.js | 2 +- .../test-mixedcontent-securityerrors.html | 21 ++++ browser/devtools/webconsole/webconsole.js | 36 ++++-- 6 files changed, 224 insertions(+), 11 deletions(-) create mode 100644 browser/devtools/webconsole/test/browser_webconsole_allow_mixedcontent_securityerrors.js create mode 100644 browser/devtools/webconsole/test/browser_webconsole_block_mixedcontent_securityerrors.js create mode 100644 browser/devtools/webconsole/test/test-mixedcontent-securityerrors.html diff --git a/browser/devtools/webconsole/test/Makefile.in b/browser/devtools/webconsole/test/Makefile.in index 1b9eaf098deb..515cd73307d4 100644 --- a/browser/devtools/webconsole/test/Makefile.in +++ b/browser/devtools/webconsole/test/Makefile.in @@ -147,6 +147,8 @@ MOCHITEST_BROWSER_FILES = \ browser_console_navigation_marker.js \ browser_webconsole_bug_762593_insecure_passwords_web_console_warning.js \ browser_webconsole_bug_762593_insecure_passwords_about_blank_web_console_warning.js \ + browser_webconsole_allow_mixedcontent_securityerrors.js \ + browser_webconsole_block_mixedcontent_securityerrors.js \ head.js \ $(NULL) @@ -254,6 +256,7 @@ MOCHITEST_BROWSER_FILES += \ test-iframe1.html \ test-iframe2.html \ test-iframe3.html \ + test-mixedcontent-securityerrors.html \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/browser/devtools/webconsole/test/browser_webconsole_allow_mixedcontent_securityerrors.js b/browser/devtools/webconsole/test/browser_webconsole_allow_mixedcontent_securityerrors.js new file mode 100644 index 000000000000..8cbee929e60f --- /dev/null +++ b/browser/devtools/webconsole/test/browser_webconsole_allow_mixedcontent_securityerrors.js @@ -0,0 +1,69 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// The test loads a web page with mixed active and display content +// on it while the "block mixed content" settings are _off_. +// It then checks that the loading mixed content warning messages +// are logged to the console and have the correct "Learn More" +// url appended to them. +// Bug 875456 - Log mixed content messages from the Mixed Content +// Blocker to the Security Pane in the Web Console + +const TEST_URI = "https://example.com/browser/browser/devtools/webconsole/test/test-mixedcontent-securityerrors.html"; +const LEARN_MORE_URI = "https://developer.mozilla.org/en/Security/MixedContent"; + +function test() +{ + SpecialPowers.pushPrefEnv({"set": + [["security.mixed_content.block_active_content", false], + ["security.mixed_content.block_display_content", false] + ]}, loadingMixedContentTest); +} + +function loadingMixedContentTest() +{ + addTab(TEST_URI); + browser.addEventListener("load", function onLoad(aEvent) { + browser.removeEventListener(aEvent.type, onLoad, true); + openConsole(null, function testSecurityErrorLogged (hud) { + waitForMessages({ + webconsole: hud, + messages: [ + { + name: "Logged mixed active content", + text: "Loading mixed (insecure) active content on a secure page \"http://example.com/\"", + category: CATEGORY_SECURITY, + severity: SEVERITY_WARNING + }, + { + name: "Logged mixed passive content - image", + text: "Loading mixed (insecure) display content on a secure page \"http://example.com/tests/image/test/mochitest/blue.png\"", + category: CATEGORY_SECURITY, + severity: SEVERITY_WARNING + }, + ], + }).then(() => testClickOpenNewTab(hud)); + }); + }, true); +} + +function testClickOpenNewTab(hud) { + let warningNode = hud.outputNode.querySelector(".webconsole-learn-more-link"); + + // Invoke the click event and check if a new tab would + // open to the correct page. + let linkOpened = false; + let oldOpenUILinkIn = window.openUILinkIn; + window.openUILinkIn = function(aLink) { + if (aLink == LEARN_MORE_URI) { + linkOpened = true; + } + } + + EventUtils.synthesizeMouse(warningNode, 2, 2, {}, + warningNode.ownerDocument.defaultView); + ok(linkOpened, "Clicking the Learn More Warning node opens the desired page"); + window.openUILinkIn = oldOpenUILinkIn; + + finishTest(); +} diff --git a/browser/devtools/webconsole/test/browser_webconsole_block_mixedcontent_securityerrors.js b/browser/devtools/webconsole/test/browser_webconsole_block_mixedcontent_securityerrors.js new file mode 100644 index 000000000000..24747bc9495c --- /dev/null +++ b/browser/devtools/webconsole/test/browser_webconsole_block_mixedcontent_securityerrors.js @@ -0,0 +1,104 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// The test loads a web page with mixed active and display content +// on it while the "block mixed content" settings are _on_. +// It then checks that the blocked mixed content warning messages +// are logged to the console and have the correct "Learn More" +// url appended to them. After the first test finishes, it invokes +// a second test that overrides the mixed content blocker settings +// by clicking on the doorhanger shield and validates that the +// appropriate messages are logged to console. +// Bug 875456 - Log mixed content messages from the Mixed Content +// Blocker to the Security Pane in the Web Console + +const TEST_URI = "https://example.com/browser/browser/devtools/webconsole/test/test-mixedcontent-securityerrors.html"; +const LEARN_MORE_URI = "https://developer.mozilla.org/en/Security/MixedContent"; + +function test() +{ + SpecialPowers.pushPrefEnv({"set": [["security.mixed_content.block_active_content", true], + ["security.mixed_content.block_display_content", true]]}, blockMixedContentTest1); +} + +function blockMixedContentTest1() +{ + addTab(TEST_URI); + browser.addEventListener("load", function onLoad(aEvent) { + browser.removeEventListener(aEvent.type, onLoad, true); + openConsole(null, function testSecurityErrorLogged (hud) { + waitForMessages({ + webconsole: hud, + messages: [ + { + name: "Logged blocking mixed active content", + text: "Blocked loading mixed active content \"http://example.com/\"", + category: CATEGORY_SECURITY, + severity: SEVERITY_ERROR + }, + { + name: "Logged blocking mixed passive content - image", + text: "Blocked loading mixed active content \"http://example.com/\"", + category: CATEGORY_SECURITY, + severity: SEVERITY_ERROR + }, + ], + }).then(() => { + testClickOpenNewTab(hud); + // Call the second (MCB override) test. + mixedContentOverrideTest2(hud); + }); + }); + }, true); +} + +function mixedContentOverrideTest2(hud) +{ + var notification = PopupNotifications.getNotification("mixed-content-blocked", browser); + ok(notification, "Mixed Content Doorhanger didn't appear"); + // Click on the doorhanger. + notification.secondaryActions[0].callback(); + + waitForMessages({ + webconsole: hud, + messages: [ + { + name: "Logged blocking mixed active content", + text: "Loading mixed (insecure) active content on a secure"+ + " page \"http://example.com/\"", + category: CATEGORY_SECURITY, + severity: SEVERITY_WARNING + }, + { + name: "Logged blocking mixed passive content - image", + text: "Loading mixed (insecure) display content on a secure page"+ + " \"http://example.com/tests/image/test/mochitest/blue.png\"", + category: CATEGORY_SECURITY, + severity: SEVERITY_WARNING + }, + ], + }).then(() => { + testClickOpenNewTab(hud); + finishTest(); + }); +} + +function testClickOpenNewTab(hud) { + let warningNode = hud.outputNode.querySelector(".webconsole-learn-more-link"); + + // Invoke the click event and check if a new tab would + // open to the correct page. + let linkOpened = false; + let oldOpenUILinkIn = window.openUILinkIn; + window.openUILinkIn = function(aLink) { + if (aLink == LEARN_MORE_URI) { + linkOpened = true; + } + } + + EventUtils.synthesizeMouse(warningNode, 2, 2, {}, + warningNode.ownerDocument.defaultView); + ok(linkOpened, "Clicking the Learn More Warning node opens the desired page"); + window.openUILinkIn = oldOpenUILinkIn; + +} diff --git a/browser/devtools/webconsole/test/head.js b/browser/devtools/webconsole/test/head.js index 9518e125df5f..74e8f4f94f9c 100644 --- a/browser/devtools/webconsole/test/head.js +++ b/browser/devtools/webconsole/test/head.js @@ -1087,7 +1087,7 @@ function waitForMessages(aOptions) let partialMatch = !!(aRule.consoleTrace || aRule.consoleTime || aRule.consoleTimeEnd || aRule.type); - if (aRule.category && aElement.category != aRule.category) { + if ("category" in aRule && aElement.category != aRule.category) { if (partialMatch) { is(aElement.category, aRule.category, "message category for rule: " + displayRule(aRule)); diff --git a/browser/devtools/webconsole/test/test-mixedcontent-securityerrors.html b/browser/devtools/webconsole/test/test-mixedcontent-securityerrors.html new file mode 100644 index 000000000000..cb8cfdaaf57b --- /dev/null +++ b/browser/devtools/webconsole/test/test-mixedcontent-securityerrors.html @@ -0,0 +1,21 @@ + + + + + + + Mixed Content test - http on https + + + + + + + + diff --git a/browser/devtools/webconsole/webconsole.js b/browser/devtools/webconsole/webconsole.js index 752e496f720e..61b5a4db6aca 100644 --- a/browser/devtools/webconsole/webconsole.js +++ b/browser/devtools/webconsole/webconsole.js @@ -1446,21 +1446,36 @@ WebConsoleFrame.prototype = { */ addMoreInfoLink: function WCF_addMoreInfoLink(aNode, aScriptError) { - // We have a single category for now, but more are to be - // expected soon + let url; if (aScriptError.category == "Insecure Password Field") { - this.addInsecurePasswordsWarningNode(aNode); + url = INSECURE_PASSWORDS_LEARN_MORE; } + else if (aScriptError.category == "Mixed Content Message" || + aScriptError.category == "Mixed Content Blocker") { + url = MIXED_CONTENT_LEARN_MORE; + } + else { + // Unknown category. Return without adding more info node. + return; + } + + this.addLearnMoreWarningNode(aNode, url); }, /* - * Appends a clickable insecure passwords warning node to the node passed + * Appends a clickable warning node to the node passed * as a parameter to the function. When a user clicks on the appended - * warning node, the browser navigates to a page where the user can learn - * more about security issues associated with insecure passwords. + * warning node, the browser navigates to the provided url. + * + * @param aNode + * The node to which we will be adding a clickable warning node. + * @param aURL + * The url which points to the page where the user can learn more + * about security issues associated with the specific message that's + * being logged. */ - addInsecurePasswordsWarningNode: - function WCF_addInsecurePasswordsWarningNode(aNode) + addLearnMoreWarningNode: + function WCF_addLearnMoreWarningNode(aNode, aURL) { let moreInfoLabel = "[" + l10n.getStr("webConsoleMoreInfoLabel") + "]"; @@ -1472,7 +1487,7 @@ WebConsoleFrame.prototype = { linkNode.classList.add("webconsole-msg-link"); aNode.appendChild(linkNode); - // Create the actual insecure passwords warning node and make it clickable + // Create the actual warning node and make it clickable let warningNode = this.document.createElement("label"); warningNode.setAttribute("value", moreInfoLabel); warningNode.setAttribute("title", moreInfoLabel); @@ -1480,7 +1495,7 @@ WebConsoleFrame.prototype = { warningNode.classList.add("webconsole-learn-more-link"); warningNode.addEventListener("click", function(aEvent) { - this.owner.openLink(INSECURE_PASSWORDS_LEARN_MORE); + this.owner.openLink(aURL); aEvent.preventDefault(); aEvent.stopPropagation(); }.bind(this)); @@ -4547,6 +4562,7 @@ var Utils = { return CATEGORY_CSS; case "Mixed Content Blocker": + case "Mixed Content Message": case "CSP": case "Invalid HSTS Headers": case "Insecure Password Field": From f8985f80ad60ae1c2352d94200f889d880587f09 Mon Sep 17 00:00:00 2001 From: Ivan Alagenchev Date: Mon, 26 Aug 2013 11:27:00 -0400 Subject: [PATCH 10/85] Bug 875456 - DOM patch. Modifies Mixed Content Blocker, so that its messages are appropriately logged to the security console. r=bz --- content/base/src/nsMixedContentBlocker.cpp | 52 +++++++++++++++---- .../en-US/chrome/security/security.properties | 2 + 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/content/base/src/nsMixedContentBlocker.cpp b/content/base/src/nsMixedContentBlocker.cpp index 7dd519b62e32..203679a2d184 100644 --- a/content/base/src/nsMixedContentBlocker.cpp +++ b/content/base/src/nsMixedContentBlocker.cpp @@ -31,6 +31,11 @@ using namespace mozilla; +enum nsMixedContentBlockerMessageType { + eBlocked = 0x00, + eUserOverride = 0x01 +}; + // Is mixed script blocking (fonts, plugin content, scripts, stylesheets, // iframes, websockets, XHR) enabled? bool nsMixedContentBlocker::sBlockMixedScript = false; @@ -147,22 +152,42 @@ nsMixedContentBlocker::~nsMixedContentBlocker() NS_IMPL_ISUPPORTS1(nsMixedContentBlocker, nsIContentPolicy) -void -LogBlockingMixedContent(MixedContentTypes classification, - nsIURI* aContentLocation, - nsIDocument* aRootDoc) +static void +LogMixedContentMessage(MixedContentTypes aClassification, + nsIURI* aContentLocation, + nsIDocument* aRootDoc, + nsMixedContentBlockerMessageType aMessageType) { + nsAutoCString messageCategory; + uint32_t severityFlag; + nsAutoCString messageLookupKey; + + if (aMessageType == eBlocked) { + severityFlag = nsIScriptError::errorFlag; + messageCategory.AssignLiteral("Mixed Content Blocker"); + if (aClassification == eMixedDisplay) { + messageLookupKey.AssignLiteral("BlockMixedDisplayContent"); + } else { + messageLookupKey.AssignLiteral("BlockMixedActiveContent"); + } + } else { + severityFlag = nsIScriptError::warningFlag; + messageCategory.AssignLiteral("Mixed Content Message"); + if (aClassification == eMixedDisplay) { + messageLookupKey.AssignLiteral("LoadingMixedDisplayContent"); + } else { + messageLookupKey.AssignLiteral("LoadingMixedActiveContent"); + } + } + nsAutoCString locationSpec; aContentLocation->GetSpec(locationSpec); NS_ConvertUTF8toUTF16 locationSpecUTF16(locationSpec); const PRUnichar* strings[] = { locationSpecUTF16.get() }; - nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, - NS_LITERAL_CSTRING("Mixed Content Blocker"), - aRootDoc, + nsContentUtils::ReportToConsole(severityFlag, messageCategory, aRootDoc, nsContentUtils::eSECURITY_PROPERTIES, - classification == eMixedDisplay ? "BlockMixedDisplayContent" : "BlockMixedActiveContent", - strings, ArrayLength(strings)); + messageLookupKey.get(), strings, ArrayLength(strings)); } NS_IMETHODIMP @@ -453,6 +478,7 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType, // If the content is display content, and the pref says display content should be blocked, block it. if (sBlockMixedDisplay && classification == eMixedDisplay) { if (allowMixedContent) { + LogMixedContentMessage(classification, aContentLocation, rootDoc, eUserOverride); *aDecision = nsIContentPolicy::ACCEPT; rootDoc->SetHasMixedActiveContentLoaded(true); if (!rootDoc->GetHasMixedDisplayContentLoaded() && NS_SUCCEEDED(stateRV)) { @@ -460,7 +486,7 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType, } } else { *aDecision = nsIContentPolicy::REJECT_REQUEST; - LogBlockingMixedContent(classification, aContentLocation, rootDoc); + LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked); if (!rootDoc->GetHasMixedDisplayContentBlocked() && NS_SUCCEEDED(stateRV)) { eventSink->OnSecurityChange(aRequestingContext, (State | nsIWebProgressListener::STATE_BLOCKED_MIXED_DISPLAY_CONTENT)); } @@ -471,6 +497,7 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType, // If the content is active content, and the pref says active content should be blocked, block it // unless the user has choosen to override the pref if (allowMixedContent) { + LogMixedContentMessage(classification, aContentLocation, rootDoc, eUserOverride); *aDecision = nsIContentPolicy::ACCEPT; // See if the pref will change here. If it will, only then do we need to call OnSecurityChange() to update the UI. if (rootDoc->GetHasMixedActiveContentLoaded()) { @@ -501,7 +528,7 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType, } else { //User has not overriden the pref by Disabling protection. Reject the request and update the security state. *aDecision = nsIContentPolicy::REJECT_REQUEST; - LogBlockingMixedContent(classification, aContentLocation, rootDoc); + LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked); // See if the pref will change here. If it will, only then do we need to call OnSecurityChange() to update the UI. if (rootDoc->GetHasMixedActiveContentBlocked()) { return NS_OK; @@ -519,6 +546,9 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType, } else { // The content is not blocked by the mixed content prefs. + // Log a message that we are loading mixed content. + LogMixedContentMessage(classification, aContentLocation, rootDoc, eUserOverride); + // Fire the event from a script runner as it is unsafe to run script // from within ShouldLoad nsContentUtils::AddScriptRunner( diff --git a/dom/locales/en-US/chrome/security/security.properties b/dom/locales/en-US/chrome/security/security.properties index f6b2ef502602..c8091807f63a 100644 --- a/dom/locales/en-US/chrome/security/security.properties +++ b/dom/locales/en-US/chrome/security/security.properties @@ -14,3 +14,5 @@ InvalidSTSHeaders=The site specified an invalid Strict-Transport-Security header InsecurePasswordsPresentOnPage=Password fields present on an insecure (http://) page. This is a security risk that allows user login credentials to be stolen. InsecureFormActionPasswordsPresent=Password fields present in a form with an insecure (http://) form action. This is a security risk that allows user login credentials to be stolen. InsecurePasswordsPresentOnIframe=Password fields present on an insecure (http://) iframe. This is a security risk that allows user login credentials to be stolen. +LoadingMixedActiveContent=Loading mixed (insecure) active content on a secure page "%1$S" +LoadingMixedDisplayContent=Loading mixed (insecure) display content on a secure page "%1$S" From a91c08b8d10586c9914b97af45543decb76cb808 Mon Sep 17 00:00:00 2001 From: Robert Bindar Date: Mon, 26 Aug 2013 11:27:28 -0400 Subject: [PATCH 11/85] Bug 905325 - about:networking tab auto-refresh, global refresh button. r=ttaubert --- toolkit/content/aboutNetworking.js | 49 ++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/toolkit/content/aboutNetworking.js b/toolkit/content/aboutNetworking.js index b8bc32ae0c71..1bfac7f246eb 100644 --- a/toolkit/content/aboutNetworking.js +++ b/toolkit/content/aboutNetworking.js @@ -12,6 +12,18 @@ const gDashboard = Cc['@mozilla.org/network/dashboard;1']. getService(Ci.nsIDashboard); const gPrefs = Cc["@mozilla.org/preferences-service;1"]. getService(Ci.nsIPrefService).getBranch("network."); +const gRequestNetworkingData = { + "http": gDashboard.requestHttpConnections, + "sockets": gDashboard.requestSockets, + "dns": gDashboard.requestDNSInfo, + "websockets": gDashboard.requestWebsocketConnections +}; +const gDashboardCallbacks = { + "http": displayHttp, + "sockets": displaySockets, + "dns": displayDns, + "websockets": displayWebsockets +}; const REFRESH_INTERVAL_MS = 3000; @@ -107,11 +119,13 @@ function displayWebsockets(data) { parent.replaceChild(new_cont, cont); } -function requestNetworkingData() { - gDashboard.requestSockets(displaySockets); - gDashboard.requestHttpConnections(displayHttp); - gDashboard.requestWebsocketConnections(displayWebsockets); - gDashboard.requestDNSInfo(displayDns); +function requestAllNetworkingData() { + for (let id in gRequestNetworkingData) + requestNetworkingDataForTab(id); +} + +function requestNetworkingDataForTab(id) { + gRequestNetworkingData[id](gDashboardCallbacks[id]); } function init() { @@ -122,12 +136,16 @@ function init() { document.getElementById("confpref").addEventListener("click", confirm); } - requestNetworkingData(); + requestAllNetworkingData(); - document.getElementById("autorefcheck").addEventListener("click", function() { + let autoRefresh = document.getElementById("autorefcheck"); + if (autoRefresh.checked) + setAutoRefreshInterval(autoRefresh); + + autoRefresh.addEventListener("click", function() { let refrButton = document.getElementById("refreshButton"); if (this.checked) { - this.interval = setInterval(requestNetworkingData, REFRESH_INTERVAL_MS); + setAutoRefreshInterval(this); refrButton.disabled = "disabled"; } else { clearInterval(this.interval); @@ -136,7 +154,7 @@ function init() { }); let refr = document.getElementById("refreshButton"); - refr.addEventListener("click", requestNetworkingData); + refr.addEventListener("click", requestAllNetworkingData); if (document.getElementById("autorefcheck").checked) refr.disabled = "disabled"; @@ -166,6 +184,19 @@ function show(button) { let current_button = document.querySelector(".selected"); current_button.classList.remove("selected"); button.classList.add("selected"); + + let autoRefresh = document.getElementById("autorefcheck"); + if (autoRefresh.checked) { + clearInterval(autoRefresh.interval); + setAutoRefreshInterval(autoRefresh); + } +} + +function setAutoRefreshInterval(checkBox) { + let active_tab = document.querySelector(".active"); + checkBox.interval = setInterval(function() { + requestNetworkingDataForTab(active_tab.id); + }, REFRESH_INTERVAL_MS); } window.addEventListener("DOMContentLoaded", function load() { From b772ac570e565de9ff444f610bc80fd7e8eda050 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Mon, 26 Aug 2013 11:27:49 -0400 Subject: [PATCH 12/85] Bug 907002 - Add restart_syscall to seccomp whitelist. r=kang --- security/sandbox/seccomp_filter.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/security/sandbox/seccomp_filter.h b/security/sandbox/seccomp_filter.h index 39e427a61c53..4e6a629ec946 100644 --- a/security/sandbox/seccomp_filter.h +++ b/security/sandbox/seccomp_filter.h @@ -83,6 +83,8 @@ ALLOW_SYSCALL(sigprocmask), \ /* Always last and always OK calls */ \ SECCOMP_WHITELIST_ADD \ + /* restart_syscall is called internally, generally when debugging */ \ + ALLOW_SYSCALL(restart_syscall), \ ALLOW_SYSCALL(exit_group), \ ALLOW_SYSCALL(exit) From c834c1d2bf0c17a27e23dc04088e22f08effce36 Mon Sep 17 00:00:00 2001 From: Mike Hordecki Date: Mon, 26 Aug 2013 11:28:26 -0400 Subject: [PATCH 13/85] Bug 908918 - Fix an XPConnect typo. r=bholley --- js/xpconnect/src/Sandbox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/xpconnect/src/Sandbox.cpp b/js/xpconnect/src/Sandbox.cpp index ea4ad7c13903..23326dc3fc05 100644 --- a/js/xpconnect/src/Sandbox.cpp +++ b/js/xpconnect/src/Sandbox.cpp @@ -1165,7 +1165,7 @@ GetPropFromOptions(JSContext *cx, HandleObject from, const char *name, MutableHa if (!JS_HasProperty(cx, from, name, found)) return NS_ERROR_INVALID_ARG; - if (found && !JS_GetProperty(cx, from, name, prop)) + if (*found && !JS_GetProperty(cx, from, name, prop)) return NS_ERROR_INVALID_ARG; return NS_OK; From 3bf51d9f3079a9eb5a92d9e122e3346f801c887d Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Fri, 23 Aug 2013 17:23:37 -0700 Subject: [PATCH 14/85] Bug 908942 - Fix some exact rooting hazards in dom; r=bz --- dom/base/WindowNamedPropertiesHandler.cpp | 2 +- dom/base/nsDOMClassInfo.cpp | 5 +++-- dom/base/nsHistory.cpp | 2 +- dom/base/nsHistory.h | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/dom/base/WindowNamedPropertiesHandler.cpp b/dom/base/WindowNamedPropertiesHandler.cpp index 8bdc150e40cb..32409f08745f 100644 --- a/dom/base/WindowNamedPropertiesHandler.cpp +++ b/dom/base/WindowNamedPropertiesHandler.cpp @@ -26,7 +26,7 @@ WindowNamedPropertiesHandler::getOwnPropertyDescriptor(JSContext* aCx, return true; } - JSObject* global = JS_GetGlobalForObject(aCx, aProxy); + JS::Rooted global(aCx, JS_GetGlobalForObject(aCx, aProxy)); nsresult rv = nsDOMClassInfo::ScriptSecurityManager()->CheckPropertyAccess(aCx, global, "Window", aId, diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 189e4dcc698c..0d1801909039 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -2190,12 +2190,13 @@ nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx, NS_IMETHODIMP nsWindowSH::PostCreatePrototype(JSContext* aCx, JSObject* aProto) { - nsresult rv = nsDOMClassInfo::PostCreatePrototype(aCx, aProto); + JS::Rooted proto(aCx, aProto); + + nsresult rv = nsDOMClassInfo::PostCreatePrototype(aCx, proto); NS_ENSURE_SUCCESS(rv, rv); // We should probably move this into the CreateInterfaceObjects for Window // once it is on WebIDL bindings. - JS::Rooted proto(aCx, aProto); WindowNamedPropertiesHandler::Install(aCx, proto); return NS_OK; } diff --git a/dom/base/nsHistory.cpp b/dom/base/nsHistory.cpp index f3cd4c69dc4c..f188678a207e 100644 --- a/dom/base/nsHistory.cpp +++ b/dom/base/nsHistory.cpp @@ -255,7 +255,7 @@ nsHistory::ReplaceState(JSContext* aCx, JS::Handle aData, } void -nsHistory::PushOrReplaceState(JSContext* aCx, JS::Value aData, +nsHistory::PushOrReplaceState(JSContext* aCx, JS::Handle aData, const nsAString& aTitle, const nsAString& aUrl, ErrorResult& aRv, bool aReplace) { diff --git a/dom/base/nsHistory.h b/dom/base/nsHistory.h index 61862548ffe9..7653ef8fd678 100644 --- a/dom/base/nsHistory.h +++ b/dom/base/nsHistory.h @@ -56,7 +56,7 @@ protected: return win->GetDocShell(); } - void PushOrReplaceState(JSContext* aCx, JS::Value aData, + void PushOrReplaceState(JSContext* aCx, JS::Handle aData, const nsAString& aTitle, const nsAString& aUrl, mozilla::ErrorResult& aRv, bool aReplace); From af70a91e1698edc60cc4ff748c53d67018c41c93 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Fri, 16 Aug 2013 16:39:22 -0400 Subject: [PATCH 15/85] bug 908347 - rm nsIElementObserver r=mrbkap --- .../html/document/src/nsHTMLContentSink.cpp | 1 - parser/htmlparser/public/moz.build | 1 - parser/htmlparser/public/nsIElementObserver.h | 46 ------------------- parser/htmlparser/public/nsIParserService.h | 1 - 4 files changed, 49 deletions(-) delete mode 100644 parser/htmlparser/public/nsIElementObserver.h diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index 29df82557c75..c3833091c2e9 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -77,7 +77,6 @@ #include "nsIDocShellTreeItem.h" #include "nsEscape.h" -#include "nsIElementObserver.h" #include "nsNodeInfoManager.h" #include "nsContentCreatorFunctions.h" #include "mozAutoDocUpdate.h" diff --git a/parser/htmlparser/public/moz.build b/parser/htmlparser/public/moz.build index 265364d48e78..924679a795bb 100644 --- a/parser/htmlparser/public/moz.build +++ b/parser/htmlparser/public/moz.build @@ -16,7 +16,6 @@ EXPORTS += [ 'nsHTMLTags.h', 'nsIContentSink.h', 'nsIDTD.h', - 'nsIElementObserver.h', 'nsIFragmentContentSink.h', 'nsIHTMLContentSink.h', 'nsIParser.h', diff --git a/parser/htmlparser/public/nsIElementObserver.h b/parser/htmlparser/public/nsIElementObserver.h deleted file mode 100644 index 880fc2ae4624..000000000000 --- a/parser/htmlparser/public/nsIElementObserver.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - -/** - * MODULE NOTES: - * @update rickg 03.23.2000 //removed unused NS_PARSER_SUBJECT and predecl of nsString - * - */ - -#ifndef nsIElementObserver_h__ -#define nsIElementObserver_h__ - -#include "nsISupports.h" -#include "prtypes.h" -#include "nsHTMLTags.h" -#include "nsTArray.h" - - -// {4672AA04-F6AE-11d2-B3B7-00805F8A6670} -#define NS_IELEMENTOBSERVER_IID \ -{ 0x4672aa04, 0xf6ae, 0x11d2, { 0xb3, 0xb7, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70 } } - - -class nsIElementObserver : public nsISupports { -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_IELEMENTOBSERVER_IID) - - enum { IS_DOCUMENT_WRITE = 1U }; - - /* Subject call observer when the parser hit the tag */ - NS_IMETHOD Notify(nsISupports* aDocShell, - nsISupports* aChannel, - const PRUnichar* aTag, - const nsTArray* aKeys, - const nsTArray* aValues, - const uint32_t aFlags) = 0; - -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsIElementObserver, NS_IELEMENTOBSERVER_IID) - -#endif /* nsIElementObserver_h__ */ - diff --git a/parser/htmlparser/public/nsIParserService.h b/parser/htmlparser/public/nsIParserService.h index 18c0b309b48c..c6ce658b27db 100644 --- a/parser/htmlparser/public/nsIParserService.h +++ b/parser/htmlparser/public/nsIParserService.h @@ -9,7 +9,6 @@ #include "nsISupports.h" #include "nsStringGlue.h" #include "nsHTMLTags.h" -#include "nsIElementObserver.h" class nsIParser; class nsIParserNode; From aa32c27fa612f339b280a69408af37d199516dc4 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Fri, 16 Aug 2013 17:29:04 -0400 Subject: [PATCH 16/85] bug 908347 - rm useless includes in nsToken.h r=mrbkap --- parser/htmlparser/public/nsToken.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/parser/htmlparser/public/nsToken.h b/parser/htmlparser/public/nsToken.h index a46474da5605..6221aca57a00 100644 --- a/parser/htmlparser/public/nsToken.h +++ b/parser/htmlparser/public/nsToken.h @@ -6,13 +6,6 @@ #ifndef CTOKEN__ #define CTOKEN__ -#include "prtypes.h" -#include "nsString.h" -#include "nsError.h" - -class nsScanner; -class nsTokenAllocator; - enum eHTMLTokenTypes { eToken_unknown=0, eToken_start=1, eToken_end, eToken_comment, eToken_entity, From fa4593394a78b6f08359935004bb8ee9f348fda5 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Fri, 16 Aug 2013 19:51:58 -0400 Subject: [PATCH 17/85] bug 908347 - remove HTMLContentSink::AddAttribute() r=mrbkap the first thing it does is to return if nsIParserNode.GetAttributeCount() returned 0 which the one impl always does, so its all dead code we can remove. --- .../html/document/src/nsHTMLContentSink.cpp | 107 +----------------- 1 file changed, 2 insertions(+), 105 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index c3833091c2e9..d285f2670da5 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -180,11 +180,6 @@ public: #endif protected: - // If aCheckIfPresent is true, will only set an attribute in cases - // when it's not already set. - nsresult AddAttributes(const nsIParserNode& aNode, nsIContent* aContent, - bool aNotify = false, - bool aCheckIfPresent = false); already_AddRefed CreateContentObject(const nsIParserNode& aNode, nsHTMLTag aNodeType); @@ -333,91 +328,6 @@ HTMLContentSink::SinkTraceNode(uint32_t aBit, } #endif -nsresult -HTMLContentSink::AddAttributes(const nsIParserNode& aNode, - nsIContent* aContent, bool aNotify, - bool aCheckIfPresent) -{ - // Add tag attributes to the content attributes - - int32_t ac = aNode.GetAttributeCount(); - - if (ac == 0) { - // No attributes, nothing to do. Do an early return to avoid - // constructing the nsAutoString object for nothing. - - return NS_OK; - } - - nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType()); - - // The attributes are on the parser node in the order they came in in the - // source. What we want to happen if a single attribute is set multiple - // times on an element is that the first time should "win". That is, should show "foo". So we loop over the - // attributes backwards; this ensures that the first attribute in the set - // wins. This does mean that we do some extra work in the case when the same - // attribute is set multiple times, but we save a HasAttr call in the much - // more common case of reasonable HTML. Note that if aCheckIfPresent is set - // then we actually want to loop _forwards_ to preserve the "first attribute - // wins" behavior. That does mean that when aCheckIfPresent is set the order - // of attributes will get "reversed" from the point of view of the - // serializer. But aCheckIfPresent is only true for malformed documents with - // multiple , , or tags, so we're doing fixup anyway at - // that point. - - int32_t i, limit, step; - if (aCheckIfPresent) { - i = 0; - limit = ac; - step = 1; - } else { - i = ac - 1; - limit = -1; - step = -1; - } - - nsAutoString key; - for (; i != limit; i += step) { - // Get lower-cased key - nsresult rv = nsContentUtils::ASCIIToLower(aNode.GetKeyAt(i), key); - if (NS_FAILED(rv)) { - return rv; - } - - nsCOMPtr keyAtom = do_GetAtom(key); - - if (aCheckIfPresent && aContent->HasAttr(kNameSpaceID_None, keyAtom)) { - continue; - } - - // Get value and remove mandatory quotes - static const char* kWhitespace = "\n\r\t\b"; - - // Bug 114997: Don't trim whitespace on : - // Using ?: outside the function call would be more efficient, but - // we don't trust ?: with references. - const nsAString& v = - nsContentUtils::TrimCharsInSet( - (nodeType == eHTMLTag_input && - keyAtom == nsGkAtoms::value) ? - "" : kWhitespace, aNode.GetValueAt(i)); - - if (nodeType == eHTMLTag_a && keyAtom == nsGkAtoms::name) { - NS_ConvertUTF16toUTF8 cname(v); - NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting())); - - // Add attribute to content - aContent->SetAttr(kNameSpaceID_None, keyAtom, uv, aNotify); - } else { - // Add attribute to content - aContent->SetAttr(kNameSpaceID_None, keyAtom, v, aNotify); - } - } - - return NS_OK; -} - /** * Factory subroutine to create all of the html content objects. */ @@ -641,13 +551,7 @@ SinkContext::OpenContainer(const nsIParserNode& aNode) mStack[mStackPos].mNumFlushed = 0; mStack[mStackPos].mInsertionPoint = -1; ++mStackPos; - - rv = mSink->AddAttributes(aNode, content); - mStack[mStackPos - 2].Add(content); - - NS_ENSURE_SUCCESS(rv, rv); - if (mSink->IsMonolithicContainer(nodeType)) { mSink->mInMonolithicContainer++; } @@ -829,9 +733,6 @@ SinkContext::AddLeaf(const nsIParserNode& aNode) mSink->CreateContentObject(aNode, nodeType); NS_ENSURE_TRUE(content, NS_ERROR_OUT_OF_MEMORY); - rv = mSink->AddAttributes(aNode, content); - NS_ENSURE_SUCCESS(rv, rv); - // Add new leaf to its parent AddLeaf(content); @@ -1614,9 +1515,8 @@ HTMLContentSink::OpenBody(const nsIParserNode& aNode) CloseHeadContext(); // do this just in case if the HEAD was left open! - // Add attributes, if any, to the current BODY node + // if we already have a body we're done if (mBody) { - AddAttributes(aNode, mBody, true, true); return NS_OK; } @@ -1714,7 +1614,6 @@ HTMLContentSink::OpenContainer(const nsIParserNode& aNode) case eHTMLTag_head: rv = OpenHeadContext(); if (NS_SUCCEEDED(rv)) { - rv = AddAttributes(aNode, mHead, true, mHaveSeenHead); mHaveSeenHead = true; } break; @@ -1723,9 +1622,7 @@ HTMLContentSink::OpenContainer(const nsIParserNode& aNode) break; case eHTMLTag_html: if (mRoot) { - // If we've already hit this code once, need to check for - // already-present attributes on the root. - AddAttributes(aNode, mRoot, true, mNotifiedRootInsertion); + // If we've already hit this code once, then we're done if (!mNotifiedRootInsertion) { NotifyRootInsertion(); } From a044a3c0f1b0cdef188d6be6673ab444796e27b9 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Fri, 16 Aug 2013 20:29:23 -0400 Subject: [PATCH 18/85] bug 908347 - CreateContentObject() doesn't need a parser node r=mrbkap --- content/html/document/src/nsHTMLContentSink.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index d285f2670da5..3c217d833819 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -181,7 +181,7 @@ public: protected: already_AddRefed - CreateContentObject(const nsIParserNode& aNode, nsHTMLTag aNodeType); + CreateContentObject(nsHTMLTag aNodeType); #ifdef DEBUG void SinkTraceNode(uint32_t aBit, @@ -332,8 +332,7 @@ HTMLContentSink::SinkTraceNode(uint32_t aBit, * Factory subroutine to create all of the html content objects. */ already_AddRefed -HTMLContentSink::CreateContentObject(const nsIParserNode& aNode, - nsHTMLTag aNodeType) +HTMLContentSink::CreateContentObject(nsHTMLTag aNodeType) { // Find/create atom for the tag name @@ -541,7 +540,7 @@ SinkContext::OpenContainer(const nsIParserNode& aNode) // Create new container content object nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType()); nsGenericHTMLElement* content = - mSink->CreateContentObject(aNode, nodeType).get(); + mSink->CreateContentObject(nodeType).get(); if (!content) { return NS_ERROR_OUT_OF_MEMORY; } @@ -730,7 +729,7 @@ SinkContext::AddLeaf(const nsIParserNode& aNode) // Create new leaf content object nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType()); nsRefPtr content = - mSink->CreateContentObject(aNode, nodeType); + mSink->CreateContentObject(nodeType); NS_ENSURE_TRUE(content, NS_ERROR_OUT_OF_MEMORY); // Add new leaf to its parent From 821f912748131271cf672b518bcb43f291ef6b1c Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Fri, 16 Aug 2013 20:45:39 -0400 Subject: [PATCH 19/85] bug 908347 - SinkContext::OpenContainer() only needs a tag r=mrbkap --- .../html/document/src/nsHTMLContentSink.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index 3c217d833819..575855e6e80d 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -251,7 +251,7 @@ public: nsresult Begin(nsHTMLTag aNodeType, nsGenericHTMLElement* aRoot, uint32_t aNumFlushed, int32_t aInsertionPoint); - nsresult OpenContainer(const nsIParserNode& aNode); + nsresult OpenContainer(nsHTMLTag aNodeType); nsresult CloseContainer(const nsHTMLTag aTag); nsresult AddLeaf(const nsIParserNode& aNode); nsresult AddLeaf(nsIContent* aContent); @@ -513,13 +513,13 @@ SinkContext::DidAddContent(nsIContent* aContent) } nsresult -SinkContext::OpenContainer(const nsIParserNode& aNode) +SinkContext::OpenContainer(nsHTMLTag aNodeType) { FlushTextAndRelease(); SINK_TRACE_NODE(SINK_TRACE_CALLS, "SinkContext::OpenContainer", - nsHTMLTag(aNode.GetNodeType()), + aNodeType, mStackPos, mSink); @@ -538,25 +538,24 @@ SinkContext::OpenContainer(const nsIParserNode& aNode) } // Create new container content object - nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType()); nsGenericHTMLElement* content = - mSink->CreateContentObject(nodeType).get(); + mSink->CreateContentObject(aNodeType).get(); if (!content) { return NS_ERROR_OUT_OF_MEMORY; } - mStack[mStackPos].mType = nodeType; + mStack[mStackPos].mType = aNodeType; mStack[mStackPos].mContent = content; mStack[mStackPos].mNumFlushed = 0; mStack[mStackPos].mInsertionPoint = -1; ++mStackPos; mStack[mStackPos - 2].Add(content); - if (mSink->IsMonolithicContainer(nodeType)) { + if (mSink->IsMonolithicContainer(aNodeType)) { mSink->mInMonolithicContainer++; } // Special handling for certain tags - switch (nodeType) { + switch (aNodeType) { case eHTMLTag_form: MOZ_CRASH("Must not use HTMLContentSink for forms."); @@ -1519,7 +1518,7 @@ HTMLContentSink::OpenBody(const nsIParserNode& aNode) return NS_OK; } - nsresult rv = mCurrentContext->OpenContainer(aNode); + nsresult rv = mCurrentContext->OpenContainer(nsHTMLTag(aNode.GetNodeType())); if (NS_FAILED(rv)) { return rv; @@ -1632,7 +1631,7 @@ HTMLContentSink::OpenContainer(const nsIParserNode& aNode) MOZ_CRASH("Must not use HTMLContentSink for forms."); default: - rv = mCurrentContext->OpenContainer(aNode); + rv = mCurrentContext->OpenContainer(nsHTMLTag(aNode.GetNodeType())); break; } From dbec94e16bddd4030907f7779ec81f9ae62500e6 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Fri, 16 Aug 2013 21:00:33 -0400 Subject: [PATCH 20/85] bug 908347 - OpenBody() doesn't need a parser node r=mrbkap --- content/html/document/src/nsHTMLContentSink.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index 575855e6e80d..622b6c90e5a6 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -222,7 +222,7 @@ protected: // Routines for tags that require special handling nsresult CloseHTML(); - nsresult OpenBody(const nsIParserNode& aNode); + nsresult OpenBody(nsHTMLTag aNodeType); nsresult CloseBody(); nsresult OpenHeadContext(); @@ -1503,7 +1503,7 @@ HTMLContentSink::OpenHead() } nsresult -HTMLContentSink::OpenBody(const nsIParserNode& aNode) +HTMLContentSink::OpenBody(nsHTMLTag aNodeType) { SINK_TRACE_NODE(SINK_TRACE_CALLS, "HTMLContentSink::OpenBody", @@ -1518,7 +1518,7 @@ HTMLContentSink::OpenBody(const nsIParserNode& aNode) return NS_OK; } - nsresult rv = mCurrentContext->OpenContainer(nsHTMLTag(aNode.GetNodeType())); + nsresult rv = mCurrentContext->OpenContainer(aNodeType); if (NS_FAILED(rv)) { return rv; @@ -1616,7 +1616,7 @@ HTMLContentSink::OpenContainer(const nsIParserNode& aNode) } break; case eHTMLTag_body: - rv = OpenBody(aNode); + rv = OpenBody(nsHTMLTag(aNode.GetNodeType())); break; case eHTMLTag_html: if (mRoot) { From c44bd619307e6620ea00cdabb0e8e50675ba4d0b Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Fri, 16 Aug 2013 21:20:57 -0400 Subject: [PATCH 21/85] bug 908347 - HTMLContentSink::OpenContainer() doesn't need a parser node either r=mrbkap --- content/html/document/src/nsHTMLContentSink.cpp | 10 +++++----- parser/htmlparser/public/nsIHTMLContentSink.h | 2 +- parser/htmlparser/src/CNavDTD.cpp | 7 ++----- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index 622b6c90e5a6..6669ff50dccf 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -162,7 +162,7 @@ public: virtual bool IsScriptExecuting(); // nsIHTMLContentSink - NS_IMETHOD OpenContainer(const nsIParserNode& aNode); + NS_IMETHOD OpenContainer(nsHTMLTag aNodeType); NS_IMETHOD CloseContainer(const nsHTMLTag aTag); NS_IMETHOD CloseMalformedContainer(const nsHTMLTag aTag); NS_IMETHOD AddLeaf(const nsIParserNode& aNode); @@ -1601,11 +1601,11 @@ HTMLContentSink::IsEnabled(int32_t aTag, bool* aReturn) } NS_IMETHODIMP -HTMLContentSink::OpenContainer(const nsIParserNode& aNode) +HTMLContentSink::OpenContainer(nsHTMLTag aNodeType) { nsresult rv = NS_OK; - switch (aNode.GetNodeType()) { + switch (aNodeType) { case eHTMLTag_frameset: MOZ_CRASH("Must not use HTMLContentSink for frames."); @@ -1616,7 +1616,7 @@ HTMLContentSink::OpenContainer(const nsIParserNode& aNode) } break; case eHTMLTag_body: - rv = OpenBody(nsHTMLTag(aNode.GetNodeType())); + rv = OpenBody(aNodeType); break; case eHTMLTag_html: if (mRoot) { @@ -1631,7 +1631,7 @@ HTMLContentSink::OpenContainer(const nsIParserNode& aNode) MOZ_CRASH("Must not use HTMLContentSink for forms."); default: - rv = mCurrentContext->OpenContainer(nsHTMLTag(aNode.GetNodeType())); + rv = mCurrentContext->OpenContainer(aNodeType); break; } diff --git a/parser/htmlparser/public/nsIHTMLContentSink.h b/parser/htmlparser/public/nsIHTMLContentSink.h index a29b84522b91..f4694ddcc406 100644 --- a/parser/htmlparser/public/nsIHTMLContentSink.h +++ b/parser/htmlparser/public/nsIHTMLContentSink.h @@ -126,7 +126,7 @@ public: * @update 4/1/98 gess * @param nsIParserNode reference to parser node interface */ - NS_IMETHOD OpenContainer(const nsIParserNode& aNode) = 0; + NS_IMETHOD OpenContainer(nsHTMLTag aNodeType) = 0; /** * This method gets called by the parser when a close diff --git a/parser/htmlparser/src/CNavDTD.cpp b/parser/htmlparser/src/CNavDTD.cpp index 2c66cda3f83d..adfae201c7d1 100644 --- a/parser/htmlparser/src/CNavDTD.cpp +++ b/parser/htmlparser/src/CNavDTD.cpp @@ -42,12 +42,9 @@ CNavDTD::BuildModel(nsITokenizer* aTokenizer, return NS_ERROR_HTMLPARSER_STOPPARSING; } - nsParserNode html(eHTMLTag_html); - nsParserNode body(eHTMLTag_body); - - nsresult rv = sink->OpenContainer(html); + nsresult rv = sink->OpenContainer(eHTMLTag_html); NS_ENSURE_SUCCESS(rv, rv); - rv = sink->OpenContainer(body); + rv = sink->OpenContainer(eHTMLTag_body); NS_ENSURE_SUCCESS(rv, rv); rv = sink->CloseContainer(eHTMLTag_body); From 3eec5c14680c3338bab7ae08c2f20d612065125e Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Fri, 16 Aug 2013 22:02:26 -0400 Subject: [PATCH 22/85] bug 908347 - rm the bits of nsIHTMLContentSink nobody calls r=mrbkap --- .../html/document/src/nsHTMLContentSink.cpp | 217 +----------------- parser/htmlparser/public/nsIHTMLContentSink.h | 72 +----- 2 files changed, 2 insertions(+), 287 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index 6669ff50dccf..f962e3abe752 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -162,17 +162,9 @@ public: virtual bool IsScriptExecuting(); // nsIHTMLContentSink + NS_IMETHOD IsEnabled(int32_t, bool*); NS_IMETHOD OpenContainer(nsHTMLTag aNodeType); NS_IMETHOD CloseContainer(const nsHTMLTag aTag); - NS_IMETHOD CloseMalformedContainer(const nsHTMLTag aTag); - NS_IMETHOD AddLeaf(const nsIParserNode& aNode); - NS_IMETHOD DidProcessTokens(void); - NS_IMETHOD WillProcessAToken(void); - NS_IMETHOD DidProcessAToken(void); - NS_IMETHOD BeginContext(int32_t aID); - NS_IMETHOD EndContext(int32_t aID); - NS_IMETHOD OpenHead(); - NS_IMETHOD IsEnabled(int32_t aTag, bool* aReturn); #ifdef DEBUG // nsIDebugDumpContent @@ -253,7 +245,6 @@ public: uint32_t aNumFlushed, int32_t aInsertionPoint); nsresult OpenContainer(nsHTMLTag aNodeType); nsresult CloseContainer(const nsHTMLTag aTag); - nsresult AddLeaf(const nsIParserNode& aNode); nsresult AddLeaf(nsIContent* aContent); nsresult End(); @@ -710,66 +701,6 @@ SinkContext::CloseContainer(const nsHTMLTag aTag) return result; } -nsresult -SinkContext::AddLeaf(const nsIParserNode& aNode) -{ - SINK_TRACE_NODE(SINK_TRACE_CALLS, - "SinkContext::AddLeaf", - nsHTMLTag(aNode.GetNodeType()), - mStackPos, mSink); - - nsresult rv = NS_OK; - - switch (aNode.GetTokenType()) { - case eToken_start: - { - FlushTextAndRelease(); - - // Create new leaf content object - nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType()); - nsRefPtr content = - mSink->CreateContentObject(nodeType); - NS_ENSURE_TRUE(content, NS_ERROR_OUT_OF_MEMORY); - - // Add new leaf to its parent - AddLeaf(content); - - // Additional processing needed once the element is in the tree - switch (nodeType) { - case eHTMLTag_meta: - MOZ_CRASH("Must not use HTMLContentSink for metas."); - - case eHTMLTag_input: - content->DoneCreatingElement(); - break; - - case eHTMLTag_menuitem: - content->DoneCreatingElement(); - break; - - default: - break; - } - } - break; - - case eToken_text: - case eToken_whitespace: - case eToken_newline: - MOZ_CRASH(); - - break; - case eToken_entity: - MOZ_CRASH(); - - break; - default: - break; - } - - return rv; -} - nsresult SinkContext::AddLeaf(nsIContent* aContent) { @@ -1372,102 +1303,6 @@ HTMLContentSink::SetParser(nsParserBase* aParser) return NS_OK; } -NS_IMETHODIMP -HTMLContentSink::BeginContext(int32_t aPosition) -{ - NS_PRECONDITION(aPosition > -1, "out of bounds"); - - if (!mCurrentContext) { - NS_ERROR("Nonexistent context"); - - return NS_ERROR_FAILURE; - } - - // Flush everything in the current context so that we don't have - // to worry about insertions resulting in inconsistent frame creation. - mCurrentContext->FlushTags(); - - // Sanity check. - if (mCurrentContext->mStackPos <= aPosition) { - NS_ERROR("Out of bounds position"); - return NS_ERROR_FAILURE; - } - - int32_t insertionPoint = -1; - nsHTMLTag nodeType = mCurrentContext->mStack[aPosition].mType; - nsGenericHTMLElement* content = mCurrentContext->mStack[aPosition].mContent; - - // If the content under which the new context is created - // has a child on the stack, the insertion point is - // before the last child. - if (aPosition < (mCurrentContext->mStackPos - 1)) { - insertionPoint = content->GetChildCount() - 1; - } - - SinkContext* sc = new SinkContext(this); - sc->Begin(nodeType, - content, - mCurrentContext->mStack[aPosition].mNumFlushed, - insertionPoint); - NS_ADDREF(sc->mSink); - - mContextStack.AppendElement(mCurrentContext); - mCurrentContext = sc; - return NS_OK; -} - -NS_IMETHODIMP -HTMLContentSink::EndContext(int32_t aPosition) -{ - NS_PRECONDITION(mCurrentContext && aPosition > -1, "nonexistent context"); - - uint32_t n = mContextStack.Length() - 1; - SinkContext* sc = mContextStack.ElementAt(n); - - const SinkContext::Node &bottom = mCurrentContext->mStack[0]; - - NS_ASSERTION(sc->mStack[aPosition].mType == bottom.mType, - "ending a wrong context"); - - mCurrentContext->FlushTextAndRelease(); - - NS_ASSERTION(bottom.mContent->GetChildCount() == bottom.mNumFlushed, - "Node at base of context stack not fully flushed."); - - // Flushing tags before the assertion on the previous line would - // undoubtedly prevent the assertion from failing, but it shouldn't - // be failing anyway, FlushTags or no. Flushing here is nevertheless - // a worthwhile precaution, since we lose some information (e.g., - // mInsertionPoints) when we end the current context. - mCurrentContext->FlushTags(); - - sc->mStack[aPosition].mNumFlushed = bottom.mNumFlushed; - - for (int32_t i = 0; imStackPos; i++) { - NS_IF_RELEASE(mCurrentContext->mStack[i].mContent); - } - - delete [] mCurrentContext->mStack; - - mCurrentContext->mStack = nullptr; - mCurrentContext->mStackPos = 0; - mCurrentContext->mStackSize = 0; - - delete [] mCurrentContext->mText; - - mCurrentContext->mText = nullptr; - mCurrentContext->mTextLength = 0; - mCurrentContext->mTextSize = 0; - - NS_IF_RELEASE(mCurrentContext->mSink); - - delete mCurrentContext; - - mCurrentContext = sc; - mContextStack.RemoveElementAt(n); - return NS_OK; -} - nsresult HTMLContentSink::CloseHTML() { @@ -1495,13 +1330,6 @@ HTMLContentSink::CloseHTML() return NS_OK; } -nsresult -HTMLContentSink::OpenHead() -{ - nsresult rv = OpenHeadContext(); - return rv; -} - nsresult HTMLContentSink::OpenBody(nsHTMLTag aNodeType) { @@ -1667,49 +1495,6 @@ HTMLContentSink::CloseContainer(const eHTMLTags aTag) return rv; } -NS_IMETHODIMP -HTMLContentSink::CloseMalformedContainer(const eHTMLTags aTag) -{ - return mCurrentContext->CloseContainer(aTag); -} - -NS_IMETHODIMP -HTMLContentSink::AddLeaf(const nsIParserNode& aNode) -{ - nsresult rv; - - nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType()); - switch (nodeType) { - case eHTMLTag_link: - MOZ_CRASH("Must not use HTMLContentSink for links."); - - default: - rv = mCurrentContext->AddLeaf(aNode); - - break; - } - - return rv; -} - -NS_IMETHODIMP -HTMLContentSink::DidProcessTokens(void) -{ - return NS_OK; -} - -NS_IMETHODIMP -HTMLContentSink::WillProcessAToken(void) -{ - return NS_OK; -} - -NS_IMETHODIMP -HTMLContentSink::DidProcessAToken(void) -{ - return DidProcessATokenImpl(); -} - NS_IMETHODIMP HTMLContentSink::WillInterrupt() { diff --git a/parser/htmlparser/public/nsIHTMLContentSink.h b/parser/htmlparser/public/nsIHTMLContentSink.h index f4694ddcc406..4dc83f5fec42 100644 --- a/parser/htmlparser/public/nsIHTMLContentSink.h +++ b/parser/htmlparser/public/nsIHTMLContentSink.h @@ -54,8 +54,7 @@ #include "nsHTMLTags.h" #define NS_IHTML_CONTENT_SINK_IID \ -{ 0xb6d6ae00, 0x0884, 0x4a30, \ - { 0xa8, 0xb4, 0xce, 0xca, 0x57, 0x27, 0x1a, 0x3e } } + {0xb08b0f29, 0xe61c, 0x4647, {0xaf, 0x1e, 0x05, 0x1a, 0x75, 0x2f, 0xe6, 0x3d}} /** * This interface is OBSOLETE and in the process of being REMOVED. @@ -67,59 +66,12 @@ public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_IHTML_CONTENT_SINK_IID) - /** - * This method is used to open the HEAD container. It is useful if a tag - * is forcing us to open the head (probably again), like if we find a - * tag in the body. - */ - NS_IMETHOD OpenHead() = 0; - - /** - * This gets called when handling illegal contents, especially - * in dealing with tables. This method creates a new context. - * - * @update 04/04/99 harishd - * @param aPosition - The position from where the new context begins. - */ - NS_IMETHOD BeginContext(int32_t aPosition) = 0; - - /** - * This method terminates any new context that got created by - * BeginContext and switches back to the main context. - * - * @update 04/04/99 harishd - * @param aPosition - Validates the end of a context. - */ - NS_IMETHOD EndContext(int32_t aPosition) = 0; - /** * @update 01/09/2003 harishd * @param aTag - Check if this tag is enabled or not. */ NS_IMETHOD IsEnabled(int32_t aTag, bool* aReturn) = 0; - /** - * This method is called when parser has - * completed processing a chunk of tokens. The processing of the - * tokens may be interrupted by returning NS_ERROR_HTMLPARSER_INTERRUPTED from - * DidProcessAToken. - */ - NS_IMETHOD DidProcessTokens() = 0; - - /** - * This method is called when parser is about to - * process a single token - */ - NS_IMETHOD WillProcessAToken(void) = 0; - - /** - * This method is called when parser has completed - * the processing for a single token. - * @return NS_OK if processing should not be interrupted - * NS_ERROR_HTMLPARSER_INTERRUPTED if the parsing should be interrupted - */ - NS_IMETHOD DidProcessAToken(void) = 0; - /** * This method is used to open a generic container in the sink. * @@ -135,28 +87,6 @@ public: * @param aTag - The tag to be closed. */ NS_IMETHOD CloseContainer(const nsHTMLTag aTag) = 0; - - /** - * This method is used when we're closing a tag that was malformed - * in some way. This way, the content sink can do special processing - * (e.g., not execute a malformed script tag). - * - * @param aTag The tag to be closed. - */ - NS_IMETHOD CloseMalformedContainer(const nsHTMLTag aTag) - { - return CloseContainer(aTag); - } - - /** - * This gets called by the parser when you want to add - * a leaf node to the current container in the content - * model. - * - * @update 4/1/98 gess - * @param nsIParserNode reference to parser node interface - */ - NS_IMETHOD AddLeaf(const nsIParserNode& aNode) = 0; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLContentSink, NS_IHTML_CONTENT_SINK_IID) From 39875cb047edf109af7b95e261b3d09506ebbba4 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Fri, 16 Aug 2013 22:19:32 -0400 Subject: [PATCH 23/85] bug 908347 - kill nsIParserNode r=mrbkap --- .../xml/document/public/nsIXMLContentSink.h | 1 - parser/htmlparser/public/moz.build | 1 - parser/htmlparser/public/nsIHTMLContentSink.h | 2 - parser/htmlparser/public/nsIParserNode.h | 78 -------------- parser/htmlparser/public/nsIParserService.h | 1 - parser/htmlparser/src/CNavDTD.cpp | 1 - parser/htmlparser/src/moz.build | 1 - parser/htmlparser/src/nsParser.h | 1 - parser/htmlparser/src/nsParserNode.cpp | 102 ------------------ parser/htmlparser/src/nsParserNode.h | 68 ------------ 10 files changed, 256 deletions(-) delete mode 100644 parser/htmlparser/public/nsIParserNode.h delete mode 100644 parser/htmlparser/src/nsParserNode.cpp delete mode 100644 parser/htmlparser/src/nsParserNode.h diff --git a/content/xml/document/public/nsIXMLContentSink.h b/content/xml/document/public/nsIXMLContentSink.h index a98a0b19a7be..4d39a561b368 100644 --- a/content/xml/document/public/nsIXMLContentSink.h +++ b/content/xml/document/public/nsIXMLContentSink.h @@ -6,7 +6,6 @@ #define nsIXMLContentSink_h___ #include "nsIContentSink.h" -#include "nsIParserNode.h" #include "nsISupports.h" class nsIDocument; diff --git a/parser/htmlparser/public/moz.build b/parser/htmlparser/public/moz.build index 924679a795bb..151b171c6751 100644 --- a/parser/htmlparser/public/moz.build +++ b/parser/htmlparser/public/moz.build @@ -19,7 +19,6 @@ EXPORTS += [ 'nsIFragmentContentSink.h', 'nsIHTMLContentSink.h', 'nsIParser.h', - 'nsIParserNode.h', 'nsIParserService.h', 'nsITokenizer.h', 'nsParserBase.h', diff --git a/parser/htmlparser/public/nsIHTMLContentSink.h b/parser/htmlparser/public/nsIHTMLContentSink.h index 4dc83f5fec42..d567ae2ca8d7 100644 --- a/parser/htmlparser/public/nsIHTMLContentSink.h +++ b/parser/htmlparser/public/nsIHTMLContentSink.h @@ -49,7 +49,6 @@ * NOTE: I haven't figured out how sub-documents (non-frames) * are going to be handled. Stay tuned. */ -#include "nsIParserNode.h" #include "nsIContentSink.h" #include "nsHTMLTags.h" @@ -76,7 +75,6 @@ public: * This method is used to open a generic container in the sink. * * @update 4/1/98 gess - * @param nsIParserNode reference to parser node interface */ NS_IMETHOD OpenContainer(nsHTMLTag aNodeType) = 0; diff --git a/parser/htmlparser/public/nsIParserNode.h b/parser/htmlparser/public/nsIParserNode.h deleted file mode 100644 index 057dfcc97ba7..000000000000 --- a/parser/htmlparser/public/nsIParserNode.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - -/** - * MODULE NOTES: - * @update gess 4/1/98 - * - * This class is defines the basic interface between the - * parser and the content sink. The parser will iterate - * over the collection of tokens that it sees from the - * tokenizer, coverting each related "group" into one of - * these. This object gets passed to the sink, and is - * then immediately reused. - * - * If you want to hang onto one of these, you should - * make your own copy. - * - */ - -#ifndef NS_IPARSERNODE__ -#define NS_IPARSERNODE__ - -#include "nsStringGlue.h" - -class nsIAtom; - -/** - * Parser nodes are the unit of exchange between the - * parser and the content sink. Nodes offer access to - * the current token, its attributes, and its skipped- - * content if applicable. - * - * @update gess 3/25/98 - */ -class nsIParserNode { - public: - /** - * Retrieve the type of the parser node. - * @update gess5/11/98 - * @return node type. - */ - virtual int32_t GetNodeType() const =0; - - /** - * Retrieve token type of parser node - * @update gess5/11/98 - * @return token type - */ - virtual int32_t GetTokenType() const =0; - - /** - * Retrieve the number of attributes in this node. - * @update gess5/11/98 - * @return count of attributes (may be 0) - */ - virtual int32_t GetAttributeCount() const =0; - - /** - * Retrieve the key (of key/value pair) at given index - * @update gess5/11/98 - * @param anIndex is the index of the key you want - * @return string containing key. - */ - virtual const nsAString& GetKeyAt(uint32_t anIndex) const = 0; - - /** - * Retrieve the value (of key/value pair) at given index - * @update gess5/11/98 - * @param anIndex is the index of the value you want - * @return string containing value. - */ - virtual const nsAString& GetValueAt(uint32_t anIndex) const = 0; -}; - -#endif diff --git a/parser/htmlparser/public/nsIParserService.h b/parser/htmlparser/public/nsIParserService.h index c6ce658b27db..a369cb852e8a 100644 --- a/parser/htmlparser/public/nsIParserService.h +++ b/parser/htmlparser/public/nsIParserService.h @@ -11,7 +11,6 @@ #include "nsHTMLTags.h" class nsIParser; -class nsIParserNode; #define NS_PARSERSERVICE_CONTRACTID "@mozilla.org/parser/parser-service;1" diff --git a/parser/htmlparser/src/CNavDTD.cpp b/parser/htmlparser/src/CNavDTD.cpp index adfae201c7d1..11ca9deeef35 100644 --- a/parser/htmlparser/src/CNavDTD.cpp +++ b/parser/htmlparser/src/CNavDTD.cpp @@ -11,7 +11,6 @@ #include "nsIParser.h" #include "CNavDTD.h" #include "nsIHTMLContentSink.h" -#include "nsParserNode.h" NS_IMPL_ISUPPORTS1(CNavDTD, nsIDTD); diff --git a/parser/htmlparser/src/moz.build b/parser/htmlparser/src/moz.build index ba2b514ae3f7..4b09c71a3d47 100644 --- a/parser/htmlparser/src/moz.build +++ b/parser/htmlparser/src/moz.build @@ -17,7 +17,6 @@ CPP_SOURCES += [ 'nsParser.cpp', 'nsParserModule.cpp', 'nsParserMsgUtils.cpp', - 'nsParserNode.cpp', 'nsParserService.cpp', 'nsScanner.cpp', 'nsScannerString.cpp', diff --git a/parser/htmlparser/src/nsParser.h b/parser/htmlparser/src/nsParser.h index 31a043190e42..ea4e4bd734a4 100644 --- a/parser/htmlparser/src/nsParser.h +++ b/parser/htmlparser/src/nsParser.h @@ -43,7 +43,6 @@ #include "nsIParser.h" #include "nsDeque.h" -#include "nsParserNode.h" #include "nsIURL.h" #include "CParserContext.h" #include "nsParserCIID.h" diff --git a/parser/htmlparser/src/nsParserNode.cpp b/parser/htmlparser/src/nsParserNode.cpp deleted file mode 100644 index 077e4227c1d8..000000000000 --- a/parser/htmlparser/src/nsParserNode.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - -#include "nsParserNode.h" -#include "nsToken.h" - -/** - * Constructor - * - * @update gess 3/25/98 - * @param aToken -- token to init internal token - * @return - */ -nsParserNode::nsParserNode(eHTMLTags aTag) - : mTag(aTag) -{ -} - -/** - * destructor - * NOTE: We intentionally DON'T recycle mToken here. - * It may get cached for use elsewhere - * @update gess 3/25/98 - * @param - * @return - */ -nsParserNode::~nsParserNode() { -} - - -/** - * Get node type, meaning, get the tag type of the - * underlying token - * - * @update gess 3/25/98 - * @param - * @return int value that represents tag type - */ -int32_t -nsParserNode::GetNodeType(void) const -{ - return mTag; -} - - -/** - * Gets the token type, which corresponds to a value from - * eHTMLTokens_xxx. - * - * @update gess 3/25/98 - * @param - * @return - */ -int32_t -nsParserNode::GetTokenType(void) const -{ - return eToken_start; -} - - -/** - * Retrieve the number of attributes on this node - * - * @update gess 3/25/98 - * @param - * @return int -- representing attribute count - */ -int32_t -nsParserNode::GetAttributeCount() const -{ - return 0; -} - -/** - * Retrieve the string rep of the attribute key at the - * given index. - * - * @update gess 3/25/98 - * @param anIndex-- offset of attribute to retrieve - * @return string rep of given attribute text key - */ -const nsAString& -nsParserNode::GetKeyAt(uint32_t anIndex) const -{ - return EmptyString(); -} - -/** - * Retrieve the string rep of the attribute at given offset - * - * @update gess 3/25/98 - * @param anIndex-- offset of attribute to retrieve - * @return string rep of given attribute text value - */ -const nsAString& -nsParserNode::GetValueAt(uint32_t anIndex) const -{ - return EmptyString(); -} diff --git a/parser/htmlparser/src/nsParserNode.h b/parser/htmlparser/src/nsParserNode.h deleted file mode 100644 index 04a7362032dc..000000000000 --- a/parser/htmlparser/src/nsParserNode.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef NS_PARSERNODE__ -#define NS_PARSERNODE__ - -#include "nscore.h" -#include "nsIParserNode.h" -#include "nsHTMLTags.h" - -class nsParserNode : public nsIParserNode -{ - public: - /** - * Constructor - */ - nsParserNode(eHTMLTags aTag); - - /** - * Destructor - */ - virtual ~nsParserNode(); - - /** - * Retrieve the type of the parser node. - * @return node type. - */ - virtual int32_t GetNodeType() const; - - /** - * Retrieve token type of parser node - * @return token type - */ - virtual int32_t GetTokenType() const; - - - //*************************************** - //methods for accessing key/value pairs - //*************************************** - - /** - * Retrieve the number of attributes in this node. - * @return 0 - */ - virtual int32_t GetAttributeCount() const; - - /** - * Retrieve the key (of key/value pair) at given index - * @param anIndex is the index of the key you want - * @return string containing key. - */ - virtual const nsAString& GetKeyAt(uint32_t anIndex) const; - - /** - * Retrieve the value (of key/value pair) at given index - * @update gess5/11/98 - * @param anIndex is the index of the value you want - * @return string containing value. - */ - virtual const nsAString& GetValueAt(uint32_t anIndex) const; - - private: - eHTMLTags mTag; -}; - -#endif From 6af92f981e5e3d2e8299a73c62aeabeb4873c6d2 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Sat, 17 Aug 2013 07:27:09 -0400 Subject: [PATCH 24/85] bug 908347 - gut nsHTMLTokenizer a bit more r=mrbkap --- parser/htmlparser/src/CParserContext.cpp | 7 +--- parser/htmlparser/src/nsHTMLTokenizer.cpp | 40 ++--------------------- parser/htmlparser/src/nsHTMLTokenizer.h | 15 ++------- 3 files changed, 6 insertions(+), 56 deletions(-) diff --git a/parser/htmlparser/src/CParserContext.cpp b/parser/htmlparser/src/CParserContext.cpp index a321a6d348e2..7c69bd98ff6d 100644 --- a/parser/htmlparser/src/CParserContext.cpp +++ b/parser/htmlparser/src/CParserContext.cpp @@ -73,12 +73,7 @@ CParserContext::GetTokenizer(nsIDTD* aDTD, if (!mTokenizer) { if (type == NS_IPARSER_FLAG_HTML || mParserCommand == eViewSource) { - nsCOMPtr theSink = do_QueryInterface(aSink); - mTokenizer = new nsHTMLTokenizer(mDTDMode, mDocType, mParserCommand, - nsHTMLTokenizer::GetFlags(aSink)); - if (!mTokenizer) { - return NS_ERROR_OUT_OF_MEMORY; - } + mTokenizer = new nsHTMLTokenizer; } else if (type == NS_IPARSER_FLAG_XML) { mTokenizer = do_QueryInterface(aDTD, &result); diff --git a/parser/htmlparser/src/nsHTMLTokenizer.cpp b/parser/htmlparser/src/nsHTMLTokenizer.cpp index f86dcedfbb99..5b55a1530218 100644 --- a/parser/htmlparser/src/nsHTMLTokenizer.cpp +++ b/parser/htmlparser/src/nsHTMLTokenizer.cpp @@ -14,10 +14,9 @@ * "tokenization" takes place in nsHTMLTokens.cpp. */ -#include "nsIAtom.h" #include "nsHTMLTokenizer.h" +#include "nsIParser.h" #include "nsParserConstants.h" -#include "nsIHTMLContentSink.h" /************************************************************************ And now for the main class -- nsHTMLTokenizer... @@ -30,45 +29,10 @@ NS_IMPL_ISUPPORTS1(nsHTMLTokenizer, nsITokenizer) /** * Default constructor - * - * @param aParseMode The current mode the document is in (quirks, etc.) - * @param aDocType The document type of the current document - * @param aCommand What we are trying to do (view-source, parse a fragment, etc.) */ -nsHTMLTokenizer::nsHTMLTokenizer(nsDTDMode aParseMode, - eParserDocType aDocType, - eParserCommands aCommand, - uint32_t aFlags) +nsHTMLTokenizer::nsHTMLTokenizer() { // TODO Assert about:blank-ness. - MOZ_ASSERT(!(aFlags & NS_IPARSER_FLAG_XML)); -} - -/** - * The destructor ensures that we don't leak any left over tokens. - */ -nsHTMLTokenizer::~nsHTMLTokenizer() -{ -} - -/*static*/ uint32_t -nsHTMLTokenizer::GetFlags(const nsIContentSink* aSink) -{ - uint32_t flags = 0; - nsCOMPtr sink = - do_QueryInterface(const_cast(aSink)); - if (sink) { - bool enabled = true; - sink->IsEnabled(eHTMLTag_frameset, &enabled); - if (enabled) { - flags |= NS_IPARSER_FLAG_FRAMES_ENABLED; - } - sink->IsEnabled(eHTMLTag_script, &enabled); - if (enabled) { - flags |= NS_IPARSER_FLAG_SCRIPT_ENABLED; - } - } - return flags; } nsresult diff --git a/parser/htmlparser/src/nsHTMLTokenizer.h b/parser/htmlparser/src/nsHTMLTokenizer.h index 201163448623..4153dc8da494 100644 --- a/parser/htmlparser/src/nsHTMLTokenizer.h +++ b/parser/htmlparser/src/nsHTMLTokenizer.h @@ -13,29 +13,20 @@ #ifndef __NSHTMLTOKENIZER #define __NSHTMLTOKENIZER +#include "mozilla/Attributes.h" #include "nsISupports.h" #include "nsITokenizer.h" -#include "nsIDTD.h" -#include "prtypes.h" -#include "nsDeque.h" -#include "nsScanner.h" #ifdef _MSC_VER #pragma warning( disable : 4275 ) #endif -class nsHTMLTokenizer : public nsITokenizer { +class nsHTMLTokenizer MOZ_FINAL : public nsITokenizer { public: NS_DECL_ISUPPORTS NS_DECL_NSITOKENIZER - nsHTMLTokenizer(nsDTDMode aParseMode = eDTDMode_quirks, - eParserDocType aDocType = eHTML_Quirks, - eParserCommands aCommand = eViewNormal, - uint32_t aFlags = 0); - virtual ~nsHTMLTokenizer(); - - static uint32_t GetFlags(const nsIContentSink* aSink); + nsHTMLTokenizer(); }; #endif From afea806bceeb272c7fa23582a344f656c603574b Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Sat, 17 Aug 2013 07:45:46 -0400 Subject: [PATCH 25/85] bug 908347 - remove nsIHTMLCOntentSink::IsEnabled r=mrbkap --- content/html/document/src/nsHTMLContentSink.cpp | 17 ----------------- parser/htmlparser/public/nsIHTMLContentSink.h | 8 +------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index f962e3abe752..cad3253c026f 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -162,7 +162,6 @@ public: virtual bool IsScriptExecuting(); // nsIHTMLContentSink - NS_IMETHOD IsEnabled(int32_t, bool*); NS_IMETHOD OpenContainer(nsHTMLTag aNodeType); NS_IMETHOD CloseContainer(const nsHTMLTag aTag); @@ -1412,22 +1411,6 @@ HTMLContentSink::CloseBody() return NS_OK; } -NS_IMETHODIMP -HTMLContentSink::IsEnabled(int32_t aTag, bool* aReturn) -{ - nsHTMLTag theHTMLTag = nsHTMLTag(aTag); - - if (theHTMLTag == eHTMLTag_script) { - *aReturn = mScriptEnabled; - } else if (theHTMLTag == eHTMLTag_frameset) { - *aReturn = mFramesEnabled; - } else { - *aReturn = false; - } - - return NS_OK; -} - NS_IMETHODIMP HTMLContentSink::OpenContainer(nsHTMLTag aNodeType) { diff --git a/parser/htmlparser/public/nsIHTMLContentSink.h b/parser/htmlparser/public/nsIHTMLContentSink.h index d567ae2ca8d7..de87cef44c62 100644 --- a/parser/htmlparser/public/nsIHTMLContentSink.h +++ b/parser/htmlparser/public/nsIHTMLContentSink.h @@ -53,7 +53,7 @@ #include "nsHTMLTags.h" #define NS_IHTML_CONTENT_SINK_IID \ - {0xb08b0f29, 0xe61c, 0x4647, {0xaf, 0x1e, 0x05, 0x1a, 0x75, 0x2f, 0xe6, 0x3d}} + {0xefc5af86, 0x5cfd, 0x4918, {0x9d, 0xd3, 0x5f, 0x7a, 0xb2, 0x88, 0xb2, 0x68}} /** * This interface is OBSOLETE and in the process of being REMOVED. @@ -65,12 +65,6 @@ public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_IHTML_CONTENT_SINK_IID) - /** - * @update 01/09/2003 harishd - * @param aTag - Check if this tag is enabled or not. - */ - NS_IMETHOD IsEnabled(int32_t aTag, bool* aReturn) = 0; - /** * This method is used to open a generic container in the sink. * From 0c205298fcf06b62df496834606a1f876da9241d Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Sat, 17 Aug 2013 08:06:23 -0400 Subject: [PATCH 26/85] bug 908347 - make Open / Close Container() take an enum with only html and body elements r=mrbkap --- .../html/document/src/nsHTMLContentSink.cpp | 47 ++++--------------- parser/htmlparser/public/nsIHTMLContentSink.h | 6 ++- parser/htmlparser/src/CNavDTD.cpp | 8 ++-- 3 files changed, 18 insertions(+), 43 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index cad3253c026f..d76c03c37902 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -162,8 +162,8 @@ public: virtual bool IsScriptExecuting(); // nsIHTMLContentSink - NS_IMETHOD OpenContainer(nsHTMLTag aNodeType); - NS_IMETHOD CloseContainer(const nsHTMLTag aTag); + NS_IMETHOD OpenContainer(ElementType aNodeType); + NS_IMETHOD CloseContainer(ElementType aTag); #ifdef DEBUG // nsIDebugDumpContent @@ -1412,24 +1412,15 @@ HTMLContentSink::CloseBody() } NS_IMETHODIMP -HTMLContentSink::OpenContainer(nsHTMLTag aNodeType) +HTMLContentSink::OpenContainer(ElementType aElementType) { nsresult rv = NS_OK; - switch (aNodeType) { - case eHTMLTag_frameset: - MOZ_CRASH("Must not use HTMLContentSink for frames."); - - case eHTMLTag_head: - rv = OpenHeadContext(); - if (NS_SUCCEEDED(rv)) { - mHaveSeenHead = true; - } + switch (aElementType) { + case eBody: + rv = OpenBody(eHTMLTag_body); break; - case eHTMLTag_body: - rv = OpenBody(aNodeType); - break; - case eHTMLTag_html: + case eHTML: if (mRoot) { // If we've already hit this code once, then we're done if (!mNotifiedRootInsertion) { @@ -1438,41 +1429,23 @@ HTMLContentSink::OpenContainer(nsHTMLTag aNodeType) ProcessOfflineManifest(mRoot); } break; - case eHTMLTag_form: - MOZ_CRASH("Must not use HTMLContentSink for forms."); - - default: - rv = mCurrentContext->OpenContainer(aNodeType); - break; } return rv; } NS_IMETHODIMP -HTMLContentSink::CloseContainer(const eHTMLTags aTag) +HTMLContentSink::CloseContainer(const ElementType aTag) { nsresult rv = NS_OK; switch (aTag) { - case eHTMLTag_frameset: - MOZ_CRASH("Must not use HTMLContentSink for frames."); - - case eHTMLTag_head: - CloseHeadContext(); - break; - case eHTMLTag_body: + case eBody: rv = CloseBody(); break; - case eHTMLTag_html: + case eHTML: rv = CloseHTML(); break; - case eHTMLTag_form: - MOZ_CRASH("Must not use HTMLContentSink for forms."); - - default: - rv = mCurrentContext->CloseContainer(aTag); - break; } return rv; diff --git a/parser/htmlparser/public/nsIHTMLContentSink.h b/parser/htmlparser/public/nsIHTMLContentSink.h index de87cef44c62..bf08c4b5ed1b 100644 --- a/parser/htmlparser/public/nsIHTMLContentSink.h +++ b/parser/htmlparser/public/nsIHTMLContentSink.h @@ -65,12 +65,14 @@ public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_IHTML_CONTENT_SINK_IID) + enum ElementType { eHTML, eBody }; + /** * This method is used to open a generic container in the sink. * * @update 4/1/98 gess */ - NS_IMETHOD OpenContainer(nsHTMLTag aNodeType) = 0; + NS_IMETHOD OpenContainer(ElementType aNodeType) = 0; /** * This method gets called by the parser when a close @@ -78,7 +80,7 @@ public: * * @param aTag - The tag to be closed. */ - NS_IMETHOD CloseContainer(const nsHTMLTag aTag) = 0; + NS_IMETHOD CloseContainer(ElementType aTag) = 0; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLContentSink, NS_IHTML_CONTENT_SINK_IID) diff --git a/parser/htmlparser/src/CNavDTD.cpp b/parser/htmlparser/src/CNavDTD.cpp index 11ca9deeef35..8657b6aa0f27 100644 --- a/parser/htmlparser/src/CNavDTD.cpp +++ b/parser/htmlparser/src/CNavDTD.cpp @@ -41,14 +41,14 @@ CNavDTD::BuildModel(nsITokenizer* aTokenizer, return NS_ERROR_HTMLPARSER_STOPPARSING; } - nsresult rv = sink->OpenContainer(eHTMLTag_html); + nsresult rv = sink->OpenContainer(nsIHTMLContentSink::eHTML); NS_ENSURE_SUCCESS(rv, rv); - rv = sink->OpenContainer(eHTMLTag_body); + rv = sink->OpenContainer(nsIHTMLContentSink::eBody); NS_ENSURE_SUCCESS(rv, rv); - rv = sink->CloseContainer(eHTMLTag_body); + rv = sink->CloseContainer(nsIHTMLContentSink::eBody); MOZ_ASSERT(NS_SUCCEEDED(rv)); - rv = sink->CloseContainer(eHTMLTag_html); + rv = sink->CloseContainer(nsIHTMLContentSink::eHTML); MOZ_ASSERT(NS_SUCCEEDED(rv)); return NS_OK; From 15092f8b877dd3633751d7eb9d6cc90dfb634d95 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Sat, 17 Aug 2013 09:11:18 -0400 Subject: [PATCH 27/85] bug 908347 - remove OpenHeadContext() r=mrbkap --- .../html/document/src/nsHTMLContentSink.cpp | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index d76c03c37902..2ef3c91bb90c 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -216,7 +216,6 @@ protected: nsresult OpenBody(nsHTMLTag aNodeType); nsresult CloseBody(); - nsresult OpenHeadContext(); void CloseHeadContext(); // nsContentSink overrides @@ -1463,37 +1462,6 @@ HTMLContentSink::WillResume() return WillResumeImpl(); } -nsresult -HTMLContentSink::OpenHeadContext() -{ - if (mCurrentContext && mCurrentContext->IsCurrentContainer(eHTMLTag_head)) - return NS_OK; - - // Flush everything in the current context so that we don't have - // to worry about insertions resulting in inconsistent frame creation. - // - // Try to do this only if needed (costly), i.e., only if we are sure - // we are changing contexts from some other context to the head. - // - // PERF: This call causes approximately a 2% slowdown in page load time - // according to jrgm's page load tests, but seems to be a necessary evil - if (mCurrentContext && (mCurrentContext != mHeadContext)) { - mCurrentContext->FlushTags(); - } - - if (!mHeadContext) { - mHeadContext = new SinkContext(this); - - nsresult rv = mHeadContext->Begin(eHTMLTag_head, mHead, 0, -1); - NS_ENSURE_SUCCESS(rv, rv); - } - - mContextStack.AppendElement(mCurrentContext); - mCurrentContext = mHeadContext; - - return NS_OK; -} - void HTMLContentSink::CloseHeadContext() { From b2a552be0cfc4b572c330729cadd0481642e4d52 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Sat, 17 Aug 2013 10:46:38 -0400 Subject: [PATCH 28/85] bug 908347 - rm nsIDebugDumpContent r=mrbkap --- .../html/document/src/nsHTMLContentSink.cpp | 48 ------------------- parser/htmlparser/public/nsIParser.h | 17 ------- parser/htmlparser/src/nsParser.cpp | 24 ---------- 3 files changed, 89 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index 2ef3c91bb90c..d172df765033 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -129,9 +129,6 @@ class HTMLContentSink; * Don't bother adding new stuff in this file. */ class HTMLContentSink : public nsContentSink, -#ifdef DEBUG - public nsIDebugDumpContent, -#endif public nsIHTMLContentSink { public: @@ -165,11 +162,6 @@ public: NS_IMETHOD OpenContainer(ElementType aNodeType); NS_IMETHOD CloseContainer(ElementType aTag); -#ifdef DEBUG - // nsIDebugDumpContent - NS_IMETHOD DumpContentModel(); -#endif - protected: already_AddRefed CreateContentObject(nsHTMLTag aNodeType); @@ -1094,9 +1086,6 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLContentSink) NS_INTERFACE_TABLE_BEGIN NS_INTERFACE_TABLE_ENTRY(HTMLContentSink, nsIContentSink) NS_INTERFACE_TABLE_ENTRY(HTMLContentSink, nsIHTMLContentSink) -#if DEBUG - NS_INTERFACE_TABLE_ENTRY(HTMLContentSink, nsIDebugDumpContent) -#endif NS_INTERFACE_TABLE_END NS_INTERFACE_TABLE_TAIL_INHERITING(nsContentSink) @@ -1655,40 +1644,3 @@ HTMLContentSink::IsScriptExecuting() { return IsScriptExecutingImpl(); } - -#ifdef DEBUG -/** - * This will dump content model into the output file. - * - * @update harishd 05/25/00 - * @param - * @return NS_OK all went well, error on failure - */ - -NS_IMETHODIMP -HTMLContentSink::DumpContentModel() -{ - FILE* out = ::fopen("rtest_html.txt", "a"); - if (out) { - if (mDocument) { - Element* root = mDocument->GetRootElement(); - if (root) { - if (mDocumentURI) { - nsAutoCString buf; - mDocumentURI->GetSpec(buf); - fputs(buf.get(), out); - } - - fputs(";", out); - root->DumpContent(out, 0, false); - fputs(";\n", out); - } - } - - fclose(out); - } - - return NS_OK; -} -#endif - diff --git a/parser/htmlparser/public/nsIParser.h b/parser/htmlparser/public/nsIParser.h index 62ec3520bbc5..b5bfc469365a 100644 --- a/parser/htmlparser/public/nsIParser.h +++ b/parser/htmlparser/public/nsIParser.h @@ -58,23 +58,6 @@ enum eParserDocType { enum eStreamState {eNone,eOnStart,eOnDataAvail,eOnStop}; -/** - * FOR DEBUG PURPOSE ONLY - * - * Use this interface to query objects that contain content information. - * Ex. Parser can trigger dump content by querying the sink that has - * access to the content. - * - * @update harishd 05/25/00 - */ -class nsIDebugDumpContent : public nsISupports { -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDEBUG_DUMP_CONTENT_IID) - NS_IMETHOD DumpContentModel()=0; -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsIDebugDumpContent, NS_IDEBUG_DUMP_CONTENT_IID) - /** * This GECKO-INTERNAL interface is on track to being REMOVED (or refactored * to the point of being near-unrecognizable). diff --git a/parser/htmlparser/src/nsParser.cpp b/parser/htmlparser/src/nsParser.cpp index 106e33f26bf6..4cea5cc5aad4 100644 --- a/parser/htmlparser/src/nsParser.cpp +++ b/parser/htmlparser/src/nsParser.cpp @@ -162,10 +162,6 @@ void nsParser::Shutdown() NS_IF_RELEASE(sCharsetConverterManager); } -#ifdef DEBUG -static bool gDumpContent=false; -#endif - /** * default constructor */ @@ -182,12 +178,6 @@ nsParser::~nsParser() void nsParser::Initialize(bool aConstructor) { -#ifdef DEBUG - if (!gDumpContent) { - gDumpContent = PR_GetEnv("PARSER_DUMP_CONTENT") != nullptr; - } -#endif - if (aConstructor) { // Raw pointer mParserContext = 0; @@ -215,20 +205,6 @@ nsParser::Initialize(bool aConstructor) void nsParser::Cleanup() { -#ifdef DEBUG - if (gDumpContent) { - if (mSink) { - // Sink (HTMLContentSink at this time) supports nsIDebugDumpContent - // interface. We can get to the content model through the sink. - nsresult result = NS_OK; - nsCOMPtr trigger = do_QueryInterface(mSink, &result); - if (NS_SUCCEEDED(result)) { - trigger->DumpContentModel(); - } - } - } -#endif - #ifdef DEBUG if (mParserContext && mParserContext->mPrevContext) { NS_WARNING("Extra parser contexts still on the parser stack"); From d878929bbff22196d8e962064678786fb212893a Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Sat, 17 Aug 2013 11:39:34 -0400 Subject: [PATCH 29/85] bug 908347 - make a bunch of html content sink stuff explicitly only deal with html:body r=mrbkap --- .../html/document/src/nsHTMLContentSink.cpp | 99 ++++--------------- 1 file changed, 20 insertions(+), 79 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index d172df765033..a3b2fbcb2d85 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -163,9 +163,6 @@ public: NS_IMETHOD CloseContainer(ElementType aTag); protected: - already_AddRefed - CreateContentObject(nsHTMLTag aNodeType); - #ifdef DEBUG void SinkTraceNode(uint32_t aBit, const char* aMsg, @@ -205,7 +202,7 @@ protected: // Routines for tags that require special handling nsresult CloseHTML(); - nsresult OpenBody(nsHTMLTag aNodeType); + nsresult OpenBody(); nsresult CloseBody(); void CloseHeadContext(); @@ -233,7 +230,7 @@ public: nsresult Begin(nsHTMLTag aNodeType, nsGenericHTMLElement* aRoot, uint32_t aNumFlushed, int32_t aInsertionPoint); - nsresult OpenContainer(nsHTMLTag aNodeType); + nsresult OpenBody(); nsresult CloseContainer(const nsHTMLTag aTag); nsresult AddLeaf(nsIContent* aContent); nsresult End(); @@ -309,39 +306,6 @@ HTMLContentSink::SinkTraceNode(uint32_t aBit, } #endif -/** - * Factory subroutine to create all of the html content objects. - */ -already_AddRefed -HTMLContentSink::CreateContentObject(nsHTMLTag aNodeType) -{ - // Find/create atom for the tag name - - nsCOMPtr nodeInfo; - - MOZ_ASSERT(aNodeType != eHTMLTag_userdefined); - if (mNodeInfoCache[aNodeType]) { - nodeInfo = mNodeInfoCache[aNodeType]; - } - else { - nsIParserService *parserService = nsContentUtils::GetParserService(); - if (!parserService) - return nullptr; - - nsIAtom *name = parserService->HTMLIdToAtomTag(aNodeType); - NS_ASSERTION(name, "What? Reverse mapping of id to string broken!!!"); - - nodeInfo = mNodeInfoManager->GetNodeInfo(name, nullptr, kNameSpaceID_XHTML, - nsIDOMNode::ELEMENT_NODE); - NS_IF_ADDREF(mNodeInfoCache[aNodeType] = nodeInfo); - } - - NS_ENSURE_TRUE(nodeInfo, nullptr); - - // Make the content object - return CreateHTMLElement(aNodeType, nodeInfo.forget(), FROM_PARSER_NETWORK); -} - nsresult NS_NewHTMLElement(nsIContent** aResult, already_AddRefed aNodeInfo, FromParser aFromParser) @@ -494,13 +458,13 @@ SinkContext::DidAddContent(nsIContent* aContent) } nsresult -SinkContext::OpenContainer(nsHTMLTag aNodeType) +SinkContext::OpenBody() { FlushTextAndRelease(); SINK_TRACE_NODE(SINK_TRACE_CALLS, "SinkContext::OpenContainer", - aNodeType, + eHTMLTag_body, mStackPos, mSink); @@ -518,48 +482,25 @@ SinkContext::OpenContainer(nsHTMLTag aNodeType) } } - // Create new container content object - nsGenericHTMLElement* content = - mSink->CreateContentObject(aNodeType).get(); - if (!content) { + nsCOMPtr nodeInfo = + mSink->mNodeInfoManager->GetNodeInfo(nsGkAtoms::body, nullptr, + kNameSpaceID_XHTML, + nsIDOMNode::ELEMENT_NODE); + NS_ENSURE_TRUE(nodeInfo, NS_ERROR_UNEXPECTED); + + // Make the content object + nsRefPtr body = + NS_NewHTMLBodyElement(nodeInfo.forget(), FROM_PARSER_NETWORK); + if (!body) { return NS_ERROR_OUT_OF_MEMORY; } - mStack[mStackPos].mType = aNodeType; - mStack[mStackPos].mContent = content; + mStack[mStackPos].mType = eHTMLTag_body; + body.forget(&mStack[mStackPos].mContent); mStack[mStackPos].mNumFlushed = 0; mStack[mStackPos].mInsertionPoint = -1; ++mStackPos; - mStack[mStackPos - 2].Add(content); - if (mSink->IsMonolithicContainer(aNodeType)) { - mSink->mInMonolithicContainer++; - } - - // Special handling for certain tags - switch (aNodeType) { - case eHTMLTag_form: - MOZ_CRASH("Must not use HTMLContentSink for forms."); - - case eHTMLTag_frameset: - MOZ_CRASH("Must not use HTMLContentSink for frames."); - - case eHTMLTag_noembed: - case eHTMLTag_noframes: - MOZ_CRASH("Must not use HTMLContentSink for noembed/noframes."); - - case eHTMLTag_script: - case eHTMLTag_style: - MOZ_CRASH("Must not use HTMLContentSink for styles and scripts."); - - case eHTMLTag_button: - case eHTMLTag_audio: - case eHTMLTag_video: - content->DoneCreatingElement(); - break; - - default: - break; - } + mStack[mStackPos - 2].Add(mStack[mStackPos - 1].mContent); return NS_OK; } @@ -1318,7 +1259,7 @@ HTMLContentSink::CloseHTML() } nsresult -HTMLContentSink::OpenBody(nsHTMLTag aNodeType) +HTMLContentSink::OpenBody() { SINK_TRACE_NODE(SINK_TRACE_CALLS, "HTMLContentSink::OpenBody", @@ -1333,7 +1274,7 @@ HTMLContentSink::OpenBody(nsHTMLTag aNodeType) return NS_OK; } - nsresult rv = mCurrentContext->OpenContainer(aNodeType); + nsresult rv = mCurrentContext->OpenBody(); if (NS_FAILED(rv)) { return rv; @@ -1406,7 +1347,7 @@ HTMLContentSink::OpenContainer(ElementType aElementType) switch (aElementType) { case eBody: - rv = OpenBody(eHTMLTag_body); + rv = OpenBody(); break; case eHTML: if (mRoot) { From 618cc871fb6e68099f0154208de82d42bb28df3a Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Sat, 17 Aug 2013 14:42:20 -0400 Subject: [PATCH 30/85] bug 908347 - remove text handling from html content sink r=mrbkap --- .../html/document/src/nsHTMLContentSink.cpp | 180 +----------------- 1 file changed, 1 insertion(+), 179 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index a3b2fbcb2d85..4984b3badfdb 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -236,14 +236,6 @@ public: nsresult End(); nsresult GrowStack(); - nsresult AddText(const nsAString& aText); - nsresult FlushText(bool* aDidFlush = nullptr, - bool aReleaseLast = false); - nsresult FlushTextAndRelease(bool* aDidFlush = nullptr) - { - return FlushText(aDidFlush, true); - } - nsresult FlushTags(); bool IsCurrentContainer(nsHTMLTag mType); @@ -260,8 +252,6 @@ private: public: HTMLContentSink* mSink; int32_t mNotifyLevel; - nsCOMPtr mLastTextNode; - int32_t mLastTextNodeSize; struct Node { nsHTMLTag mType; @@ -275,13 +265,6 @@ public: Node* mStack; int32_t mStackSize; int32_t mStackPos; - - PRUnichar* mText; - int32_t mTextLength; - int32_t mTextSize; - -private: - bool mLastTextCharWasCR; }; //---------------------------------------------------------------------- @@ -352,14 +335,9 @@ CreateHTMLElement(uint32_t aNodeType, already_AddRefed aNodeInfo, SinkContext::SinkContext(HTMLContentSink* aSink) : mSink(aSink), mNotifyLevel(0), - mLastTextNodeSize(0), mStack(nullptr), mStackSize(0), - mStackPos(0), - mText(nullptr), - mTextLength(0), - mTextSize(0), - mLastTextCharWasCR(false) + mStackPos(0) { MOZ_COUNT_CTOR(SinkContext); } @@ -374,8 +352,6 @@ SinkContext::~SinkContext() } delete [] mStack; } - - delete [] mText; } nsresult @@ -397,7 +373,6 @@ SinkContext::Begin(nsHTMLTag aNodeType, mStack[0].mInsertionPoint = aInsertionPoint; NS_ADDREF(aRoot); mStackPos = 1; - mTextLength = 0; return NS_OK; } @@ -460,8 +435,6 @@ SinkContext::DidAddContent(nsIContent* aContent) nsresult SinkContext::OpenBody() { - FlushTextAndRelease(); - SINK_TRACE_NODE(SINK_TRACE_CALLS, "SinkContext::OpenContainer", eHTMLTag_body, @@ -535,10 +508,6 @@ SinkContext::CloseContainer(const nsHTMLTag aTag) { nsresult result = NS_OK; - // Flush any collected text content. Release the last text - // node to indicate that no more should be added to it. - FlushTextAndRelease(); - SINK_TRACE_NODE(SINK_TRACE_CALLS, "SinkContext::CloseContainer", aTag, mStackPos - 1, mSink); @@ -659,7 +628,6 @@ SinkContext::End() } mStackPos = 0; - mTextLength = 0; return NS_OK; } @@ -685,63 +653,6 @@ SinkContext::GrowStack() return NS_OK; } -/** - * Add textual content to the current running text buffer. If the text buffer - * overflows, flush out the text by creating a text content object and adding - * it to the content tree. - */ - -// XXX If we get a giant string grow the buffer instead of chopping it -// up??? -nsresult -SinkContext::AddText(const nsAString& aText) -{ - int32_t addLen = aText.Length(); - if (addLen == 0) { - return NS_OK; - } - - // Create buffer when we first need it - if (mTextSize == 0) { - mText = new PRUnichar[4096]; - mTextSize = 4096; - } - - // Copy data from string into our buffer; flush buffer when it fills up - int32_t offset = 0; - - while (addLen != 0) { - int32_t amount = mTextSize - mTextLength; - - if (amount > addLen) { - amount = addLen; - } - - if (amount == 0) { - // Don't release last text node so we can add to it again - nsresult rv = FlushText(); - if (NS_FAILED(rv)) { - return rv; - } - - // Go back to the top of the loop so we re-calculate amount and - // don't fall through to CopyNewlineNormalizedUnicodeTo with a - // zero-length amount (which invalidates mLastTextCharWasCR). - continue; - } - - mTextLength += - nsContentUtils::CopyNewlineNormalizedUnicodeTo(aText, offset, - &mText[mTextLength], - amount, - mLastTextCharWasCR); - offset += amount; - addLen -= amount; - } - - return NS_OK; -} - /** * NOTE!! Forked into nsXMLContentSink. Please keep in sync. * @@ -766,9 +677,6 @@ SinkContext::FlushTags() true); mSink->mBeganUpdate = true; - // Don't release last text node in case we need to add to it again - FlushText(); - // Start from the base of the stack (growing downward) and do // a notification from the node that is closest to the root of // tree for any content that has been added. @@ -854,80 +762,6 @@ SinkContext::UpdateChildCounts() mNotifyLevel = mStackPos - 1; } -/** - * Flush any buffered text out by creating a text content object and - * adding it to the content. - */ -nsresult -SinkContext::FlushText(bool* aDidFlush, bool aReleaseLast) -{ - nsresult rv = NS_OK; - bool didFlush = false; - - if (mTextLength != 0) { - if (mLastTextNode) { - if ((mLastTextNodeSize + mTextLength) > mSink->mMaxTextRun) { - mLastTextNodeSize = 0; - mLastTextNode = nullptr; - FlushText(aDidFlush, aReleaseLast); - } else { - bool notify = HaveNotifiedForCurrentContent(); - // We could probably always increase mInNotification here since - // if AppendText doesn't notify it shouldn't trigger evil code. - // But just in case it does, we don't want to mask any notifications. - if (notify) { - ++mSink->mInNotification; - } - rv = mLastTextNode->AppendText(mText, mTextLength, notify); - if (notify) { - --mSink->mInNotification; - } - - mLastTextNodeSize += mTextLength; - mTextLength = 0; - didFlush = true; - } - } else { - nsRefPtr textContent = - new nsTextNode(mSink->mNodeInfoManager); - - mLastTextNode = textContent; - - // Set the text in the text node - mLastTextNode->SetText(mText, mTextLength, false); - - // Eat up the rest of the text up in state. - mLastTextNodeSize += mTextLength; - mTextLength = 0; - - rv = AddLeaf(mLastTextNode); - NS_ENSURE_SUCCESS(rv, rv); - - didFlush = true; - } - } - - if (aDidFlush) { - *aDidFlush = didFlush; - } - - if (aReleaseLast) { - mLastTextNodeSize = 0; - mLastTextNode = nullptr; - mLastTextCharWasCR = false; - } - -#ifdef DEBUG - if (didFlush && - SINK_LOG_TEST(gSinkLogModuleInfo, SINK_ALWAYS_REFLOW)) { - mSink->ForceReflow(); - } -#endif - - return rv; -} - - nsresult NS_NewHTMLContentSink(nsIHTMLContentSink** aResult, nsIDocument* aDoc, @@ -1247,8 +1081,6 @@ HTMLContentSink::CloseHTML() mContextStack.RemoveElementAt(numContexts); } - NS_ASSERTION(mHeadContext->mTextLength == 0, "Losing text"); - mHeadContext->End(); delete mHeadContext; @@ -1324,12 +1156,6 @@ HTMLContentSink::CloseBody() mCurrentContext->mStackPos - 1, this); - bool didFlush; - nsresult rv = mCurrentContext->FlushTextAndRelease(&didFlush); - if (NS_FAILED(rv)) { - return rv; - } - // Flush out anything that's left SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW, ("HTMLContentSink::CloseBody: layout final body content")); @@ -1399,7 +1225,6 @@ HTMLContentSink::CloseHeadContext() if (!mCurrentContext->IsCurrentContainer(eHTMLTag_head)) return; - mCurrentContext->FlushTextAndRelease(); mCurrentContext->FlushTags(); } @@ -1505,9 +1330,6 @@ HTMLContentSink::FlushPendingNotifications(mozFlushType aType) if (aType >= Flush_ContentAndNotify) { FlushTags(); } - else if (mCurrentContext) { - mCurrentContext->FlushText(); - } } if (aType >= Flush_InterruptibleLayout) { // Make sure that layout has started so that the reflow flush From a6328074f0f7ddedb983a83f540cae25492c9b86 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Sat, 17 Aug 2013 14:48:06 -0400 Subject: [PATCH 31/85] bug 908347 - remove AddLeaf() r=mrbkap --- .../html/document/src/nsHTMLContentSink.cpp | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index 4984b3badfdb..9758ffc1d4cc 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -232,7 +232,6 @@ public: uint32_t aNumFlushed, int32_t aInsertionPoint); nsresult OpenBody(); nsresult CloseContainer(const nsHTMLTag aTag); - nsresult AddLeaf(nsIContent* aContent); nsresult End(); nsresult GrowStack(); @@ -601,25 +600,6 @@ SinkContext::CloseContainer(const nsHTMLTag aTag) return result; } -nsresult -SinkContext::AddLeaf(nsIContent* aContent) -{ - NS_ASSERTION(mStackPos > 0, "leaf w/o container"); - if (mStackPos <= 0) { - return NS_ERROR_FAILURE; - } - - DidAddContent(mStack[mStackPos - 1].Add(aContent)); - -#ifdef DEBUG - if (SINK_LOG_TEST(gSinkLogModuleInfo, SINK_ALWAYS_REFLOW)) { - mSink->ForceReflow(); - } -#endif - - return NS_OK; -} - nsresult SinkContext::End() { From a0f3076c40c2d1c5d038b59eeb214ff63c1007f6 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Sat, 17 Aug 2013 15:18:03 -0400 Subject: [PATCH 32/85] bug 908347 - remove logging stuff for html content sink r=mrbkap It hardly seems useful to have debug logging for creating about:blank --- .../html/document/src/nsHTMLContentSink.cpp | 147 ------------------ 1 file changed, 147 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index 9758ffc1d4cc..a5c18da4a0c8 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -85,16 +85,6 @@ using namespace mozilla; using namespace mozilla::dom; -#ifdef DEBUG -static PRLogModuleInfo* gSinkLogModuleInfo; - -#define SINK_TRACE_NODE(_bit, _msg, _tag, _sp, _obj) \ - _obj->SinkTraceNode(_bit, _msg, _tag, _sp, this) - -#else -#define SINK_TRACE_NODE(_bit, _msg, _tag, _sp, _obj) -#endif - //---------------------------------------------------------------------- typedef nsGenericHTMLElement* @@ -163,14 +153,6 @@ public: NS_IMETHOD CloseContainer(ElementType aTag); protected: -#ifdef DEBUG - void SinkTraceNode(uint32_t aBit, - const char* aMsg, - const nsHTMLTag aTag, - int32_t aStackPos, - void* aThis); -#endif - nsCOMPtr mHTMLDocument; // The maximum length of a text run @@ -216,10 +198,6 @@ protected: void NotifyRootInsertion(); bool IsMonolithicContainer(nsHTMLTag aTag); - -#ifdef DEBUG - void ForceReflow(); -#endif }; class SinkContext @@ -266,28 +244,6 @@ public: int32_t mStackPos; }; -//---------------------------------------------------------------------- - -#ifdef DEBUG -void -HTMLContentSink::SinkTraceNode(uint32_t aBit, - const char* aMsg, - const nsHTMLTag aTag, - int32_t aStackPos, - void* aThis) -{ - if (SINK_LOG_TEST(gSinkLogModuleInfo, aBit)) { - nsIParserService *parserService = nsContentUtils::GetParserService(); - if (!parserService) - return; - - NS_ConvertUTF16toUTF8 tag(parserService->HTMLIdToStringTag(aTag)); - PR_LogPrint("%s: this=%p node='%s' stackPos=%d", - aMsg, aThis, tag.get(), aStackPos); - } -} -#endif - nsresult NS_NewHTMLElement(nsIContent** aResult, already_AddRefed aNodeInfo, FromParser aFromParser) @@ -402,31 +358,12 @@ SinkContext::DidAddContent(nsIContent* aContent) mStack[mStackPos - 1].mNumFlushed < mStack[mStackPos - 1].mContent->GetChildCount()) { nsIContent* parent = mStack[mStackPos - 1].mContent; - -#ifdef DEBUG - // Tracing code - nsIParserService *parserService = nsContentUtils::GetParserService(); - if (parserService) { - nsHTMLTag tag = nsHTMLTag(mStack[mStackPos - 1].mType); - NS_ConvertUTF16toUTF8 str(parserService->HTMLIdToStringTag(tag)); - - SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW, - ("SinkContext::DidAddContent: Insertion notification for " - "parent=%s at position=%d and stackPos=%d", - str.get(), mStack[mStackPos - 1].mInsertionPoint - 1, - mStackPos - 1)); - } -#endif - int32_t childIndex = mStack[mStackPos - 1].mInsertionPoint - 1; NS_ASSERTION(parent->GetChildAt(childIndex) == aContent, "Flushing the wrong child."); mSink->NotifyInsert(parent, aContent, childIndex); mStack[mStackPos - 1].mNumFlushed = parent->GetChildCount(); } else if (mSink->IsTimeToNotify()) { - SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW, - ("SinkContext::DidAddContent: Notification as a result of the " - "interval expiring; backoff count: %d", mSink->mBackoffCount)); FlushTags(); } } @@ -434,12 +371,6 @@ SinkContext::DidAddContent(nsIContent* aContent) nsresult SinkContext::OpenBody() { - SINK_TRACE_NODE(SINK_TRACE_CALLS, - "SinkContext::OpenContainer", - eHTMLTag_body, - mStackPos, - mSink); - if (mStackPos <= 0) { NS_ERROR("container w/o parent"); @@ -506,11 +437,6 @@ nsresult SinkContext::CloseContainer(const nsHTMLTag aTag) { nsresult result = NS_OK; - - SINK_TRACE_NODE(SINK_TRACE_CALLS, - "SinkContext::CloseContainer", - aTag, mStackPos - 1, mSink); - NS_ASSERTION(mStackPos > 0, "stack out of bounds. wrong context probably!"); @@ -536,16 +462,6 @@ SinkContext::CloseContainer(const nsHTMLTag aTag) // notification if (mStack[mStackPos].mNumFlushed < content->GetChildCount()) { -#ifdef DEBUG - { - // Tracing code - SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW, - ("SinkContext::CloseContainer: reflow on notifyImmediate " - "tag=%s newIndex=%d stackPos=%d", - nsAtomCString(mStack[mStackPos].mContent->Tag()).get(), - mStack[mStackPos].mNumFlushed, mStackPos)); - } -#endif mSink->NotifyAppend(content, mStack[mStackPos].mNumFlushed); mStack[mStackPos].mNumFlushed = content->GetChildCount(); } @@ -591,12 +507,6 @@ SinkContext::CloseContainer(const nsHTMLTag aTag) NS_IF_RELEASE(content); -#ifdef DEBUG - if (SINK_LOG_TEST(gSinkLogModuleInfo, SINK_ALWAYS_REFLOW)) { - mSink->ForceReflow(); - } -#endif - return result; } @@ -674,16 +584,6 @@ SinkContext::FlushTags() childCount = content->GetChildCount(); if (!flushed && (mStack[stackPos].mNumFlushed < childCount)) { -#ifdef DEBUG - { - // Tracing code - SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW, - ("SinkContext::FlushTags: tag=%s from newindex=%d at " - "stackPos=%d", - nsAtomCString(mStack[stackPos].mContent->Tag()).get(), - mStack[stackPos].mNumFlushed, stackPos)); - } -#endif if (mStack[stackPos].mInsertionPoint != -1) { // We might have popped the child off our stack already // but not notified on it yet, which is why we have to get it @@ -766,13 +666,6 @@ NS_NewHTMLContentSink(nsIHTMLContentSink** aResult, HTMLContentSink::HTMLContentSink() { // Note: operator new zeros our memory - - -#ifdef DEBUG - if (!gSinkLogModuleInfo) { - gSinkLogModuleInfo = PR_NewLogModule("htmlcontentsink"); - } -#endif } HTMLContentSink::~HTMLContentSink() @@ -946,13 +839,6 @@ HTMLContentSink::Init(nsIDocument* aDoc, mCurrentContext->Begin(eHTMLTag_html, mRoot, 0, -1); mContextStack.AppendElement(mCurrentContext); -#ifdef DEBUG - nsAutoCString spec; - (void)aURI->GetSpec(spec); - SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_CALLS, - ("HTMLContentSink::Init: this=%p url='%s'", - this, spec.get())); -#endif return NS_OK; } @@ -995,16 +881,10 @@ HTMLContentSink::DidBuildModel(bool aTerminated) // Reflow the last batch of content if (mBody) { - SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW, - ("HTMLContentSink::DidBuildModel: layout final content")); mCurrentContext->FlushTags(); } else if (!mLayoutStarted) { // We never saw the body, and layout never got started. Force // layout *now*, to get an initial reflow. - SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW, - ("HTMLContentSink::DidBuildModel: forcing reflow on empty " - "document")); - // NOTE: only force the layout if we are NOT destroying the // docshell. If we are destroying it, then starting layout will // likely cause us to crash, or at best waste a lot of time as we @@ -1048,10 +928,6 @@ HTMLContentSink::SetParser(nsParserBase* aParser) nsresult HTMLContentSink::CloseHTML() { - SINK_TRACE_NODE(SINK_TRACE_CALLS, - "HTMLContentSink::CloseHTML", - eHTMLTag_html, 0, this); - if (mHeadContext) { if (mCurrentContext == mHeadContext) { uint32_t numContexts = mContextStack.Length(); @@ -1073,12 +949,6 @@ HTMLContentSink::CloseHTML() nsresult HTMLContentSink::OpenBody() { - SINK_TRACE_NODE(SINK_TRACE_CALLS, - "HTMLContentSink::OpenBody", - eHTMLTag_body, - mCurrentContext->mStackPos, - this); - CloseHeadContext(); // do this just in case if the HEAD was left open! // if we already have a body we're done @@ -1130,16 +1000,7 @@ HTMLContentSink::OpenBody() nsresult HTMLContentSink::CloseBody() { - SINK_TRACE_NODE(SINK_TRACE_CALLS, - "HTMLContentSink::CloseBody", - eHTMLTag_body, - mCurrentContext->mStackPos - 1, - this); - // Flush out anything that's left - SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW, - ("HTMLContentSink::CloseBody: layout final body content")); - mCurrentContext->FlushTags(); mCurrentContext->CloseContainer(eHTMLTag_body); @@ -1216,14 +1077,6 @@ HTMLContentSink::CloseHeadContext() } } -#ifdef DEBUG -void -HTMLContentSink::ForceReflow() -{ - mCurrentContext->FlushTags(); -} -#endif - void HTMLContentSink::NotifyInsert(nsIContent* aContent, nsIContent* aChildContent, From 7ec442fab8c6b37b794433feef490362437fbf02 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Sat, 17 Aug 2013 15:26:48 -0400 Subject: [PATCH 33/85] bug 908347 - rename CloseContainer() to CloseBody() r=mrbkap --- .../html/document/src/nsHTMLContentSink.cpp | 62 ++----------------- 1 file changed, 5 insertions(+), 57 deletions(-) diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index a5c18da4a0c8..7cb1e09138da 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -196,8 +196,6 @@ protected: nsIContent* aChildContent, int32_t aIndexInContainer); void NotifyRootInsertion(); - - bool IsMonolithicContainer(nsHTMLTag aTag); }; class SinkContext @@ -209,7 +207,7 @@ public: nsresult Begin(nsHTMLTag aNodeType, nsGenericHTMLElement* aRoot, uint32_t aNumFlushed, int32_t aInsertionPoint); nsresult OpenBody(); - nsresult CloseContainer(const nsHTMLTag aTag); + nsresult CloseBody(); nsresult End(); nsresult GrowStack(); @@ -434,9 +432,8 @@ SinkContext::Node::Add(nsIContent *child) } nsresult -SinkContext::CloseContainer(const nsHTMLTag aTag) +SinkContext::CloseBody() { - nsresult result = NS_OK; NS_ASSERTION(mStackPos > 0, "stack out of bounds. wrong context probably!"); @@ -445,9 +442,7 @@ SinkContext::CloseContainer(const nsHTMLTag aTag) } --mStackPos; - nsHTMLTag nodeType = mStack[mStackPos].mType; - - NS_ASSERTION(nodeType == aTag, + NS_ASSERTION(mStack[mStackPos].mType == eHTMLTag_body, "Tag mismatch. Closing tag on wrong context or something?"); nsGenericHTMLElement* content = mStack[mStackPos].mContent; @@ -470,44 +465,10 @@ SinkContext::CloseContainer(const nsHTMLTag aTag) mNotifyLevel = mStackPos - 1; } - if (mSink->IsMonolithicContainer(nodeType)) { - --mSink->mInMonolithicContainer; - } - DidAddContent(content); - - // Special handling for certain tags - switch (nodeType) { - case eHTMLTag_noembed: - case eHTMLTag_noframes: - MOZ_CRASH("Must not use HTMLContentSink for noembed/noframes."); - - case eHTMLTag_form: - MOZ_CRASH("Must not use HTMLContentSink for forms."); - - case eHTMLTag_video: - case eHTMLTag_audio: - case eHTMLTag_select: - case eHTMLTag_textarea: - case eHTMLTag_object: - case eHTMLTag_applet: - case eHTMLTag_title: - content->DoneAddingChildren(HaveNotifiedForCurrentContent()); - break; - - case eHTMLTag_script: - MOZ_CRASH("Must not use HTMLContentSink to run scripts."); - - case eHTMLTag_style: - MOZ_CRASH("Must not use HTMLContentSink for styles."); - - default: - break; - } - NS_IF_RELEASE(content); - return result; + return NS_OK; } nsresult @@ -1002,7 +963,7 @@ HTMLContentSink::CloseBody() { // Flush out anything that's left mCurrentContext->FlushTags(); - mCurrentContext->CloseContainer(eHTMLTag_body); + mCurrentContext->CloseBody(); return NS_OK; } @@ -1125,19 +1086,6 @@ HTMLContentSink::NotifyRootInsertion() UpdateChildCounts(); } -bool -HTMLContentSink::IsMonolithicContainer(nsHTMLTag aTag) -{ - if (aTag == eHTMLTag_tr || - aTag == eHTMLTag_select || - aTag == eHTMLTag_applet || - aTag == eHTMLTag_object) { - return true; - } - - return false; -} - void HTMLContentSink::UpdateChildCounts() { From da7e9c8bbc457810ce01b88c22f76e31b8b6d5d1 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Mon, 26 Aug 2013 09:04:09 -0700 Subject: [PATCH 34/85] Bug 909363 - Mark redirect() as unsafe for fuzzing. r=till --HG-- extra : rebase_source : bb748d87138e71afe3bcfdaedc958e5b0ef20fd5 --- js/src/shell/js.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 1afa27669e3e..b2796216f7ee 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -3909,11 +3909,6 @@ static const JSFunctionSpecWithHelp shell_functions[] = { " Read filename into returned string. Filename is relative to the directory\n" " containing the current script."), - JS_FN_HELP("redirect", RedirectOutput, 2, 0, -"redirect(stdoutFilename[, stderrFilename])", -" Redirect stdout and/or stderr to the named file. Pass undefined to avoid\n" -" redirecting. Filenames are relative to the current working directory."), - JS_FN_HELP("compile", Compile, 1, 0, "compile(code)", " Compiles a string to bytecode, potentially throwing."), @@ -4018,6 +4013,11 @@ static const JSFunctionSpecWithHelp fuzzing_unsafe_functions[] = { "pc2line(fun[, pc])", " Map PC to line number."), + JS_FN_HELP("redirect", RedirectOutput, 2, 0, +"redirect(stdoutFilename[, stderrFilename])", +" Redirect stdout and/or stderr to the named file. Pass undefined to avoid\n" +" redirecting. Filenames are relative to the current working directory."), + JS_FN_HELP("setThrowHook", SetThrowHook, 1, 0, "setThrowHook(f)", " Set throw hook to f."), From 97aaf5587a6696d4974e7e4fdc5895b138b4821f Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Thu, 22 Aug 2013 21:21:00 -0400 Subject: [PATCH 35/85] Bug 908526 - remove Element.h include from PContent.ipdl; r=bz --- dom/ipc/PContent.ipdl | 1 - 1 file changed, 1 deletion(-) diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 89763a664a8b..58616b5fed04 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -30,7 +30,6 @@ include URIParams; include "mozilla/chrome/RegistryMessageUtils.h"; include "mozilla/dom/PermissionMessageUtils.h"; include "mozilla/dom/TabMessageUtils.h"; -include "mozilla/dom/Element.h"; include "mozilla/HalTypes.h"; include "mozilla/layout/RenderFrameUtils.h"; include "mozilla/net/NeckoMessageUtils.h"; From 1b7ec73c80dc8195befa6c327e2199991c046d84 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Mon, 26 Aug 2013 11:46:21 -0500 Subject: [PATCH 36/85] Bug 907937 - Move JSCompartment::wrap again to avoid 'used but not defined' warnings (r=themaid) --- js/src/jscompartment.h | 62 ++--------------------------------- js/src/jscompartmentinlines.h | 61 ++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 60 deletions(-) diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index af8aef53b78a..ea524d847256 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -279,66 +279,8 @@ struct JSCompartment void markCrossCompartmentWrappers(JSTracer *trc); void markAllCrossCompartmentWrappers(JSTracer *trc); - bool wrap(JSContext *cx, JS::MutableHandleValue vp, - JS::HandleObject existing = js::NullPtr()) - { - JS_ASSERT_IF(existing, vp.isObject()); - - /* Only GC things have to be wrapped or copied. */ - if (!vp.isMarkable()) - return true; - - /* Handle strings. */ - if (vp.isString()) { - JSString *str = vp.toString(); - if (!wrap(cx, &str)) - return false; - vp.setString(str); - return true; - } - - JS_ASSERT(vp.isObject()); - - /* - * All that's left are objects. - * - * Object wrapping isn't the fastest thing in the world, in part because - * we have to unwrap and invoke the prewrap hook to find the identity - * object before we even start checking the cache. Neither of these - * operations are needed in the common case, where we're just wrapping - * a plain JS object from the wrappee's side of the membrane to the - * wrapper's side. - * - * To optimize this, we note that the cache should only ever contain - * identity objects - that is to say, objects that serve as the - * canonical representation for a unique object identity observable by - * script. Unwrap and prewrap are both steps that we take to get to the - * identity of an incoming objects, and as such, they shuld never map - * one identity object to another object. This means that we can safely - * check the cache immediately, and only risk false negatives. Do this - * in opt builds, and do both in debug builds so that we can assert - * that we get the same answer. - */ -#ifdef DEBUG - JS::RootedObject cacheResult(cx); -#endif - JS::RootedValue v(cx, vp); - if (js::WrapperMap::Ptr p = crossCompartmentWrappers.lookup(v)) { -#ifdef DEBUG - cacheResult = &p->value.get().toObject(); -#else - vp.set(p->value); - return true; -#endif - } - - JS::RootedObject obj(cx, &vp.toObject()); - if (!wrap(cx, &obj, existing)) - return false; - vp.setObject(*obj); - JS_ASSERT_IF(cacheResult, obj == cacheResult); - return true; - } + inline bool wrap(JSContext *cx, JS::MutableHandleValue vp, + JS::HandleObject existing = js::NullPtr()); bool wrap(JSContext *cx, JSString **strp); bool wrap(JSContext *cx, js::HeapPtrString *strp); diff --git a/js/src/jscompartmentinlines.h b/js/src/jscompartmentinlines.h index 16a21d918fc6..607868ed0511 100644 --- a/js/src/jscompartmentinlines.h +++ b/js/src/jscompartmentinlines.h @@ -43,4 +43,65 @@ js::AutoCompartment::~AutoCompartment() cx_->leaveCompartment(origin_); } +inline bool +JSCompartment::wrap(JSContext *cx, JS::MutableHandleValue vp, JS::HandleObject existing) +{ + JS_ASSERT_IF(existing, vp.isObject()); + + /* Only GC things have to be wrapped or copied. */ + if (!vp.isMarkable()) + return true; + + /* Handle strings. */ + if (vp.isString()) { + JSString *str = vp.toString(); + if (!wrap(cx, &str)) + return false; + vp.setString(str); + return true; + } + + JS_ASSERT(vp.isObject()); + + /* + * All that's left are objects. + * + * Object wrapping isn't the fastest thing in the world, in part because + * we have to unwrap and invoke the prewrap hook to find the identity + * object before we even start checking the cache. Neither of these + * operations are needed in the common case, where we're just wrapping + * a plain JS object from the wrappee's side of the membrane to the + * wrapper's side. + * + * To optimize this, we note that the cache should only ever contain + * identity objects - that is to say, objects that serve as the + * canonical representation for a unique object identity observable by + * script. Unwrap and prewrap are both steps that we take to get to the + * identity of an incoming objects, and as such, they shuld never map + * one identity object to another object. This means that we can safely + * check the cache immediately, and only risk false negatives. Do this + * in opt builds, and do both in debug builds so that we can assert + * that we get the same answer. + */ +#ifdef DEBUG + JS::RootedObject cacheResult(cx); +#endif + JS::RootedValue v(cx, vp); + if (js::WrapperMap::Ptr p = crossCompartmentWrappers.lookup(v)) { +#ifdef DEBUG + cacheResult = &p->value.get().toObject(); +#else + vp.set(p->value); + return true; +#endif + } + + JS::RootedObject obj(cx, &vp.toObject()); + if (!wrap(cx, &obj, existing)) + return false; + vp.setObject(*obj); + JS_ASSERT_IF(cacheResult, obj == cacheResult); + return true; +} + #endif /* jscompartmentinlines_h */ From 3852a8bde0c2ffa769e5752bbcae5f53182d408e Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Mon, 26 Aug 2013 11:50:04 -0500 Subject: [PATCH 37/85] Bug 858551 - Add jsscriptinlines.h to fix 'used by not defined' warnings (r=themaid) --- js/src/jit/ExecutionModeInlines.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/src/jit/ExecutionModeInlines.h b/js/src/jit/ExecutionModeInlines.h index 5030a052f40e..0be32f5425e8 100644 --- a/js/src/jit/ExecutionModeInlines.h +++ b/js/src/jit/ExecutionModeInlines.h @@ -11,6 +11,8 @@ #include "jit/CompileInfo.h" +#include "jsscriptinlines.h" + namespace js { namespace ion { From 0837eb50965bbe0491cf85eea53b407841a88ee2 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Fri, 23 Aug 2013 09:52:32 -0400 Subject: [PATCH 38/85] Bug 902651 - Restore the DrawTarget transform and clip when demoting r=mattwoodrow,bz --HG-- rename : browser/config/mozconfigs/win64/common-opt => browser/config/mozconfigs/win64/nightly extra : rebase_source : 1f1438d54fb97935c9186b69afc37a5d17028dbb --- .../canvas/src/CanvasRenderingContext2D.cpp | 35 ++++++++++----- content/canvas/src/CanvasRenderingContext2D.h | 8 ++-- content/canvas/test/Makefile.in | 1 + content/canvas/test/test_bug902651.html | 44 +++++++++++++++++++ dom/webidl/CanvasRenderingContext2D.webidl | 6 +++ 5 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 content/canvas/test/test_bug902651.html diff --git a/content/canvas/src/CanvasRenderingContext2D.cpp b/content/canvas/src/CanvasRenderingContext2D.cpp index 052d99c90028..dcebbcc2d351 100644 --- a/content/canvas/src/CanvasRenderingContext2D.cpp +++ b/content/canvas/src/CanvasRenderingContext2D.cpp @@ -547,7 +547,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D() sNumLivingContexts++; SetIsDOMBinding(); -#if USE_SKIA_GPU +#ifdef USE_SKIA_GPU mForceSoftware = false; #endif } @@ -564,10 +564,8 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D() NS_IF_RELEASE(sErrorTarget); } -#if USE_SKIA_GPU - std::vector::iterator iter = std::find(DemotableContexts().begin(), DemotableContexts().end(), this); - if (iter != DemotableContexts().end()) - DemotableContexts().erase(iter); +#ifdef USE_SKIA_GPU + RemoveDemotableContext(this); #endif } @@ -746,13 +744,14 @@ CanvasRenderingContext2D::RedrawUser(const gfxRect& r) Redraw(newr); } -#if USE_SKIA_GPU - void CanvasRenderingContext2D::Demote() { +#ifdef USE_SKIA_GPU if (!IsTargetValid() || mForceSoftware) return; + RemoveDemotableContext(this); + RefPtr snapshot = mTarget->Snapshot(); RefPtr oldTarget = mTarget; mTarget = nullptr; @@ -764,11 +763,21 @@ void CanvasRenderingContext2D::Demote() if (!IsTargetValid()) return; - // Put back the content from the old DrawTarget + // Restore the content from the old DrawTarget mgfx::Rect r(0, 0, mWidth, mHeight); mTarget->DrawSurface(snapshot, r, r); + + // Restore the clips and transform + for (uint32_t i = 0; i < CurrentState().clipsPushed.size(); i++) { + mTarget->PushClip(CurrentState().clipsPushed[i]); + } + + mTarget->SetTransform(oldTarget->GetTransform()); +#endif } +#ifdef USE_SKIA_GPU + std::vector& CanvasRenderingContext2D::DemotableContexts() { @@ -790,8 +799,6 @@ CanvasRenderingContext2D::DemoteOldestContextIfNecessary() return; CanvasRenderingContext2D* oldest = contexts.front(); - contexts.erase(contexts.begin()); - oldest->Demote(); } @@ -805,6 +812,14 @@ CanvasRenderingContext2D::AddDemotableContext(CanvasRenderingContext2D* context) DemotableContexts().push_back(context); } +void +CanvasRenderingContext2D::RemoveDemotableContext(CanvasRenderingContext2D* context) +{ + std::vector::iterator iter = std::find(DemotableContexts().begin(), DemotableContexts().end(), context); + if (iter != DemotableContexts().end()) + DemotableContexts().erase(iter); +} + #define MIN_SKIA_GL_DIMENSION 16 bool diff --git a/content/canvas/src/CanvasRenderingContext2D.h b/content/canvas/src/CanvasRenderingContext2D.h index 28929f5a6560..dc78180a080e 100644 --- a/content/canvas/src/CanvasRenderingContext2D.h +++ b/content/canvas/src/CanvasRenderingContext2D.h @@ -367,6 +367,8 @@ public: double h, const nsAString& bgColor, uint32_t flags, mozilla::ErrorResult& error); + void Demote(); + nsresult Redraw(); // nsICanvasRenderingContextInternal @@ -567,13 +569,11 @@ protected: } #if USE_SKIA_GPU - - // Recreate the DrawTarget in software mode - void Demote(); - static std::vector& DemotableContexts(); static void DemoteOldestContextIfNecessary(); + static void AddDemotableContext(CanvasRenderingContext2D* context); + static void RemoveDemotableContext(CanvasRenderingContext2D* context); // Do not use GL bool mForceSoftware; diff --git a/content/canvas/test/Makefile.in b/content/canvas/test/Makefile.in index 63c825bed0a0..2af137464d66 100644 --- a/content/canvas/test/Makefile.in +++ b/content/canvas/test/Makefile.in @@ -88,6 +88,7 @@ MOCHITEST_FILES = \ file_drawImage_document_domain.html \ test_windingRuleUndefined.html \ test_strokeText_throw.html \ + test_bug902651.html \ $(NULL) # SkiaGL on Android/Gonk does not implement these composite ops yet diff --git a/content/canvas/test/test_bug902651.html b/content/canvas/test/test_bug902651.html new file mode 100644 index 000000000000..9ddb2960993c --- /dev/null +++ b/content/canvas/test/test_bug902651.html @@ -0,0 +1,44 @@ + +Canvas test: canvas demotion + + + + +

FAIL (fallback content)

+ + diff --git a/dom/webidl/CanvasRenderingContext2D.webidl b/dom/webidl/CanvasRenderingContext2D.webidl index 34f8f1f30e96..02d8fd1d3209 100644 --- a/dom/webidl/CanvasRenderingContext2D.webidl +++ b/dom/webidl/CanvasRenderingContext2D.webidl @@ -207,6 +207,12 @@ interface CanvasRenderingContext2D { void asyncDrawXULElement(XULElement elem, double x, double y, double w, double h, DOMString bgColor, optional unsigned long flags = 0); + /** + * This causes a context that is currently using a hardware-accelerated + * backend to fallback to a software one. All state should be preserved. + */ + [ChromeOnly] + void demote(); }; CanvasRenderingContext2D implements CanvasDrawingStyles; CanvasRenderingContext2D implements CanvasPathMethods; From 644765265ad0973911acd11586c383831ae1f721 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Mon, 26 Aug 2013 12:21:06 -0500 Subject: [PATCH 39/85] Also recognize Inlines.h as a inlines header suffix in check-style (no bug, r=bustage) --HG-- extra : rebase_source : 876ee986c8533afa0a3ba5b67c0a8efd588bd083 --- js/src/config/check_spidermonkey_style.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/config/check_spidermonkey_style.py b/js/src/config/check_spidermonkey_style.py index accccdbdc560..737ad1a2f6fd 100644 --- a/js/src/config/check_spidermonkey_style.py +++ b/js/src/config/check_spidermonkey_style.py @@ -200,7 +200,7 @@ class FileKind(object): if filename.endswith('.cpp'): return FileKind.CPP - if filename.endswith(('inlines.h', '-inl.h')): + if filename.endswith(('inlines.h', '-inl.h', 'Inlines.h')): return FileKind.INL_H if filename.endswith('.h'): From f095398fa2388483f37b8b1eeafcdfdcf0877f81 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Mon, 26 Aug 2013 12:36:56 -0500 Subject: [PATCH 40/85] Update check_spidermonkey_style.py in BOTH places (no bug, r=burning, CLOSED TREE) --- config/check_spidermonkey_style.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/check_spidermonkey_style.py b/config/check_spidermonkey_style.py index accccdbdc560..737ad1a2f6fd 100644 --- a/config/check_spidermonkey_style.py +++ b/config/check_spidermonkey_style.py @@ -200,7 +200,7 @@ class FileKind(object): if filename.endswith('.cpp'): return FileKind.CPP - if filename.endswith(('inlines.h', '-inl.h')): + if filename.endswith(('inlines.h', '-inl.h', 'Inlines.h')): return FileKind.INL_H if filename.endswith('.h'): From 356542a41c9e7b58375c636972d0889b684ea26c Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Mon, 26 Aug 2013 13:48:16 -0400 Subject: [PATCH 41/85] Bug 848104 - Mark test as random on OSX 10.6/10.7. rs=Bas --- dom/plugins/test/reftest/reftest.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/plugins/test/reftest/reftest.list b/dom/plugins/test/reftest/reftest.list index cef03366e424..3b978e283b2d 100644 --- a/dom/plugins/test/reftest/reftest.list +++ b/dom/plugins/test/reftest/reftest.list @@ -5,7 +5,7 @@ fails-if(!haveTestPlugin) == plugin-sanity.html div-sanity.html fails-if(!haveTestPlugin) == plugin-asyncbitmap-sanity.html div-sanity.html fails-if(!haveTestPlugin) == plugin-asyncdxgi-sanity.html div-sanity.html skip-if(!haveTestPlugin) == plugin-asyncbitmap-update.html plugin-async-update-ref.html -skip-if(!haveTestPlugin) == plugin-asyncdxgi-update.html plugin-async-update-ref.html +random-if(OSX==10.6||OSX==10.7) skip-if(!haveTestPlugin) == plugin-asyncdxgi-update.html plugin-async-update-ref.html fails-if(!haveTestPlugin) == plugin-alpha-zindex.html div-alpha-zindex.html fails-if(!haveTestPlugin) == plugin-alpha-opacity.html div-alpha-opacity.html random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == windowless-clipping-1.html windowless-clipping-1-ref.html # bug 631832 From c5e387c60ce8ed1fc567a1dbe0d5bb8503ebdc69 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Mon, 26 Aug 2013 17:56:52 +0000 Subject: [PATCH 42/85] Bug 909078 - Pretend the inner table frame is top-of-page if the outer table frame is. r=roc --- ...21-table-page-break-inside-avoid-6-ref.html | 15 +++++++++++++++ ...-css21-table-page-break-inside-avoid-6.html | 17 +++++++++++++++++ ...21-table-page-break-inside-avoid-7-ref.html | 17 +++++++++++++++++ ...-css21-table-page-break-inside-avoid-7.html | 18 ++++++++++++++++++ ...-css21-table-page-break-inside-avoid-8.html | 17 +++++++++++++++++ .../submitted/css21/pagination/reftest.list | 3 +++ layout/tables/nsTableOuterFrame.cpp | 13 +++++-------- 7 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-6-ref.html create mode 100644 layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-6.html create mode 100644 layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-7-ref.html create mode 100644 layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-7.html create mode 100644 layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-8.html diff --git a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-6-ref.html b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-6-ref.html new file mode 100644 index 000000000000..0560667a4e6a --- /dev/null +++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-6-ref.html @@ -0,0 +1,15 @@ + + + + CSS Test: CSS 2.1 page-break-inside:avoid + + + + + +

1

1

2

+ + diff --git a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-6.html b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-6.html new file mode 100644 index 000000000000..234165299909 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-6.html @@ -0,0 +1,17 @@ + + + + CSS Test: CSS 2.1 page-break-inside:avoid + + + + + + +

1

1

2

+ + diff --git a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-7-ref.html b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-7-ref.html new file mode 100644 index 000000000000..1a2d3d304e8c --- /dev/null +++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-7-ref.html @@ -0,0 +1,17 @@ + + + + CSS Test: CSS 2.1 page-break-inside:avoid + + + + + +
Text
+

1

1

2

+ + diff --git a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-7.html b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-7.html new file mode 100644 index 000000000000..8ca89496016c --- /dev/null +++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-7.html @@ -0,0 +1,18 @@ + + + + CSS Test: CSS 2.1 page-break-inside:avoid + + + + + + +
Text
+

1

1

2

+ + diff --git a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-8.html b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-8.html new file mode 100644 index 000000000000..a66f485cea21 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-8.html @@ -0,0 +1,17 @@ + + + + CSS Test: CSS 2.1 page-break-inside:avoid + + + + + + +

1

1

2

+ + diff --git a/layout/reftests/w3c-css/submitted/css21/pagination/reftest.list b/layout/reftests/w3c-css/submitted/css21/pagination/reftest.list index 359642e93e38..dee7aa242548 100644 --- a/layout/reftests/w3c-css/submitted/css21/pagination/reftest.list +++ b/layout/reftests/w3c-css/submitted/css21/pagination/reftest.list @@ -18,6 +18,9 @@ == moz-css21-table-page-break-inside-avoid-3.html moz-css21-table-page-break-inside-avoid-3-ref.html == moz-css21-table-page-break-inside-avoid-4.html moz-css21-table-page-break-inside-avoid-4-ref.html == moz-css21-table-page-break-inside-avoid-5.html moz-css21-table-page-break-inside-avoid-5-ref.html +== moz-css21-table-page-break-inside-avoid-6.html moz-css21-table-page-break-inside-avoid-6-ref.html +== moz-css21-table-page-break-inside-avoid-7.html moz-css21-table-page-break-inside-avoid-7-ref.html +== moz-css21-table-page-break-inside-avoid-8.html moz-css21-table-page-break-inside-avoid-6-ref.html == moz-css21-float-page-break-inside-avoid-1.html moz-css21-table-page-break-inside-avoid-ref.html == moz-css21-float-page-break-inside-avoid-2.html moz-css21-float-page-break-inside-avoid-2-ref.html == moz-css21-float-page-break-inside-avoid-3.html moz-css21-block-page-break-inside-avoid-ref.html diff --git a/layout/tables/nsTableOuterFrame.cpp b/layout/tables/nsTableOuterFrame.cpp index f19aba3d48a7..c50c822e4610 100644 --- a/layout/tables/nsTableOuterFrame.cpp +++ b/layout/tables/nsTableOuterFrame.cpp @@ -827,15 +827,12 @@ nsTableOuterFrame::OuterBeginReflowChild(nsPresContext* aPresContext, -1, -1, false); InitChildReflowState(*aPresContext, childRS); - // see if we need to reset top of page due to a caption - if (mCaptionFrames.NotEmpty()) { + // see if we need to reset top-of-page due to a caption + if (childRS.mFlags.mIsTopOfPage && + mCaptionFrames.FirstChild() == aChildFrame) { uint8_t captionSide = GetCaptionSide(); - if (((captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM || - captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE) && - mCaptionFrames.FirstChild() == aChildFrame) || - ((captionSide == NS_STYLE_CAPTION_SIDE_TOP || - captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE) && - InnerTableFrame() == aChildFrame)) { + if (captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM || + captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE) { childRS.mFlags.mIsTopOfPage = false; } } From 7ec6b9edf14eeaec33c582eb0949ed05f97c0fcc Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Mon, 26 Aug 2013 14:07:34 -0400 Subject: [PATCH 43/85] Bug 908919 - Backout 1117002f074f:c03239a1493a (bug 906088) for causing Ts regressions; r=performance-is-job-1 --- build/mobile/robocop/Actions.java.in | 16 ----- .../robocop/FennecNativeActions.java.in | 22 ------- mobile/android/base/GeckoEvent.java | 20 +------ mobile/android/base/GeckoPreferences.java | 4 +- mobile/android/base/PrefsHelper.java | 40 +++++++++---- mobile/android/base/RobocopAPI.java | 8 --- mobile/android/base/gfx/Axis.java | 13 ++-- .../base/gfx/DisplayPortCalculator.java | 25 ++++---- .../base/tests/testAddonManager.java.in | 15 +++-- .../base/tests/testDistribution.java.in | 59 ++++++++++++------- .../android/base/tests/testDoorHanger.java.in | 15 +++-- .../base/tests/testPasswordEncrypt.java.in | 15 +++-- .../base/tests/testPrefsObserver.java.in | 16 +++-- mobile/android/chrome/content/browser.js | 35 +++++------ widget/android/AndroidJavaWrappers.cpp | 59 +++++++------------ widget/android/AndroidJavaWrappers.h | 10 ---- widget/android/nsAppShell.cpp | 16 ----- widget/android/nsIAndroidBridge.idl | 8 +-- 18 files changed, 166 insertions(+), 230 deletions(-) diff --git a/build/mobile/robocop/Actions.java.in b/build/mobile/robocop/Actions.java.in index 14b72e8effec..e96420755483 100644 --- a/build/mobile/robocop/Actions.java.in +++ b/build/mobile/robocop/Actions.java.in @@ -48,22 +48,6 @@ public interface Actions { */ void sendGeckoEvent(String geckoEvent, String data); - /** - * Sends a preferences get event to Gecko. - * - * @param requestId The id of this request. - * @param prefNames The preferences being requested. - */ - void sendPreferencesGetEvent(int requestId, String[] prefNames); - - /** - * Sends a preferences observe event to Gecko. - * - * @param requestId The id of this request. - * @param prefNames The preferences being requested. - */ - void sendPreferencesObserveEvent(int requestId, String[] prefNames); - /** * Listens for a gecko event to be sent from the Gecko instance. * The returned object can be used to test if the event has been diff --git a/build/mobile/robocop/FennecNativeActions.java.in b/build/mobile/robocop/FennecNativeActions.java.in index 81295ddfabb8..9813fd8746c5 100644 --- a/build/mobile/robocop/FennecNativeActions.java.in +++ b/build/mobile/robocop/FennecNativeActions.java.in @@ -44,8 +44,6 @@ public class FennecNativeActions implements Actions { private Method mRegisterEventListener; private Method mUnregisterEventListener; private Method mBroadcastEvent; - private Method mPreferencesGetEvent; - private Method mPreferencesObserveEvent; private Method mSetDrawListener; private Method mQuerySql; private Object mRobocopApi; @@ -68,8 +66,6 @@ public class FennecNativeActions implements Actions { mRegisterEventListener = mApiClass.getMethod("registerEventListener", String.class, mEventListenerClass); mUnregisterEventListener = mApiClass.getMethod("unregisterEventListener", String.class, mEventListenerClass); mBroadcastEvent = mApiClass.getMethod("broadcastEvent", String.class, String.class); - mPreferencesGetEvent = mApiClass.getMethod("preferencesGetEvent", Integer.TYPE, String[].class); - mPreferencesObserveEvent = mApiClass.getMethod("preferencesObserveEvent", Integer.TYPE, String[].class); mSetDrawListener = mApiClass.getMethod("setDrawListener", mDrawListenerClass); mQuerySql = mApiClass.getMethod("querySql", String.class, String.class); @@ -269,24 +265,6 @@ public class FennecNativeActions implements Actions { } } - private void sendPreferencesEvent(Method method, int requestId, String[] prefNames) { - try { - method.invoke(mRobocopApi, requestId, prefNames); - } catch (IllegalAccessException e) { - FennecNativeDriver.log(LogLevel.ERROR, e); - } catch (InvocationTargetException e) { - FennecNativeDriver.log(LogLevel.ERROR, e); - } - } - - public void sendPreferencesGetEvent(int requestId, String[] prefNames) { - sendPreferencesEvent(mPreferencesGetEvent, requestId, prefNames); - } - - public void sendPreferencesObserveEvent(int requestId, String[] prefNames) { - sendPreferencesEvent(mPreferencesObserveEvent, requestId, prefNames); - } - class DrawListenerProxy implements InvocationHandler { private final PaintExpecter mPaintExpecter; diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index ef9c1c411528..1bd59a8e390d 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -67,9 +67,7 @@ public class GeckoEvent { REMOVE_OBSERVER(34), LOW_MEMORY(35), NETWORK_LINK_CHANGE(36), - TELEMETRY_HISTOGRAM_ADD(37), - PREFERENCES_OBSERVE(38), - PREFERENCES_GET(39); + TELEMETRY_HISTOGRAM_ADD(37); public final int value; @@ -188,8 +186,6 @@ public class GeckoEvent { private int mWidth; private int mHeight; - private String[] mPrefNames; - private GeckoEvent(NativeGeckoEvent event) { mType = event.value; } @@ -693,20 +689,6 @@ public class GeckoEvent { return event; } - public static GeckoEvent createPreferencesObserveEvent(int requestId, String[] prefNames) { - GeckoEvent event = new GeckoEvent(NativeGeckoEvent.PREFERENCES_OBSERVE); - event.mCount = requestId; - event.mPrefNames = prefNames; - return event; - } - - public static GeckoEvent createPreferencesGetEvent(int requestId, String[] prefNames) { - GeckoEvent event = new GeckoEvent(NativeGeckoEvent.PREFERENCES_GET); - event.mCount = requestId; - event.mPrefNames = prefNames; - return event; - } - public static GeckoEvent createLowMemoryEvent(int level) { GeckoEvent event = new GeckoEvent(NativeGeckoEvent.LOW_MEMORY); event.mMetaState = level; diff --git a/mobile/android/base/GeckoPreferences.java b/mobile/android/base/GeckoPreferences.java index c61521ff1ba5..29b928de70ff 100644 --- a/mobile/android/base/GeckoPreferences.java +++ b/mobile/android/base/GeckoPreferences.java @@ -664,7 +664,9 @@ public class GeckoPreferences // Initialize preferences by requesting the preference values from Gecko private int getGeckoPreferences(final PreferenceGroup screen, ArrayList prefs) { - return PrefsHelper.getPrefs(prefs, new PrefsHelper.PrefHandlerBase() { + JSONArray jsonPrefs = new JSONArray(prefs); + + return PrefsHelper.getPrefs(jsonPrefs, new PrefsHelper.PrefHandlerBase() { private Preference getField(String prefName) { return screen.findPreference(prefName); } diff --git a/mobile/android/base/PrefsHelper.java b/mobile/android/base/PrefsHelper.java index b3f97371af52..d2a1538a4403 100644 --- a/mobile/android/base/PrefsHelper.java +++ b/mobile/android/base/PrefsHelper.java @@ -13,7 +13,6 @@ import org.json.JSONObject; import android.util.Log; -import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -28,18 +27,20 @@ public final class PrefsHelper { private static int sUniqueRequestId = 1; public static int getPref(String prefName, PrefHandler callback) { - return getPrefsInternal(new String[] { prefName }, callback); + JSONArray prefs = new JSONArray(); + prefs.put(prefName); + return getPrefs(prefs, callback); } public static int getPrefs(String[] prefNames, PrefHandler callback) { - return getPrefsInternal(prefNames, callback); + JSONArray prefs = new JSONArray(); + for (String p : prefNames) { + prefs.put(p); + } + return getPrefs(prefs, callback); } - public static int getPrefs(ArrayList prefNames, PrefHandler callback) { - return getPrefsInternal(prefNames.toArray(new String[prefNames.size()]), callback); - } - - private static int getPrefsInternal(String[] prefNames, PrefHandler callback) { + public static int getPrefs(JSONArray prefNames, PrefHandler callback) { int requestId; synchronized (PrefsHelper.class) { ensureRegistered(); @@ -49,12 +50,25 @@ public final class PrefsHelper { } GeckoEvent event; - if (callback.isObserver()) { - event = GeckoEvent.createPreferencesObserveEvent(requestId, prefNames); - } else { - event = GeckoEvent.createPreferencesGetEvent(requestId, prefNames); + try { + JSONObject message = new JSONObject(); + message.put("requestId", Integer.toString(requestId)); + message.put("preferences", prefNames); + event = GeckoEvent.createBroadcastEvent(callback.isObserver() ? + "Preferences:Observe" : "Preferences:Get", message.toString()); + GeckoAppShell.sendEventToGecko(event); + } catch (Exception e) { + Log.e(LOGTAG, "Error while composing Preferences:" + + (callback.isObserver() ? "Observe" : "Get") + " message", e); + + // if we failed to send the message, drop our reference to the callback because + // otherwise it will leak since we will never get the response + synchronized (PrefsHelper.class) { + sCallbacks.remove(requestId); + } + + return -1; } - GeckoAppShell.sendEventToGecko(event); return requestId; } diff --git a/mobile/android/base/RobocopAPI.java b/mobile/android/base/RobocopAPI.java index e03c28b6fe13..89941d4289c6 100644 --- a/mobile/android/base/RobocopAPI.java +++ b/mobile/android/base/RobocopAPI.java @@ -35,14 +35,6 @@ public class RobocopAPI { GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(subject, data)); } - public void preferencesGetEvent(int requestId, String[] prefNames) { - GeckoAppShell.sendEventToGecko(GeckoEvent.createPreferencesGetEvent(requestId, prefNames)); - } - - public void preferencesObserveEvent(int requestId, String[] prefNames) { - GeckoAppShell.sendEventToGecko(GeckoEvent.createPreferencesObserveEvent(requestId, prefNames)); - } - public void setDrawListener(GeckoLayerClient.DrawListener listener) { GeckoAppShell.getLayerView().getLayerClient().setDrawListener(listener); } diff --git a/mobile/android/base/gfx/Axis.java b/mobile/android/base/gfx/Axis.java index 9dc59685de9f..cf7db8fe0c9d 100644 --- a/mobile/android/base/gfx/Axis.java +++ b/mobile/android/base/gfx/Axis.java @@ -64,12 +64,13 @@ abstract class Axis { } static void initPrefs() { - final String[] prefs = { PREF_SCROLLING_FRICTION_FAST, - PREF_SCROLLING_FRICTION_SLOW, - PREF_SCROLLING_MAX_EVENT_ACCELERATION, - PREF_SCROLLING_OVERSCROLL_DECEL_RATE, - PREF_SCROLLING_OVERSCROLL_SNAP_LIMIT, - PREF_SCROLLING_MIN_SCROLLABLE_DISTANCE }; + JSONArray prefs = new JSONArray(); + prefs.put(PREF_SCROLLING_FRICTION_FAST); + prefs.put(PREF_SCROLLING_FRICTION_SLOW); + prefs.put(PREF_SCROLLING_MAX_EVENT_ACCELERATION); + prefs.put(PREF_SCROLLING_OVERSCROLL_DECEL_RATE); + prefs.put(PREF_SCROLLING_OVERSCROLL_SNAP_LIMIT); + prefs.put(PREF_SCROLLING_MIN_SCROLLABLE_DISTANCE); PrefsHelper.getPrefs(prefs, new PrefsHelper.PrefHandlerBase() { Map mPrefs = new HashMap(); diff --git a/mobile/android/base/gfx/DisplayPortCalculator.java b/mobile/android/base/gfx/DisplayPortCalculator.java index 442962da5e30..debc6e48e669 100644 --- a/mobile/android/base/gfx/DisplayPortCalculator.java +++ b/mobile/android/base/gfx/DisplayPortCalculator.java @@ -61,18 +61,19 @@ final class DisplayPortCalculator { } static void initPrefs() { - final String[] prefs = { PREF_DISPLAYPORT_STRATEGY, - PREF_DISPLAYPORT_FM_MULTIPLIER, - PREF_DISPLAYPORT_FM_DANGER_X, - PREF_DISPLAYPORT_FM_DANGER_Y, - PREF_DISPLAYPORT_VB_MULTIPLIER, - PREF_DISPLAYPORT_VB_VELOCITY_THRESHOLD, - PREF_DISPLAYPORT_VB_REVERSE_BUFFER, - PREF_DISPLAYPORT_VB_DANGER_X_BASE, - PREF_DISPLAYPORT_VB_DANGER_Y_BASE, - PREF_DISPLAYPORT_VB_DANGER_X_INCR, - PREF_DISPLAYPORT_VB_DANGER_Y_INCR, - PREF_DISPLAYPORT_PB_VELOCITY_THRESHOLD }; + JSONArray prefs = new JSONArray(); + prefs.put(PREF_DISPLAYPORT_STRATEGY); + prefs.put(PREF_DISPLAYPORT_FM_MULTIPLIER); + prefs.put(PREF_DISPLAYPORT_FM_DANGER_X); + prefs.put(PREF_DISPLAYPORT_FM_DANGER_Y); + prefs.put(PREF_DISPLAYPORT_VB_MULTIPLIER); + prefs.put(PREF_DISPLAYPORT_VB_VELOCITY_THRESHOLD); + prefs.put(PREF_DISPLAYPORT_VB_REVERSE_BUFFER); + prefs.put(PREF_DISPLAYPORT_VB_DANGER_X_BASE); + prefs.put(PREF_DISPLAYPORT_VB_DANGER_Y_BASE); + prefs.put(PREF_DISPLAYPORT_VB_DANGER_X_INCR); + prefs.put(PREF_DISPLAYPORT_VB_DANGER_Y_INCR); + prefs.put(PREF_DISPLAYPORT_PB_VELOCITY_THRESHOLD); PrefsHelper.getPrefs(prefs, new PrefsHelper.PrefHandlerBase() { private Map mValues = new HashMap(); diff --git a/mobile/android/base/tests/testAddonManager.java.in b/mobile/android/base/tests/testAddonManager.java.in index a932b3c394a0..148b5920cca9 100644 --- a/mobile/android/base/tests/testAddonManager.java.in +++ b/mobile/android/base/tests/testAddonManager.java.in @@ -59,18 +59,21 @@ public class testAddonManager extends PixelTest { mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString()); // Wait for confirmation of the pref change before proceeding with the test. - final String[] prefNames = { "extensions.getAddons.browseAddons" }; - final int ourRequestId = 0x7357; + JSONArray getPrefData = new JSONArray(); + getPrefData.put("extensions.getAddons.browseAddons"); + JSONObject message = new JSONObject(); + message.put("requestId", "testAddonManager"); + message.put("preferences", getPrefData); Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data"); - mActions.sendPreferencesGetEvent(ourRequestId, prefNames); + mActions.sendGeckoEvent("Preferences:Get", message.toString()); JSONObject data = null; - int requestId = -1; + String requestId = ""; // Wait until we get the correct "Preferences:Data" event - while (requestId != ourRequestId) { + while (!requestId.equals("testAddonManager")) { data = new JSONObject(eventExpecter.blockForEventData()); - requestId = data.getInt("requestId"); + requestId = data.getString("requestId"); } eventExpecter.unregisterListener(); diff --git a/mobile/android/base/tests/testDistribution.java.in b/mobile/android/base/tests/testDistribution.java.in index 6b094c92d11b..a918cf7cebe6 100644 --- a/mobile/android/base/tests/testDistribution.java.in +++ b/mobile/android/base/tests/testDistribution.java.in @@ -29,7 +29,7 @@ import org.json.JSONObject; */ public class testDistribution extends ContentProviderTest { private static final String MOCK_PACKAGE = "mock-package.zip"; - private static final int PREF_REQUEST_ID = 0x7357; + private static final String PREF_REQUEST_ID = "testDistribution"; private Activity mActivity; @@ -86,23 +86,28 @@ public class testDistribution extends ContentProviderTest { String prefTestInt = "distribution.test.int"; try { - final String[] prefNames = { prefID, - prefAbout, - prefVersion, - prefTestBoolean, - prefTestString, - prefTestInt }; + JSONArray getPrefData = new JSONArray(); + getPrefData.put(prefID); + getPrefData.put(prefAbout); + getPrefData.put(prefVersion); + getPrefData.put(prefTestBoolean); + getPrefData.put(prefTestString); + getPrefData.put(prefTestInt); + + JSONObject message = new JSONObject(); + message.put("requestId", PREF_REQUEST_ID); + message.put("preferences", getPrefData); Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data"); - mActions.sendPreferencesGetEvent(PREF_REQUEST_ID, prefNames); + mActions.sendGeckoEvent("Preferences:Get", message.toString()); JSONObject data = null; - int requestId = -1; + String requestId = ""; // Wait until we get the correct "Preferences:Data" event - while (requestId != PREF_REQUEST_ID) { + while (!requestId.equals(PREF_REQUEST_ID)) { data = new JSONObject(eventExpecter.blockForEventData()); - requestId = data.getInt("requestId"); + requestId = data.getString("requestId"); } eventExpecter.unregisterListener(); @@ -167,18 +172,23 @@ public class testDistribution extends ContentProviderTest { mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString()); // Wait for confirmation of the pref change. - final String[] prefNames = { prefUseragentLocale }; + JSONArray getPrefData = new JSONArray(); + getPrefData.put(prefUseragentLocale); + + JSONObject message = new JSONObject(); + message.put("requestId", PREF_REQUEST_ID); + message.put("preferences", getPrefData); Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data"); - mActions.sendPreferencesGetEvent(PREF_REQUEST_ID, prefNames); + mActions.sendGeckoEvent("Preferences:Get", message.toString()); JSONObject data = null; - int requestId = -1; + String requestId = ""; // Wait until we get the correct "Preferences:Data" event - while (requestId != PREF_REQUEST_ID) { + while (!requestId.equals(PREF_REQUEST_ID)) { data = new JSONObject(eventExpecter.blockForEventData()); - requestId = data.getInt("requestId"); + requestId = data.getString("requestId"); } eventExpecter.unregisterListener(); @@ -194,18 +204,25 @@ public class testDistribution extends ContentProviderTest { String prefLocalizeableOverride = "distribution.test.localizeable-override"; try { - final String[] prefNames = { prefAbout, prefLocalizeable, prefLocalizeableOverride }; + JSONArray getPrefData = new JSONArray(); + getPrefData.put(prefAbout); + getPrefData.put(prefLocalizeable); + getPrefData.put(prefLocalizeableOverride); + + JSONObject message = new JSONObject(); + message.put("requestId", PREF_REQUEST_ID); + message.put("preferences", getPrefData); Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data"); - mActions.sendPreferencesGetEvent(PREF_REQUEST_ID, prefNames); + mActions.sendGeckoEvent("Preferences:Get", message.toString()); JSONObject data = null; - int requestId = -1; + String requestId = ""; // Wait until we get the correct "Preferences:Data" event - while (requestId != PREF_REQUEST_ID) { + while (!requestId.equals(PREF_REQUEST_ID)) { data = new JSONObject(eventExpecter.blockForEventData()); - requestId = data.getInt("requestId"); + requestId = data.getString("requestId"); } eventExpecter.unregisterListener(); diff --git a/mobile/android/base/tests/testDoorHanger.java.in b/mobile/android/base/tests/testDoorHanger.java.in index 516351e00d3b..a88307a64781 100644 --- a/mobile/android/base/tests/testDoorHanger.java.in +++ b/mobile/android/base/tests/testDoorHanger.java.in @@ -81,19 +81,22 @@ public class testDoorHanger extends BaseTest { boolean offlineAllowedByDefault = true; try { // Save offline-allow-by-default preferences first - final String[] prefNames = { "offline-apps.allow_by_default" }; - final int ourRequestId = 0x7357; + JSONArray getPrefData = new JSONArray(); + getPrefData.put("offline-apps.allow_by_default"); + JSONObject message = new JSONObject(); + message.put("requestId", "testDoorHanger"); + message.put("preferences", getPrefData); Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data"); - mActions.sendPreferencesGetEvent(ourRequestId, prefNames); + mActions.sendGeckoEvent("Preferences:Get", message.toString()); JSONObject data = null; - int requestId = -1; + String requestId = ""; // Wait until we get the correct "Preferences:Data" event - while (requestId != ourRequestId) { + while (!requestId.equals("testDoorHanger")) { data = new JSONObject(eventExpecter.blockForEventData()); - requestId = data.getInt("requestId"); + requestId = data.getString("requestId"); } eventExpecter.unregisterListener(); diff --git a/mobile/android/base/tests/testPasswordEncrypt.java.in b/mobile/android/base/tests/testPasswordEncrypt.java.in index aa408283b982..b43e6168776b 100644 --- a/mobile/android/base/tests/testPasswordEncrypt.java.in +++ b/mobile/android/base/tests/testPasswordEncrypt.java.in @@ -126,18 +126,21 @@ public class testPasswordEncrypt extends BaseTest { mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString()); // Wait for confirmation of the pref change before proceeding with the test. - final String[] prefNames = { "privacy.masterpassword.enabled" }; - final int ourRequestId = 0x73577; + JSONArray getPrefData = new JSONArray(); + getPrefData.put("privacy.masterpassword.enabled"); + JSONObject message = new JSONObject(); + message.put("requestId", "testPasswordEncrypt"); + message.put("preferences", getPrefData); Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data"); - mActions.sendPreferencesGetEvent(ourRequestId, prefNames); + mActions.sendGeckoEvent("Preferences:Get", message.toString()); JSONObject data = null; - int requestId = -1; + String requestId = ""; // Wait until we get the correct "Preferences:Data" event - while (requestId != ourRequestId) { + while (!requestId.equals("testPasswordEncrypt")) { data = new JSONObject(eventExpecter.blockForEventData()); - requestId = data.getInt("requestId"); + requestId = data.getString("requestId"); } } catch (Exception ex) { mAsserter.ok(false, "exception in toggleMasterPassword", ex.toString()); diff --git a/mobile/android/base/tests/testPrefsObserver.java.in b/mobile/android/base/tests/testPrefsObserver.java.in index c7ce6d8e099d..7321d88846c7 100644 --- a/mobile/android/base/tests/testPrefsObserver.java.in +++ b/mobile/android/base/tests/testPrefsObserver.java.in @@ -16,7 +16,6 @@ import org.json.JSONObject; */ public class testPrefsObserver extends BaseTest { private static final String PREF_TEST_PREF = "robocop.tests.dummy"; - private static final int PREF_OBSERVE_REQUEST_ID = 0x7357; private static final String PREF_REQUEST_ID = "testPrefsObserver"; private static final long PREF_TIMEOUT = 10000; @@ -41,15 +40,15 @@ public class testPrefsObserver extends BaseTest { mAsserter.dumpLog("Waiting to check pref"); JSONObject data = null; - int requestId = -1; + String requestId = ""; - while (requestId != PREF_OBSERVE_REQUEST_ID) { + while (!requestId.equals(PREF_REQUEST_ID)) { data = new JSONObject(mExpecter.blockForEventData()); if (!mExpecter.eventReceived()) { mAsserter.ok(false, "Checking pref is correct value", "Didn't receive pref"); return; } - requestId = data.getInt("requestId"); + requestId = data.getString("requestId"); } JSONObject pref = data.getJSONArray("preferences").getJSONObject(0); @@ -81,14 +80,19 @@ public class testPrefsObserver extends BaseTest { mAsserter.dumpLog("Setting up pref observer"); // Setup the pref observer + JSONArray getPrefData = new JSONArray(); + getPrefData.put(PREF_TEST_PREF); + JSONObject message = new JSONObject(); + message.put("requestId", PREF_REQUEST_ID); + message.put("preferences", getPrefData); mExpecter = mActions.expectGeckoEvent("Preferences:Data"); - mActions.sendPreferencesObserveEvent(PREF_OBSERVE_REQUEST_ID, new String[] { PREF_TEST_PREF }); + mActions.sendGeckoEvent("Preferences:Observe", message.toString()); } public void removePrefObserver() { mAsserter.dumpLog("Removing pref observer"); - mActions.sendGeckoEvent("Preferences:RemoveObservers", Integer.toString(PREF_OBSERVE_REQUEST_ID)); + mActions.sendGeckoEvent("Preferences:RemoveObservers", PREF_REQUEST_ID); } public void testPrefsObserver() { diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index b4ff4cd79a82..2d7de494939b 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -278,7 +278,9 @@ var BrowserApp = { Services.obs.addObserver(this, "Session:Stop", false); Services.obs.addObserver(this, "SaveAs:PDF", false); Services.obs.addObserver(this, "Browser:Quit", false); + Services.obs.addObserver(this, "Preferences:Get", false); Services.obs.addObserver(this, "Preferences:Set", false); + Services.obs.addObserver(this, "Preferences:Observe", false); Services.obs.addObserver(this, "Preferences:RemoveObservers", false); Services.obs.addObserver(this, "ScrollTo:FocusedInput", false); Services.obs.addObserver(this, "Sanitize:ClearData", false); @@ -986,17 +988,16 @@ var BrowserApp = { notifyPrefObservers: function(aPref) { this._prefObservers[aPref].forEach(function(aRequestId) { - this.getPreferences(aRequestId, [aPref], 1); + let request = { requestId : aRequestId, + preferences : [aPref] }; + this.getPreferences(request); }, this); }, - handlePreferencesRequest: function handlePreferencesRequest(aRequestId, - aPrefNames, - aListen) { - + getPreferences: function getPreferences(aPrefsRequest, aListen) { let prefs = []; - for (let prefName of aPrefNames) { + for (let prefName of aPrefsRequest.preferences) { let pref = { name: prefName, type: "", @@ -1005,9 +1006,9 @@ var BrowserApp = { if (aListen) { if (this._prefObservers[prefName]) - this._prefObservers[prefName].push(aRequestId); + this._prefObservers[prefName].push(aPrefsRequest.requestId); else - this._prefObservers[prefName] = [ aRequestId ]; + this._prefObservers[prefName] = [ aPrefsRequest.requestId ]; Services.prefs.addObserver(prefName, this, false); } @@ -1114,7 +1115,7 @@ var BrowserApp = { sendMessageToJava({ type: "Preferences:Data", - requestId: aRequestId, // opaque request identifier, can be any string/int/whatever + requestId: aPrefsRequest.requestId, // opaque request identifier, can be any string/int/whatever preferences: prefs }); }, @@ -1437,10 +1438,18 @@ var BrowserApp = { this.saveAsPDF(browser); break; + case "Preferences:Get": + this.getPreferences(JSON.parse(aData)); + break; + case "Preferences:Set": this.setPreferences(aData); break; + case "Preferences:Observe": + this.getPreferences(JSON.parse(aData), true); + break; + case "Preferences:RemoveObservers": this.removePreferenceObservers(aData); break; @@ -1518,14 +1527,6 @@ var BrowserApp = { return this.getTabForId(tabId); }, - getPreferences: function getPreferences(requestId, prefNames, count) { - this.handlePreferencesRequest(requestId, prefNames, false); - }, - - observePreferences: function observePreferences(requestId, prefNames, count) { - this.handlePreferencesRequest(requestId, prefNames, true); - }, - // This method will print a list from fromIndex to toIndex, optionally // selecting selIndex(if fromIndex<=selIndex<=toIndex) showHistory: function(fromIndex, toIndex, selIndex) { diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index dc5b8243e33a..a7df5501fe02 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -60,7 +60,6 @@ jfieldID AndroidGeckoEvent::jScreenOrientationField = 0; jfieldID AndroidGeckoEvent::jByteBufferField = 0; jfieldID AndroidGeckoEvent::jWidthField = 0; jfieldID AndroidGeckoEvent::jHeightField = 0; -jfieldID AndroidGeckoEvent::jPrefNamesField = 0; jclass AndroidGeckoEvent::jDomKeyLocationClass = 0; jfieldID AndroidGeckoEvent::jDomKeyLocationValueField = 0; @@ -267,7 +266,6 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) jByteBufferField = getField("mBuffer", "Ljava/nio/ByteBuffer;"); jWidthField = getField("mWidth", "I"); jHeightField = getField("mHeight", "I"); - jPrefNamesField = getField("mPrefNames", "[Ljava/lang/String;"); // Init GeckoEvent.DomKeyLocation enum jDomKeyLocationClass = getClassGlobalRef("org/mozilla/gecko/GeckoEvent$DomKeyLocation"); @@ -477,21 +475,6 @@ AndroidGeckoEvent::ReadFloatArray(nsTArray &aVals, jenv->ReleaseFloatArrayElements(jFloatArray, vals, JNI_ABORT); } -void -AndroidGeckoEvent::ReadStringArray(nsTArray &array, - JNIEnv *jenv, - jfieldID field) -{ - jarray jArray = (jarray)jenv->GetObjectField(wrapped_obj, field); - jsize length = jenv->GetArrayLength(jArray); - jobjectArray jStringArray = (jobjectArray)jArray; - nsString *strings = array.AppendElements(length); - for (jsize i = 0; i < length; ++i) { - jstring javastring = (jstring) jenv->GetObjectArrayElement(jStringArray, i); - ReadStringFromJString(strings[i], jenv, javastring); - } -} - void AndroidGeckoEvent::ReadRectField(JNIEnv *jenv) { @@ -507,38 +490,45 @@ AndroidGeckoEvent::ReadRectField(JNIEnv *jenv) } void -AndroidGeckoEvent::ReadStringFromJString(nsString &aString, JNIEnv *jenv, - jstring s) +AndroidGeckoEvent::ReadCharactersField(JNIEnv *jenv) { + jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jCharactersField); if (!s) { - aString.SetIsVoid(true); + mCharacters.SetIsVoid(true); return; } int len = jenv->GetStringLength(s); - aString.SetLength(len); - jenv->GetStringRegion(s, 0, len, aString.BeginWriting()); -} - -void -AndroidGeckoEvent::ReadCharactersField(JNIEnv *jenv) -{ - jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jCharactersField); - ReadStringFromJString(mCharacters, jenv, s); + mCharacters.SetLength(len); + jenv->GetStringRegion(s, 0, len, mCharacters.BeginWriting()); } void AndroidGeckoEvent::ReadCharactersExtraField(JNIEnv *jenv) { jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jCharactersExtraField); - ReadStringFromJString(mCharactersExtra, jenv, s); + if (!s) { + mCharactersExtra.SetIsVoid(true); + return; + } + + int len = jenv->GetStringLength(s); + mCharactersExtra.SetLength(len); + jenv->GetStringRegion(s, 0, len, mCharactersExtra.BeginWriting()); } void AndroidGeckoEvent::ReadDataField(JNIEnv *jenv) { jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jDataField); - ReadStringFromJString(mData, jenv, s); + if (!s) { + mData.SetIsVoid(true); + return; + } + + int len = jenv->GetStringLength(s); + mData.SetLength(len); + jenv->GetStringRegion(s, 0, len, mData.BeginWriting()); } void @@ -727,13 +717,6 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) break; } - case PREFERENCES_OBSERVE: - case PREFERENCES_GET: { - ReadStringArray(mPrefNames, jenv, jPrefNamesField); - mCount = jenv->GetIntField(jobj, jCountField); - break; - } - default: break; } diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index 7fe064b49258..63a0b27ca65e 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -539,7 +539,6 @@ public: const nsTArray& Pressures() { return mPressures; } const nsTArray& Orientations() { return mOrientations; } const nsTArray& PointRadii() { return mPointRadii; } - const nsTArray& PrefNames() { return mPrefNames; } double X() { return mX; } double Y() { return mY; } double Z() { return mZ; } @@ -578,7 +577,6 @@ public: RefCountedJavaObject* ByteBuffer() { return mByteBuffer; } int Width() { return mWidth; } int Height() { return mHeight; } - int RequestId() { return mCount; } // for convenience nsTouchEvent MakeTouchEvent(nsIWidget* widget); MultiTouchInput MakeMultiTouchInput(nsIWidget* widget); void UnionRect(nsIntRect const& aRect); @@ -614,7 +612,6 @@ protected: short mScreenOrientation; nsRefPtr mByteBuffer; int mWidth, mHeight; - nsTArray mPrefNames; void ReadIntArray(nsTArray &aVals, JNIEnv *jenv, @@ -628,14 +625,10 @@ protected: JNIEnv *jenv, jfieldID field, int32_t count); - void ReadStringArray(nsTArray &aStrings, - JNIEnv *jenv, - jfieldID field); void ReadRectField(JNIEnv *jenv); void ReadCharactersField(JNIEnv *jenv); void ReadCharactersExtraField(JNIEnv *jenv); void ReadDataField(JNIEnv *jenv); - void ReadStringFromJString(nsString &aString, JNIEnv *jenv, jstring s); uint32_t ReadDomKeyLocation(JNIEnv* jenv, jobject jGeckoEventObj); @@ -678,7 +671,6 @@ protected: static jfieldID jRangeBackColorField; static jfieldID jRangeLineColorField; static jfieldID jLocationField; - static jfieldID jPrefNamesField; static jfieldID jBandwidthField; static jfieldID jCanBeMeteredField; @@ -725,8 +717,6 @@ public: LOW_MEMORY = 35, NETWORK_LINK_CHANGE = 36, TELEMETRY_HISTOGRAM_ADD = 37, - PREFERENCES_OBSERVE = 38, - PREFERENCES_GET = 39, dummy_java_enum_list_end }; diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp index 717e59c560bb..e5fe13d85e0d 100644 --- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -541,22 +541,6 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) mObserversHash.Remove(curEvent->Characters()); break; - case AndroidGeckoEvent::PREFERENCES_GET: - case AndroidGeckoEvent::PREFERENCES_OBSERVE: { - const nsTArray &prefNames = curEvent->PrefNames(); - size_t count = prefNames.Length(); - nsAutoArrayPtr prefNamePtrs(new const PRUnichar*[count]); - for (size_t i = 0; i < count; ++i) { - prefNamePtrs[i] = prefNames[i].get(); - } - - if (curEvent->Type() == AndroidGeckoEvent::PREFERENCES_GET) { - mBrowserApp->GetPreferences(curEvent->RequestId(), prefNamePtrs, count); - } else { - mBrowserApp->ObservePreferences(curEvent->RequestId(), prefNamePtrs, count); - } - } - case AndroidGeckoEvent::LOW_MEMORY: // TODO hook in memory-reduction stuff for different levels here if (curEvent->MetaState() >= AndroidGeckoEvent::MEMORY_PRESSURE_MEDIUM) { diff --git a/widget/android/nsIAndroidBridge.idl b/widget/android/nsIAndroidBridge.idl index 9ba139ca5ff2..b7e05f0fa8be 100644 --- a/widget/android/nsIAndroidBridge.idl +++ b/widget/android/nsIAndroidBridge.idl @@ -11,15 +11,9 @@ interface nsIBrowserTab : nsISupports { readonly attribute float scale; }; -[scriptable, uuid(6455c49b-7497-4eb6-b137-c9e9b68462ec)] +[scriptable, uuid(d10377b4-1c90-493a-a532-63cb3f16ee2b)] interface nsIAndroidBrowserApp : nsISupports { nsIBrowserTab getBrowserTab(in int32_t tabId); - void getPreferences(in int32_t requestId, - [array, size_is(count)] in wstring prefNames, - in unsigned long count); - void observePreferences(in int32_t requestId, - [array, size_is(count)] in wstring prefNames, - in unsigned long count); }; [scriptable, uuid(59cfcb35-69b7-47b2-8155-32b193272666)] interface nsIAndroidViewport : nsISupports { From 990ec8e20cf62ba58b237efd2c11e818ffaf72ff Mon Sep 17 00:00:00 2001 From: William Chen Date: Mon, 26 Aug 2013 11:56:23 -0700 Subject: [PATCH 44/85] Bug 903290 - Add a memory reporter for the observer service. r=njn --- xpcom/ds/nsObserverList.h | 6 ++ xpcom/ds/nsObserverService.cpp | 176 ++++++++++++++++++++++++++++++++- xpcom/ds/nsObserverService.h | 10 ++ 3 files changed, 191 insertions(+), 1 deletion(-) diff --git a/xpcom/ds/nsObserverList.h b/xpcom/ds/nsObserverList.h index 6592c01d3104..bd46dcdbbad9 100644 --- a/xpcom/ds/nsObserverList.h +++ b/xpcom/ds/nsObserverList.h @@ -16,6 +16,10 @@ #include "nsISimpleEnumerator.h" #include "mozilla/Attributes.h" +namespace mozilla { +class ObserverServiceReporter; +} // namespace mozilla + struct ObserverRef { ObserverRef(const ObserverRef& o) : @@ -42,6 +46,8 @@ struct ObserverRef class nsObserverList : public nsCharPtrHashKey { + friend class mozilla::ObserverServiceReporter; + public: nsObserverList(const char *key) : nsCharPtrHashKey(key) { MOZ_COUNT_CTOR(nsObserverList); } diff --git a/xpcom/ds/nsObserverService.cpp b/xpcom/ds/nsObserverService.cpp index cb9cb4d1e31e..4b8448eb6d85 100644 --- a/xpcom/ds/nsObserverService.cpp +++ b/xpcom/ds/nsObserverService.cpp @@ -17,7 +17,9 @@ #include "nsThreadUtils.h" #include "nsIWeakReference.h" #include "nsEnumeratorUtils.h" +#include "nsIMemoryReporter.h" #include "mozilla/net/NeckoCommon.h" +#include "mozilla/Services.h" #define NOTIFY_GLOBAL_OBSERVERS @@ -44,6 +46,159 @@ GetObserverServiceLog() #define LOG(x) #endif /* PR_LOGGING */ +namespace mozilla { + +class ObserverServiceReporter MOZ_FINAL : public nsIMemoryMultiReporter +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIMEMORYMULTIREPORTER +protected: + static const size_t kSuspectReferentCount = 1000; + static PLDHashOperator CountReferents(nsObserverList* aObserverList, + void* aClosure); +}; + +NS_IMPL_ISUPPORTS1(ObserverServiceReporter, nsIMemoryMultiReporter) + +NS_IMETHODIMP +ObserverServiceReporter::GetName(nsACString& aName) +{ + aName.AssignLiteral("observer-service"); + return NS_OK; +} + +struct SuspectObserver { + SuspectObserver(const char* aTopic, size_t aReferentCount) + : topic(aTopic), referentCount(aReferentCount) {} + const char* topic; + size_t referentCount; +}; + +struct ReferentCount { + ReferentCount() : numStrong(0), numWeakAlive(0), numWeakDead(0) {} + size_t numStrong; + size_t numWeakAlive; + size_t numWeakDead; + nsTArray suspectObservers; +}; + +PLDHashOperator +ObserverServiceReporter::CountReferents(nsObserverList* aObserverList, + void* aClosure) +{ + if (!aObserverList) { + return PL_DHASH_NEXT; + } + + ReferentCount* referentCount = static_cast(aClosure); + + size_t numStrong = 0; + size_t numWeakAlive = 0; + size_t numWeakDead = 0; + + nsTArray& observers = aObserverList->mObservers; + for (uint32_t i = 0; i < observers.Length(); i++) { + if (observers[i].isWeakRef) { + nsCOMPtr observerRef( + do_QueryReferent(observers[i].asWeak())); + if (observerRef) { + numWeakAlive++; + } else { + numWeakDead++; + } + } else { + numStrong++; + } + } + + referentCount->numStrong += numStrong; + referentCount->numWeakAlive += numWeakAlive; + referentCount->numWeakDead += numWeakDead; + + // Keep track of topics that have a suspiciously large number + // of referents (symptom of leaks). + size_t total = numStrong + numWeakAlive + numWeakDead; + if (total > kSuspectReferentCount) { + SuspectObserver suspect(aObserverList->GetKey(), total); + referentCount->suspectObservers.AppendElement(suspect); + } + + return PL_DHASH_NEXT; +} + +NS_IMETHODIMP +ObserverServiceReporter::CollectReports(nsIMemoryMultiReporterCallback* cb, + nsISupports* aClosure) +{ + nsCOMPtr os = mozilla::services::GetObserverService(); + nsObserverService* service = static_cast(os.get()); + if (!service) { + return NS_OK; + } + + ReferentCount referentCount; + service->mObserverTopicTable.EnumerateEntries(CountReferents, + &referentCount); + + nsresult rv; + for (uint32_t i = 0; i < referentCount.suspectObservers.Length(); i++) { + SuspectObserver& suspect = referentCount.suspectObservers[i]; + nsPrintfCString suspectPath("observer-service-suspect/" + "referent(topic=%s)", + suspect.topic); + rv = cb->Callback(/* process */ EmptyCString(), + suspectPath, + nsIMemoryReporter::KIND_OTHER, + nsIMemoryReporter::UNITS_COUNT, + suspect.referentCount, + NS_LITERAL_CSTRING("A topic with a suspiciously large number " + "referents (symptom of a leak)."), + aClosure); + + NS_ENSURE_SUCCESS(rv, rv); + } + + rv = cb->Callback(/* process */ EmptyCString(), + NS_LITERAL_CSTRING("observer-service/referent/strong"), + nsIMemoryReporter::KIND_OTHER, + nsIMemoryReporter::UNITS_COUNT, + referentCount.numStrong, + NS_LITERAL_CSTRING("The number of strong references held by the " + "observer service."), + aClosure); + + NS_ENSURE_SUCCESS(rv, rv); + + rv = cb->Callback(/* process */ EmptyCString(), + NS_LITERAL_CSTRING("observer-service/referent/weak/alive"), + nsIMemoryReporter::KIND_OTHER, + nsIMemoryReporter::UNITS_COUNT, + referentCount.numWeakAlive, + NS_LITERAL_CSTRING("The number of weak references held by the " + "observer service that are still alive."), + aClosure); + + NS_ENSURE_SUCCESS(rv, rv); + + rv = cb->Callback(/* process */ EmptyCString(), + NS_LITERAL_CSTRING("observer-service/referent/weak/dead"), + nsIMemoryReporter::KIND_OTHER, + nsIMemoryReporter::UNITS_COUNT, + referentCount.numWeakDead, + NS_LITERAL_CSTRING("The number of weak references held by the " + "observer service that are dead."), + aClosure); + + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +} // namespace mozilla + +using namespace mozilla; + //////////////////////////////////////////////////////////////////////////////// // nsObserverService Implementation @@ -51,7 +206,7 @@ GetObserverServiceLog() NS_IMPL_ISUPPORTS2(nsObserverService, nsIObserverService, nsObserverService) nsObserverService::nsObserverService() : - mShuttingDown(false) + mShuttingDown(false), mReporter(nullptr) { mObserverTopicTable.Init(); } @@ -61,9 +216,20 @@ nsObserverService::~nsObserverService(void) Shutdown(); } +void +nsObserverService::RegisterReporter() +{ + mReporter = new ObserverServiceReporter(); + NS_RegisterMemoryMultiReporter(mReporter); +} + void nsObserverService::Shutdown() { + if (mReporter) { + NS_UnregisterMemoryMultiReporter(mReporter); + } + mShuttingDown = true; if (mObserverTopicTable.IsInitialized()) @@ -80,6 +246,13 @@ nsObserverService::Create(nsISupports* outer, const nsIID& aIID, void* *aInstanc if (!os || !os->mObserverTopicTable.IsInitialized()) return NS_ERROR_OUT_OF_MEMORY; + // The memory reporter can not be immediately registered here because + // the nsMemoryReporterManager may attempt to get the nsObserverService + // during initialization, causing a recursive GetService. + nsRefPtr > registerRunnable = + NS_NewRunnableMethod(os, &nsObserverService::RegisterReporter); + NS_DispatchToCurrentThread(registerRunnable); + return os->QueryInterface(aIID, aInstancePtr); } @@ -187,3 +360,4 @@ nsObserverService::UnmarkGrayStrongObservers() return NS_OK; } + diff --git a/xpcom/ds/nsObserverService.h b/xpcom/ds/nsObserverService.h index 31d8b152226b..0c559a8a1ec3 100644 --- a/xpcom/ds/nsObserverService.h +++ b/xpcom/ds/nsObserverService.h @@ -15,7 +15,15 @@ #define NS_OBSERVERSERVICE_CID \ { 0xd07f5195, 0xe3d1, 0x11d2, { 0x8a, 0xcd, 0x0, 0x10, 0x5a, 0x1b, 0x88, 0x60 } } +class nsIMemoryMultiReporter; + +namespace mozilla { +class ObserverServiceReporter; +} // namespace mozilla + class nsObserverService MOZ_FINAL : public nsIObserverService { + friend class mozilla::ObserverServiceReporter; + public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_OBSERVERSERVICE_CID) @@ -35,9 +43,11 @@ public: private: ~nsObserverService(void); + void RegisterReporter(); bool mShuttingDown; nsTHashtable mObserverTopicTable; + nsCOMPtr mReporter; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsObserverService, NS_OBSERVERSERVICE_CID) From ebb7ef4ee38ed0bc84f06e7b66e247566716190d Mon Sep 17 00:00:00 2001 From: Ben Brittain Date: Mon, 26 Aug 2013 14:33:31 -0400 Subject: [PATCH 45/85] Bug 874175 - Add telemetry for ice success rates. r=derf --- dom/media/PeerConnection.js | 3 +++ toolkit/components/telemetry/Histograms.json | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/dom/media/PeerConnection.js b/dom/media/PeerConnection.js index e2d505dfe754..4306a0d52a6a 100644 --- a/dom/media/PeerConnection.js +++ b/dom/media/PeerConnection.js @@ -1015,6 +1015,7 @@ PeerConnectionObserver.prototype = { }, handleIceStateChanges: function(iceState) { + var histogram = Services.telemetry.getHistogramById("WEBRTC_ICE_SUCCESS_RATE"); switch (iceState) { case Ci.IPeerConnection.kIceWaiting: this._dompc.changeIceConnectionState("new"); @@ -1033,10 +1034,12 @@ PeerConnectionObserver.prototype = { break; case Ci.IPeerConnection.kIceConnected: // ICE gathering complete. + histogram.add(true); this._dompc.changeIceConnectionState("connected"); this.callCB(this._onicechange, "connected"); break; case Ci.IPeerConnection.kIceFailed: + histogram.add(false); this._dompc.changeIceConnectionState("failed"); this.callCB(this._onicechange, "failed"); break; diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index ba8f68342a94..420d1f05c7e1 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -3498,6 +3498,10 @@ "n_buckets": "1000", "description": "The time (in milliseconds) that it took a 'detach' request to go round trip." }, + "WEBRTC_ICE_SUCCESS_RATE":{ + "kind": "boolean", + "description": "The number of failed ICE Connections (0) vs. number of successful ICE connections (1)." + }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_TRACERDETACH_MS": { "kind": "exponential", "high": "10000", From 977802dfc8c37dc7a6e55b5ca0c2d8ffa338324f Mon Sep 17 00:00:00 2001 From: Georg Fritzsche Date: Mon, 26 Aug 2013 16:48:41 +0200 Subject: [PATCH 46/85] Bug 905084 - Fix "Activate this plugin" action in context menu. r=jaws --- browser/base/content/nsContextMenu.js | 2 +- browser/base/content/test/Makefile.in | 7 ++ .../content/test/browser_CTP_context_menu.js | 103 ++++++++++++++++++ 3 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 browser/base/content/test/browser_CTP_context_menu.js diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js index 5aa48f6c3f10..106762610472 100644 --- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -1285,7 +1285,7 @@ nsContextMenu.prototype = { }, playPlugin: function() { - gPluginHandler.activateSinglePlugin(this.target.ownerDocument.defaultView.top, this.target); + gPluginHandler._showClickToPlayNotification(this.browser, this.target); }, hidePlugin: function() { diff --git a/browser/base/content/test/Makefile.in b/browser/base/content/test/Makefile.in index 0e3174f6a6ef..22c6671dceab 100644 --- a/browser/base/content/test/Makefile.in +++ b/browser/base/content/test/Makefile.in @@ -373,4 +373,11 @@ MOCHITEST_BROWSER_FILES += \ $(NULL) endif +# browser_CTP_context_menu.js fails intermittently on Linux (bug 909342) +ifndef MOZ_WIDGET_GTK +MOCHITEST_BROWSER_FILES += \ + browser_CTP_context_menu.js \ + $(NULL) +endif + include $(topsrcdir)/config/rules.mk diff --git a/browser/base/content/test/browser_CTP_context_menu.js b/browser/base/content/test/browser_CTP_context_menu.js new file mode 100644 index 000000000000..3dcff2b8b2b6 --- /dev/null +++ b/browser/base/content/test/browser_CTP_context_menu.js @@ -0,0 +1,103 @@ +var rootDir = getRootDirectory(gTestPath); +const gTestRoot = rootDir; +const gHttpTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); + +var gTestBrowser = null; +var gNextTest = null; +var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); + +Components.utils.import("resource://gre/modules/Services.jsm"); + +function test() { + waitForExplicitFinish(); + registerCleanupFunction(function() { + clearAllPluginPermissions(); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_ENABLED; + }); + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + + let newTab = gBrowser.addTab(); + gBrowser.selectedTab = newTab; + gTestBrowser = gBrowser.selectedBrowser; + gTestBrowser.addEventListener("load", pageLoad, true); + + Services.prefs.setBoolPref("plugins.click_to_play", true); + getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY; + + prepareTest(runAfterPluginBindingAttached(test1), gHttpTestRoot + "plugin_test.html"); +} + +function finishTest() { + clearAllPluginPermissions(); + gTestBrowser.removeEventListener("load", pageLoad, true); + gBrowser.removeCurrentTab(); + window.focus(); + finish(); +} + +function pageLoad() { + // The plugin events are async dispatched and can come after the load event + // This just allows the events to fire before we then go on to test the states + executeSoon(gNextTest); +} + +function prepareTest(nextTest, url) { + gNextTest = nextTest; + gTestBrowser.contentWindow.location = url; +} + +// Due to layout being async, "PluginBindAttached" may trigger later. +// This wraps a function to force a layout flush, thus triggering it, +// and schedules the function execution so they're definitely executed +// afterwards. +function runAfterPluginBindingAttached(func) { + return function() { + let doc = gTestBrowser.contentDocument; + let elems = doc.getElementsByTagName('embed'); + if (elems.length < 1) { + elems = doc.getElementsByTagName('object'); + } + elems[0].clientTop; + executeSoon(func); + }; +} + +// Test that the activate action in content menus for CTP plugins works +function test1() { + let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(popupNotification, "Test 1, Should have a click-to-play notification"); + + let plugin = gTestBrowser.contentDocument.getElementById("test"); + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(!objLoadingContent.activated, "Test 1, Plugin should not be activated"); + + window.document.addEventListener("popupshown", test2, false); + EventUtils.synthesizeMouseAtCenter(plugin, + { type: "contextmenu", button: 2 }, + gTestBrowser.contentWindow); +} + +function test2() { + window.document.removeEventListener("popupshown", test2, false); + let activate = window.document.getElementById("context-ctp-play"); + ok(activate, "Test 2, Should have a context menu entry for activating the plugin"); + + // Trigger the click-to-play popup + activate.doCommand(); + + let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(notification, "Test 2, Should have a click-to-play notification"); + ok(!notification.dismissed, "Test 2, The click-to-play notification should not be dismissed"); + + // Activate the plugin + PopupNotifications.panel.firstChild._primaryButton.click(); + + let plugin = gTestBrowser.contentDocument.getElementById("test"); + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + waitForCondition(() => objLoadingContent.activated, test3, "Waited too long for plugin to activate"); +} + +function test3() { + finishTest(); +} From 53890c2c91661caf9fe7ec8b45ac42ef86f06ccb Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Mon, 26 Aug 2013 12:35:28 -0400 Subject: [PATCH 47/85] Bug 909328 - make NativePropertyHook pointers resolvable at compile-time, rather than run-time; r=bz --- dom/bindings/Codegen.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index f9078068c5d5..992ae7949883 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -80,7 +80,14 @@ class CGNativePropertyHooks(CGThing): def declare(self): if self.descriptor.workers: return "" - return "extern const NativePropertyHooks* sNativePropertyHooks;\n" + return """// We declare this as an array so that retrieving a pointer to this +// binding's property hooks only requires compile/link-time resolvable +// address arithmetic. Declaring it as a pointer instead would require +// doing a run-time load to fetch a pointer to this binding's property +// hooks. And then structures which embedded a pointer to this structure +// would require a run-time load for proper initialization, which would +// then induce static constructors. Lots of static constructors. +extern const NativePropertyHooks sNativePropertyHooks[];""" def define(self): if self.descriptor.workers: return "" @@ -125,10 +132,9 @@ class CGNativePropertyHooks(CGThing): CGGeneric(constructorID), CGGeneric(parentHooks)], ",\n")), - pre="static const NativePropertyHooks sNativePropertyHooksStruct = {\n", + pre="const NativePropertyHooks sNativePropertyHooks[] = { {\n", post=("\n" - "};\n" - "const NativePropertyHooks* sNativePropertyHooks = &sNativePropertyHooksStruct;\n")).define() + "} };\n")).define() def NativePropertyHooks(descriptor): return "&sWorkerNativePropertyHooks" if descriptor.workers else "sNativePropertyHooks" From 54fb4bac29c21f5bfcc0cb34eb3d88efb0bbc5ce Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Sat, 6 Jul 2013 16:55:10 -0400 Subject: [PATCH 48/85] bug 899210 - convert camera control to WebIDL r=bz --- .../media/webrtc/MediaEngineWebRTCVideo.cpp | 4 +- dom/base/nsDOMClassInfo.cpp | 6 - dom/base/nsDOMClassInfoClasses.h | 1 - dom/bindings/Bindings.conf | 18 + dom/camera/DOMCameraControl.cpp | 431 ++++++++++-------- dom/camera/DOMCameraControl.h | 65 ++- dom/camera/DOMCameraManager.cpp | 4 +- dom/camera/FallbackCameraControl.cpp | 4 +- dom/camera/GonkCameraControl.cpp | 9 +- dom/camera/nsIDOMCameraManager.idl | 165 +------ dom/webidl/CameraControl.webidl | 195 ++++++++ dom/webidl/DummyBinding.webidl | 1 - dom/webidl/WebIDL.mk | 1 + 13 files changed, 523 insertions(+), 381 deletions(-) create mode 100644 dom/webidl/CameraControl.webidl diff --git a/content/media/webrtc/MediaEngineWebRTCVideo.cpp b/content/media/webrtc/MediaEngineWebRTCVideo.cpp index 85920cb1f8c4..55bb061cd565 100644 --- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp +++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp @@ -612,7 +612,7 @@ MediaEngineWebRTCVideoSource::AllocImpl() { mCameraThread, this, this, - mWindowId); + nsGlobalWindow::GetInnerWindowWithId(mWindowId)); mCameraManager->Register(mDOMCameraControl); } @@ -662,7 +662,7 @@ MediaEngineWebRTCVideoSource::SnapshotImpl() { // nsICameraGetCameraCallback nsresult -MediaEngineWebRTCVideoSource::HandleEvent(nsICameraControl* camera) { +MediaEngineWebRTCVideoSource::HandleEvent(nsISupports* /* unused */) { MOZ_ASSERT(NS_IsMainThread()); ReentrantMonitorAutoEnter sync(mCallbackMonitor); mNativeCameraControl = static_cast(mDOMCameraControl->GetNativeCameraControl().get()); diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 0d1801909039..59845a433856 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -554,8 +554,6 @@ static nsDOMClassInfoData sClassInfoData[] = { EVENTTARGET_SCRIPTABLE_FLAGS) #endif - NS_DEFINE_CLASSINFO_DATA(CameraControl, nsDOMGenericSH, - DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(CameraCapabilities, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) @@ -1432,10 +1430,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_END #endif - DOM_CLASSINFO_MAP_BEGIN(CameraControl, nsICameraControl) - DOM_CLASSINFO_MAP_ENTRY(nsICameraControl) - DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(CameraCapabilities, nsICameraCapabilities) DOM_CLASSINFO_MAP_ENTRY(nsICameraCapabilities) DOM_CLASSINFO_MAP_END diff --git a/dom/base/nsDOMClassInfoClasses.h b/dom/base/nsDOMClassInfoClasses.h index a2d04982ccfb..5a17c80e5c54 100644 --- a/dom/base/nsDOMClassInfoClasses.h +++ b/dom/base/nsDOMClassInfoClasses.h @@ -140,7 +140,6 @@ DOMCI_CLASS(FMRadio) DOMCI_CLASS(BluetoothDevice) #endif -DOMCI_CLASS(CameraControl) DOMCI_CLASS(CameraCapabilities) DOMCI_CLASS(LockedFile) diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 96dfed318f3b..c39d7902bcb3 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -176,6 +176,14 @@ DOMInterfaces = { 'headerFile': 'CallsList.h', }, +'CameraControl': { + 'nativeType': 'mozilla::nsDOMCameraControl', + 'headerFile': 'DOMCameraControl.h', + 'binaryNames': { + "release": "ReleaseHardware" + } +}, + 'CameraManager': { 'nativeType': 'nsDOMCameraManager', 'headerFile': 'DOMCameraManager.h' @@ -1815,3 +1823,13 @@ addExternalIface('XULCommandDispatcher') addExternalIface('DataTransfer', notflattened=True) addExternalIface('GetCameraCallback', nativeType='nsICameraGetCameraCallback', headerFile='nsIDOMCameraManager.h') addExternalIface('CameraErrorCallback', nativeType='nsICameraErrorCallback', headerFile='nsIDOMCameraManager.h') +addExternalIface('CameraCapabilities', nativeType='nsICameraCapabilities', headerFile='nsIDOMCameraManager.h') +addExternalIface('CameraAutoFocusCallback', nativeType='nsICameraAutoFocusCallback', headerFile='nsIDOMCameraManager.h') +addExternalIface('CameraShutterCallback', nativeType='nsICameraShutterCallback', headerFile='nsIDOMCameraManager.h') +addExternalIface('CameraClosedCallback', nativeType='nsICameraClosedCallback', headerFile='nsIDOMCameraManager.h') +addExternalIface('CameraTakePictureCallback', nativeType='nsICameraTakePictureCallback', headerFile='nsIDOMCameraManager.h') +addExternalIface('CameraReleaseCallback', nativeType='nsICameraReleaseCallback', headerFile='nsIDOMCameraManager.h') +addExternalIface('CameraStartRecordingCallback', nativeType='nsICameraStartRecordingCallback', headerFile='nsIDOMCameraManager.h') +addExternalIface('CameraPreviewStateChange', nativeType='nsICameraPreviewStateChange', headerFile='nsIDOMCameraManager.h') +addExternalIface('CameraPreviewStreamCallback', nativeType='nsICameraPreviewStreamCallback', headerFile='nsIDOMCameraManager.h') +addExternalIface('CameraRecorderStateChange', nativeType='nsICameraRecorderStateChange', headerFile='nsIDOMCameraManager.h') diff --git a/dom/camera/DOMCameraControl.cpp b/dom/camera/DOMCameraControl.cpp index 681341c8c780..b4d12e02d6f1 100644 --- a/dom/camera/DOMCameraControl.cpp +++ b/dom/camera/DOMCameraControl.cpp @@ -7,6 +7,8 @@ #include "nsDOMClassInfo.h" #include "jsapi.h" #include "nsThread.h" +#include "DeviceStorage.h" +#include "mozilla/dom/CameraControlBinding.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/Services.h" #include "mozilla/unused.h" @@ -23,15 +25,11 @@ using namespace mozilla; using namespace mozilla::dom; -DOMCI_DATA(CameraControl, nsICameraControl) - -NS_IMPL_CYCLE_COLLECTION_1(nsDOMCameraControl, - mDOMCapabilities) +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(nsDOMCameraControl, mDOMCapabilities, mWindow) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCameraControl) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRY(nsISupports) - NS_INTERFACE_MAP_ENTRY(nsICameraControl) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraControl) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCameraControl) @@ -42,235 +40,242 @@ nsDOMCameraControl::~nsDOMCameraControl() DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); } -/* readonly attribute nsICameraCapabilities capabilities; */ -NS_IMETHODIMP -nsDOMCameraControl::GetCapabilities(nsICameraCapabilities** aCapabilities) +JSObject* +nsDOMCameraControl::WrapObject(JSContext* aCx, JS::Handle aScope) +{ + return CameraControlBinding::Wrap(aCx, aScope, this); +} + +nsICameraCapabilities* +nsDOMCameraControl::Capabilities() { if (!mDOMCapabilities) { mDOMCapabilities = new DOMCameraCapabilities(mCameraControl); } - nsCOMPtr capabilities = mDOMCapabilities; - capabilities.forget(aCapabilities); - return NS_OK; + return mDOMCapabilities; } -/* attribute DOMString effect; */ -NS_IMETHODIMP -nsDOMCameraControl::GetEffect(nsAString& aEffect) +void +nsDOMCameraControl::GetEffect(nsString& aEffect, ErrorResult& aRv) { - return mCameraControl->Get(CAMERA_PARAM_EFFECT, aEffect); + aRv = mCameraControl->Get(CAMERA_PARAM_EFFECT, aEffect); } -NS_IMETHODIMP -nsDOMCameraControl::SetEffect(const nsAString& aEffect) +void +nsDOMCameraControl::SetEffect(const nsAString& aEffect, ErrorResult& aRv) { - return mCameraControl->Set(CAMERA_PARAM_EFFECT, aEffect); + aRv = mCameraControl->Set(CAMERA_PARAM_EFFECT, aEffect); } -/* attribute DOMString whiteBalanceMode; */ -NS_IMETHODIMP -nsDOMCameraControl::GetWhiteBalanceMode(nsAString& aWhiteBalanceMode) +void +nsDOMCameraControl::GetWhiteBalanceMode(nsString& aWhiteBalanceMode, ErrorResult& aRv) { - return mCameraControl->Get(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode); + aRv = mCameraControl->Get(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode); } -NS_IMETHODIMP -nsDOMCameraControl::SetWhiteBalanceMode(const nsAString& aWhiteBalanceMode) +void +nsDOMCameraControl::SetWhiteBalanceMode(const nsAString& aWhiteBalanceMode, ErrorResult& aRv) { - return mCameraControl->Set(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode); + aRv = mCameraControl->Set(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode); } -/* attribute DOMString sceneMode; */ -NS_IMETHODIMP -nsDOMCameraControl::GetSceneMode(nsAString& aSceneMode) +void +nsDOMCameraControl::GetSceneMode(nsString& aSceneMode, ErrorResult& aRv) { - return mCameraControl->Get(CAMERA_PARAM_SCENEMODE, aSceneMode); + aRv = mCameraControl->Get(CAMERA_PARAM_SCENEMODE, aSceneMode); } -NS_IMETHODIMP -nsDOMCameraControl::SetSceneMode(const nsAString& aSceneMode) +void +nsDOMCameraControl::SetSceneMode(const nsAString& aSceneMode, ErrorResult& aRv) { - return mCameraControl->Set(CAMERA_PARAM_SCENEMODE, aSceneMode); + aRv = mCameraControl->Set(CAMERA_PARAM_SCENEMODE, aSceneMode); } -/* attribute DOMString flashMode; */ -NS_IMETHODIMP -nsDOMCameraControl::GetFlashMode(nsAString& aFlashMode) +void +nsDOMCameraControl::GetFlashMode(nsString& aFlashMode, ErrorResult& aRv) { - return mCameraControl->Get(CAMERA_PARAM_FLASHMODE, aFlashMode); + aRv = mCameraControl->Get(CAMERA_PARAM_FLASHMODE, aFlashMode); } -NS_IMETHODIMP -nsDOMCameraControl::SetFlashMode(const nsAString& aFlashMode) +void +nsDOMCameraControl::SetFlashMode(const nsAString& aFlashMode, ErrorResult& aRv) { - return mCameraControl->Set(CAMERA_PARAM_FLASHMODE, aFlashMode); + aRv = mCameraControl->Set(CAMERA_PARAM_FLASHMODE, aFlashMode); } -/* attribute DOMString focusMode; */ -NS_IMETHODIMP -nsDOMCameraControl::GetFocusMode(nsAString& aFocusMode) +void +nsDOMCameraControl::GetFocusMode(nsString& aFocusMode, ErrorResult& aRv) { - return mCameraControl->Get(CAMERA_PARAM_FOCUSMODE, aFocusMode); + aRv = mCameraControl->Get(CAMERA_PARAM_FOCUSMODE, aFocusMode); } -NS_IMETHODIMP -nsDOMCameraControl::SetFocusMode(const nsAString& aFocusMode) +void +nsDOMCameraControl::SetFocusMode(const nsAString& aFocusMode, ErrorResult& aRv) { - return mCameraControl->Set(CAMERA_PARAM_FOCUSMODE, aFocusMode); + aRv = mCameraControl->Set(CAMERA_PARAM_FOCUSMODE, aFocusMode); } -/* attribute double zoom; */ -NS_IMETHODIMP -nsDOMCameraControl::GetZoom(double* aZoom) +double +nsDOMCameraControl::GetZoom(ErrorResult& aRv) { - return mCameraControl->Get(CAMERA_PARAM_ZOOM, aZoom); + double zoom; + aRv = mCameraControl->Get(CAMERA_PARAM_ZOOM, &zoom); + return zoom; } -NS_IMETHODIMP -nsDOMCameraControl::SetZoom(double aZoom) + +void +nsDOMCameraControl::SetZoom(double aZoom, ErrorResult& aRv) { - return mCameraControl->Set(CAMERA_PARAM_ZOOM, aZoom); + aRv = mCameraControl->Set(CAMERA_PARAM_ZOOM, aZoom); } /* attribute jsval meteringAreas; */ -NS_IMETHODIMP -nsDOMCameraControl::GetMeteringAreas(JSContext* cx, JS::Value* aMeteringAreas) +JS::Value +nsDOMCameraControl::GetMeteringAreas(JSContext* cx, ErrorResult& aRv) { - return mCameraControl->Get(cx, CAMERA_PARAM_METERINGAREAS, aMeteringAreas); -} -NS_IMETHODIMP -nsDOMCameraControl::SetMeteringAreas(JSContext* cx, const JS::Value& aMeteringAreas) -{ - return mCameraControl->SetMeteringAreas(cx, aMeteringAreas); + JS::Rooted areas(cx); + aRv = mCameraControl->Get(cx, CAMERA_PARAM_METERINGAREAS, areas.address()); + return areas; } -/* attribute jsval focusAreas; */ -NS_IMETHODIMP -nsDOMCameraControl::GetFocusAreas(JSContext* cx, JS::Value* aFocusAreas) +void +nsDOMCameraControl::SetMeteringAreas(JSContext* cx, JS::Handle aMeteringAreas, ErrorResult& aRv) { - return mCameraControl->Get(cx, CAMERA_PARAM_FOCUSAREAS, aFocusAreas); -} -NS_IMETHODIMP -nsDOMCameraControl::SetFocusAreas(JSContext* cx, const JS::Value& aFocusAreas) -{ - return mCameraControl->SetFocusAreas(cx, aFocusAreas); + aRv = mCameraControl->SetMeteringAreas(cx, aMeteringAreas); } -/* readonly attribute double focalLength; */ -NS_IMETHODIMP -nsDOMCameraControl::GetFocalLength(double* aFocalLength) +JS::Value +nsDOMCameraControl::GetFocusAreas(JSContext* cx, ErrorResult& aRv) { - return mCameraControl->Get(CAMERA_PARAM_FOCALLENGTH, aFocalLength); + JS::Rooted value(cx); + aRv = mCameraControl->Get(cx, CAMERA_PARAM_FOCUSAREAS, value.address()); + return value; +} +void +nsDOMCameraControl::SetFocusAreas(JSContext* cx, JS::Handle aFocusAreas, ErrorResult& aRv) +{ + aRv = mCameraControl->SetFocusAreas(cx, aFocusAreas); } -/* readonly attribute double focusDistanceNear; */ -NS_IMETHODIMP -nsDOMCameraControl::GetFocusDistanceNear(double* aFocusDistanceNear) +double +nsDOMCameraControl::GetFocalLength(ErrorResult& aRv) { - return mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCENEAR, aFocusDistanceNear); + double focalLength; + aRv = mCameraControl->Get(CAMERA_PARAM_FOCALLENGTH, &focalLength); + return focalLength; } -/* readonly attribute double focusDistanceOptimum; */ -NS_IMETHODIMP -nsDOMCameraControl::GetFocusDistanceOptimum(double* aFocusDistanceOptimum) +double +nsDOMCameraControl::GetFocusDistanceNear(ErrorResult& aRv) { - return mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCEOPTIMUM, aFocusDistanceOptimum); + double distance; + aRv = mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCENEAR, &distance); + return distance; } -/* readonly attribute double focusDistanceFar; */ -NS_IMETHODIMP -nsDOMCameraControl::GetFocusDistanceFar(double* aFocusDistanceFar) +double +nsDOMCameraControl::GetFocusDistanceOptimum(ErrorResult& aRv) { - return mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCEFAR, aFocusDistanceFar); + double distance; + aRv = mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCEOPTIMUM, &distance); + return distance; } -/* void setExposureCompensation (const JS::Value& aCompensation, JSContext* cx); */ -NS_IMETHODIMP -nsDOMCameraControl::SetExposureCompensation(const JS::Value& aCompensation, JSContext* cx) +double +nsDOMCameraControl::GetFocusDistanceFar(ErrorResult& aRv) { - if (aCompensation.isNullOrUndefined()) { + double distance; + aRv = mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCEFAR, &distance); + return distance; +} + +void +nsDOMCameraControl::SetExposureCompensation(const Optional& aCompensation, ErrorResult& aRv) +{ + if (!aCompensation.WasPassed()) { // use NaN to switch the camera back into auto mode - return mCameraControl->Set(CAMERA_PARAM_EXPOSURECOMPENSATION, NAN); + aRv = mCameraControl->Set(CAMERA_PARAM_EXPOSURECOMPENSATION, NAN); } + aRv = mCameraControl->Set(CAMERA_PARAM_EXPOSURECOMPENSATION, aCompensation.Value()); +} + +double +nsDOMCameraControl::GetExposureCompensation(ErrorResult& aRv) +{ double compensation; - if (!JS_ValueToNumber(cx, aCompensation, &compensation)) { - return NS_ERROR_INVALID_ARG; - } - - return mCameraControl->Set(CAMERA_PARAM_EXPOSURECOMPENSATION, compensation); + aRv = mCameraControl->Get(CAMERA_PARAM_EXPOSURECOMPENSATION, &compensation); + return compensation; } -/* readonly attribute double exposureCompensation; */ -NS_IMETHODIMP -nsDOMCameraControl::GetExposureCompensation(double* aExposureCompensation) +already_AddRefed +nsDOMCameraControl::GetOnShutter(ErrorResult& aRv) { - return mCameraControl->Get(CAMERA_PARAM_EXPOSURECOMPENSATION, aExposureCompensation); + nsCOMPtr cb; + aRv = mCameraControl->Get(getter_AddRefs(cb)); + return cb.forget(); } -/* attribute nsICameraShutterCallback onShutter; */ -NS_IMETHODIMP -nsDOMCameraControl::GetOnShutter(nsICameraShutterCallback** aOnShutter) +void +nsDOMCameraControl::SetOnShutter(nsICameraShutterCallback* aOnShutter, + ErrorResult& aRv) { - return mCameraControl->Get(aOnShutter); -} -NS_IMETHODIMP -nsDOMCameraControl::SetOnShutter(nsICameraShutterCallback* aOnShutter) -{ - return mCameraControl->Set(aOnShutter); + aRv = mCameraControl->Set(aOnShutter); } /* attribute nsICameraClosedCallback onClosed; */ -NS_IMETHODIMP -nsDOMCameraControl::GetOnClosed(nsICameraClosedCallback** aOnClosed) +already_AddRefed +nsDOMCameraControl::GetOnClosed(ErrorResult& aRv) { - return mCameraControl->Get(aOnClosed); -} -NS_IMETHODIMP -nsDOMCameraControl::SetOnClosed(nsICameraClosedCallback* aOnClosed) -{ - return mCameraControl->Set(aOnClosed); + nsCOMPtr onClosed; + aRv = mCameraControl->Get(getter_AddRefs(onClosed)); + return onClosed.forget(); } -/* attribute nsICameraRecorderStateChange onRecorderStateChange; */ -NS_IMETHODIMP -nsDOMCameraControl::GetOnRecorderStateChange(nsICameraRecorderStateChange** aOnRecorderStateChange) +void +nsDOMCameraControl::SetOnClosed(nsICameraClosedCallback* aOnClosed, + ErrorResult& aRv) { - return mCameraControl->Get(aOnRecorderStateChange); -} -NS_IMETHODIMP -nsDOMCameraControl::SetOnRecorderStateChange(nsICameraRecorderStateChange* aOnRecorderStateChange) -{ - return mCameraControl->Set(aOnRecorderStateChange); + aRv = mCameraControl->Set(aOnClosed); } -/* attribute nsICameraPreviewStateChange onPreviewStateChange; */ -NS_IMETHODIMP -nsDOMCameraControl::GetOnPreviewStateChange(nsICameraPreviewStateChange** aOnPreviewStateChange) +already_AddRefed +nsDOMCameraControl::GetOnRecorderStateChange(ErrorResult& aRv) { - return mCameraControl->Get(aOnPreviewStateChange); -} -NS_IMETHODIMP -nsDOMCameraControl::SetOnPreviewStateChange(nsICameraPreviewStateChange* aOnPreviewStateChange) -{ - return mCameraControl->Set(aOnPreviewStateChange); + nsCOMPtr cb; + aRv = mCameraControl->Get(getter_AddRefs(cb)); + return cb.forget(); } -/* [implicit_jscontext] void startRecording (in jsval aOptions, in nsIDOMDeviceStorage storageArea, in DOMString filename, in nsICameraStartRecordingCallback onSuccess, [optional] in nsICameraErrorCallback onError); */ -NS_IMETHODIMP -nsDOMCameraControl::StartRecording(const JS::Value& aOptions, nsIDOMDeviceStorage* storageArea, const nsAString& filename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx) +void +nsDOMCameraControl::SetOnRecorderStateChange(nsICameraRecorderStateChange* aOnRecorderStateChange, + ErrorResult& aRv) { - NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG); - NS_ENSURE_TRUE(storageArea, NS_ERROR_INVALID_ARG); + aRv = mCameraControl->Set(aOnRecorderStateChange); +} +void +nsDOMCameraControl::StartRecording(JSContext* aCx, + JS::Handle aOptions, + nsDOMDeviceStorage& storageArea, + const nsAString& filename, + nsICameraStartRecordingCallback* onSuccess, + const Optional& onError, + ErrorResult& aRv) +{ + MOZ_ASSERT(onSuccess, "no onSuccess handler passed"); mozilla::idl::CameraStartRecordingOptions options; // Default values, until the dictionary parser can handle them. options.rotation = 0; options.maxFileSizeBytes = 0; options.maxVideoLengthMs = 0; - nsresult rv = options.Init(cx, &aOptions); - NS_ENSURE_SUCCESS(rv, rv); + aRv = options.Init(aCx, aOptions.address()); + if (aRv.Failed()) { + return; + } - nsCOMPtr obs = mozilla::services::GetObserverService(); + nsCOMPtr obs = services::GetObserverService(); if (!obs) { NS_WARNING("Could not get the Observer service for CameraControl::StartRecording."); - return NS_ERROR_FAILURE; + aRv.Throw(NS_ERROR_FAILURE); + return; } obs->NotifyObservers(nullptr, @@ -296,19 +301,21 @@ nsDOMCameraControl::StartRecording(const JS::Value& aOptions, nsIDOMDeviceStorag #endif nsCOMPtr folder; - rv = storageArea->GetRootDirectoryForFile(filename, getter_AddRefs(folder)); - NS_ENSURE_SUCCESS(rv, rv); - return mCameraControl->StartRecording(&options, folder, filename, onSuccess, onError); + aRv = storageArea.GetRootDirectoryForFile(filename, getter_AddRefs(folder)); + if (aRv.Failed()) { + return; + } + aRv = mCameraControl->StartRecording(&options, folder, filename, onSuccess, + onError.WasPassed() ? onError.Value() : nullptr); } -/* void stopRecording (); */ -NS_IMETHODIMP -nsDOMCameraControl::StopRecording() +void +nsDOMCameraControl::StopRecording(ErrorResult& aRv) { - nsCOMPtr obs = mozilla::services::GetObserverService(); + nsCOMPtr obs = services::GetObserverService(); if (!obs) { NS_WARNING("Could not get the Observer service for CameraControl::StopRecording."); - return NS_ERROR_FAILURE; + aRv.Throw(NS_ERROR_FAILURE); } obs->NotifyObservers(nullptr, @@ -327,55 +334,71 @@ nsDOMCameraControl::StopRecording() } #endif - return mCameraControl->StopRecording(); + aRv = mCameraControl->StopRecording(); } -/* [implicit_jscontext] void getPreviewStream (in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError); */ -NS_IMETHODIMP -nsDOMCameraControl::GetPreviewStream(const JS::Value& aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx) +void +nsDOMCameraControl::GetPreviewStream(JSContext* aCx, + JS::Handle aOptions, + nsICameraPreviewStreamCallback* onSuccess, + const Optional& onError, + ErrorResult& aRv) { - NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG); - mozilla::idl::CameraSize size; - nsresult rv = size.Init(cx, &aOptions); - NS_ENSURE_SUCCESS(rv, rv); + aRv = size.Init(aCx, aOptions.address()); + if (aRv.Failed()) { + return; + } - return mCameraControl->GetPreviewStream(size, onSuccess, onError); + aRv = mCameraControl->GetPreviewStream(size, onSuccess, + onError.WasPassed() + ? onError.Value() : nullptr); } -/* void resumePreview(); */ -NS_IMETHODIMP -nsDOMCameraControl::ResumePreview() +void +nsDOMCameraControl::ResumePreview(ErrorResult& aRv) { - return mCameraControl->StartPreview(nullptr); + aRv = mCameraControl->StartPreview(nullptr); } -/* void autoFocus (in nsICameraAutoFocusCallback onSuccess, [optional] in nsICameraErrorCallback onError); */ -NS_IMETHODIMP -nsDOMCameraControl::AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError) +already_AddRefed +nsDOMCameraControl::GetOnPreviewStateChange() const { - NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG); - return mCameraControl->AutoFocus(onSuccess, onError); + nsCOMPtr cb; + mCameraControl->Get(getter_AddRefs(cb)); + return cb.forget(); } -/* void takePicture (in jsval aOptions, in nsICameraTakePictureCallback onSuccess, [optional] in nsICameraErrorCallback onError); */ -NS_IMETHODIMP -nsDOMCameraControl::TakePicture(const JS::Value& aOptions, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx) +void +nsDOMCameraControl::SetOnPreviewStateChange(nsICameraPreviewStateChange* aCb) { - NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG); + mCameraControl->Set(aCb); +} - RootedDictionary options(cx); +void +nsDOMCameraControl::AutoFocus(nsICameraAutoFocusCallback* onSuccess, + const Optional& onError, + ErrorResult& aRv) +{ + aRv = mCameraControl->AutoFocus(onSuccess, + onError.WasPassed() ? onError.Value() : nullptr); +} + +void +nsDOMCameraControl::TakePicture(JSContext* aCx, + const CameraPictureOptions& aOptions, + nsICameraTakePictureCallback* onSuccess, + const Optional& aOnError, + ErrorResult& aRv) +{ mozilla::idl::CameraSize size; mozilla::idl::CameraPosition pos; - JS::Rooted optionVal(cx, aOptions); - if (!options.Init(cx, optionVal)) { - return NS_ERROR_FAILURE; + aRv = size.Init(aCx, &aOptions.mPictureSize); + if (aRv.Failed()) { + return; } - nsresult rv = size.Init(cx, &options.mPictureSize); - NS_ENSURE_SUCCESS(rv, rv); - /** * Default values, until the dictionary parser can handle them. * NaN indicates no value provided. @@ -384,29 +407,45 @@ nsDOMCameraControl::TakePicture(const JS::Value& aOptions, nsICameraTakePictureC pos.longitude = NAN; pos.altitude = NAN; pos.timestamp = NAN; - rv = pos.Init(cx, &options.mPosition); - NS_ENSURE_SUCCESS(rv, rv); + aRv = pos.Init(aCx, &aOptions.mPosition); + if (aRv.Failed()) { + return; + } - return mCameraControl->TakePicture(size, options.mRotation, options.mFileFormat, pos, options.mDateTime, onSuccess, onError); + nsICameraErrorCallback* onError = + aOnError.WasPassed() ? aOnError.Value() : nullptr; + aRv = mCameraControl->TakePicture(size, aOptions.mRotation, + aOptions.mFileFormat, pos, + aOptions.mDateTime, onSuccess, onError); } -/* [implicit_jscontext] void GetPreviewStreamVideoMode (in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError); */ -NS_IMETHODIMP -nsDOMCameraControl::GetPreviewStreamVideoMode(const JS::Value& aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx) +void +nsDOMCameraControl::GetPreviewStreamVideoMode(JSContext* aCx, + JS::Handle aOptions, + nsICameraPreviewStreamCallback* onSuccess, + const Optional& onError, + ErrorResult& aRv) { - NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG); - mozilla::idl::CameraRecorderOptions options; - nsresult rv = options.Init(cx, &aOptions); - NS_ENSURE_SUCCESS(rv, rv); + aRv = options.Init(aCx, aOptions.address()); + if (aRv.Failed()) { + return; + } - return mCameraControl->GetPreviewStreamVideoMode(&options, onSuccess, onError); + aRv = mCameraControl->GetPreviewStreamVideoMode(&options, onSuccess, + onError.WasPassed() + ? onError.Value() : nullptr); } -NS_IMETHODIMP -nsDOMCameraControl::ReleaseHardware(nsICameraReleaseCallback* onSuccess, nsICameraErrorCallback* onError) +void +nsDOMCameraControl::ReleaseHardware(const Optional& onSuccess, + const Optional& onError, + ErrorResult& aRv) { - return mCameraControl->ReleaseHardware(onSuccess, onError); + aRv = + mCameraControl->ReleaseHardware( + onSuccess.WasPassed() ? onSuccess.Value() : nullptr, + onError.WasPassed() ? onError.Value() : nullptr); } class GetCameraResult : public nsRunnable diff --git a/dom/camera/DOMCameraControl.h b/dom/camera/DOMCameraControl.h index ab0a0a82babc..d9aa4ca09ed6 100644 --- a/dom/camera/DOMCameraControl.h +++ b/dom/camera/DOMCameraControl.h @@ -16,19 +16,27 @@ #include "AudioChannelAgent.h" #include "nsProxyRelease.h" +class nsDOMDeviceStorage; +class nsPIDOMWindow; + namespace mozilla { +namespace dom { +class CameraPictureOptions; +template class Optional; +} +class ErrorResult; // Main camera control. -class nsDOMCameraControl : public nsICameraControl +class nsDOMCameraControl MOZ_FINAL : public nsISupports, + public nsWrapperCache { public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMCameraControl) - NS_DECL_NSICAMERACONTROL + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMCameraControl) nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsICameraGetCameraCallback* onSuccess, - nsICameraErrorCallback* onError, uint64_t aWindowId); + nsICameraErrorCallback* onError, nsPIDOMWindow* aWindow); nsresult Result(nsresult aResult, const nsMainThreadPtrHandle& onSuccess, const nsMainThreadPtrHandle& onError, @@ -37,6 +45,52 @@ public: void Shutdown(); + nsPIDOMWindow* GetParentObject() const { return mWindow; } + + // WebIDL + nsICameraCapabilities* Capabilities(); + void GetEffect(nsString& aEffect, ErrorResult& aRv); + void SetEffect(const nsAString& aEffect, ErrorResult& aRv); + void GetWhiteBalanceMode(nsString& aMode, ErrorResult& aRv); + void SetWhiteBalanceMode(const nsAString& aMode, ErrorResult& aRv); + void GetSceneMode(nsString& aMode, ErrorResult& aRv); + void SetSceneMode(const nsAString& aMode, ErrorResult& aRv); + void GetFlashMode(nsString& aMode, ErrorResult& aRv); + void SetFlashMode(const nsAString& aMode, ErrorResult& aRv); + void GetFocusMode(nsString& aMode, ErrorResult& aRv); + void SetFocusMode(const nsAString& aMode, ErrorResult& aRv); + double GetZoom(ErrorResult& aRv); + void SetZoom(double aZoom, ErrorResult& aRv); + JS::Value GetMeteringAreas(JSContext* aCx, ErrorResult& aRv); + void SetMeteringAreas(JSContext* aCx, JS::Handle aAreas, ErrorResult& aRv); + JS::Value GetFocusAreas(JSContext* aCx, ErrorResult& aRv); + void SetFocusAreas(JSContext* aCx, JS::Handle aAreas, ErrorResult& aRv); + double GetFocalLength(ErrorResult& aRv); + double GetFocusDistanceNear(ErrorResult& aRv); + double GetFocusDistanceOptimum(ErrorResult& aRv); + double GetFocusDistanceFar(ErrorResult& aRv); + void SetExposureCompensation(const dom::Optional& aCompensation, ErrorResult& aRv); + double GetExposureCompensation(ErrorResult& aRv); + already_AddRefed GetOnShutter(ErrorResult& aRv); + void SetOnShutter(nsICameraShutterCallback* aCb, ErrorResult& aRv); + already_AddRefed GetOnClosed(ErrorResult& aRv); + void SetOnClosed(nsICameraClosedCallback* aCb, ErrorResult& aRv); + already_AddRefed GetOnRecorderStateChange(ErrorResult& aRv); + void SetOnRecorderStateChange(nsICameraRecorderStateChange* aCb, ErrorResult& aRv); + void AutoFocus(nsICameraAutoFocusCallback* aOnSuccess, const dom::Optional& aOnErro, ErrorResult& aRvr); + void TakePicture(JSContext* aCx, const dom::CameraPictureOptions& aOptions, + nsICameraTakePictureCallback* onSuccess, + const dom::Optional& onError, + ErrorResult& aRv); + already_AddRefed GetOnPreviewStateChange() const; + void SetOnPreviewStateChange(nsICameraPreviewStateChange* aOnStateChange); + void GetPreviewStreamVideoMode(JSContext* cx, JS::Handle aOptions, nsICameraPreviewStreamCallback* onSuccess, const dom::Optional& onError, ErrorResult& aRv); + void StartRecording(JSContext* cx, JS::Handle aOptions, nsDOMDeviceStorage& storageArea, const nsAString& filename, nsICameraStartRecordingCallback* onSuccess, const dom::Optional& onError, ErrorResult& aRv); + void StopRecording(ErrorResult& aRv); + void GetPreviewStream(JSContext* cx, JS::Handle aOptions, nsICameraPreviewStreamCallback* onSuccess, const dom::Optional& onError, ErrorResult& aRv); + void ResumePreview(ErrorResult& aRv); + void ReleaseHardware(const dom::Optional& onSuccess, const dom::Optional& onError, ErrorResult& aRv); + protected: virtual ~nsDOMCameraControl(); @@ -44,12 +98,15 @@ private: nsDOMCameraControl(const nsDOMCameraControl&) MOZ_DELETE; nsDOMCameraControl& operator=(const nsDOMCameraControl&) MOZ_DELETE; + virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE; + protected: /* additional members */ nsRefPtr mCameraControl; // non-DOM camera control nsCOMPtr mDOMCapabilities; // An agent used to join audio channel service. nsCOMPtr mAudioChannelAgent; + nsCOMPtr mWindow; }; } // namespace mozilla diff --git a/dom/camera/DOMCameraManager.cpp b/dom/camera/DOMCameraManager.cpp index bb75c32aea23..1190f57e7d14 100644 --- a/dom/camera/DOMCameraManager.cpp +++ b/dom/camera/DOMCameraManager.cpp @@ -127,9 +127,9 @@ nsDOMCameraManager::GetCamera(const CameraSelector& aOptions, DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__); // Creating this object will trigger the onSuccess handler - nsCOMPtr cameraControl = + nsRefPtr cameraControl = new nsDOMCameraControl(cameraId, mCameraThread, - onSuccess, onError.WasPassed() ? onError.Value() : nullptr, mWindowId); + onSuccess, onError.WasPassed() ? onError.Value() : nullptr, mWindow); Register(cameraControl); } diff --git a/dom/camera/FallbackCameraControl.cpp b/dom/camera/FallbackCameraControl.cpp index da7b552f49ee..cd16564c91c5 100644 --- a/dom/camera/FallbackCameraControl.cpp +++ b/dom/camera/FallbackCameraControl.cpp @@ -59,8 +59,10 @@ private: * store a reference in the 'mCameraControl' member (which is why it is * defined here). */ -nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, uint64_t aWindowId) +nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, nsPIDOMWindow* aWindow) : + mWindow(aWindow) { + MOZ_ASSERT(aWindow, "shouldn't be created with null window!"); } /** diff --git a/dom/camera/GonkCameraControl.cpp b/dom/camera/GonkCameraControl.cpp index 29d714efb40c..a289977a9f22 100644 --- a/dom/camera/GonkCameraControl.cpp +++ b/dom/camera/GonkCameraControl.cpp @@ -143,9 +143,10 @@ static const char* getKeyText(uint32_t aKey) } // nsDOMCameraControl implementation-specific constructor -nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, uint64_t aWindowId) - : mDOMCapabilities(nullptr) +nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, nsPIDOMWindow* aWindow) + : mDOMCapabilities(nullptr), mWindow(aWindow) { + MOZ_ASSERT(aWindow, "shouldn't be created with null window!"); DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); /** @@ -160,8 +161,8 @@ nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThr * nsDOMCameraControl or memory will leak! */ NS_ADDREF_THIS(); - nsRefPtr control = new nsGonkCameraControl(aCameraId, aCameraThread, this, onSuccess, onError, aWindowId); - control->DispatchInit(this, onSuccess, onError, aWindowId); + nsRefPtr control = new nsGonkCameraControl(aCameraId, aCameraThread, this, onSuccess, onError, aWindow->WindowID()); + control->DispatchInit(this, onSuccess, onError, aWindow->WindowID()); mCameraControl = control; } diff --git a/dom/camera/nsIDOMCameraManager.idl b/dom/camera/nsIDOMCameraManager.idl index 7c1b52982081..6f94034b9627 100644 --- a/dom/camera/nsIDOMCameraManager.idl +++ b/dom/camera/nsIDOMCameraManager.idl @@ -217,171 +217,8 @@ interface nsICameraErrorCallback : nsISupports void handleEvent(in DOMString error); }; -/* - attributes here affect the preview, any pictures taken, and/or - any video recorded by the camera. -*/ -[scriptable, uuid(74dc7f1f-c88f-4774-860b-44aef9de5dc8)] -interface nsICameraControl : nsISupports -{ - readonly attribute nsICameraCapabilities capabilities; - - /* one of the vales chosen from capabilities.effects; - default is "none" */ - attribute DOMString effect; - - /* one of the values chosen from capabilities.whiteBalanceModes; - default is "auto" */ - attribute DOMString whiteBalanceMode; - - /* one of the valus chosen from capabilities.sceneModes; - default is "auto" */ - attribute DOMString sceneMode; - - /* one of the values chosen from capabilities.flashModes; - default is "auto" */ - attribute DOMString flashMode; - - /* one of the values chosen from capabilities.focusModes; - default is "auto", if supported, or "fixed" */ - attribute DOMString focusMode; - - /* one of the values chosen from capabilities.zoomRatios; other - values will be rounded to the nearest supported value; - default is 1.0 */ - attribute double zoom; - - /* an array of one or more objects that define where the - camera will perform light metering, each defining the properties: - { - top: -1000, - left: -1000, - bottom: 1000, - right: 1000, - weight: 1000 - } - - 'top', 'left', 'bottom', and 'right' all range from -1000 at - the top-/leftmost of the sensor to 1000 at the bottom-/rightmost - of the sensor. - - objects missing one or more of these properties will be ignored; - if the array contains more than capabilities.maxMeteringAreas, - extra areas will be ignored. - - this attribute can be set to null to allow the camera to determine - where to perform light metering. */ - [implicit_jscontext] - attribute jsval meteringAreas; - - /* an array of one or more objects that define where the camera will - perform auto-focusing, with the same definition as meteringAreas. - - if the array contains more than capabilities.maxFocusAreas, extra - areas will be ignored. - - this attribute can be set to null to allow the camera to determine - where to focus. */ - [implicit_jscontext] - attribute jsval focusAreas; - - /* focal length in millimetres */ - readonly attribute double focalLength; - - /* the distances in metres to where the image subject appears to be - in focus. 'focusDistanceOptimum' is where the subject will appear - sharpest; the difference between 'focusDistanceFar' and - 'focusDistanceNear' is the image's depth of field. - - 'focusDistanceFar' may be infinity. */ - readonly attribute double focusDistanceNear; - readonly attribute double focusDistanceOptimum; - readonly attribute double focusDistanceFar; - - /* 'compensation' is optional, and if missing, will - set the camera to use automatic exposure compensation. - - acceptable values must range from minExposureCompensation - to maxExposureCompensation in steps of stepExposureCompensation; - invalid values will be rounded to the nearest valid value. */ - [implicit_jscontext] - void setExposureCompensation([optional] in jsval compensation); - readonly attribute double exposureCompensation; - - /* the function to call on the camera's shutter event, to trigger - a shutter sound and/or a visual shutter indicator. */ - attribute nsICameraShutterCallback onShutter; - - /* the function to call when the camera hardware is closed - by the underlying framework, e.g. when another app makes a more - recent call to get the camera. */ - attribute nsICameraClosedCallback onClosed; - - /* the function to call when the recorder changes state, either because - the recording process encountered an error, or because one of the - recording limits (see CameraStartRecordingOptions) was reached. */ - attribute nsICameraRecorderStateChange onRecorderStateChange; - - /* the function to call when the preview stream is actually started and - stopped; this is usually used to enable and disable the camera UI, - since the low-level hardware often does not support taking pictures - unless the preview is running. */ - attribute nsICameraPreviewStateChange onPreviewStateChange; - - /* tell the camera to attempt to focus the image */ - void autoFocus(in nsICameraAutoFocusCallback onSuccess, [optional] in nsICameraErrorCallback onError); - - /* capture an image and return it as a blob to the 'onSuccess' callback; - if the camera supports it, this may be invoked while the camera is - already recording video. - - invoking this function will stop the preview stream, which must be - manually restarted (e.g. by calling .play() on it). */ - [implicit_jscontext] - void takePicture(in jsval aOptions, in nsICameraTakePictureCallback onSuccess, [optional] in nsICameraErrorCallback onError); - - /* get a media stream to be used as a camera viewfinder in video mode; - 'aOptions' is an CameraRecorderOptions object. */ - [implicit_jscontext] - void getPreviewStreamVideoMode(in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError); - - /* start recording video; 'aOptions' is a - CameraStartRecordingOptions object. */ - [implicit_jscontext] - void startRecording(in jsval aOptions, in nsIDOMDeviceStorage storageArea, in DOMString filename, in nsICameraStartRecordingCallback onSuccess, [optional] in nsICameraErrorCallback onError); - - /* stop precording video. */ - void stopRecording(); - - /* get a media stream to be used as a camera viewfinder; the options - define the desired frame size of the preview, chosen from - capabilities.previewSizes, e.g.: - { - height: 640, - width: 480, - } - */ - [implicit_jscontext] - void getPreviewStream(in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError); - - /* call in or after the takePicture() onSuccess callback to - resume the camera preview stream. */ - void resumePreview(); - - /* release the camera so that other applications can use it; you should - probably call this whenever the camera is not longer in the foreground - (depending on your usage model). - - the callbacks are optional, unless you really need to know when - the hardware is ultimately released. - - once this is called, the camera control object is to be considered - defunct; a new instance will need to be created to access the camera. */ - [binaryname(ReleaseHardware)] void release([optional] in nsICameraReleaseCallback onSuccess, [optional] in nsICameraErrorCallback onError); -}; - [scriptable, function, uuid(a267afbc-d91c-413a-8de5-0b94aecffa3e)] interface nsICameraGetCameraCallback : nsISupports { - void handleEvent(in nsICameraControl camera); + void handleEvent(in nsISupports camera); }; diff --git a/dom/webidl/CameraControl.webidl b/dom/webidl/CameraControl.webidl new file mode 100644 index 000000000000..73b021ff1509 --- /dev/null +++ b/dom/webidl/CameraControl.webidl @@ -0,0 +1,195 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +interface CameraCapabilities; +interface GetCameraCallback; +interface CameraErrorCallback; +interface CameraShutterCallback; +interface CameraClosedCallback; +interface CameraRecorderStateChange; +interface CameraAutoFocusCallback; +interface CameraTakePictureCallback; +interface CameraPreviewStateChange; +interface CameraPreviewStreamCallback; +interface CameraStartRecordingCallback; +interface CameraReleaseCallback; + +/* + attributes here affect the preview, any pictures taken, and/or + any video recorded by the camera. +*/ +interface CameraControl { + readonly attribute CameraCapabilities capabilities; + + /* one of the values chosen from capabilities.effects; + default is "none" */ + [Throws] + attribute DOMString effect; + + /* one of the values chosen from capabilities.whiteBalanceModes; + default is "auto" */ + [Throws] + attribute DOMString whiteBalanceMode; + + /* one of the values chosen from capabilities.sceneModes; + default is "auto" */ + [Throws] + attribute DOMString sceneMode; + + /* one of the values chosen from capabilities.flashModes; + default is "auto" */ + [Throws] + attribute DOMString flashMode; + + /* one of the values chosen from capabilities.focusModes; + default is "auto", if supported, or "fixed" */ + [Throws] + attribute DOMString focusMode; + + /* one of the values chosen from capabilities.zoomRatios; other + values will be rounded to the nearest supported value; + default is 1.0 */ + [Throws] + attribute double zoom; + + /* an array of one or more objects that define where the + camera will perform light metering, each defining the properties: + { + top: -1000, + left: -1000, + bottom: 1000, + right: 1000, + weight: 1000 + } + + 'top', 'left', 'bottom', and 'right' all range from -1000 at + the top-/leftmost of the sensor to 1000 at the bottom-/rightmost + of the sensor. + + objects missing one or more of these properties will be ignored; + if the array contains more than capabilities.maxMeteringAreas, + extra areas will be ignored. + + this attribute can be set to null to allow the camera to determine + where to perform light metering. */ + [Throws] + attribute any meteringAreas; + + /* an array of one or more objects that define where the camera will + perform auto-focusing, with the same definition as meteringAreas. + + if the array contains more than capabilities.maxFocusAreas, extra + areas will be ignored. + + this attribute can be set to null to allow the camera to determine + where to focus. */ + [Throws] + attribute any focusAreas; + + /* focal length in millimetres */ + [Throws] + readonly attribute double focalLength; + + /* the distances in metres to where the image subject appears to be + in focus. 'focusDistanceOptimum' is where the subject will appear + sharpest; the difference between 'focusDistanceFar' and + 'focusDistanceNear' is the image's depth of field. + + 'focusDistanceFar' may be infinity. */ + [Throws] + readonly attribute double focusDistanceNear; + [Throws] + readonly attribute double focusDistanceOptimum; + [Throws] + readonly attribute unrestricted double focusDistanceFar; + + /* 'compensation' is optional, and if missing, will + set the camera to use automatic exposure compensation. + + acceptable values must range from minExposureCompensation + to maxExposureCompensation in steps of stepExposureCompensation; + invalid values will be rounded to the nearest valid value. */ + [Throws] + void setExposureCompensation(optional double compensation); + [Throws] + readonly attribute unrestricted double exposureCompensation; + + /* the function to call on the camera's shutter event, to trigger + a shutter sound and/or a visual shutter indicator. */ + [Throws] + attribute CameraShutterCallback? onShutter; + + /* the function to call when the camera hardware is closed + by the underlying framework, e.g. when another app makes a more + recent call to get the camera. */ + [Throws] + attribute CameraClosedCallback? onClosed; + + /* the function to call when the recorder changes state, either because + the recording process encountered an error, or because one of the + recording limits (see CameraStartRecordingOptions) was reached. */ + [Throws] + attribute CameraRecorderStateChange? onRecorderStateChange; + attribute CameraPreviewStateChange? onPreviewStateChange; + + /* tell the camera to attempt to focus the image */ + [Throws] + void autoFocus(CameraAutoFocusCallback onSuccess, optional CameraErrorCallback onError); + + /* capture an image and return it as a blob to the 'onSuccess' callback; + if the camera supports it, this may be invoked while the camera is + already recording video. + + invoking this function will stop the preview stream, which must be + manually restarted (e.g. by calling .play() on it). */ + [Throws] + void takePicture(CameraPictureOptions aOptions, + CameraTakePictureCallback onSuccess, + optional CameraErrorCallback onError); + + /* get a media stream to be used as a camera viewfinder in video mode; + 'aOptions' is an CameraRecorderOptions object. */ + [Throws] + void getPreviewStreamVideoMode(any aOptions, CameraPreviewStreamCallback onSuccess, optional CameraErrorCallback onError); + + /* start recording video; 'aOptions' is a + CameraStartRecordingOptions object. */ + [Throws] + void startRecording(any aOptions, DeviceStorage storageArea, DOMString filename, CameraStartRecordingCallback onSuccess, optional CameraErrorCallback onError); + + /* stop precording video. */ + [Throws] + void stopRecording(); + + /* get a media stream to be used as a camera viewfinder; the options + define the desired frame size of the preview, chosen from + capabilities.previewSizes, e.g.: + { + height: 640, + width: 480, + } + */ + [Throws] + void getPreviewStream(any aOptions, CameraPreviewStreamCallback onSuccess, optional CameraErrorCallback onError); + + /* call in or after the takePicture() onSuccess callback to + resume the camera preview stream. */ + [Throws] + void resumePreview(); + + /* release the camera so that other applications can use it; you should + probably call this whenever the camera is not longer in the foreground + (depending on your usage model). + + the callbacks are optional, unless you really need to know when + the hardware is ultimately released. + + once this is called, the camera control object is to be considered + defunct; a new instance will need to be created to access the camera. */ + [Throws] + void release(optional CameraReleaseCallback onSuccess, optional CameraErrorCallback onError); +}; diff --git a/dom/webidl/DummyBinding.webidl b/dom/webidl/DummyBinding.webidl index e10c83084226..fba8dc3ab390 100644 --- a/dom/webidl/DummyBinding.webidl +++ b/dom/webidl/DummyBinding.webidl @@ -19,7 +19,6 @@ interface DummyInterface { void funcDNSLookupDict(optional DNSLookupDict arg); void funcConnStatusDict(optional ConnStatusDict arg); void frameRequestCallback(FrameRequestCallback arg); - void CameraPictureOptions(optional CameraPictureOptions arg); void MmsParameters(optional MmsParameters arg); void MmsAttachment(optional MmsAttachment arg); void AsyncScrollEventDetail(optional AsyncScrollEventDetail arg); diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index 473db53ea820..80643993d8d0 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -34,6 +34,7 @@ webidl_files = \ BiquadFilterNode.webidl \ Blob.webidl \ BrowserElementDictionaries.webidl \ + CameraControl.webidl \ CameraManager.webidl \ CanvasRenderingContext2D.webidl \ CaretPosition.webidl \ From 57a43f4202829bbd0bc32095c5052c6753f22d26 Mon Sep 17 00:00:00 2001 From: Mark Hammond Date: Mon, 26 Aug 2013 17:45:42 +1000 Subject: [PATCH 49/85] Fix indentation in previous checkin. No bug, r=me --- browser/base/content/test/social/browser_chat_tearoff.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/base/content/test/social/browser_chat_tearoff.js b/browser/base/content/test/social/browser_chat_tearoff.js index 5906f73d8c35..5bac086527f2 100644 --- a/browser/base/content/test/social/browser_chat_tearoff.js +++ b/browser/base/content/test/social/browser_chat_tearoff.js @@ -171,7 +171,7 @@ var tests = { domwindow.removeEventListener("load", _load, false); domwindow.addEventListener("unload", function _close(event) { - if (event.target != doc) + if (event.target != doc) return; domwindow.removeEventListener("unload", _close, false); ok(true, "window has been closed"); From ed6d8cdd5ea85075c0c022128114e3272cdfdd3c Mon Sep 17 00:00:00 2001 From: Heather Arthur Date: Mon, 26 Aug 2013 10:24:41 +0200 Subject: [PATCH 50/85] Bug 905312 - Make monospace font consistent across devtools; r=paul --- browser/devtools/debugger/debugger-panes.js | 10 ++++++---- browser/devtools/debugger/debugger.xul | 10 +++++----- browser/devtools/layoutview/view.css | 2 -- browser/devtools/layoutview/view.xhtml | 3 ++- browser/devtools/netmonitor/netmonitor.xul | 16 ++++++++-------- browser/devtools/shared/autocomplete-popup.js | 3 ++- browser/devtools/webconsole/console-output.js | 1 + browser/devtools/webconsole/webconsole.js | 4 ++++ browser/devtools/webconsole/webconsole.xul | 7 ++++--- browser/themes/linux/devtools/common.css | 2 +- browser/themes/linux/devtools/debugger.css | 5 ----- browser/themes/linux/devtools/font-inspector.css | 6 ++---- browser/themes/linux/devtools/netmonitor.css | 1 - browser/themes/linux/devtools/webconsole.css | 14 -------------- browser/themes/osx/devtools/common.css | 1 + browser/themes/osx/devtools/debugger.css | 5 ----- browser/themes/osx/devtools/font-inspector.css | 6 ++---- browser/themes/osx/devtools/netmonitor.css | 1 - browser/themes/osx/devtools/webconsole.css | 14 +------------- .../themes/shared/devtools/webconsole.inc.css | 7 ------- browser/themes/windows/devtools/debugger.css | 5 ----- .../themes/windows/devtools/font-inspector.css | 6 ++---- browser/themes/windows/devtools/netmonitor.css | 1 - browser/themes/windows/devtools/webconsole.css | 7 ------- 24 files changed, 41 insertions(+), 96 deletions(-) diff --git a/browser/devtools/debugger/debugger-panes.js b/browser/devtools/debugger/debugger-panes.js index 3ce6f28e2f74..166e1dbd8f44 100644 --- a/browser/devtools/debugger/debugger-panes.js +++ b/browser/devtools/debugger/debugger-panes.js @@ -466,7 +466,8 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, { let container = document.createElement("hbox"); container.id = "breakpoint-" + aOptions.actor; - container.className = "dbg-breakpoint side-menu-widget-item-other"; + container.className = "dbg-breakpoint devtools-monospace" + + " side-menu-widget-item-other"; container.setAttribute("align", "center"); container.setAttribute("flex", "1"); @@ -1429,7 +1430,7 @@ WatchExpressionsView.prototype = Heritage.extend(WidgetMethods, { arrowNode.className = "dbg-expression-arrow"; let inputNode = document.createElement("textbox"); - inputNode.className = "plain dbg-expression-input"; + inputNode.className = "plain dbg-expression-input devtools-monospace"; inputNode.setAttribute("value", aAttachment.initialExpression); inputNode.setAttribute("flex", "1"); @@ -2194,9 +2195,10 @@ LineResults.prototype = { let lineLength = 0; let firstMatch = null; - lineNumberNode.className = "plain dbg-results-line-number"; + lineNumberNode.className = "plain dbg-results-line-number devtools-monospace"; lineNumberNode.setAttribute("value", aLineNumber + 1); - lineContentsNode.className = "light list-widget-item dbg-results-line-contents"; + lineContentsNode.className = "light list-widget-item devtools-monospace" + + " dbg-results-line-contents"; lineContentsNode.setAttribute("flex", "1"); for (let chunk of this._store) { diff --git a/browser/devtools/debugger/debugger.xul b/browser/devtools/debugger/debugger.xul index 8e6e52320fa6..1062346a127c 100644 --- a/browser/devtools/debugger/debugger.xul +++ b/browser/devtools/debugger/debugger.xul @@ -347,35 +347,35 @@ value="&debuggerUI.searchPanelOperators;"/>