author | Ed Morley <emorley@mozilla.com> |
Mon, 21 May 2012 07:49:47 +0100 | |
changeset 94483 | 1158503601be5ca5f0591732c96dde073b632cc4 |
parent 94482 | c0065b9d90bfeb01fc75d8ffa5b97e997ec9f261 (current diff) |
parent 94468 | b5352f7337b15c7456cc1eafea7d2b5754360082 (diff) |
child 94484 | f4157e8c410708d76703f19e4dfb61859bfe32d8 |
push id | 9632 |
push user | emorley@mozilla.com |
push date | Mon, 21 May 2012 12:28:17 +0000 |
treeherder | mozilla-inbound@42835eaf1f2c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 15.0a1 |
first release with | nightly linux32
1158503601be
/
15.0a1
/
20120521030525
/
files
nightly linux64
1158503601be
/
15.0a1
/
20120521030525
/
files
nightly mac
1158503601be
/
15.0a1
/
20120521030525
/
files
nightly win32
1158503601be
/
15.0a1
/
20120521030525
/
files
nightly win64
1158503601be
/
15.0a1
/
20120521030525
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
15.0a1
/
20120521030525
/
pushlog to previous
nightly linux64
15.0a1
/
20120521030525
/
pushlog to previous
nightly mac
15.0a1
/
20120521030525
/
pushlog to previous
nightly win32
15.0a1
/
20120521030525
/
pushlog to previous
nightly win64
15.0a1
/
20120521030525
/
pushlog to previous
|
build/mobile/robocop/robotium-solo-3.1.jar | file | annotate | diff | comparison | revisions | |
content/xul/content/test/test_bug330705-2.xul | file | annotate | diff | comparison | revisions | |
dom/imptests/failures.txt | file | annotate | diff | comparison | revisions | |
dom/imptests/html.json | file | annotate | diff | comparison | revisions | |
dom/imptests/testharnessreport.js.in | file | annotate | diff | comparison | revisions | |
dom/imptests/webapps.json | file | annotate | diff | comparison | revisions | |
dom/imptests/writeReporter.py | file | annotate | diff | comparison | revisions | |
dom/plugins/base/nsIPluginStreamListener.idl | file | annotate | diff | comparison | revisions | |
js/src/jit-test/tests/basic/testCrossGlobalInvokeSession.js | file | annotate | diff | comparison | revisions | |
js/src/jit-test/tests/basic/testReconstructImacroPCStack.js | file | annotate | diff | comparison | revisions | |
tools/profiler/thread_helper.h | file | annotate | diff | comparison | revisions |
--- a/.gitignore +++ b/.gitignore @@ -13,16 +13,17 @@ ID .*.sw[a-z] # User files that may appear at the root /.mozconfig* /mozconfig /configure /config.cache /config.log +/.clang_complete # Empty marker file that's generated when we check out NSS security/manager/.nss.checkout # Build directories /obj*/ # Build directories for js shell
--- a/.hgignore +++ b/.hgignore @@ -12,16 +12,17 @@ .[^/]*\.sw.$ # User files that may appear at the root ^\.mozconfig ^mozconfig* ^configure$ ^config\.cache$ ^config\.log$ +^\.clang_complete # Empty marker file that's generated when we check out NSS ^security/manager/\.nss\.checkout$ # Build directories ^obj # Build directories for js shell
--- a/accessible/src/base/nsAccDocManager.cpp +++ b/accessible/src/base/nsAccDocManager.cpp @@ -390,18 +390,17 @@ nsAccDocManager::CreateDocOrRootAccessib // We only create root accessibles for the true root, otherwise create a // doc accessible. nsRefPtr<nsDocAccessible> docAcc = isRootDoc ? new RootAccessibleWrap(aDocument, rootElm, presShell) : new nsDocAccessibleWrap(aDocument, rootElm, presShell); // Cache the document accessible into document cache. - if (!docAcc || !mDocAccessibleCache.Put(aDocument, docAcc)) - return nsnull; + mDocAccessibleCache.Put(aDocument, docAcc); // Initialize the document accessible. if (!docAcc->Init()) { docAcc->Shutdown(); return nsnull; } docAcc->SetRoleMapEntry(aria::GetRoleMap(aDocument));
--- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -741,23 +741,31 @@ nsAccessible::NativeState() if (frame && (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) state |= states::FLOATING; // Check if a XUL element has the popup attribute (an attached popup menu). if (mContent->IsXUL()) if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::popup)) state |= states::HASPOPUP; - // Add 'linked' state for simple xlink. - if (nsCoreUtils::IsXLink(mContent)) - state |= states::LINKED; + // Bypass the link states specialization for non links. + if (!mRoleMapEntry || mRoleMapEntry->roleRule == kUseNativeRole || + mRoleMapEntry->role == roles::LINK) + state |= NativeLinkState(); return state; } +PRUint64 +nsAccessible::NativeLinkState() const +{ + // Expose linked state for simple xlink. + return nsCoreUtils::IsXLink(mContent) ? states::LINKED : 0; +} + /* readonly attribute boolean focusedChild; */ NS_IMETHODIMP nsAccessible::GetFocusedChild(nsIAccessible** aChild) { NS_ENSURE_ARG_POINTER(aChild); *aChild = nsnull; if (IsDefunct()) @@ -1613,17 +1621,17 @@ nsAccessible::State() state |= states::HORIZONTAL; } } return state; } void -nsAccessible::ApplyARIAState(PRUint64* aState) +nsAccessible::ApplyARIAState(PRUint64* aState) const { if (!mContent->IsElement()) return; dom::Element* element = mContent->AsElement(); // Test for universal states first *aState |= nsARIAMap::UniversalStatesFor(element);
--- a/accessible/src/base/nsAccessible.h +++ b/accessible/src/base/nsAccessible.h @@ -180,17 +180,17 @@ public: /** * Maps ARIA state attributes to state of accessible. Note the given state * argument should hold states for accessible before you pass it into this * method. * * @param [in/out] where to fill the states into. */ - virtual void ApplyARIAState(PRUint64* aState); + virtual void ApplyARIAState(PRUint64* aState) const; /** * Returns the accessible name provided by native markup. It doesn't take * into account ARIA markup used to specify the name. * * @param aName [out] the accessible name * * @return NS_OK_EMPTY_NAME points empty name was specified by native markup @@ -223,22 +223,37 @@ public: virtual mozilla::a11y::role NativeRole(); /** * Return all states of accessible (including ARIA states). */ virtual PRUint64 State(); /** + * Return link states present on the accessible. + */ + PRUint64 LinkState() const + { + PRUint64 state = NativeLinkState(); + ApplyARIAState(&state); + return state; + } + + /** * Return the states of accessible, not taking into account ARIA states. * Use State() to get complete set of states. */ virtual PRUint64 NativeState(); /** + * Return native link states present on the accessible. + */ + virtual PRUint64 NativeLinkState() const; + + /** * Return bit set of invisible and offscreen states. */ PRUint64 VisibilityState(); /** * Returns attributes for accessible without explicitly setted ARIA * attributes. */
--- a/accessible/src/base/nsBaseWidgetAccessible.cpp +++ b/accessible/src/base/nsBaseWidgetAccessible.cpp @@ -108,26 +108,22 @@ NS_IMPL_ISUPPORTS_INHERITED0(nsLinkableA NS_IMETHODIMP nsLinkableAccessible::TakeFocus() { return mActionAcc ? mActionAcc->TakeFocus() : nsAccessibleWrap::TakeFocus(); } PRUint64 -nsLinkableAccessible::NativeState() +nsLinkableAccessible::NativeLinkState() const { - PRUint64 states = nsAccessibleWrap::NativeState(); - if (mIsLink) { - states |= states::LINKED; - if (mActionAcc->State() & states::TRAVERSED) - states |= states::TRAVERSED; - } + if (mIsLink) + return states::LINKED | (mActionAcc->LinkState() & states::TRAVERSED); - return states; + return 0; } void nsLinkableAccessible::Value(nsString& aValue) { aValue.Truncate(); nsAccessible::Value(aValue); @@ -230,21 +226,20 @@ nsLinkableAccessible::BindToParent(nsAcc return; } // XXX: The logic looks broken since the click listener may be registered // on non accessible node in parent chain but this node is skipped when tree // is traversed. nsAccessible* walkUpAcc = this; while ((walkUpAcc = walkUpAcc->Parent()) && !walkUpAcc->IsDoc()) { - if (walkUpAcc->Role() == roles::LINK && - walkUpAcc->State() & states::LINKED) { - mIsLink = true; - mActionAcc = walkUpAcc; - return; + if (walkUpAcc->LinkState() & states::LINKED) { + mIsLink = true; + mActionAcc = walkUpAcc; + return; } if (nsCoreUtils::HasClickListener(walkUpAcc->GetContent())) { mActionAcc = walkUpAcc; mIsOnclick = true; return; } }
--- a/accessible/src/base/nsBaseWidgetAccessible.h +++ b/accessible/src/base/nsBaseWidgetAccessible.h @@ -91,17 +91,17 @@ public: NS_IMETHOD DoAction(PRUint8 index); NS_IMETHOD TakeFocus(); // nsAccessNode virtual void Shutdown(); // nsAccessible virtual void Value(nsString& aValue); - virtual PRUint64 NativeState(); + virtual PRUint64 NativeLinkState() const; // ActionAccessible virtual PRUint8 ActionCount(); virtual KeyBinding AccessKey() const; // HyperLinkAccessible virtual already_AddRefed<nsIURI> AnchorURIAt(PRUint32 aAnchorIndex);
--- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -336,17 +336,17 @@ nsDocAccessible::NativeState() nsCOMPtr<nsIEditor> editor = GetEditor(); state |= editor ? states::EDITABLE : states::READONLY; return state; } // nsAccessible public method void -nsDocAccessible::ApplyARIAState(PRUint64* aState) +nsDocAccessible::ApplyARIAState(PRUint64* aState) const { // Combine with states from outer doc // nsAccessible::ApplyARIAState(aState); // Allow iframe/frame etc. to have final state override via ARIA if (mParent) mParent->ApplyARIAState(aState); @@ -1364,27 +1364,21 @@ nsDocAccessible::GetAccessibleOrContaine bool nsDocAccessible::BindToDocument(nsAccessible* aAccessible, nsRoleMapEntry* aRoleMapEntry) { if (!aAccessible) return false; // Put into DOM node cache. - if (aAccessible->IsPrimaryForNode() && - !mNodeToAccessibleMap.Put(aAccessible->GetNode(), aAccessible)) - return false; + if (aAccessible->IsPrimaryForNode()) + mNodeToAccessibleMap.Put(aAccessible->GetNode(), aAccessible); // Put into unique ID cache. - if (!mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible)) { - if (aAccessible->IsPrimaryForNode()) - mNodeToAccessibleMap.Remove(aAccessible->GetNode()); - - return false; - } + mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible); // Initialize the accessible. if (!aAccessible->Init()) { NS_ERROR("Failed to initialize an accessible!"); UnbindFromDocument(aAccessible); return false; } @@ -1616,20 +1610,17 @@ nsDocAccessible::AddDependentIDsFor(nsAc const nsDependentSubstring id = iter.NextID(); if (id.IsEmpty()) break; AttrRelProviderArray* providers = mDependentIDsHash.Get(id); if (!providers) { providers = new AttrRelProviderArray(); if (providers) { - if (!mDependentIDsHash.Put(id, providers)) { - delete providers; - providers = nsnull; - } + mDependentIDsHash.Put(id, providers); } } if (providers) { AttrRelProvider* provider = new AttrRelProvider(relAttr, aRelProvider->GetContent()); if (provider) { providers->AppendElement(provider);
--- a/accessible/src/base/nsDocAccessible.h +++ b/accessible/src/base/nsDocAccessible.h @@ -110,17 +110,17 @@ public: virtual nsIDocument* GetDocumentNode() const { return mDocument; } // nsAccessible virtual mozilla::a11y::ENameValueFlag Name(nsString& aName); virtual void Description(nsString& aDescription); virtual nsAccessible* FocusedChild(); virtual mozilla::a11y::role NativeRole(); virtual PRUint64 NativeState(); - virtual void ApplyARIAState(PRUint64* aState); + virtual void ApplyARIAState(PRUint64* aState) const; virtual void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry); #ifdef DEBUG_ACCDOCMGR virtual nsresult HandleAccEvent(AccEvent* aAccEvent); #endif virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
--- a/accessible/src/generic/ARIAGridAccessible.cpp +++ b/accessible/src/generic/ARIAGridAccessible.cpp @@ -1040,17 +1040,17 @@ ARIAGridCellAccessible::IsSelected(bool* *aIsSelected = true; return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // nsAccessible void -ARIAGridCellAccessible::ApplyARIAState(PRUint64* aState) +ARIAGridCellAccessible::ApplyARIAState(PRUint64* aState) const { nsHyperTextAccessibleWrap::ApplyARIAState(aState); // Return if the gridcell has aria-selected="true". if (*aState & states::SELECTED) return; // Check aria-selected="true" on the row.
--- a/accessible/src/generic/ARIAGridAccessible.h +++ b/accessible/src/generic/ARIAGridAccessible.h @@ -133,16 +133,16 @@ public: // nsISupports NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTableCell NS_DECL_NSIACCESSIBLETABLECELL // nsAccessible - virtual void ApplyARIAState(PRUint64* aState); + virtual void ApplyARIAState(PRUint64* aState) const; virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes); }; } // namespace a11y } // namespace mozilla #endif
--- a/accessible/src/generic/ApplicationAccessible.cpp +++ b/accessible/src/generic/ApplicationAccessible.cpp @@ -328,17 +328,17 @@ ApplicationAccessible::IsPrimaryForNode( { return false; } //////////////////////////////////////////////////////////////////////////////// // nsAccessible public methods void -ApplicationAccessible::ApplyARIAState(PRUint64* aState) +ApplicationAccessible::ApplyARIAState(PRUint64* aState) const { } role ApplicationAccessible::NativeRole() { return roles::APP_ROOT; }
--- a/accessible/src/generic/ApplicationAccessible.h +++ b/accessible/src/generic/ApplicationAccessible.h @@ -99,17 +99,17 @@ public: // nsAccessNode virtual bool Init(); virtual void Shutdown(); virtual bool IsPrimaryForNode() const; // nsAccessible virtual mozilla::a11y::ENameValueFlag Name(nsString& aName); - virtual void ApplyARIAState(PRUint64* aState); + virtual void ApplyARIAState(PRUint64* aState) const; virtual void Description(nsString& aDescription); virtual void Value(nsString& aValue); virtual mozilla::a11y::role NativeRole(); virtual PRUint64 State(); virtual PRUint64 NativeState(); virtual Relation RelationByType(PRUint32 aRelType); virtual nsAccessible* ChildAtPoint(PRInt32 aX, PRInt32 aY,
--- a/accessible/src/html/HTMLFormControlAccessible.cpp +++ b/accessible/src/html/HTMLFormControlAccessible.cpp @@ -432,17 +432,17 @@ HTMLTextFieldAccessible::Value(nsString& nsCOMPtr<nsIDOMHTMLInputElement> inputElement(do_QueryInterface(mContent)); if (inputElement) { inputElement->GetValue(aValue); } } void -HTMLTextFieldAccessible::ApplyARIAState(PRUint64* aState) +HTMLTextFieldAccessible::ApplyARIAState(PRUint64* aState) const { nsHyperTextAccessibleWrap::ApplyARIAState(aState); aria::MapToState(aria::eARIAAutoComplete, mContent->AsElement(), aState); } PRUint64 HTMLTextFieldAccessible::State()
--- a/accessible/src/html/HTMLFormControlAccessible.h +++ b/accessible/src/html/HTMLFormControlAccessible.h @@ -140,17 +140,17 @@ public: NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName); NS_IMETHOD DoAction(PRUint8 index); // nsHyperTextAccessible virtual already_AddRefed<nsIEditor> GetEditor() const; // nsAccessible virtual void Value(nsString& aValue); - virtual void ApplyARIAState(PRUint64* aState); + virtual void ApplyARIAState(PRUint64* aState) const; virtual nsresult GetNameInternal(nsAString& aName); virtual mozilla::a11y::role NativeRole(); virtual PRUint64 State(); virtual PRUint64 NativeState(); // ActionAccessible virtual PRUint8 ActionCount();
--- a/accessible/src/html/nsHTMLImageMapAccessible.cpp +++ b/accessible/src/html/nsHTMLImageMapAccessible.cpp @@ -226,29 +226,16 @@ nsHTMLAreaAccessible::IsPrimaryForNode() // Make HTML area DOM element not accessible. HTML image map accessible // manages its tree itself. return false; } //////////////////////////////////////////////////////////////////////////////// // nsHTMLAreaAccessible: nsAccessible public -PRUint64 -nsHTMLAreaAccessible::NativeState() -{ - // Bypass the link states specialization for non links. - if (mRoleMapEntry && - mRoleMapEntry->role != roles::NOTHING && - mRoleMapEntry->role != roles::LINK) { - return nsAccessible::NativeState(); - } - - return nsHTMLLinkAccessible::NativeState(); -} - nsAccessible* nsHTMLAreaAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY, EWhichChildAtPoint aWhichChild) { // Don't walk into area accessibles. return this; }
--- a/accessible/src/html/nsHTMLImageMapAccessible.h +++ b/accessible/src/html/nsHTMLImageMapAccessible.h @@ -97,17 +97,16 @@ public: nsHTMLAreaAccessible(nsIContent* aContent, nsDocAccessible* aDoc); // nsAccessNode virtual bool IsPrimaryForNode() const; // nsAccessible virtual void Description(nsString& aDescription); virtual nsresult GetNameInternal(nsAString& aName); - virtual PRUint64 NativeState(); virtual nsAccessible* ChildAtPoint(PRInt32 aX, PRInt32 aY, EWhichChildAtPoint aWhichChild); virtual void GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame); // HyperLinkAccessible virtual PRUint32 StartOffset(); virtual PRUint32 EndOffset();
--- a/accessible/src/html/nsHTMLLinkAccessible.cpp +++ b/accessible/src/html/nsHTMLLinkAccessible.cpp @@ -81,34 +81,33 @@ nsHTMLLinkAccessible::NativeState() if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::name)) { // This is how we indicate it is a named anchor // In other words, this anchor can be selected as a location :) // There is no other better state to use to indicate this. states |= states::SELECTABLE; } - nsEventStates state = mContent->AsElement()->State(); - if (state.HasAtLeastOneOfStates(NS_EVENT_STATE_VISITED | - NS_EVENT_STATE_UNVISITED)) { - states |= states::LINKED; + return states; +} - if (state.HasState(NS_EVENT_STATE_VISITED)) - states |= states::TRAVERSED; +PRUint64 +nsHTMLLinkAccessible::NativeLinkState() const +{ + nsEventStates eventState = mContent->AsElement()->State(); + if (eventState.HasState(NS_EVENT_STATE_UNVISITED)) + return states::LINKED; - return states; - } + if (eventState.HasState(NS_EVENT_STATE_VISITED)) + return states::LINKED | states::TRAVERSED; // This is a either named anchor (a link with also a name attribute) or // it doesn't have any attributes. Check if 'click' event handler is // registered, otherwise bail out. - if (nsCoreUtils::HasClickListener(mContent)) - states |= states::LINKED; - - return states; + return nsCoreUtils::HasClickListener(mContent) ? states::LINKED : 0; } void nsHTMLLinkAccessible::Value(nsString& aValue) { aValue.Truncate(); nsHyperTextAccessible::Value(aValue);
--- a/accessible/src/html/nsHTMLLinkAccessible.h +++ b/accessible/src/html/nsHTMLLinkAccessible.h @@ -52,16 +52,17 @@ public: // nsIAccessible NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName); NS_IMETHOD DoAction(PRUint8 aIndex); // nsAccessible virtual void Value(nsString& aValue); virtual mozilla::a11y::role NativeRole(); virtual PRUint64 NativeState(); + virtual PRUint64 NativeLinkState() const; // ActionAccessible virtual PRUint8 ActionCount(); // HyperLinkAccessible virtual bool IsLink(); virtual already_AddRefed<nsIURI> AnchorURIAt(PRUint32 aAnchorIndex);
--- a/accessible/src/html/nsHyperTextAccessible.cpp +++ b/accessible/src/html/nsHyperTextAccessible.cpp @@ -1493,17 +1493,17 @@ nsHyperTextAccessible::DeleteText(PRInt3 return NS_ERROR_FAILURE; nsCOMPtr<nsIEditor> editor = GetEditor(); NS_ENSURE_STATE(editor); nsresult rv = SetSelectionRange(aStartPos, aEndPos); NS_ENSURE_SUCCESS(rv, rv); - return editor->DeleteSelection(nsIEditor::eNone); + return editor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip); } NS_IMETHODIMP nsHyperTextAccessible::PasteText(PRInt32 aPosition) { if (IsDefunct()) return NS_ERROR_FAILURE;
--- a/accessible/src/jsat/AccessFu.jsm +++ b/accessible/src/jsat/AccessFu.jsm @@ -34,22 +34,22 @@ var AccessFu = { // XXX: only supports attaching to one window now. throw new Error('Only one window could be attached to AccessFu'); dump('AccessFu attach!! ' + Services.appinfo.OS + '\n'); this.chromeWin = aWindow; this.presenters = []; this.prefsBranch = Cc['@mozilla.org/preferences-service;1'] - .getService(Ci.nsIPrefService).getBranch('accessibility.'); - this.prefsBranch.addObserver('accessfu', this, false); + .getService(Ci.nsIPrefService).getBranch('accessibility.accessfu.'); + this.prefsBranch.addObserver('activate', this, false); let accessPref = ACCESSFU_DISABLE; try { - accessPref = this.prefsBranch.getIntPref('accessfu'); + accessPref = this.prefsBranch.getIntPref('activate'); } catch (x) { } this._processPreferences(accessPref); }, /** * Start AccessFu mode, this primarily means controlling the virtual cursor @@ -171,18 +171,18 @@ var AccessFu = { switch (aTopic) { case 'Accessibility:Settings': if (JSON.parse(aData).enabled) this._enable(); else this._disable(); break; case 'nsPref:changed': - if (aData == 'accessfu') - this._processPreferences(this.prefsBranch.getIntPref('accessfu')); + if (aData == 'activate') + this._processPreferences(this.prefsBranch.getIntPref('activate')); break; case 'accessible-event': let event; try { event = aSubject.QueryInterface(Ci.nsIAccessibleEvent); this._handleAccEvent(event); } catch (ex) { dump(ex); @@ -210,22 +210,20 @@ var AccessFu = { // focus. let sel = doc.getSelection(); sel.collapse(position.DOMNode, 0); Cc["@mozilla.org/focus-manager;1"] .getService(Ci.nsIFocusManager).moveFocus( doc.defaultView, null, Ci.nsIFocusManager.MOVEFOCUS_CARET, 0); } - let newContext = this.getNewContext(event.oldAccessible, - pivot.position); + let presenterContext = new PresenterContext(pivot.position, + event.oldAccessible); this.presenters.forEach( - function(p) { - p.pivotChanged(pivot.position, newContext); - }); + function(p) { p.pivotChanged(presenterContext); }); break; } case Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE: { let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent); if (event.state == Ci.nsIAccessibleStates.STATE_CHECKED && !(event.isExtraState())) { this.presenters.forEach( @@ -308,18 +306,23 @@ var AccessFu = { } ); break; } case Ci.nsIAccessibleEvent.EVENT_FOCUS: { if (this._isBrowserDoc(aEvent.accessible)) { // The document recieved focus, call tabSelected to present current tab. + let docContext = new PresenterContext(aEvent.accessible, null); + let cursorable = aEvent.accessible. + QueryInterface(Ci.nsIAccessibleCursorable); + let vcContext = new PresenterContext( + (cursorable) ? cursorable.virtualCursor.position : null, null); this.presenters.forEach( - function(p) { p.tabSelected(aEvent.accessible); }); + function(p) { p.tabSelected(docContext, vcContext); }); } break; } case Ci.nsIAccessibleEvent.EVENT_TEXT_INSERTED: case Ci.nsIAccessibleEvent.EVENT_TEXT_REMOVED: { if (aEvent.isFromUserInput) { // XXX support live regions as well. @@ -378,51 +381,16 @@ var AccessFu = { _isNotChromeDoc: function _isNotChromeDoc(aDocument) { let location = aDocument.DOMNode.location; if (!location) return false; return location.protocol != "about:"; }, - getNewContext: function getNewContext(aOldObject, aNewObject) { - let newLineage = []; - let oldLineage = []; - - let parent = aNewObject; - while ((parent = parent.parent)) - newLineage.push(parent); - - if (aOldObject) { - parent = aOldObject; - while ((parent = parent.parent)) - oldLineage.push(parent); - } - -// newLineage.reverse(); -// oldLineage.reverse(); - - let i = 0; - let newContext = []; - - while (true) { - let newAncestor = newLineage.pop(); - let oldAncestor = oldLineage.pop(); - - if (newAncestor == undefined) - break; - - if (newAncestor != oldAncestor) - newContext.push(newAncestor); - i++; - } - - return newContext; - }, - // A hash of documents that don't yet have an accessible tree. _pendingDocuments: {}, // So we don't enable/disable twice _enabled: false, // Observing accessibility settings _observingSystemSettings: false
--- a/accessible/src/jsat/Presenters.jsm +++ b/accessible/src/jsat/Presenters.jsm @@ -9,17 +9,18 @@ const Ci = Components.interfaces; const Cu = Components.utils; const Cr = Components.results; Cu.import('resource://gre/modules/accessibility/UtteranceGenerator.jsm'); Cu.import('resource://gre/modules/Services.jsm'); var EXPORTED_SYMBOLS = ['VisualPresenter', 'AndroidPresenter', - 'DummyAndroidPresenter']; + 'DummyAndroidPresenter', + 'PresenterContext']; /** * The interface for all presenter classes. A presenter could be, for example, * a speech output module, or a visual cursor indicator. */ function Presenter() {} Presenter.prototype = { @@ -31,21 +32,20 @@ Presenter.prototype = { /** * Detach function. */ detach: function detach() {}, /** * The virtual cursor's position changed. - * @param {nsIAccessible} aObject the new position. - * @param {nsIAccessible[]} aNewContext the ancestry of the new position that - * is different from the old virtual cursor position. + * @param {PresenterContext} aContext the context object for the new pivot + * position. */ - pivotChanged: function pivotChanged(aObject, aNewContext) {}, + pivotChanged: function pivotChanged(aContext) {}, /** * An object's action has been invoked. * @param {nsIAccessible} aObject the object that has been invoked. * @param {string} aActionName the name of the action. */ actionInvoked: function actionInvoked(aObject, aActionName) {}, @@ -73,21 +73,22 @@ Presenter.prototype = { * state changed, or null if the tab has no associated document yet. * @param {string} aPageState the state name for the tab, valid states are: * 'newtab', 'loading', 'newdoc', 'loaded', 'stopped', and 'reload'. */ tabStateChanged: function tabStateChanged(aDocObj, aPageState) {}, /** * The current tab has changed. - * @param {nsIAccessible} aObject the document contained by the tab - * accessible, or null if it is a new tab with no attached - * document yet. + * @param {PresenterContext} aDocContext context object for tab's + * document. + * @param {PresenterContext} aVCContext context object for tab's current + * virtual cursor position. */ - tabSelected: function tabSelected(aDocObj) {}, + tabSelected: function tabSelected(aDocContext, aVCContext) {}, /** * The viewport has changed, either a scroll, pan, zoom, or * landscape/portrait toggle. */ viewportChanged: function viewportChanged() {} }; @@ -134,44 +135,42 @@ VisualPresenter.prototype = { this.highlightBox = this.stylesheet = null; }, viewportChanged: function VisualPresenter_viewportChanged() { if (this._currentObject) this._highlight(this._currentObject); }, - pivotChanged: function VisualPresenter_pivotChanged(aObject, aNewContext) { - this._currentObject = aObject; + pivotChanged: function VisualPresenter_pivotChanged(aContext) { + this._currentObject = aContext.accessible; - if (!aObject) { + if (!aContext.accessible) { this._hide(); return; } try { - aObject.scrollTo(Ci.nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE); - this._highlight(aObject); + aContext.accessible.scrollTo( + Ci.nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE); + this._highlight(aContext.accessible); } catch (e) { dump('Error getting bounds: ' + e); return; } }, - tabSelected: function VisualPresenter_tabSelected(aDocObj) { - let vcPos = aDocObj ? aDocObj.QueryInterface(Ci.nsIAccessibleCursorable). - virtualCursor.position : null; - - this.pivotChanged(vcPos); + tabSelected: function VisualPresenter_tabSelected(aDocContext, aVCContext) { + this.pivotChanged(aVCContext); }, tabStateChanged: function VisualPresenter_tabStateChanged(aDocObj, aPageState) { if (aPageState == 'newdoc') - this.pivotChanged(null); + this._hide(); }, // Internals _hide: function _hide() { this.highlightBox.style.display = 'none'; }, @@ -229,24 +228,25 @@ AndroidPresenter.prototype = { // Android AccessibilityEvent type constants. ANDROID_VIEW_CLICKED: 0x01, ANDROID_VIEW_LONG_CLICKED: 0x02, ANDROID_VIEW_SELECTED: 0x04, ANDROID_VIEW_FOCUSED: 0x08, ANDROID_VIEW_TEXT_CHANGED: 0x10, ANDROID_WINDOW_STATE_CHANGED: 0x20, - pivotChanged: function AndroidPresenter_pivotChanged(aObject, aNewContext) { + pivotChanged: function AndroidPresenter_pivotChanged(aContext) { let output = []; - for (let i in aNewContext) - output.push.apply(output, - UtteranceGenerator.genForObject(aNewContext[i])); + for (let i in aContext.newAncestry) + output.push.apply( + output, UtteranceGenerator.genForObject(aContext.newAncestry[i])); output.push.apply(output, - UtteranceGenerator.genForObject(aObject, true)); + UtteranceGenerator.genForObject(aContext.accessible, + true)); this.sendMessageToJava({ gecko: { type: 'Accessibility:Event', eventType: this.ANDROID_VIEW_FOCUSED, text: output } }); @@ -257,31 +257,19 @@ AndroidPresenter.prototype = { gecko: { type: 'Accessibility:Event', eventType: this.ANDROID_VIEW_CLICKED, text: UtteranceGenerator.genForAction(aObject, aActionName) } }); }, - tabSelected: function AndroidPresenter_tabSelected(aDocObj) { + tabSelected: function AndroidPresenter_tabSelected(aDocContext, aVCContext) { // Send a pivot change message with the full context utterance for this doc. - let vcDoc = aDocObj.QueryInterface(Ci.nsIAccessibleCursorable); - let context = []; - - let parent = vcDoc.virtualCursor.position || aDocObj; - while ((parent = parent.parent)) { - context.push(parent); - if (parent == aDocObj) - break; - } - - context.reverse(); - - this.pivotChanged(vcDoc.virtualCursor.position || aDocObj, context); + this.pivotChanged(aVCContext); }, tabStateChanged: function AndroidPresenter_tabStateChanged(aDocObj, aPageState) { let stateUtterance = UtteranceGenerator. genForTabStateChange(aDocObj, aPageState); if (!stateUtterance.length) @@ -337,8 +325,67 @@ function DummyAndroidPresenter() {} DummyAndroidPresenter.prototype = { __proto__: AndroidPresenter.prototype, sendMessageToJava: function DummyAndroidPresenter_sendMessageToJava(aMsg) { dump(JSON.stringify(aMsg, null, 2) + '\n'); } }; + +/** + * PresenterContext: An object that generates and caches context information + * for a given accessible and its relationship with another accessible. + */ +function PresenterContext(aAccessible, aOldAccessible) { + this._accessible = aAccessible; + this._oldAccessible = aOldAccessible; +} + +PresenterContext.prototype = { + get accessible() { + return this._accessible; + }, + + get oldAccessible() { + return this._oldAccessible; + }, + + /* + * This is a list of the accessible's ancestry up to the common ancestor + * of the accessible and the old accessible. It is useful for giving the + * user context as to where they are in the heirarchy. + */ + get newAncestry() { + if (!this._newAncestry) { + let newLineage = []; + let oldLineage = []; + + let parent = this._accessible; + while ((parent = parent.parent)) + newLineage.push(parent); + + if (this._oldAccessible) { + parent = this._oldAccessible; + while ((parent = parent.parent)) + oldLineage.push(parent); + } + + let i = 0; + this._newAncestry = []; + + while (true) { + let newAncestor = newLineage.pop(); + let oldAncestor = oldLineage.pop(); + + if (newAncestor == undefined) + break; + + if (newAncestor != oldAncestor) + this._newAncestry.push(newAncestor); + i++; + } + + } + + return this._newAncestry; + } +};
--- a/accessible/src/xul/XULFormControlAccessible.cpp +++ b/accessible/src/xul/XULFormControlAccessible.cpp @@ -749,22 +749,21 @@ XULTextFieldAccessible::Value(nsString& } nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent)); if (menuList) menuList->GetLabel(aValue); } void -XULTextFieldAccessible::ApplyARIAState(PRUint64* aState) +XULTextFieldAccessible::ApplyARIAState(PRUint64* aState) const { nsHyperTextAccessibleWrap::ApplyARIAState(aState); aria::MapToState(aria::eARIAAutoComplete, mContent->AsElement(), aState); - } PRUint64 XULTextFieldAccessible::NativeState() { PRUint64 state = nsHyperTextAccessibleWrap::NativeState(); nsCOMPtr<nsIContent> inputField(GetInputField());
--- a/accessible/src/xul/XULFormControlAccessible.h +++ b/accessible/src/xul/XULFormControlAccessible.h @@ -260,17 +260,17 @@ public: NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName); NS_IMETHOD DoAction(PRUint8 index); // nsHyperTextAccessible virtual already_AddRefed<nsIEditor> GetEditor() const; // nsAccessible virtual void Value(nsString& aValue); - virtual void ApplyARIAState(PRUint64* aState); + virtual void ApplyARIAState(PRUint64* aState) const; virtual mozilla::a11y::role NativeRole(); virtual PRUint64 NativeState(); virtual bool CanHaveAnonChildren(); // ActionAccessible virtual PRUint8 ActionCount(); protected:
--- a/accessible/src/xul/nsXULTextAccessible.cpp +++ b/accessible/src/xul/nsXULTextAccessible.cpp @@ -173,19 +173,19 @@ nsXULLinkAccessible::GetNameInternal(nsA role nsXULLinkAccessible::NativeRole() { return roles::LINK; } PRUint64 -nsXULLinkAccessible::NativeState() +nsXULLinkAccessible::NativeLinkState() const { - return nsHyperTextAccessible::NativeState() | states::LINKED; + return states::LINKED; } PRUint8 nsXULLinkAccessible::ActionCount() { return 1; }
--- a/accessible/src/xul/nsXULTextAccessible.h +++ b/accessible/src/xul/nsXULTextAccessible.h @@ -83,17 +83,17 @@ public: // nsIAccessible NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName); NS_IMETHOD DoAction(PRUint8 aIndex); // nsAccessible virtual void Value(nsString& aValue); virtual nsresult GetNameInternal(nsAString& aName); virtual mozilla::a11y::role NativeRole(); - virtual PRUint64 NativeState(); + virtual PRUint64 NativeLinkState() const; // ActionAccessible virtual PRUint8 ActionCount(); // HyperLinkAccessible virtual bool IsLink(); virtual PRUint32 StartOffset(); virtual PRUint32 EndOffset();
--- a/accessible/src/xul/nsXULTreeAccessible.cpp +++ b/accessible/src/xul/nsXULTreeAccessible.cpp @@ -569,22 +569,21 @@ nsXULTreeAccessible::GetTreeItemAccessib void *key = reinterpret_cast<void*>(aRow); nsAccessible* cachedTreeItem = mAccessibleCache.GetWeak(key); if (cachedTreeItem) return cachedTreeItem; nsRefPtr<nsAccessible> treeItem = CreateTreeItemAccessible(aRow); if (treeItem) { - if (mAccessibleCache.Put(key, treeItem)) { - if (Document()->BindToDocument(treeItem, nsnull)) - return treeItem; + mAccessibleCache.Put(key, treeItem); + if (Document()->BindToDocument(treeItem, nsnull)) + return treeItem; - mAccessibleCache.Remove(key); - } + mAccessibleCache.Remove(key); } return nsnull; } void nsXULTreeAccessible::InvalidateCache(PRInt32 aRow, PRInt32 aCount) {
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp +++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp @@ -727,22 +727,21 @@ nsXULTreeGridRowAccessible::GetCellAcces nsAccessible* cachedCell = mAccessibleCache.GetWeak(key); if (cachedCell) return cachedCell; nsRefPtr<nsAccessible> cell = new nsXULTreeGridCellAccessibleWrap(mContent, mDoc, this, mTree, mTreeView, mRow, aColumn); if (cell) { - if (mAccessibleCache.Put(key, cell)) { - if (Document()->BindToDocument(cell, nsnull)) - return cell; + mAccessibleCache.Put(key, cell); + if (Document()->BindToDocument(cell, nsnull)) + return cell; - mAccessibleCache.Remove(key); - } + mAccessibleCache.Remove(key); } return nsnull; } void nsXULTreeGridRowAccessible::RowInvalidated(PRInt32 aStartColIdx, PRInt32 aEndColIdx)
--- a/accessible/tests/mochitest/states/test_link.html +++ b/accessible/tests/mochitest/states/test_link.html @@ -3,54 +3,99 @@ <head> <title>HTML link states testing</title> <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" + src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" src="../role.js"></script> <script type="application/javascript" src="../states.js"></script> + <script type="application/javascript" + src="../events.js"></script> <script type="application/javascript"> function doTest() { - testStates("link1", STATE_LINKED); - testStates("link2", STATE_LINKED); - testStates("link3", STATE_LINKED); - testStates("link4", STATE_LINKED); - testStates("link5", 0, 0, STATE_LINKED); + // a@href and its text node + testStates("link_href", STATE_LINKED); + testStates(getAccessible("link_href").firstChild, STATE_LINKED); + + // a@onclick + testStates("link_click", STATE_LINKED); + + // a@onmousedown + testStates("link_mousedown", STATE_LINKED); + + // a@onmouseup + testStates("link_mouseup", STATE_LINKED); + + // a@role="link" + testStates("link_arialink", STATE_LINKED); + + // a@role="button" + testStates("link_ariabutton", 0, 0, STATE_LINKED); - SimpleTest.finish(); + // a (no @href, no click event listener) + testStates("link_notlink", 0, 0, STATE_LINKED); + + // a: traversal state + testStates("link_traversed", 0, 0, STATE_TRAVERSED); + registerA11yEventListener(EVENT_DOCUMENT_LOAD_COMPLETE, + traversedLinkTester); + + synthesizeMouse(getNode("link_traversed"), 1, 1, { shiftKey: true }); } + var traversedLinkTester = { + handleEvent: function traversedLinkTester_handleEvent(aEvent) { + unregisterA11yEventListener(EVENT_DOCUMENT_LOAD_COMPLETE, + traversedLinkTester); + aEvent.accessible.rootDocument.window.close(); + + testStates("link_traversed", STATE_TRAVERSED); + SimpleTest.finish(); + } + }; + SimpleTest.waitForExplicitFinish(); addA11yLoadEvent(doTest); </script> </head> <body> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=423409" title="Expose click action if mouseup and mousedown are registered"> Mozilla Bug 423409 </a> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=754830" + title="Calculate link states separately"> + Mozilla Bug 754830 + </a> <p id="display"></p> <div id="content" style="display: none"></div> <pre id="test"> </pre> - <a id="link1" href="http://mozilla.org">link</a> - <a id="link2" onclick="">link</a> - <a id="link3" onmousedown="">link</a> - <a id="link4" onmouseup="">link</a> - <a id="link5">not link</a> + <a id="link_href" href="http://mozilla.org">link</a> + <a id="link_click" onclick="">link</a> + <a id="link_mousedown" onmousedown="">link</a> + <a id="link_mouseup" onmouseup="">link</a> + <a id="link_arialink" role="link">aria link</a> + <a id="link_ariabutton" role="button">aria button</a> + <a id="link_notlink">not link</a> + + <a id="link_traversed" href="http://www.example.com" target="_top">example.com</a> </body> </html>
--- a/accessible/tests/mochitest/test_nsIAccessibleDocument.html +++ b/accessible/tests/mochitest/test_nsIAccessibleDocument.html @@ -4,27 +4,24 @@ https://bugzilla.mozilla.org/show_bug.cg --> <head> <title>nsIAccessibleDocument chrome tests</title> <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" - src="common.js"></script> + src="common.js"></script> <script type="application/javascript" - src="role.js"></script> + src="role.js"></script> <script type="application/javascript" - src="states.js"></script> + src="states.js"></script> - <!-- chrome-harness.js breaks this test (bug 736886) --> - <!-- <script type="application/javascript" - src="chrome://mochikit/content/chrome-harness.js"/> - --> + src="chrome://mochikit/content/chrome-harness.js"></script> <script type="application/javascript"> function doTest() { var docAcc = getAccessible(document, [nsIAccessibleDocument]); if (docAcc) { // nsIAccessible is(docAcc.name, "nsIAccessibleDocument chrome tests", @@ -38,29 +35,27 @@ https://bugzilla.mozilla.org/show_bug.cg // No actions wanted on doc is(docAcc.numActions, 0, "Wrong number of actions for document!"); // attributes should contain tag:body attributes = docAcc.attributes; is(attributes.getStringProperty("tag"), "body", "Wrong attribute on document!"); - // nsIAccessibleDocument - // getRootDirectory() depends on broken chrome-harness.js include (bug - // 736886) - /* + // Document URL. var rootDir = getRootDirectory(window.location.href); - is(docAcc.URL, rootDir.path + "test_nsIAccessibleDocument.html", + is(docAcc.URL, rootDir + "test_nsIAccessibleDocument.html", "Wrong URL for document!"); - */ - todo(false, "chrome-harness.js include is broken (bug 736886)"); - is(docAcc.title, "nsIAccessibleDocument chrome tests", + + // Document title and mime type. + is(docAcc.title, "nsIAccessibleDocument chrome tests", "Wrong title for document!"); is(docAcc.mimeType, "text/html", "Wrong mime type for document!"); + // nsDocAccessible::getDocType currently returns NS_ERROR_FAILURE. // See bug 442005. After fixing, please remove this comment and // uncomment the below two lines to enable the test. // is(docAcc.docType, "HTML", // "Wrong type of document!"); // Test for correct nsIDOMDocument retrieval. var domDoc = null;
--- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -619,17 +619,17 @@ SettingsListener.observe('language.curre request.onerror = function onError() { if (!idleTimeout) return; Services.idle.addIdleObserver(idleHandler, idleTimeout); power.addWakeLockListener(wakeLockHandler); }; - SettingsListener.observe('power.screen.timeout', 30, function(value) { + SettingsListener.observe('power.screen.timeout', idleTimeout, function(value) { if (!value) return; Services.idle.removeIdleObserver(idleHandler, idleTimeout); idleTimeout = value; Services.idle.addIdleObserver(idleHandler, idleTimeout); });
--- a/browser/app/blocklist.xml +++ b/browser/app/blocklist.xml @@ -1,10 +1,10 @@ <?xml version="1.0"?> -<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1336406310000"> +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1337190282000"> <emItems> <emItem blockID="i58" id="webmaster@buzzzzvideos.info"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> <emItem blockID="i86" id="{45147e67-4020-47e2-8f7a-55464fb535aa}"> <versionRange minVersion="0" maxVersion="*"> </versionRange> @@ -56,18 +56,22 @@ <emItem blockID="i16" id="{27182e60-b5f3-411c-b545-b44205977502}"> <versionRange minVersion="1.0" maxVersion="1.0"> </versionRange> </emItem> <emItem blockID="i39" id="{c2d64ff7-0ab8-4263-89c9-ea3b0f8f050c}"> <versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1"> </versionRange> </emItem> - <emItem blockID="i42" id="{D19CA586-DD6C-4a0a-96F8-14644F340D60}"> - <versionRange minVersion="0.1" maxVersion="14.4.0" severity="1"> + <emItem blockID="i92" id="play5@vide04flash.com"> + <versionRange minVersion="0" maxVersion="*"> + </versionRange> + </emItem> + <emItem blockID="i93" id="{68b8676b-99a5-46d1-b390-22411d8bcd61}"> + <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> <emItem blockID="i61" id="youtube@youtube3.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> @@ -151,20 +155,28 @@ <emItem blockID="i68" id="flashupdate@adobe.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> <emItem blockID="i90" id="videoplugin@player.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> + <emItem blockID="i91" id="crossriderapp4926@crossrider.com"> + <versionRange minVersion="0" maxVersion="0.81.43" severity="1"> + </versionRange> + </emItem> <emItem blockID="i84" id="pink@rosaplugin.info"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> + <emItem blockID="i42" id="{D19CA586-DD6C-4a0a-96F8-14644F340D60}"> + <versionRange minVersion="0.1" maxVersion="14.4.0" severity="1"> + </versionRange> + </emItem> <emItem blockID="i67" id="youtube2@youtube2.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> <emItem blockID="i60" id="youtb3@youtb3.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem>
--- a/browser/base/content/browser-thumbnails.js +++ b/browser/base/content/browser-thumbnails.js @@ -117,18 +117,18 @@ let gBrowserThumbnails = { this._timeouts.set(aBrowser, timeout); }, _shouldCapture: function Thumbnails_shouldCapture(aBrowser) { // Capture only if it's the currently selected tab. if (aBrowser != gBrowser.selectedBrowser) return false; - // Don't capture in private browsing mode. - if (gPrivateBrowsingUI.privateBrowsingEnabled) + // Don't capture in per-window private browsing mode. + if (gPrivateBrowsingUI.privateWindow) return false; let doc = aBrowser.contentDocument; // FIXME Bug 720575 - Don't capture thumbnails for SVG or XML documents as // that currently regresses Talos SVG tests. if (doc instanceof SVGDocument || doc instanceof XMLDocument) return false;
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -8863,27 +8863,29 @@ let gPrivateBrowsingUI = { }, /** * These accessors are used to support per-window Private Browsing mode. * For now the getter returns nsIPrivateBrowsingService.privateBrowsingEnabled, * and the setter should only be used in tests. */ get privateWindow() { - return window.getInterface(Ci.nsIWebNavigation) + return window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIDocShellTreeItem) .treeOwner .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIXULWindow) .docShell.QueryInterface(Ci.nsILoadContext) .usePrivateBrowsing; }, set privateWindow(val) { - return window.getInterface(Ci.nsIWebNavigation) + return window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIDocShellTreeItem) .treeOwner .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIXULWindow) .docShell.QueryInterface(Ci.nsILoadContext) .usePrivateBrowsing = val; } };
--- a/browser/components/preferences/advanced.js +++ b/browser/components/preferences/advanced.js @@ -56,16 +56,19 @@ var gAdvancedPane = { if (extraArgs && extraArgs["advancedTab"]){ advancedPrefs.selectedTab = document.getElementById(extraArgs["advancedTab"]); } else { var preference = document.getElementById("browser.preferences.advanced.selectedTabIndex"); if (preference.value !== null) advancedPrefs.selectedIndex = preference.value; } +#ifdef HAVE_SHELL_SERVICE + this.updateSetDefaultBrowser(); +#endif #ifdef MOZ_UPDATER this.updateReadPrefs(); #endif this.updateOfflineApps(); #ifdef MOZ_CRASHREPORTER this.initSubmitCrashes(); #endif this.updateActualCacheSize("disk"); @@ -699,42 +702,31 @@ var gAdvancedPane = { * Preferences: * * browser.shell.checkDefault * - true if a default-browser check (and prompt to make it so if necessary) * occurs at startup, false otherwise */ /** - * Checks whether the browser is currently registered with the operating - * system as the default browser. If the browser is not currently the - * default browser, the user is given the option of making it the default; - * otherwise, the user is informed that this browser already is the browser. + * Show button for setting browser as default browser or information that + * browser is already the default browser. */ - checkNow: function () + updateSetDefaultBrowser: function() { var shellSvc = Components.classes["@mozilla.org/browser/shell-service;1"] .getService(Components.interfaces.nsIShellService); - var brandBundle = document.getElementById("bundleBrand"); - var shellBundle = document.getElementById("bundleShell"); - var brandShortName = brandBundle.getString("brandShortName"); - var promptTitle = shellBundle.getString("setDefaultBrowserTitle"); - var promptMessage; - const IPS = Components.interfaces.nsIPromptService; - var psvc = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] - .getService(IPS); - if (!shellSvc.isDefaultBrowser(false)) { - promptMessage = shellBundle.getFormattedString("setDefaultBrowserMessage", - [brandShortName]); - var rv = psvc.confirmEx(window, promptTitle, promptMessage, - IPS.STD_YES_NO_BUTTONS, - null, null, null, null, { }); - if (rv == 0) - shellSvc.setDefaultBrowser(true, false); - } - else { - promptMessage = shellBundle.getFormattedString("alreadyDefaultBrowser", - [brandShortName]); - psvc.alert(window, promptTitle, promptMessage); - } + let selectedIndex = shellSvc.isDefaultBrowser(false) ? 1 : 0; + document.getElementById("setDefaultPane").selectedIndex = selectedIndex; + }, + + /** + * Set browser as the operating system default browser. + */ + setDefaultBrowser: function() + { + var shellSvc = Components.classes["@mozilla.org/browser/shell-service;1"] + .getService(Components.interfaces.nsIShellService); + shellSvc.setDefaultBrowser(true, false); + document.getElementById("setDefaultPane").selectedIndex = 1; } #endif };
--- a/browser/components/preferences/advanced.xul +++ b/browser/components/preferences/advanced.xul @@ -199,24 +199,27 @@ preference="layout.spellcheckDefault"/> </groupbox> <!-- System Defaults --> <groupbox id="systemDefaultsGroup" orient="vertical"> <caption label="&systemDefaults.label;"/> #ifdef HAVE_SHELL_SERVICE - <hbox id="checkDefaultBox" align="center" flex="1"> - <checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser" - label="&alwaysCheckDefault.label;" accesskey="&alwaysCheckDefault.accesskey;" - flex="1"/> - <button id="checkDefaultButton" - label="&checkNow.label;" accesskey="&checkNow.accesskey;" - oncommand="gAdvancedPane.checkNow()" - preference="pref.general.disable_button.default_browser"/> + <checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser" + label="&alwaysCheckDefault.label;" accesskey="&alwaysCheckDefault.accesskey;" + flex="1"/> + <hbox class="indent"> + <deck id="setDefaultPane"> + <button id="setDefaultButton" + label="&setDefault.label;" accesskey="&setDefault.accesskey;" + oncommand="gAdvancedPane.setDefaultBrowser();" + preference="pref.general.disable_button.default_browser"/> + <description>&isDefault.label;</description> + </deck> </hbox> #ifdef MOZ_CRASHREPORTER <checkbox id="submitCrashesBox" flex="1" oncommand="gAdvancedPane.updateSubmitCrashes();" label="&submitCrashes.label;" accesskey="&submitCrashes.accesskey;"/> #endif #endif <checkbox id="submitTelemetryBox" flex="1"
--- a/browser/components/preferences/in-content/advanced.js +++ b/browser/components/preferences/in-content/advanced.js @@ -15,16 +15,19 @@ var gAdvancedPane = { { this._inited = true; var advancedPrefs = document.getElementById("advancedPrefs"); var preference = document.getElementById("browser.preferences.advanced.selectedTabIndex"); if (preference.value !== null) advancedPrefs.selectedIndex = preference.value; +#ifdef HAVE_SHELL_SERVICE + this.updateSetDefaultBrowser(); +#endif #ifdef MOZ_UPDATER this.updateReadPrefs(); #endif this.updateOfflineApps(); #ifdef MOZ_CRASHREPORTER this.initSubmitCrashes(); #endif this.updateActualCacheSize("disk"); @@ -662,42 +665,31 @@ var gAdvancedPane = { * Preferences: * * browser.shell.checkDefault * - true if a default-browser check (and prompt to make it so if necessary) * occurs at startup, false otherwise */ /** - * Checks whether the browser is currently registered with the operating - * system as the default browser. If the browser is not currently the - * default browser, the user is given the option of making it the default; - * otherwise, the user is informed that this browser already is the browser. + * Show button for setting browser as default browser or information that + * browser is already the default browser. */ - checkNow: function () + updateSetDefaultBrowser: function() { var shellSvc = Components.classes["@mozilla.org/browser/shell-service;1"] .getService(Components.interfaces.nsIShellService); - var brandBundle = document.getElementById("bundleBrand"); - var shellBundle = document.getElementById("bundleShell"); - var brandShortName = brandBundle.getString("brandShortName"); - var promptTitle = shellBundle.getString("setDefaultBrowserTitle"); - var promptMessage; - const IPS = Components.interfaces.nsIPromptService; - var psvc = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] - .getService(IPS); - if (!shellSvc.isDefaultBrowser(false)) { - promptMessage = shellBundle.getFormattedString("setDefaultBrowserMessage", - [brandShortName]); - var rv = psvc.confirmEx(window, promptTitle, promptMessage, - IPS.STD_YES_NO_BUTTONS, - null, null, null, null, { }); - if (rv == 0) - shellSvc.setDefaultBrowser(true, false); - } - else { - promptMessage = shellBundle.getFormattedString("alreadyDefaultBrowser", - [brandShortName]); - psvc.alert(window, promptTitle, promptMessage); - } + let selectedIndex = shellSvc.isDefaultBrowser(false) ? 1 : 0; + document.getElementById("setDefaultPane").selectedIndex = selectedIndex; + }, + + /** + * Set browser as the operating system default browser. + */ + setDefaultBrowser: function() + { + var shellSvc = Components.classes["@mozilla.org/browser/shell-service;1"] + .getService(Components.interfaces.nsIShellService); + shellSvc.setDefaultBrowser(true, false); + document.getElementById("setDefaultPane").selectedIndex = 1; } #endif };
--- a/browser/components/preferences/in-content/advanced.xul +++ b/browser/components/preferences/in-content/advanced.xul @@ -184,24 +184,27 @@ onsynctopreference="return gAdvancedPane.writeCheckSpelling();" preference="layout.spellcheckDefault"/> </groupbox> <!-- System Defaults --> <groupbox id="systemDefaultsGroup" orient="vertical"> <caption label="&systemDefaults.label;"/> #ifdef HAVE_SHELL_SERVICE - <hbox id="checkDefaultBox" align="center" flex="1"> - <checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser" - label="&alwaysCheckDefault.label;" accesskey="&alwaysCheckDefault.accesskey;" - flex="1"/> - <button id="checkDefaultButton" - label="&checkNow.label;" accesskey="&checkNow.accesskey;" - oncommand="gAdvancedPane.checkNow()" - preference="pref.general.disable_button.default_browser"/> + <checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser" + label="&alwaysCheckDefault.label;" accesskey="&alwaysCheckDefault.accesskey;" + flex="1"/> + <hbox class="indent"> + <deck id="setDefaultPane"> + <button id="setDefaultButton" + label="&setDefault.label;" accesskey="&setDefault.accesskey;" + oncommand="gAdvancedPane.setDefaultBrowser();" + preference="pref.general.disable_button.default_browser"/> + <description>&isDefault.label;</description> + </deck> </hbox> #ifdef MOZ_CRASHREPORTER <checkbox id="submitCrashesBox" flex="1" oncommand="gAdvancedPane.updateSubmitCrashes();" label="&submitCrashes.label;" accesskey="&submitCrashes.accesskey;"/> #endif #endif <checkbox id="submitTelemetryBox" flex="1"
--- a/browser/components/preferences/in-content/sync.js +++ b/browser/components/preferences/in-content/sync.js @@ -60,17 +60,17 @@ let gSyncPane = { if (Weave.Status.service == Weave.CLIENT_NOT_CONFIGURED || Weave.Svc.Prefs.get("firstSync", "") == "notReady") { this.page = PAGE_NO_ACCOUNT; } else if (Weave.Status.login == Weave.LOGIN_FAILED_INVALID_PASSPHRASE || Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) { this.needsUpdate(); } else { this.page = PAGE_HAS_ACCOUNT; - document.getElementById("accountName").value = Weave.Service.account; + document.getElementById("accountName").value = Weave.Identity.account; document.getElementById("syncComputerName").value = Weave.Clients.localName; document.getElementById("tosPP").hidden = this._usingCustomServer; } }, startOver: function (showDialog) { if (showDialog) { let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING +
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js +++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js @@ -90,16 +90,17 @@ const STATE_RESTORE_FINISHED = 3; function PrivateBrowsingService() { this._obs = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); this._obs.addObserver(this, "profile-after-change", true); this._obs.addObserver(this, "quit-application-granted", true); this._obs.addObserver(this, "private-browsing", true); this._obs.addObserver(this, "command-line-startup", true); this._obs.addObserver(this, "sessionstore-browser-state-restored", true); + this._obs.addObserver(this, "domwindowopened", true); // List of nsIXULWindows we are going to be closing during the transition this._windowsToClose = []; } PrivateBrowsingService.prototype = { // Preferences Service get _prefs() { @@ -147,16 +148,27 @@ PrivateBrowsingService.prototype = { _unload: function PBS__destroy() { // Force an exit from the private browsing mode on shutdown this._quitting = true; if (this._inPrivateBrowsing) this.privateBrowsingEnabled = false; }, + _setPerWindowPBFlag: function PBS__setPerWindowPBFlag(aWindow, aFlag) { + aWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShellTreeItem) + .treeOwner + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIXULWindow) + .docShell.QueryInterface(Ci.nsILoadContext) + .usePrivateBrowsing = aFlag; + }, + _onBeforePrivateBrowsingModeChange: function PBS__onBeforePrivateBrowsingModeChange() { // nothing needs to be done here if we're enabling at startup if (!this._autoStarted) { let ss = Cc["@mozilla.org/browser/sessionstore;1"]. getService(Ci.nsISessionStore); let blankState = JSON.stringify({ "windows": [{ "tabs": [{ @@ -217,33 +229,25 @@ PrivateBrowsingService.prototype = { browserWindow.getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIDocShellTreeItem) .treeOwner .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIXULWindow) .docShell.contentViewer.resetCloseWindow(); } } - - if (!this._quitting) { - var windowsEnum = Services.wm.getEnumerator("navigator:browser"); - while (windowsEnum.hasMoreElements()) { - var window = windowsEnum.getNext(); - window.getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem) - .treeOwner - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIXULWindow) - .docShell.QueryInterface(Ci.nsILoadContext) - .usePrivateBrowsing = this._inPrivateBrowsing; - } - } } else this._saveSession = false; + + var windowsEnum = Services.wm.getEnumerator("navigator:browser"); + while (windowsEnum.hasMoreElements()) { + var window = windowsEnum.getNext(); + this._setPerWindowPBFlag(window, this._inPrivateBrowsing); + } }, _onAfterPrivateBrowsingModeChange: function PBS__onAfterPrivateBrowsingModeChange() { // nothing to do here if we're enabling at startup or the current session is being // used if (!this._autoStarted && this._saveSession) { let ss = Cc["@mozilla.org/browser/sessionstore;1"]. getService(Ci.nsISessionStore); @@ -518,16 +522,28 @@ PrivateBrowsingService.prototype = { } break; case "sessionstore-browser-state-restored": if (this._currentStatus == STATE_WAITING_FOR_RESTORE) { this._currentStatus = STATE_RESTORE_FINISHED; this._notifyIfTransitionComplete(); } break; + case "domwindowopened": + let aWindow = aSubject; + let self = this; + aWindow.addEventListener("load", function PBS__onWindowLoad(aEvent) { + aWindow.removeEventListener("load", arguments.callee); + if (aWindow.document + .documentElement + .getAttribute("windowtype") == "navigator:browser") { + self._setPerWindowPBFlag(aWindow, self._inPrivateBrowsing); + } + }, false); + break; } }, // nsICommandLineHandler handle: function PBS_handle(aCmdLine) { if (aCmdLine.handleFlag("private", false)) aCmdLine.preventDefault = true; // It has already been handled
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js @@ -35,71 +35,101 @@ * * ***** END LICENSE BLOCK ***** */ // This test makes sure that the gPrivateBrowsingUI object, the Private Browsing // menu item and its XUL <command> element work correctly. function test() { // initialization + waitForExplicitFinish(); gPrefService.setBoolPref("browser.privatebrowsing.keep_current_session", true); let pb = Cc["@mozilla.org/privatebrowsing;1"]. getService(Ci.nsIPrivateBrowsingService); let observerData; function observer(aSubject, aTopic, aData) { if (aTopic == "private-browsing") observerData = aData; } Services.obs.addObserver(observer, "private-browsing", false); let pbMenuItem = document.getElementById("privateBrowsingItem"); // add a new blank tab to ensure the title can be meaningfully compared later gBrowser.selectedTab = gBrowser.addTab(); let originalTitle = document.title; + function testNewWindow(aCallback, expected) { + Services.obs.addObserver(function observer1(aSubject, aTopic, aData) { + aSubject.addEventListener("load", function() { + aSubject.removeEventListener("load", arguments.callee); + executeSoon(function() { + let ui = aSubject.gPrivateBrowsingUI; + is(ui.privateBrowsingEnabled, expected, "The privateBrowsingEnabled property on the new window is set correctly"); + is(ui.privateWindow, expected, "The privateWindow property on the new window is set correctly"); + + Services.obs.addObserver(function observer2(aSubject, aTopic, aData) { + aCallback(); + Services.obs.removeObserver(observer2, "domwindowclosed"); + }, "domwindowclosed", false); + aSubject.close(); + }); + Services.obs.removeObserver(observer1, "domwindowopened"); + }, false); + }, "domwindowopened", false); + OpenBrowserWindow(); + } + // test the gPrivateBrowsingUI object ok(gPrivateBrowsingUI, "The gPrivateBrowsingUI object exists"); is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started initially"); is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status"); is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status"); ok(pbMenuItem, "The Private Browsing menu item exists"); is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\""); - gPrivateBrowsingUI.toggleMode(); - is(pb.privateBrowsingEnabled, true, "The private browsing mode should be started"); - is(gPrivateBrowsingUI.privateBrowsingEnabled, true, "gPrivateBrowsingUI should expose the correct private browsing status"); - is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should expose the correct per-window private browsing status"); - // check to see if the Private Browsing mode was activated successfully - is(observerData, "enter", "Private Browsing mode was activated using the gPrivateBrowsingUI object"); - is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("stoplabel"), "The Private Browsing menu item should read \"Stop Private Browsing\""); - gPrivateBrowsingUI.toggleMode() - is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started"); - is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status"); - is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status"); - // check to see if the Private Browsing mode was deactivated successfully - is(observerData, "exit", "Private Browsing mode was deactivated using the gPrivateBrowsingUI object"); - is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\""); + testNewWindow(function() { + gPrivateBrowsingUI.toggleMode(); + is(pb.privateBrowsingEnabled, true, "The private browsing mode should be started"); + is(gPrivateBrowsingUI.privateBrowsingEnabled, true, "gPrivateBrowsingUI should expose the correct private browsing status"); + is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should expose the correct per-window private browsing status"); + // check to see if the Private Browsing mode was activated successfully + is(observerData, "enter", "Private Browsing mode was activated using the gPrivateBrowsingUI object"); + is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("stoplabel"), "The Private Browsing menu item should read \"Stop Private Browsing\""); + testNewWindow(function() { + gPrivateBrowsingUI.toggleMode() + is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started"); + is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status"); + is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status"); + // check to see if the Private Browsing mode was deactivated successfully + is(observerData, "exit", "Private Browsing mode was deactivated using the gPrivateBrowsingUI object"); + is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\""); + + testNewWindow(function() { + // These are tests for the privateWindow setter. Note that the setter should + // not be used anywhere else for now! + gPrivateBrowsingUI.privateWindow = true; + is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should accept the correct per-window private browsing status"); + gPrivateBrowsingUI.privateWindow = false; + is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should accept the correct per-window private browsing status"); - // These are tests for the privateWindow setter. Note that the setter should - // not be used anywhere else for now! - gPrivateBrowsingUI.privateWindow = true; - is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should accept the correct per-window private browsing status"); - gPrivateBrowsingUI.privateWindow = false; - is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should accept the correct per-window private browsing status"); + // now, test using the <command> object + let cmd = document.getElementById("Tools:PrivateBrowsing"); + isnot(cmd, null, "XUL command object for the private browsing service exists"); + var func = new Function("", cmd.getAttribute("oncommand")); + func.call(cmd); + // check to see if the Private Browsing mode was activated successfully + is(observerData, "enter", "Private Browsing mode was activated using the command object"); + // check to see that the window title has been changed correctly + isnot(document.title, originalTitle, "Private browsing mode has correctly changed the title"); + func.call(cmd); + // check to see if the Private Browsing mode was deactivated successfully + is(observerData, "exit", "Private Browsing mode was deactivated using the command object"); + // check to see that the window title has been restored correctly + is(document.title, originalTitle, "Private browsing mode has correctly restored the title"); - // now, test using the <command> object - let cmd = document.getElementById("Tools:PrivateBrowsing"); - isnot(cmd, null, "XUL command object for the private browsing service exists"); - var func = new Function("", cmd.getAttribute("oncommand")); - func.call(cmd); - // check to see if the Private Browsing mode was activated successfully - is(observerData, "enter", "Private Browsing mode was activated using the command object"); - // check to see that the window title has been changed correctly - isnot(document.title, originalTitle, "Private browsing mode has correctly changed the title"); - func.call(cmd); - // check to see if the Private Browsing mode was deactivated successfully - is(observerData, "exit", "Private Browsing mode was deactivated using the command object"); - // check to see that the window title has been restored correctly - is(document.title, originalTitle, "Private browsing mode has correctly restored the title"); + // cleanup + gBrowser.removeCurrentTab(); + Services.obs.removeObserver(observer, "private-browsing"); + gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session"); - // cleanup - gBrowser.removeCurrentTab(); - Services.obs.removeObserver(observer, "private-browsing"); - gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session"); + finish(); + }, false); + }, true); + }, false); }
--- a/browser/config/mozconfigs/win32/nightly +++ b/browser/config/mozconfigs/win32/nightly @@ -19,8 +19,14 @@ mk_add_options MOZ_MAKE_FLAGS=-j1 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then . $topsrcdir/build/win32/mozconfig.vs2010-win64 else . $topsrcdir/build/win32/mozconfig.vs2010 fi # Package js shell. export MOZ_PACKAGE_JSSHELL=1 + +# For known full-clobber builds on Windows (like nightlies/try), +# this speeds things up. IS_NIGHTLY is set by the build automation. +if test "$IS_NIGHTLY" != ""; then + ac_add_options --disable-auto-deps +fi
--- a/browser/config/mozconfigs/win64/nightly +++ b/browser/config/mozconfigs/win64/nightly @@ -17,9 +17,15 @@ export MOZILLA_OFFICIAL=1 export MOZ_TELEMETRY_REPORTING=1 mk_add_options MOZ_MAKE_FLAGS=-j1 # Package js shell. export MOZ_PACKAGE_JSSHELL=1 +# For known full-clobber builds on Windows (like nightlies/try), +# this speeds things up. IS_NIGHTLY is set by the build automation. +if test "$IS_NIGHTLY" != ""; then + ac_add_options --disable-auto-deps +fi + . $topsrcdir/build/win64/mozconfig.vs2010
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-07.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-07.js @@ -71,27 +71,28 @@ function testFrameParameters() "Should have the right property value for 'dArg'."); is(localNodes[5].querySelector(".info").textContent, "null", "Should have the right property value for 'eArg'."); is(localNodes[6].querySelector(".info").textContent, "undefined", "Should have the right property value for 'fArg'."); - is(localNodes[7].querySelector(".info").textContent, "1", - "Should have the right property value for 'a'."); - - is(localNodes[8].querySelector(".info").textContent, "[object Object]", - "Should have the right property value for 'b'."); + // FIXME bug TODO: reenable + //is(localNodes[7].querySelector(".info").textContent, "1", + // "Should have the right property value for 'a'."); - is(localNodes[9].querySelector(".info").textContent, "[object Object]", - "Should have the right property value for 'c'."); + //is(localNodes[8].querySelector(".info").textContent, "[object Object]", + // "Should have the right property value for 'b'."); - is(localNodes[10].querySelector(".info").textContent, "[object Arguments]", - "Should have the right property value for 'arguments'."); + //is(localNodes[9].querySelector(".info").textContent, "[object Object]", + // "Should have the right property value for 'c'."); + + //is(localNodes[10].querySelector(".info").textContent, "[object Arguments]", + // "Should have the right property value for 'arguments'."); resumeAndFinish(); }}, 0); }, false); EventUtils.sendMouseEvent({ type: "click" }, content.document.querySelector("button"), content.window);
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-08.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-08.js @@ -91,27 +91,27 @@ function testFrameParameters() is(localNodes[9].querySelectorAll(".property > .title > .key")[1] .textContent, "a", "Should have the right property name for 'a'."); is(localNodes[9].querySelectorAll(".property > .title > .value")[1] .textContent, 1, "Should have the right value for 'c.a'."); - is(localNodes[10].querySelector(".info").textContent, - "[object Arguments]", - "Should have the right property value for 'arguments'."); + //is(localNodes[10].querySelector(".info").textContent, + // "[object Arguments]", + // "Should have the right property value for 'arguments'."); - is(localNodes[10].querySelector(".property > .title > .key") - .textContent, "length", - "Should have the right property name for 'length'."); + //is(localNodes[10].querySelector(".property > .title > .key") + // .textContent, "length", + // "Should have the right property name for 'length'."); - is(localNodes[10].querySelector(".property > .title > .value") - .textContent, 5, - "Should have the right argument length."); + //is(localNodes[10].querySelector(".property > .title > .value") + // .textContent, 5, + // "Should have the right argument length."); resumeAndFinish(); }, 100); }}, 0); }, false); EventUtils.sendMouseEvent({ type: "click" }, content.document.querySelector("button"),
--- a/browser/devtools/sourceeditor/orion/orion.js +++ b/browser/devtools/sourceeditor/orion/orion.js @@ -11270,17 +11270,17 @@ define("examples/textview/textStyler", [ "overflow-y", "padding", "padding-bottom", "padding-left", "padding-right", "padding-top", "page", "page-break-after", "page-break-before", "page-break-inside", "page-policy", "pause", "pause-after", "pause-before", "perspective", "perspective-origin", "phonemes", "pitch", "pitch-range", "play-during", "position", "presentation-level", "punctuation-trim", "quotes", "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness", "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang", "ruby-position", "ruby-span", "size", "speak", "speak-header", "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set", "table-layout", "target", "target-name", "target-new", "target-position", "text-align", "text-align-last", "text-decoration", "text-emphasis", "text-height", "text-indent", "text-justify", "text-outline", "text-shadow", "text-transform", "text-wrap", "top", "transform", "transform-origin", "transform-style", "transition", "transition-delay", "transition-duration", "transition-property", - "transition-timing-function", "unicode-bidi", "vertical-align", "visibility", "voice-balance", "voice-duration", "voice-family", + "transition-timing-function", "unicode-bidi", "vector-effect", "vertical-align", "visibility", "voice-balance", "voice-duration", "voice-family", "voice-pitch", "voice-pitch-range", "voice-rate", "voice-stress", "voice-volume", "volume", "white-space", "white-space-collapse", "widows", "width", "word-break", "word-spacing", "word-wrap", "z-index" ]; // Scanner constants var UNKOWN = 1; var KEYWORD = 2; var STRING = 3;
--- a/browser/locales/en-US/chrome/browser/preferences/advanced.dtd +++ b/browser/locales/en-US/chrome/browser/preferences/advanced.dtd @@ -20,18 +20,19 @@ <!ENTITY allowHWAccel.label "Use hardware acceleration when available"> <!ENTITY allowHWAccel.accesskey "r"> <!ENTITY checkSpelling.label "Check my spelling as I type"> <!ENTITY checkSpelling.accesskey "t"> <!ENTITY systemDefaults.label "System Defaults"> <!ENTITY alwaysCheckDefault.label "Always check to see if &brandShortName; is the default browser on startup"><!--XXX--> <!ENTITY alwaysCheckDefault.accesskey "w"> -<!ENTITY checkNow.label "Check Now"> -<!ENTITY checkNow.accesskey "N"> +<!ENTITY setDefault.label "Make &brandShortName; the default browser"> +<!ENTITY setDefault.accesskey "d"> +<!ENTITY isDefault.label "&brandShortName; is currently your default browser"> <!ENTITY submitCrashes.label "Submit crash reports"> <!ENTITY submitCrashes.accesskey "S"> <!ENTITY submitTelemetry.label "Submit performance data"> <!ENTITY submitTelemetry.accesskey "P"> <!ENTITY networkTab.label "Network"> <!ENTITY connection.label "Connection">
--- a/build/autoconf/test/makemakefile.tpm +++ b/build/autoconf/test/makemakefile.tpm @@ -115,17 +115,17 @@ sub check_getTopDir print "Running: check_getTopDir\n" if ($main::argv{debug}); my $path = getTopDir(); ## Unit test is special, cmd not invoked from the same directory ## as the makemakefile.pm module. ok($path ? 1 : 0, 1, "getTopDir failed"); ok(-d $path ? 1 : 0, 1, "getTopDir: directory $path does not exist"); - ok($FindBin::RealBin =~ m%$path/% ? 1 : 0, 1, 'Invalid topdir path'); + ok($FindBin::RealBin =~ m%\Q$path/% ? 1 : 0, 1, 'Invalid topdir path'); ok(-e "$path/client.mk" ? 1 : 0, 1, "client.mk not found in $path"); } # check_getTopDir ########################################################################### ## Intent: Verify objdir lookup function ########################################################################### sub check_getObjDir {
--- a/build/automationutils.py +++ b/build/automationutils.py @@ -454,17 +454,17 @@ def wrapCommand(cmd): return cmd class ShutdownLeakLogger(object): """ Parses the mochitest run log when running a debug build, assigns all leaked DOM windows (that are still around after test suite shutdown, despite running the GC) to the tests that created them and prints leak statistics. """ - MAX_LEAK_COUNT = 10 + MAX_LEAK_COUNT = 7 def __init__(self, logger): self.logger = logger self.tests = [] self.leakedWindows = {} self.leakedDocShells = set() self.currentTest = None self.seenShutdown = False
--- a/build/mobile/robocop/Makefile.in +++ b/build/mobile/robocop/Makefile.in @@ -40,17 +40,17 @@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ TESTPATH = $(topsrcdir)/mobile/android/base/tests include $(DEPTH)/config/autoconf.mk MODULE = robocop -ROBOTIUM_PATH = $(srcdir)/robotium-solo-3.1.jar +ROBOTIUM_PATH = $(srcdir)/robotium-solo-3.2.1.jar JAVAFILES = \ R.java \ _JAVA_HARNESS = \ Actions.java \ Assert.java \ Driver.java \
--- a/build/mobile/robocop/README +++ b/build/mobile/robocop/README @@ -1,9 +1,9 @@ Robocop is a Mozilla project which uses Robotium to test Firefox on Android devices. Robotium is an open source tool licensed under the Apache 2.0 license and the original source can be found here: http://code.google.com/p/robotium/ -We are including robotium-solo-3.1.jar as a binary and are not modifying it in anyway +We are including robotium-solo-3.2.1.jar as a binary and are not modifying it in anyway from the original download found at: http://code.google.com/p/robotium/
deleted file mode 100644 index 0ba05859b90a8c29ca519e228674db9aebe69d90..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@<O00001
new file mode 100644 index 0000000000000000000000000000000000000000..f4107c7496ec18d7a5fc2fe56742036ef3861bb7 GIT binary patch literal 52121 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
--- a/build/unix/build-toolchain/build-gcc.py +++ b/build/unix/build-toolchain/build-gcc.py @@ -43,17 +43,18 @@ def run_in(path, args): def patch(patch, plevel, srcdir): patch = os.path.realpath(patch) check_run(['patch', '-d', srcdir, '-p%s' % plevel, '-i', patch, '--fuzz=0', '-s']) def build_package(package_source_dir, package_build_dir, configure_args, make = old_make): - os.mkdir(package_build_dir) + if not os.path.exists(package_build_dir): + os.mkdir(package_build_dir) run_in(package_build_dir, ["%s/configure" % package_source_dir] + configure_args) run_in(package_build_dir, [make, "-j8"]) run_in(package_build_dir, [make, "install"]) def build_aux_tools(base_dir): make_build_dir = base_dir + '/make_build' build_package(make_source_dir, make_build_dir, @@ -156,16 +157,22 @@ def build_one_stage_aux(stage_dir, is_st tool_inst_dir = stage_dir + '/inst' os.mkdir(tool_inst_dir) os.mkdir(tool_inst_dir + '/lib64') os.symlink('lib64', tool_inst_dir + '/lib') build_linux_headers(tool_inst_dir) + # zlib's configure only works if run from the source dir, copy the source + zlib_build_dir = stage_dir + '/zlib' + shutil.copytree(zlib_source_dir, zlib_build_dir) + build_package(zlib_build_dir, zlib_build_dir, + ["--prefix=%s" % tool_inst_dir]) + binutils_build_dir = stage_dir + '/binutils' build_package(binutils_source_dir, binutils_build_dir, ["--prefix=%s" % tool_inst_dir, "--without-zlib"]) # During stage one we have to build gcc first, this glibc doesn't even # build with gcc 4.6. During stage two, we have to build glibc first. # The problem is that libstdc++ is built with xgcc and if glibc has @@ -192,16 +199,17 @@ def build_source_dir(prefix, version): binutils_version = "2.21.1" glibc_version = "2.5.1" linux_version = "2.6.18" tar_version = "1.26" gawk_version = "3.1.5" make_version = "3.81" gcc_version = "4.5.2" mpfr_version = "2.4.2" +zlib_version = "1.2.3" gmp_version = "5.0.1" mpc_version = "0.8.1" unifdef_version = "2.6" binutils_source_uri = "http://ftp.gnu.org/gnu/binutils/binutils-%sa.tar.bz2" % \ binutils_version glibc_source_uri = "http://ftp.gnu.org/gnu/glibc/glibc-%s.tar.bz2" % \ glibc_version @@ -214,41 +222,44 @@ gawk_source_uri = "http://ftp.gnu.org/gn make_source_uri = "http://ftp.gnu.org/gnu/make/make-%s.tar.bz2" % \ make_version unifdef_source_uri = "http://dotat.at/prog/unifdef/unifdef-%s.tar.gz" % \ unifdef_version gcc_source_uri = "http://ftp.gnu.org/gnu/gcc/gcc-%s/gcc-%s.tar.bz2" % \ (gcc_version, gcc_version) mpfr_source_uri = "http://www.mpfr.org/mpfr-%s/mpfr-%s.tar.bz2" % \ (mpfr_version, mpfr_version) +zlib_source_uri = "http://iweb.dl.sourceforge.net/project/libpng/zlib/%s/zlib-%s.tar.bz2" % (zlib_version, zlib_version) gmp_source_uri = "http://ftp.gnu.org/gnu/gmp/gmp-%s.tar.bz2" % gmp_version mpc_source_uri = "http://www.multiprecision.org/mpc/download/mpc-%s.tar.gz" % \ mpc_version binutils_source_tar = download_uri(binutils_source_uri) glibc_source_tar = download_uri(glibc_source_uri) linux_source_tar = download_uri(linux_source_uri) tar_source_tar = download_uri(tar_source_uri) gawk_source_tar = download_uri(gawk_source_uri) make_source_tar = download_uri(make_source_uri) unifdef_source_tar = download_uri(unifdef_source_uri) mpc_source_tar = download_uri(mpc_source_uri) mpfr_source_tar = download_uri(mpfr_source_uri) +zlib_source_tar = download_uri(zlib_source_uri) gmp_source_tar = download_uri(gmp_source_uri) gcc_source_tar = download_uri(gcc_source_uri) binutils_source_dir = build_source_dir('binutils-', binutils_version) glibc_source_dir = build_source_dir('glibc-', glibc_version) linux_source_dir = build_source_dir('linux-', linux_version) tar_source_dir = build_source_dir('tar-', tar_version) gawk_source_dir = build_source_dir('gawk-', gawk_version) make_source_dir = build_source_dir('make-', make_version) unifdef_source_dir = build_source_dir('unifdef-', unifdef_version) mpc_source_dir = build_source_dir('mpc-', mpc_version) mpfr_source_dir = build_source_dir('mpfr-', mpfr_version) +zlib_source_dir = build_source_dir('zlib-', zlib_version) gmp_source_dir = build_source_dir('gmp-', gmp_version) gcc_source_dir = build_source_dir('gcc-', gcc_version) if not os.path.exists(source_dir): os.makedirs(source_dir) extract(binutils_source_tar, source_dir) patch('binutils-deterministic.patch', 1, binutils_source_dir) extract(glibc_source_tar, source_dir) @@ -256,16 +267,17 @@ if not os.path.exists(source_dir): patch('glibc-deterministic.patch', 1, glibc_source_dir) run_in(glibc_source_dir, ["autoconf"]) extract(tar_source_tar, source_dir) extract(gawk_source_tar, source_dir) extract(make_source_tar, source_dir) extract(unifdef_source_tar, source_dir) extract(mpc_source_tar, source_dir) extract(mpfr_source_tar, source_dir) + extract(zlib_source_tar, source_dir) extract(gmp_source_tar, source_dir) extract(gcc_source_tar, source_dir) patch('plugin_finish_decl.diff', 0, gcc_source_dir) patch('libtool-74c8993c178a1386ea5e2363a01d919738402f30.patch', 1, gcc_source_dir) patch('pr49911.diff', 1, gcc_source_dir) patch('r159628-r163231-r171807.patch', 1, gcc_source_dir) patch('gcc-fixinc.patch', 1, gcc_source_dir) patch('gcc-include.patch', 1, gcc_source_dir) @@ -279,26 +291,21 @@ build_aux_tools(build_dir) basic_path = aux_inst_dir + "/bin:/bin:/usr/bin" stage1_dir = build_dir + '/stage1' build_one_stage({"PATH" : basic_path, "CC" : "gcc", "CXX" : "g++" }, stage1_dir, True) -stage1_tool_inst_dir = stage1_dir + '/inst' -stage2_dir = build_dir + '/stage2' -build_one_stage({"PATH" : stage1_tool_inst_dir + "/bin:" + basic_path, - "CC" : "gcc -fgnu89-inline", - "CXX" : "g++", - "RANLIB" : "true" }, - stage2_dir, False) +for stage_num in range(2, 4): + prev_stage_dir = build_dir + '/stage' + str(stage_num - 1) + prev_stage_inst_dir = prev_stage_dir + '/inst' + cur_stage_dir = build_dir + '/stage' + str(stage_num) + build_one_stage({"PATH" : prev_stage_inst_dir + "/bin:" + basic_path, + "CC" : "gcc -fgnu89-inline", + "CXX" : "g++", + "RANLIB" : "true" }, + cur_stage_dir, False) -stage2_tool_inst_dir = stage2_dir + '/inst' stage3_dir = build_dir + '/stage3' -build_one_stage({"PATH" : stage2_tool_inst_dir + "/bin:" + basic_path, - "CC" : "gcc -fgnu89-inline", - "CXX" : "g++", - "RANLIB" : "true" }, - stage3_dir, False) - build_tar_package(aux_inst_dir + "/bin/tar", "toolchain.tar", stage3_dir, "inst")
--- a/caps/include/nsScriptSecurityManager.h +++ b/caps/include/nsScriptSecurityManager.h @@ -421,18 +421,18 @@ public: private: // GetScriptSecurityManager is the only call that can make one nsScriptSecurityManager(); virtual ~nsScriptSecurityManager(); static JSBool - CheckObjectAccess(JSContext *cx, JSObject *obj, - jsid id, JSAccessMode mode, + CheckObjectAccess(JSContext *cx, JSHandleObject obj, + JSHandleId id, JSAccessMode mode, jsval *vp); static JSPrincipals * ObjectPrincipalFinder(JSObject *obj); // Decides, based on CSP, whether or not eval() and stuff can be executed. static JSBool ContentSecurityPolicyPermitsJSAction(JSContext *cx);
--- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -39,16 +39,17 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "mozilla/Util.h" #include "xpcprivate.h" +#include "XPCWrapper.h" #include "nsScriptSecurityManager.h" #include "nsIServiceManager.h" #include "nsIScriptObjectPrincipal.h" #include "nsIScriptContext.h" #include "nsIURL.h" #include "nsINestedURI.h" #include "nspr.h" #include "nsJSPrincipals.h" @@ -625,18 +626,18 @@ nsScriptSecurityManager::ContentSecurity lineNum); } return evalOK; } JSBool -nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JSObject *obj, - jsid id, JSAccessMode mode, +nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JSHandleObject obj, + JSHandleId id, JSAccessMode mode, jsval *vp) { // Get the security manager nsScriptSecurityManager *ssm = nsScriptSecurityManager::GetScriptSecurityManager(); NS_ASSERTION(ssm, "Failed to get security manager service"); if (!ssm)
--- a/chrome/src/nsChromeRegistry.cpp +++ b/chrome/src/nsChromeRegistry.cpp @@ -170,18 +170,17 @@ nsChromeRegistry::GetService() } NS_ADDREF(gChromeRegistry); return gChromeRegistry; } nsresult nsChromeRegistry::Init() { - if (!mOverrideTable.Init()) - return NS_ERROR_FAILURE; + mOverrideTable.Init(); // This initialization process is fairly complicated and may cause reentrant // getservice calls to resolve chrome URIs (especially locale files). We // don't want that, so we inform the protocol handler about our existence // before we are actually fully initialized. gChromeRegistry = this; mInitialized = true;
--- a/chrome/src/nsChromeRegistryChrome.cpp +++ b/chrome/src/nsChromeRegistryChrome.cpp @@ -150,19 +150,18 @@ nsChromeRegistryChrome::~nsChromeRegistr nsresult nsChromeRegistryChrome::Init() { nsresult rv = nsChromeRegistry::Init(); if (NS_FAILED(rv)) return rv; - if (!mOverlayHash.Init() || - !mStyleHash.Init()) - return NS_ERROR_FAILURE; + mOverlayHash.Init(); + mStyleHash.Init(); mSelectedLocale = NS_LITERAL_CSTRING("en-US"); mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0"); if (!PL_DHashTableInit(&mPackagesHash, &kTableOps, nsnull, sizeof(PackageEntry), 16)) return NS_ERROR_FAILURE;
--- a/chrome/src/nsChromeRegistryChrome.h +++ b/chrome/src/nsChromeRegistryChrome.h @@ -166,17 +166,17 @@ class nsChromeRegistryChrome : public ns }; class OverlayListHash { public: OverlayListHash() { } ~OverlayListHash() { } - bool Init() { return mTable.Init(); } + void Init() { mTable.Init(); } void Add(nsIURI* aBase, nsIURI* aOverlay); void Clear() { mTable.Clear(); } const nsCOMArray<nsIURI>* GetArray(nsIURI* aBase); private: nsTHashtable<OverlayListEntry> mTable; };
--- a/chrome/src/nsChromeRegistryContent.cpp +++ b/chrome/src/nsChromeRegistryContent.cpp @@ -112,19 +112,17 @@ nsChromeRegistryContent::RegisterPackage } PackageEntry* entry = new PackageEntry; entry->flags = aPackage.flags; entry->contentBaseURI = content; entry->localeBaseURI = locale; entry->skinBaseURI = skin; - nsresult rv = mPackagesHash.Put(aPackage.package, entry); - if (NS_FAILED(rv)) - return; + mPackagesHash.Put(aPackage.package, entry); } void nsChromeRegistryContent::RegisterResource(const ResourceMapping& aResource) { nsCOMPtr<nsIIOService> io (do_GetIOService()); if (!io) return;
--- a/config/expandlibs_exec.py +++ b/config/expandlibs_exec.py @@ -120,17 +120,17 @@ class ExpandArgsMore(ExpandArgs): def makelist(self): '''Replaces object file names with a temporary list file, using a list format depending on the EXPAND_LIBS_LIST_STYLE variable ''' objs = [o for o in self if isObject(o)] if not len(objs): return fd, tmp = tempfile.mkstemp(suffix=".list",dir=os.curdir) if conf.EXPAND_LIBS_LIST_STYLE == "linkerscript": - content = ["INPUT(%s)\n" % obj for obj in objs] + content = ['INPUT("%s")\n' % obj for obj in objs] ref = tmp elif conf.EXPAND_LIBS_LIST_STYLE == "list": content = ["%s\n" % obj for obj in objs] ref = "@" + tmp else: os.close(fd) os.remove(tmp) return
--- a/config/tests/unit-expandlibs.py +++ b/config/tests/unit-expandlibs.py @@ -232,17 +232,17 @@ class TestExpandArgsMore(TestExpandInit) self.assertRelEqual(args[:3], ['foo', '-bar'] + self.files[:1]) self.assertRelEqual(args[4:], [self.files[3]] + self.files[5:] + [self.tmpfile('liby', Lib('z'))]) # Check the list file content objs = [f for f in self.files + self.liby_files + self.libx_files if f.endswith(config.OBJ_SUFFIX)] if config.EXPAND_LIBS_LIST_STYLE == "linkerscript": self.assertNotEqual(args[3][0], '@') filename = args[3] - content = ["INPUT(%s)" % relativize(f) for f in objs] + content = ['INPUT("%s")' % relativize(f) for f in objs] with open(filename, 'r') as f: self.assertEqual([l.strip() for l in f.readlines() if len(l.strip())], content) elif config.EXPAND_LIBS_LIST_STYLE == "list": self.assertEqual(args[3][0], '@') filename = args[3][1:] content = objs with open(filename, 'r') as f: self.assertRelEqual([l.strip() for l in f.readlines() if len(l.strip())], content)
--- a/content/base/public/nsISelection.idl +++ b/content/base/public/nsISelection.idl @@ -45,17 +45,17 @@ interface nsINode; /** * Interface for manipulating and querying the current selected range * of nodes within the document. * * @version 1.0 */ -[scriptable, uuid(5ac0cd5d-3c08-4c4c-8e70-230c433f5d5c)] +[scriptable, uuid(dd40d5b8-1fe1-487f-b66e-28f4b837024f)] interface nsISelection : nsISupports { /** * Returns the node in which the selection begins. */ readonly attribute nsIDOMNode anchorNode; /** @@ -72,16 +72,17 @@ interface nsISelection : nsISupports * The offset within the (text) node where the selection ends. */ readonly attribute long focusOffset; /** * Indicates if the selection is collapsed or not. */ readonly attribute boolean isCollapsed; + [noscript,notxpcom,nostdcall] boolean collapsed(); /** * Returns the number of ranges in the selection. */ readonly attribute long rangeCount; /** * Returns the range at the specified index. @@ -101,16 +102,17 @@ interface nsISelection : nsISupports /** * Extends the selection by moving the selection end to the specified node and offset, * preserving the selection begin position. The new selection end result will always * be from the anchorNode to the new focusNode, regardless of direction. * @param parentNode The node where the selection will be extended to * @param offset Where in node to place the offset in the new selection end */ void extend(in nsIDOMNode parentNode, in long offset); + [noscript] void extendNative(in nsINode parentNode, in long offset); /** * Collapses the whole selection to a single point at the start * of the current selection (irrespective of direction). If content * is focused and editable, the caret will blink there. */ void collapseToStart();
--- a/content/base/public/nsISelectionPrivate.idl +++ b/content/base/public/nsISelectionPrivate.idl @@ -61,17 +61,17 @@ struct ScrollAxis; [ptr] native nsIFrame(nsIFrame); [ptr] native nsIPresShell(nsIPresShell); [ptr] native RangeArray(nsTArray<nsRange*>); [ref] native constTextRangeStyleRef(const nsTextRangeStyle); [ref] native nsPointRef(nsPoint); native nsDirection(nsDirection); native ScrollAxis(nsIPresShell::ScrollAxis); -[scriptable, uuid(0ced91b9-3e77-4191-943f-95bcde5e2d14)] +[scriptable, uuid(719a803f-aa1e-436c-8919-c42908f00599)] interface nsISelectionPrivate : nsISelection { const short ENDOFPRECEDINGLINE=0; const short STARTOFNEXTLINE=1; attribute boolean interlinePosition; /* startBatchChanges
--- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -543,40 +543,24 @@ nsContentUtils::InitializeEventTable() { #undef WINDOW_ONLY_EVENT #undef EVENT { nsnull } }; sAtomEventTable = new nsDataHashtable<nsISupportsHashKey, EventNameMapping>; sStringEventTable = new nsDataHashtable<nsStringHashKey, EventNameMapping>; sUserDefinedEvents = new nsCOMArray<nsIAtom>(64); - - if (!sAtomEventTable || !sStringEventTable || !sUserDefinedEvents || - !sAtomEventTable->Init(int(ArrayLength(eventArray) / 0.75) + 1) || - !sStringEventTable->Init(int(ArrayLength(eventArray) / 0.75) + 1)) { - delete sAtomEventTable; - sAtomEventTable = nsnull; - delete sStringEventTable; - sStringEventTable = nsnull; - delete sUserDefinedEvents; - sUserDefinedEvents = nsnull; - return false; - } + sAtomEventTable->Init(int(ArrayLength(eventArray) / 0.75) + 1); + sStringEventTable->Init(int(ArrayLength(eventArray) / 0.75) + 1); // Subtract one from the length because of the trailing null for (PRUint32 i = 0; i < ArrayLength(eventArray) - 1; ++i) { - if (!sAtomEventTable->Put(eventArray[i].mAtom, eventArray[i]) || - !sStringEventTable->Put(Substring(nsDependentAtomString(eventArray[i].mAtom), 2), - eventArray[i])) { - delete sAtomEventTable; - sAtomEventTable = nsnull; - delete sStringEventTable; - sStringEventTable = nsnull; - return false; - } + sAtomEventTable->Put(eventArray[i].mAtom, eventArray[i]); + sStringEventTable->Put(Substring(nsDependentAtomString(eventArray[i].mAtom), 2), + eventArray[i]); } return true; } void nsContentUtils::InitializeTouchEventTable() { @@ -589,25 +573,19 @@ nsContentUtils::InitializeTouchEventTabl { nsGkAtoms::on##name_, _id, _type, _struct }, #include "nsEventNameList.h" #undef TOUCH_EVENT #undef EVENT { nsnull } }; // Subtract one from the length because of the trailing null for (PRUint32 i = 0; i < ArrayLength(touchEventArray) - 1; ++i) { - if (!sAtomEventTable->Put(touchEventArray[i].mAtom, touchEventArray[i]) || - !sStringEventTable->Put(Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2), - touchEventArray[i])) { - delete sAtomEventTable; - sAtomEventTable = nsnull; - delete sStringEventTable; - sStringEventTable = nsnull; - return; - } + sAtomEventTable->Put(touchEventArray[i].mAtom, touchEventArray[i]); + sStringEventTable->Put(Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2), + touchEventArray[i]); } } } static bool Is8bit(const nsAString& aString) { static const PRUnichar EIGHT_BIT = PRUnichar(~0x00FF); @@ -6410,16 +6388,31 @@ nsContentUtils::FindInternalContentViewe if (docFactory && aLoaderType) { *aLoaderType = TYPE_CONTENT; } return docFactory.forget(); } } } #endif + +#ifdef MOZ_GSTREAMER + if (nsHTMLMediaElement::IsH264Enabled()) { + for (unsigned int i = 0; i < ArrayLength(nsHTMLMediaElement::gH264Types); ++i) { + const char* type = nsHTMLMediaElement::gH264Types[i]; + if (!strcmp(aType, type)) { + docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1"); + if (docFactory && aLoaderType) { + *aLoaderType = TYPE_CONTENT; + } + return docFactory.forget(); + } + } + } +#endif #endif // MOZ_MEDIA return NULL; } // static bool nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
--- a/content/base/src/nsCrossSiteListenerProxy.cpp +++ b/content/base/src/nsCrossSiteListenerProxy.cpp @@ -108,17 +108,18 @@ public: ~nsPreflightCache() { Clear(); MOZ_COUNT_DTOR(nsPreflightCache); } bool Initialize() { - return mTable.Init(); + mTable.Init(); + return true; } CacheEntry* GetEntry(nsIURI* aURI, nsIPrincipal* aPrincipal, bool aWithCredentials, bool aCreate); void RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal); void Clear(); @@ -255,24 +256,17 @@ nsPreflightCache::GetEntry(nsIURI* aURI, // This will delete 'lruEntry'. mTable.Remove(lruEntry->mKey); NS_ASSERTION(mTable.Count() == PREFLIGHT_CACHE_SIZE - 1, "Somehow tried to remove an entry that was never added!"); } } - if (!mTable.Put(key, entry)) { - // Failed, clean up the new entry. - delete entry; - - NS_WARNING("Failed to add entry to the CORS preflight cache!"); - return nsnull; - } - + mTable.Put(key, entry); PR_INSERT_LINK(entry, &mList); return entry; } void nsPreflightCache::RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal) {
--- a/content/base/src/nsDOMAttributeMap.cpp +++ b/content/base/src/nsDOMAttributeMap.cpp @@ -60,17 +60,18 @@ nsDOMAttributeMap::nsDOMAttributeMap(Ele { // We don't add a reference to our content. If it goes away, // we'll be told to drop our reference } bool nsDOMAttributeMap::Init() { - return mAttributeCache.Init(); + mAttributeCache.Init(); + return true; } /** * Clear map pointer for attributes. */ PLDHashOperator RemoveMapRef(nsAttrHashKey::KeyType aKey, nsRefPtr<nsDOMAttribute>& aData, void* aUserArg) @@ -207,19 +208,18 @@ nsDOMAttributeMap::GetAttribute(nsINodeI nsAttrKey attr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom()); nsDOMAttribute* node = mAttributeCache.GetWeak(attr); if (!node) { nsCOMPtr<nsINodeInfo> ni = aNodeInfo; nsRefPtr<nsDOMAttribute> newAttr = new nsDOMAttribute(this, ni.forget(), EmptyString(), aNsAware); - if (newAttr && mAttributeCache.Put(attr, newAttr)) { - node = newAttr; - } + mAttributeCache.Put(attr, newAttr); + node = newAttr; } return node; } nsDOMAttribute* nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName, nsresult *aResult) { @@ -347,18 +347,17 @@ nsDOMAttributeMap::SetNamedItemInternal( } nsAutoString value; attribute->GetValue(value); // Add the new attribute to the attribute map before updating // its value in the element. @see bug 364413. nsAttrKey attrkey(ni->NamespaceID(), ni->NameAtom()); - rv = mAttributeCache.Put(attrkey, attribute); - NS_ENSURE_SUCCESS(rv, rv); + mAttributeCache.Put(attrkey, attribute); iAttribute->SetMap(this); rv = mContent->SetAttr(ni->NamespaceID(), ni->NameAtom(), ni->GetPrefixAtom(), value, true); if (NS_FAILED(rv)) { DropAttribute(ni->NamespaceID(), ni->NameAtom()); } }
--- a/content/base/src/nsDOMBlobBuilder.cpp +++ b/content/base/src/nsDOMBlobBuilder.cpp @@ -206,66 +206,73 @@ nsDOMMultipartFile::InitInternal(JSConte if (aArgc > 1) { mozilla::dom::BlobPropertyBag d; nsresult rv = d.Init(aCx, &aArgv[1]); NS_ENSURE_SUCCESS(rv, rv); mContentType = d.type; if (d.endings.EqualsLiteral("native")) { nativeEOL = true; } else if (!d.endings.EqualsLiteral("transparent")) { - return NS_ERROR_DOM_INVALID_STATE_ERR; + return NS_ERROR_TYPE_ERR; } } if (aArgc > 0) { if (!aArgv[0].isObject()) { - return NS_ERROR_INVALID_ARG; // We're not interested + return NS_ERROR_TYPE_ERR; // We're not interested } JSObject& obj = aArgv[0].toObject(); - if (!JS_IsArrayObject(aCx, &obj)) { - return NS_ERROR_INVALID_ARG; // We're not interested + return NS_ERROR_TYPE_ERR; // We're not interested } BlobSet blobSet; uint32_t length; JS_ALWAYS_TRUE(JS_GetArrayLength(aCx, &obj, &length)); for (uint32_t i = 0; i < length; ++i) { jsval element; if (!JS_GetElement(aCx, &obj, i, &element)) - return NS_ERROR_INVALID_ARG; + return NS_ERROR_TYPE_ERR; if (element.isObject()) { JSObject& obj = element.toObject(); nsCOMPtr<nsIDOMBlob> blob = aUnwrapFunc(aCx, &obj); if (blob) { // Flatten so that multipart blobs will never nest nsDOMFileBase* file = static_cast<nsDOMFileBase*>( static_cast<nsIDOMBlob*>(blob)); const nsTArray<nsCOMPtr<nsIDOMBlob> >* subBlobs = file->GetSubBlobs(); if (subBlobs) { blobSet.AppendBlobs(*subBlobs); } else { blobSet.AppendBlob(blob); } - } else if (JS_IsArrayBufferObject(&obj, aCx)) { + continue; + } + if (JS_IsArrayBufferViewObject(&obj, aCx)) { + blobSet.AppendVoidPtr(JS_GetArrayBufferViewData(&obj, aCx), + JS_GetArrayBufferViewByteLength(&obj, aCx)); + continue; + } + if (JS_IsArrayBufferObject(&obj, aCx)) { blobSet.AppendArrayBuffer(&obj, aCx); - } else { - // neither arraybuffer nor blob - return NS_ERROR_DOM_INVALID_STATE_ERR; + continue; } + // neither Blob nor ArrayBuffer(View) } else if (element.isString()) { blobSet.AppendString(element.toString(), nativeEOL, aCx); - } else { - // neither object nor string - return NS_ERROR_DOM_INVALID_STATE_ERR; + continue; } + // coerce it to a string + JSString* str = JS_ValueToString(aCx, element); + NS_ENSURE_TRUE(str, NS_ERROR_TYPE_ERR); + blobSet.AppendString(str, nativeEOL, aCx); } mBlobs = blobSet.GetBlobs(); } return NS_OK; }
--- a/content/base/src/nsDOMFileReader.cpp +++ b/content/base/src/nsDOMFileReader.cpp @@ -345,17 +345,17 @@ nsDOMFileReader::DoOnDataAvailable(nsIRe PRUint32 aCount) { if (mDataFormat == FILE_AS_BINARY) { //Continuously update our binary string as data comes in NS_ASSERTION(mResult.Length() == aOffset, "unexpected mResult length"); PRUint32 oldLen = mResult.Length(); PRUnichar *buf = nsnull; - mResult.GetMutableData(&buf, oldLen + aCount); + mResult.GetMutableData(&buf, oldLen + aCount, fallible_t()); NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY); PRUint32 bytesRead = 0; aInputStream->ReadSegments(ReadFuncBinaryString, buf + oldLen, aCount, &bytesRead); NS_ASSERTION(bytesRead == aCount, "failed to read data"); } else if (mDataFormat == FILE_AS_ARRAYBUFFER) { @@ -558,18 +558,18 @@ nsDOMFileReader::ConvertStream(const cha nsCOMPtr<nsIUnicodeDecoder> unicodeDecoder; rv = charsetConverter->GetUnicodeDecoder(aCharset, getter_AddRefs(unicodeDecoder)); NS_ENSURE_SUCCESS(rv, rv); PRInt32 destLength; rv = unicodeDecoder->GetMaxLength(aFileData, aDataLen, &destLength); NS_ENSURE_SUCCESS(rv, rv); - aResult.SetLength(destLength); //Make sure we have enough space for the conversion - destLength = aResult.Length(); + if (!aResult.SetLength(destLength, fallible_t())) + return NS_ERROR_OUT_OF_MEMORY; PRInt32 srcLength = aDataLen; rv = unicodeDecoder->Convert(aFileData, &srcLength, aResult.BeginWriting(), &destLength); aResult.SetLength(destLength); //Trim down to the correct size return rv; }
--- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -721,19 +721,17 @@ nsExternalResourceMap::RequestResource(n mPendingLoads.Get(clone, getter_AddRefs(load)); if (load) { load.forget(aPendingLoad); return nsnull; } load = new PendingLoad(aDisplayDocument); - if (!mPendingLoads.Put(clone, load)) { - return nsnull; - } + mPendingLoads.Put(clone, load); if (NS_FAILED(load->StartLoad(clone, aRequestingNode))) { // Make sure we don't thrash things by trying this load again, since // chances are it failed for good reasons (security check, etc). AddExternalResource(clone, nsnull, nsnull, aDisplayDocument); } else { load.forget(aPendingLoad); } @@ -915,32 +913,24 @@ nsExternalResourceMap::AddExternalResour if (NS_FAILED(rv)) { doc = nsnull; aViewer = nsnull; aLoadGroup = nsnull; } } ExternalResource* newResource = new ExternalResource(); - if (newResource && !mMap.Put(aURI, newResource)) { - delete newResource; - newResource = nsnull; - if (NS_SUCCEEDED(rv)) { - rv = NS_ERROR_OUT_OF_MEMORY; - } - } - - if (newResource) { - newResource->mDocument = doc; - newResource->mViewer = aViewer; - newResource->mLoadGroup = aLoadGroup; - if (doc) { - TransferZoomLevels(aDisplayDocument, doc); - TransferShowingState(aDisplayDocument, doc); - } + mMap.Put(aURI, newResource); + + newResource->mDocument = doc; + newResource->mViewer = aViewer; + newResource->mLoadGroup = aLoadGroup; + if (doc) { + TransferZoomLevels(aDisplayDocument, doc); + TransferShowingState(aDisplayDocument, doc); } const nsTArray< nsCOMPtr<nsIObserver> > & obs = load->Observers(); for (PRUint32 i = 0; i < obs.Length(); ++i) { obs[i]->Observe(doc, "external-resource-document-created", nsnull); } return rv; @@ -1995,17 +1985,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END nsresult nsDocument::Init() { if (mCSSLoader || mNodeInfoManager || mScriptLoader) { return NS_ERROR_ALREADY_INITIALIZED; } mIdentifierMap.Init(); - (void)mStyledLinks.Init(); + mStyledLinks.Init(); mRadioGroups.Init(); // Force initialization. nsINode::nsSlots* slots = GetSlots(); NS_ENSURE_TRUE(slots,NS_ERROR_OUT_OF_MEMORY); // Prepend self as mutation-observer whether we need it or not (some // subclasses currently do, other don't). This is because the code in @@ -2036,20 +2026,18 @@ nsDocument::Init() NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_NODE, "Bad NodeType in aNodeInfo"); NS_ASSERTION(OwnerDoc() == this, "Our nodeinfo is busted!"); mScriptLoader = new nsScriptLoader(this); NS_ENSURE_TRUE(mScriptLoader, NS_ERROR_OUT_OF_MEMORY); - if (!mImageTracker.Init() || - !mPlugins.Init()) { - return NS_ERROR_OUT_OF_MEMORY; - } + mImageTracker.Init(); + mPlugins.Init(); return NS_OK; } void nsIDocument::DeleteAllProperties() { for (PRUint32 i = 0; i < GetPropertyTableCount(); ++i) { @@ -5350,19 +5338,17 @@ nsDocument::GetBoxObjectFor(nsIDOMElemen nsContentUtils::eDOM_PROPERTIES, "UseOfGetBoxObjectForWarning"); } *aResult = nsnull; if (!mBoxObjectTable) { mBoxObjectTable = new nsInterfaceHashtable<nsPtrHashKey<nsIContent>, nsPIBoxObject>; - if (mBoxObjectTable && !mBoxObjectTable->Init(12)) { - mBoxObjectTable = nsnull; - } + mBoxObjectTable->Init(12); } else { // Want to use Get(content, aResult); but it's the wrong type *aResult = mBoxObjectTable->GetWeak(content); if (*aResult) { NS_ADDREF(*aResult); return NS_OK; } } @@ -6497,17 +6483,17 @@ nsDocument::GetRadioGroup(const nsAStrin } nsRadioGroupStruct* radioGroup; if (mRadioGroups.Get(tmKey, &radioGroup)) { return radioGroup; } nsAutoPtr<nsRadioGroupStruct> newRadioGroup(new nsRadioGroupStruct()); - NS_ENSURE_TRUE(mRadioGroups.Put(tmKey, newRadioGroup), nsnull); + mRadioGroups.Put(tmKey, newRadioGroup); return newRadioGroup.forget(); } NS_IMETHODIMP nsDocument::SetCurrentRadioButton(const nsAString& aName, nsIDOMHTMLInputElement* aRadio) { @@ -8280,19 +8266,17 @@ nsDocument::AddImage(imgIRequest* aImage { NS_ENSURE_ARG_POINTER(aImage); // See if the image is already in the hashtable. If it is, get the old count. PRUint32 oldCount = 0; mImageTracker.Get(aImage, &oldCount); // Put the image in the hashtable, with the proper count. - bool success = mImageTracker.Put(aImage, oldCount + 1); - if (!success) - return NS_ERROR_OUT_OF_MEMORY; + mImageTracker.Put(aImage, oldCount + 1); nsresult rv = NS_OK; // If this is the first insertion and we're locking images, lock this image // too. if (oldCount == 0 && mLockingImages) { rv = aImage->LockImage(); if (NS_SUCCEEDED(rv))
--- a/content/base/src/nsDocumentFragment.cpp +++ b/content/base/src/nsDocumentFragment.cpp @@ -48,16 +48,17 @@ #include "nsNodeInfoManager.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" #include "nsIDOMAttr.h" #include "nsDOMError.h" #include "nsGkAtoms.h" #include "nsDOMString.h" #include "nsIDOMUserDataHandler.h" +#include "nsContentUtils.h" class nsDocumentFragment : public nsGenericElement, public nsIDOMDocumentFragment { public: // nsISupports NS_DECL_ISUPPORTS_INHERITED @@ -156,19 +157,32 @@ nsIAtom* nsDocumentFragment::GetIDAttributeName() const { return nsnull; } DOMCI_NODE_DATA(DocumentFragment, nsDocumentFragment) // QueryInterface implementation for nsDocumentFragment -NS_INTERFACE_TABLE_HEAD(nsDocumentFragment) - NS_NODE_INTERFACE_TABLE2(nsDocumentFragment, nsIDOMNode, - nsIDOMDocumentFragment) +NS_INTERFACE_MAP_BEGIN(nsDocumentFragment) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDocumentFragment) + NS_INTERFACE_MAP_ENTRY(nsIContent) + NS_INTERFACE_MAP_ENTRY(nsINode) + NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentFragment) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget) + NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference, + new nsNodeSupportsWeakRefTearoff(this)) + NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNodeSelector, + new nsNodeSelectorTearoff(this)) + // nsNodeSH::PreCreate() depends on the identity pointer being the + // same as nsINode (which nsIContent inherits), so if you change the + // below line, make sure nsNodeSH::PreCreate() still does the right + // thing! + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DocumentFragment) -NS_INTERFACE_MAP_END_INHERITING(nsGenericElement) - +NS_INTERFACE_MAP_END NS_IMPL_ADDREF_INHERITED(nsDocumentFragment, nsGenericElement) NS_IMPL_RELEASE_INHERITED(nsDocumentFragment, nsGenericElement) NS_IMPL_ELEMENT_CLONE(nsDocumentFragment)
--- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -148,17 +148,17 @@ #include "nsCSSParser.h" #include "prprf.h" #include "nsDOMMutationObserver.h" #include "nsSVGFeatures.h" #include "nsWrapperCacheInlines.h" #include "nsCycleCollector.h" #include "xpcpublic.h" -#include "xpcprivate.h" +#include "nsIScriptError.h" #include "nsLayoutStatics.h" #include "mozilla/Telemetry.h" #include "mozilla/CORSMode.h" #include "nsStyledElement.h" using namespace mozilla;
--- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -1359,29 +1359,31 @@ GK_ATOM(text_rendering, "text-rendering" GK_ATOM(textPath, "textPath") GK_ATOM(tref, "tref") GK_ATOM(tspan, "tspan") GK_ATOM(turbulence, "turbulence") GK_ATOM(unicode_bidi, "unicode-bidi") GK_ATOM(userSpaceOnUse, "userSpaceOnUse") GK_ATOM(view, "view") GK_ATOM(viewBox, "viewBox") +GK_ATOM(viewTarget, "viewTarget") GK_ATOM(vkern, "vkern") GK_ATOM(word_spacing, "word-spacing") GK_ATOM(x, "x") GK_ATOM(x1, "x1") GK_ATOM(x2, "x2") GK_ATOM(xChannelSelector, "xChannelSelector") GK_ATOM(xor_, "xor") GK_ATOM(y, "y") GK_ATOM(y1, "y1") GK_ATOM(y2, "y2") GK_ATOM(yChannelSelector, "yChannelSelector") GK_ATOM(z, "z") GK_ATOM(zoomAndPan, "zoomAndPan") +GK_ATOM(vector_effect, "vector-effect") GK_ATOM(accumulate, "accumulate") GK_ATOM(additive, "additive") GK_ATOM(attributeName, "attributeName") GK_ATOM(attributeType, "attributeType") GK_ATOM(auto_reverse, "auto-reverse") GK_ATOM(begin, "begin") GK_ATOM(beginEvent, "beginEvent") @@ -1711,16 +1713,17 @@ GK_ATOM(onMozPressTapGesture, "onMozPres GK_ATOM(onMozTouchDown, "onMozTouchDown") GK_ATOM(onMozTouchMove, "onMozTouchMove") GK_ATOM(onMozTouchUp, "onMozTouchUp") // orientation support GK_ATOM(ondevicemotion, "ondevicemotion") GK_ATOM(ondeviceorientation, "ondeviceorientation") GK_ATOM(ondeviceproximity, "ondeviceproximity") +GK_ATOM(onuserproximity, "onuserproximity") // light sensor support GK_ATOM(ondevicelight, "ondevicelight") //--------------------------------------------------------------------------- // Special atoms //---------------------------------------------------------------------------
--- a/content/base/src/nsNameSpaceManager.cpp +++ b/content/base/src/nsNameSpaceManager.cpp @@ -135,19 +135,19 @@ private: }; static NameSpaceManagerImpl* sNameSpaceManager = nsnull; NS_IMPL_ISUPPORTS1(NameSpaceManagerImpl, nsINameSpaceManager) nsresult NameSpaceManagerImpl::Init() { - nsresult rv = mURIToIDTable.Init(32); - NS_ENSURE_SUCCESS(rv, rv); + mURIToIDTable.Init(32); + nsresult rv; #define REGISTER_NAMESPACE(uri, id) \ rv = AddNameSpace(NS_LITERAL_STRING(uri), id); \ NS_ENSURE_SUCCESS(rv, rv) // Need to be ordered according to ID. REGISTER_NAMESPACE(kXMLNSNameSpaceURI, kNameSpaceID_XMLNS); REGISTER_NAMESPACE(kXMLNameSpaceURI, kNameSpaceID_XML); REGISTER_NAMESPACE(kXHTMLNameSpaceURI, kNameSpaceID_XHTML); @@ -283,21 +283,17 @@ nsresult NameSpaceManagerImpl::AddNameSp "BAD! AddNameSpace not called in right order!"); nsString* uri = new nsString(aURI); if (!uri || !mURIArray.AppendElement(uri)) { delete uri; return NS_ERROR_OUT_OF_MEMORY; } - if (!mURIToIDTable.Put(uri, aNameSpaceID)) { - mURIArray.RemoveElementAt(aNameSpaceID - 1); - - return NS_ERROR_OUT_OF_MEMORY; - } + mURIToIDTable.Put(uri, aNameSpaceID); return NS_OK; } nsresult NS_GetNameSpaceManager(nsINameSpaceManager** aInstancePtrResult) { NS_ENSURE_ARG_POINTER(aInstancePtrResult);
--- a/content/base/src/nsTreeSanitizer.cpp +++ b/content/base/src/nsTreeSanitizer.cpp @@ -623,22 +623,23 @@ nsIAtom** const kAttributesSVG[] = { &nsGkAtoms::unicode_bidi, // unicode-bidi // unicode-range // units-per-em // v-alphabetic // v-hanging // v-ideographic // v-mathematical &nsGkAtoms::values, // values + &nsGkAtoms::vector_effect, // vector-effect // vert-adv-y // vert-origin-x // vert-origin-y &nsGkAtoms::viewBox, // viewBox + &nsGkAtoms::viewTarget, // viewTarget &nsGkAtoms::visibility, // visibility - // viewTarget &nsGkAtoms::width, // width // widths &nsGkAtoms::word_spacing, // word-spacing // writing-mode &nsGkAtoms::x, // x // x-height &nsGkAtoms::x1, // x1 &nsGkAtoms::x2, // x2
--- a/content/base/src/nsWebSocket.cpp +++ b/content/base/src/nsWebSocket.cpp @@ -385,20 +385,24 @@ nsWebSocket::OnServerClose(nsISupports * return NS_ERROR_UNEXPECTED; } // store code/string for onclose DOM event mCloseEventCode = aCode; CopyUTF8toUTF16(aReason, mCloseEventReason); if (mReadyState == nsIWebSocket::OPEN) { - // Send reciprocal Close frame. - // 5.5.1: "When sending a Close frame in response, the endpoint typically - // echos the status code it received" - CloseConnection(aCode, aReason); + // RFC 6455, 5.5.1: "When sending a Close frame in response, the endpoint + // typically echos the status code it received". + // But never send certain codes, per section 7.4.1 + if (aCode == 1005 || aCode == 1006 || aCode == 1015) { + CloseConnection(0, EmptyCString()); + } else { + CloseConnection(aCode, aReason); + } } else { // Nothing else to do: OnStop does the rest of the work. NS_ASSERTION (mReadyState == nsIWebSocket::CLOSING, "unknown state"); NS_ASSERTION(!mDisconnected, "should not be disconnected during CLOSING"); } return NS_OK; }
--- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -574,16 +574,17 @@ include $(topsrcdir)/config/rules.mk test_bug650386_redirect_303.html \ test_bug650386_redirect_307.html \ file_bug650386_content.sjs \ file_bug650386_report.sjs \ test_bug719533.html \ test_bug737087.html \ test_bug433662.html \ test_bug749367.html \ + test_bug753278.html \ $(NULL) _CHROME_FILES = \ test_bug357450.js \ $(NULL) # This test fails on the Mac for some reason ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
--- a/content/base/test/file_websocket_wsh.py +++ b/content/base/test/file_websocket_wsh.py @@ -26,16 +26,29 @@ def web_socket_do_extra_handshake(reques elif request.ws_protocol == "test-22": # The timeout is 5 seconds time.sleep(13) elif request.ws_protocol == "test-41b": request.sts = "max-age=100" else: pass +# Behave according to recommendation of RFC 6455, section # 5.5.1: +# "When sending a Close frame in response, the endpoint typically echos the +# status code it received." +# - Without this, pywebsocket replies with 1000 to any close code. +# +# Note that this function is only called when the client initiates the close +def web_socket_passive_closing_handshake(request): + if request.ws_close_code == 1005: + return None, None + else: + return request.ws_close_code, request.ws_close_reason + + def web_socket_transfer_data(request): if request.ws_protocol == "test-2.1" or request.ws_protocol == "test-2.2": msgutil.close_connection(request) elif request.ws_protocol == "test-6": resp = "wrong message" if msgutil.receive_message(request) == "1": resp = "2" msgutil.send_message(request, resp.decode('utf-8')) @@ -52,17 +65,16 @@ def web_socket_transfer_data(request): msgutil.send_message(request, "test-7 data") elif request.ws_protocol == "test-10": msgutil.close_connection(request) elif request.ws_protocol == "test-11": resp = "wrong message" if msgutil.receive_message(request) == "client data": resp = "server data" msgutil.send_message(request, resp.decode('utf-8')) - msgutil.close_connection(request) elif request.ws_protocol == "test-12": msgutil.close_connection(request) elif request.ws_protocol == "test-13": # first one binary message containing the byte 0x61 ('a') request.connection.write('\xff\x01\x61') # after a bad utf8 message request.connection.write('\x01\x61\xff') msgutil.close_connection(request)
--- a/content/base/test/test_blobconstructor.html +++ b/content/base/test/test_blobconstructor.html @@ -132,16 +132,27 @@ let testData = {start: 1, length: 2, contents: "te"}, {start: 6, length: 4, contents: "quig"}]], // Test an array buffer [[aB, blob1, "foo"], {}, [{start: 0, length: 8, contents: "ABCDEFGH"}, {start: 8, length:10, contents: "IJKLMNOPsq"}, {start: 17, length: 3, contents: "qui"}, {start: 4, length: 8, contents: "EFGHIJKL"}]], + // Test an ArrayBufferView + [[int8View, blob1, "foo"], {}, + [{start: 0, length: 8, contents: "ABCDEFGH"}, + {start: 8, length:10, contents: "IJKLMNOPsq"}, + {start: 17, length: 3, contents: "qui"}, + {start: 4, length: 8, contents: "EFGHIJKL"}]], + // Test a partial ArrayBufferView + [[new Uint8Array(aB, 3, 5), blob1, "foo"], {}, + [{start: 0, length: 8, contents: "DEFGHsqu"}, + {start: 8, length:10, contents: "igglefoo"}, + {start: 4, length: 8, contents: "Hsquiggl"}]], // Test transparent line endings [["foo\r\n", "bar\r", "baz\n"], { endings: "transparent" }, [{start: 0, length: 5, contents: "foo\r\n"}, {start: 5, length: 4, contents: "bar\r"}, {start: 9, length: 4, contents: "baz\n"}]], // Test transparent line endings when the second argument is omitted [["foo\r\n", "bar\r", "baz\n"], undefined, [{start: 0, length: 5, contents: "foo\r\n"}, @@ -152,17 +163,21 @@ let testData = navigator.platform.indexOf("Win") != -1 ? [{start: 0, length: 5, contents: "foo\r\n"}, {start: 5, length: 5, contents: "bar\r\n"}, {start: 10, length: 5, contents: "baz\r\n"}] : [{start: 0, length: 4, contents: "foo\n"}, {start: 4, length: 4, contents: "bar\n"}, {start: 8, length: 4, contents: "baz\n"}]], // Test type coercion of a number - [[3, aB, "foo"], {}, "InvalidStateError"] + [[3, int8View, "foo"], {}, + [{start: 0, length: 8, contents: "3ABCDEFG"}, + {start: 8, length:10, contents: "HIJKLMNOPf"}, + {start: 17, length: 4, contents: "foo"}, + {start: 4, length: 8, contents: "DEFGHIJK"}]] ]; let testCounter = 0; function doTest(data) { testCounter++; [blobs, options, tests] = data;
new file mode 100644 --- /dev/null +++ b/content/base/test/test_bug753278.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=753278 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 753278</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body onload="runTest();"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=753278">Mozilla Bug 753278</a> +<p id="display"></p> +<div id="content" style="display: none"> +<iframe></iframe> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 753278 **/ + +SimpleTest.waitForExplicitFinish(); + +var f = document.getElementsByTagName("iframe")[0]; + +function runTest() { + f.contentDocument.open(); + f.contentDocument.write('<script>window.location = "data:text/html;charset=utf-8,\\u003Cscript>parent.pass();\\u003C/script>"; document.close(); document.open(); document.write("\\u003Cscript>parent.fail();\\u003C/script>"); document.close();\u003c/script>'); + f.contentDocument.close(); +} + +function pass() { + ok(true, "window.location took precedence"); + SimpleTest.finish(); +} + +function fail() { + ok(false, "window.location should have taken precedence"); + SimpleTest.finish(); +} + +</script> +</pre> +</body> +</html>
--- a/content/base/test/test_websocket.html +++ b/content/base/test/test_websocket.html @@ -20,18 +20,18 @@ * tests: * 1. client tries to connect to a http scheme location; * 2. assure serialization of the connections; * 3. client tries to connect to an non-existent ws server; * 4. client tries to connect using a relative url; * 5. client uses an invalid protocol value; * 6. counter and encoding check; * 7. onmessage event origin property check - * 8. client calls close() and the server sends the close frame in - * acknowledgement; + * 8. client calls close() and the server sends the close frame (with no code + * or reason) in acknowledgement; * 9. client closes the connection before the ws connection is established; * 10. client sends a message before the ws connection is established; * 11. a simple hello echo; * 12. client sends a message with bad bytes; * 13. server sends an invalid message; * 14. server sends the close frame, it doesn't close the tcp connection and * it keeps sending normal ws messages; * 15. server closes the tcp connection, but it doesn't send the close frame; @@ -50,17 +50,17 @@ * 27. ctor with invalid sub-protocol array containing an empty element in list * 28. ctor using valid 1 element sub-protocol array * 29. ctor using all valid 5 element sub-protocol array * 30. ctor using valid 1 element sub-protocol array with element server will * reject * 31. ctor using valid 2 element sub-protocol array with 1 element server * will reject and one server will accept. * 32. ctor using invalid sub-protocol array that contains duplicate items - * 33. default close code test + * 33. test for sending/receiving custom close code (but no close reason) * 34. test for receiving custom close code and reason * 35. test for sending custom close code and reason * 36. negative test for sending out of range close code * 37. negative test for too long of a close reason * 38. ensure extensions attribute is defined * 39. a basic wss:// connectivity test * 40. negative test for wss:// with no cert * 41. HSTS @@ -382,16 +382,20 @@ function test8() ws.onopen = function() { ok(ws.protocol == "test-8", "test-8 subprotocol selection"); ws.close(); } ws.onclose = function(e) { shouldCloseCleanly(e); + // We called close() with no close code: so pywebsocket will also send no + // close code, which translates to code 1005 + ok(e.code == 1005, "test-8 close code has wrong value:" + e.code); + ok(e.reason == "", "test-8 close reason has wrong value:" + e.reason); doTest(9); }; } var waitTest9 = false; function test9() { @@ -456,26 +460,28 @@ function test11() ws.onopen = function() { ok(ws.readyState == 1, "open bad readyState in test-11!"); ws.send("client data"); } ws.onmessage = function(e) { ok(e.data == "server data", "bad received message in test-11!"); - ws.close(); + ws.close(1000, "Have a nice day"); // this ok() is disabled due to a race condition - it state may have // advanced through 2 (closing) and into 3 (closed) before it is evald // ok(ws.readyState == 2, "onmessage bad readyState in test-11!"); } ws.onclose = function(e) { ok(ws.readyState == 3, "onclose bad readyState in test-11!"); shouldCloseCleanly(e); + ok(e.code == 1000, "test 11 got wrong close code: " + e.code); + ok(e.reason == "Have a nice day", "test 11 got wrong close reason: " + e.reason); doTest(12); } } function test12() { ok(true,"test 12"); @@ -937,24 +943,25 @@ function test32() function test33() { var prots=["test33"]; var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots); ws.onopen = function(e) { ok(true, "test 33 open"); - ws.close(); + ws.close(3131); // pass code but not reason }; ws.onclose = function(e) { ok(true, "test 33 close"); - ok(e.wasClean, "test 33 closed cleanly"); - ok(e.code == 1000, "test 33 had normal 1000 error code"); + shouldCloseCleanly(e); + ok(e.code == 3131, "test 33 got wrong close code: " + e.code); + ok(e.reason === "", "test 33 got wrong close reason: " + e.reason); doTest(34); }; } function test34() { var prots=["test-34"];
--- a/content/canvas/src/CustomQS_Canvas2D.h +++ b/content/canvas/src/CustomQS_Canvas2D.h @@ -130,35 +130,35 @@ Canvas2D_GetStyleHelper(JSContext *cx, J &interfaces[k_nsIDOMCanvasGradient], vp); } default: return xpc_qsThrowGetterSetterFailed(cx, NS_ERROR_FAILURE, JSVAL_TO_OBJECT(*vp), id); } } static JSBool -nsIDOMCanvasRenderingContext2D_SetStrokeStyle(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp) +nsIDOMCanvasRenderingContext2D_SetStrokeStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp) { return Canvas2D_SetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::SetStrokeStyle_multi); } static JSBool -nsIDOMCanvasRenderingContext2D_GetStrokeStyle(JSContext *cx, JSObject *obj, jsid id, jsval *vp) +nsIDOMCanvasRenderingContext2D_GetStrokeStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp) { return Canvas2D_GetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::GetStrokeStyle_multi); } static JSBool -nsIDOMCanvasRenderingContext2D_SetFillStyle(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp) +nsIDOMCanvasRenderingContext2D_SetFillStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp) { return Canvas2D_SetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::SetFillStyle_multi); } static JSBool -nsIDOMCanvasRenderingContext2D_GetFillStyle(JSContext *cx, JSObject *obj, jsid id, jsval *vp) +nsIDOMCanvasRenderingContext2D_GetFillStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp) { return Canvas2D_GetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::GetFillStyle_multi); } static bool CreateImageData(JSContext* cx, JSObject* obj, uint32_t w, uint32_t h, jsval* vp) { using mozilla::CheckedInt;
--- a/content/canvas/src/Makefile.in +++ b/content/canvas/src/Makefile.in @@ -104,13 +104,12 @@ include $(topsrcdir)/ipc/chromium/chromi CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS) INCLUDES += \ -I$(srcdir)/../../../layout/xul/base/src \ -I$(srcdir)/../../../layout/style \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../base/src \ -I$(srcdir)/../../html/content/src \ - -I$(srcdir)/../../../js/xpconnect/src \ -I$(srcdir)/../../../dom/base \ $(NULL) DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/events/public/Makefile.in +++ b/content/events/public/Makefile.in @@ -49,16 +49,17 @@ EXPORTS = \ nsMutationEvent.h \ nsIPrivateDOMEvent.h \ nsIPrivateTextEvent.h \ nsIPrivateTextRange.h \ nsAsyncDOMEvent.h \ nsEventDispatcher.h \ nsEventStates.h \ nsEventNameList.h \ + nsVKList.h \ $(NULL) XPIDLSRCS = \ nsIEventListenerService.idl \ $(NULL) include $(topsrcdir)/config/rules.mk
--- a/content/events/public/nsEventNameList.h +++ b/content/events/public/nsEventNameList.h @@ -454,16 +454,20 @@ WINDOW_ONLY_EVENT(devicemotion, WINDOW_ONLY_EVENT(deviceorientation, NS_DEVICE_ORIENTATION, EventNameType_None, NS_EVENT) WINDOW_ONLY_EVENT(deviceproximity, NS_DEVICE_PROXIMITY, EventNameType_None, NS_EVENT) +WINDOW_ONLY_EVENT(userproximity, + NS_USER_PROXIMITY, + EventNameType_None, + NS_EVENT) WINDOW_ONLY_EVENT(devicelight, NS_DEVICE_LIGHT, EventNameType_None, NS_EVENT) TOUCH_EVENT(touchstart, NS_TOUCH_START, EventNameType_All,
--- a/content/events/public/nsIPrivateDOMEvent.h +++ b/content/events/public/nsIPrivateDOMEvent.h @@ -89,16 +89,18 @@ nsresult NS_NewDOMCompositionEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsCompositionEvent *aEvent); nsresult NS_NewDOMMutationEvent(nsIDOMEvent** aResult NS_OUTPARAM, nsPresContext* aPresContext, class nsMutationEvent* aEvent); nsresult NS_NewDOMPopupBlockedEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, nsEvent* aEvent); nsresult NS_NewDOMDeviceProximityEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent *aEvent); nsresult +NS_NewDOMUserProximityEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent *aEvent); +nsresult NS_NewDOMDeviceOrientationEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, nsEvent* aEvent); nsresult NS_NewDOMDeviceLightEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, nsEvent* aEvent); nsresult NS_NewDOMDeviceMotionEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, nsEvent* aEvent); nsresult NS_NewDOMTextEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsTextEvent* aEvent); nsresult
new file mode 100644 --- /dev/null +++ b/content/events/public/nsVKList.h @@ -0,0 +1,191 @@ +/* -*- Mode: C++; tab-width: 8; 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/. */ + +/** + * This header file defines all DOM keys which are defined in nsIDOMKeyEvent. + * You must define NS_DEFINE_VK macro before including this. + * + * It must have two arguments, (aDOMKeyName, aDOMKeyCode) + * aDOMKeyName is a key name in DOM. + * aDOMKeyCode is one of nsIDOMKeyEvent::DOM_VK_*. + */ + +#define DEFINE_VK_INTERNAL(aKeyName) \ + NS_DEFINE_VK(VK##aKeyName, nsIDOMKeyEvent::DOM_VK##aKeyName) + +// Some keycode may have different name in nsIDOMKeyEvent from its key name. +#define DEFINE_VK_INTERNAL2(aKeyName, aKeyCodeName) \ + NS_DEFINE_VK(VK##aKeyName, nsIDOMKeyEvent::DOM_VK##aKeyCodeName) + +DEFINE_VK_INTERNAL(_CANCEL), +DEFINE_VK_INTERNAL(_HELP), +DEFINE_VK_INTERNAL2(_BACK, _BACK_SPACE), +DEFINE_VK_INTERNAL(_TAB), +DEFINE_VK_INTERNAL(_CLEAR), +DEFINE_VK_INTERNAL(_RETURN), +DEFINE_VK_INTERNAL(_ENTER), +DEFINE_VK_INTERNAL(_SHIFT), +DEFINE_VK_INTERNAL(_CONTROL), +DEFINE_VK_INTERNAL(_ALT), +DEFINE_VK_INTERNAL(_PAUSE), +DEFINE_VK_INTERNAL(_CAPS_LOCK), +DEFINE_VK_INTERNAL(_KANA), +DEFINE_VK_INTERNAL(_HANGUL), +DEFINE_VK_INTERNAL(_EISU), +DEFINE_VK_INTERNAL(_JUNJA), +DEFINE_VK_INTERNAL(_FINAL), +DEFINE_VK_INTERNAL(_HANJA), +DEFINE_VK_INTERNAL(_KANJI), +DEFINE_VK_INTERNAL(_ESCAPE), +DEFINE_VK_INTERNAL(_CONVERT), +DEFINE_VK_INTERNAL(_NONCONVERT), +DEFINE_VK_INTERNAL(_ACCEPT), +DEFINE_VK_INTERNAL(_MODECHANGE), +DEFINE_VK_INTERNAL(_SPACE), +DEFINE_VK_INTERNAL(_PAGE_UP), +DEFINE_VK_INTERNAL(_PAGE_DOWN), +DEFINE_VK_INTERNAL(_END), +DEFINE_VK_INTERNAL(_HOME), +DEFINE_VK_INTERNAL(_LEFT), +DEFINE_VK_INTERNAL(_UP), +DEFINE_VK_INTERNAL(_RIGHT), +DEFINE_VK_INTERNAL(_DOWN), +DEFINE_VK_INTERNAL(_SELECT), +DEFINE_VK_INTERNAL(_PRINT), +DEFINE_VK_INTERNAL(_EXECUTE), +DEFINE_VK_INTERNAL(_PRINTSCREEN), +DEFINE_VK_INTERNAL(_INSERT), +DEFINE_VK_INTERNAL(_DELETE), + +DEFINE_VK_INTERNAL(_0), +DEFINE_VK_INTERNAL(_1), +DEFINE_VK_INTERNAL(_2), +DEFINE_VK_INTERNAL(_3), +DEFINE_VK_INTERNAL(_4), +DEFINE_VK_INTERNAL(_5), +DEFINE_VK_INTERNAL(_6), +DEFINE_VK_INTERNAL(_7), +DEFINE_VK_INTERNAL(_8), +DEFINE_VK_INTERNAL(_9), + +DEFINE_VK_INTERNAL(_COLON), +DEFINE_VK_INTERNAL(_SEMICOLON), +DEFINE_VK_INTERNAL(_LESS_THAN), +DEFINE_VK_INTERNAL(_EQUALS), +DEFINE_VK_INTERNAL(_GREATER_THAN), +DEFINE_VK_INTERNAL(_QUESTION_MARK), +DEFINE_VK_INTERNAL(_AT), + +DEFINE_VK_INTERNAL(_A), +DEFINE_VK_INTERNAL(_B), +DEFINE_VK_INTERNAL(_C), +DEFINE_VK_INTERNAL(_D), +DEFINE_VK_INTERNAL(_E), +DEFINE_VK_INTERNAL(_F), +DEFINE_VK_INTERNAL(_G), +DEFINE_VK_INTERNAL(_H), +DEFINE_VK_INTERNAL(_I), +DEFINE_VK_INTERNAL(_J), +DEFINE_VK_INTERNAL(_K), +DEFINE_VK_INTERNAL(_L), +DEFINE_VK_INTERNAL(_M), +DEFINE_VK_INTERNAL(_N), +DEFINE_VK_INTERNAL(_O), +DEFINE_VK_INTERNAL(_P), +DEFINE_VK_INTERNAL(_Q), +DEFINE_VK_INTERNAL(_R), +DEFINE_VK_INTERNAL(_S), +DEFINE_VK_INTERNAL(_T), +DEFINE_VK_INTERNAL(_U), +DEFINE_VK_INTERNAL(_V), +DEFINE_VK_INTERNAL(_W), +DEFINE_VK_INTERNAL(_X), +DEFINE_VK_INTERNAL(_Y), +DEFINE_VK_INTERNAL(_Z), + +DEFINE_VK_INTERNAL(_WIN), +DEFINE_VK_INTERNAL(_CONTEXT_MENU), +DEFINE_VK_INTERNAL(_SLEEP), + +DEFINE_VK_INTERNAL(_NUMPAD0), +DEFINE_VK_INTERNAL(_NUMPAD1), +DEFINE_VK_INTERNAL(_NUMPAD2), +DEFINE_VK_INTERNAL(_NUMPAD3), +DEFINE_VK_INTERNAL(_NUMPAD4), +DEFINE_VK_INTERNAL(_NUMPAD5), +DEFINE_VK_INTERNAL(_NUMPAD6), +DEFINE_VK_INTERNAL(_NUMPAD7), +DEFINE_VK_INTERNAL(_NUMPAD8), +DEFINE_VK_INTERNAL(_NUMPAD9), +DEFINE_VK_INTERNAL(_MULTIPLY), +DEFINE_VK_INTERNAL(_ADD), +DEFINE_VK_INTERNAL(_SEPARATOR), +DEFINE_VK_INTERNAL(_SUBTRACT), +DEFINE_VK_INTERNAL(_DECIMAL), +DEFINE_VK_INTERNAL(_DIVIDE), + +DEFINE_VK_INTERNAL(_F1), +DEFINE_VK_INTERNAL(_F2), +DEFINE_VK_INTERNAL(_F3), +DEFINE_VK_INTERNAL(_F4), +DEFINE_VK_INTERNAL(_F5), +DEFINE_VK_INTERNAL(_F6), +DEFINE_VK_INTERNAL(_F7), +DEFINE_VK_INTERNAL(_F8), +DEFINE_VK_INTERNAL(_F9), +DEFINE_VK_INTERNAL(_F10), +DEFINE_VK_INTERNAL(_F11), +DEFINE_VK_INTERNAL(_F12), +DEFINE_VK_INTERNAL(_F13), +DEFINE_VK_INTERNAL(_F14), +DEFINE_VK_INTERNAL(_F15), +DEFINE_VK_INTERNAL(_F16), +DEFINE_VK_INTERNAL(_F17), +DEFINE_VK_INTERNAL(_F18), +DEFINE_VK_INTERNAL(_F19), +DEFINE_VK_INTERNAL(_F20), +DEFINE_VK_INTERNAL(_F21), +DEFINE_VK_INTERNAL(_F22), +DEFINE_VK_INTERNAL(_F23), +DEFINE_VK_INTERNAL(_F24), + +DEFINE_VK_INTERNAL(_NUM_LOCK), +DEFINE_VK_INTERNAL(_SCROLL_LOCK), + +DEFINE_VK_INTERNAL(_CIRCUMFLEX), +DEFINE_VK_INTERNAL(_EXCLAMATION), +DEFINE_VK_INTERNAL(_DOUBLE_QUOTE), +DEFINE_VK_INTERNAL(_HASH), +DEFINE_VK_INTERNAL(_DOLLAR), +DEFINE_VK_INTERNAL(_PERCENT), +DEFINE_VK_INTERNAL(_AMPERSAND), +DEFINE_VK_INTERNAL(_UNDERSCORE), +DEFINE_VK_INTERNAL(_OPEN_PAREN), +DEFINE_VK_INTERNAL(_CLOSE_PAREN), +DEFINE_VK_INTERNAL(_ASTERISK), +DEFINE_VK_INTERNAL(_PLUS), +DEFINE_VK_INTERNAL(_PIPE), +DEFINE_VK_INTERNAL(_HYPHEN_MINUS), + +DEFINE_VK_INTERNAL(_OPEN_CURLY_BRACKET), +DEFINE_VK_INTERNAL(_CLOSE_CURLY_BRACKET), + +DEFINE_VK_INTERNAL(_TILDE), + +DEFINE_VK_INTERNAL(_COMMA), +DEFINE_VK_INTERNAL(_PERIOD), +DEFINE_VK_INTERNAL(_SLASH), +DEFINE_VK_INTERNAL(_BACK_QUOTE), +DEFINE_VK_INTERNAL(_OPEN_BRACKET), +DEFINE_VK_INTERNAL(_BACK_SLASH), +DEFINE_VK_INTERNAL(_CLOSE_BRACKET), +DEFINE_VK_INTERNAL(_QUOTE), + +DEFINE_VK_INTERNAL(_META), +DEFINE_VK_INTERNAL(_ALTGR) + +#undef DEFINE_VK_INTERNAL +#undef DEFINE_VK_INTERNAL2
--- a/content/events/src/Makefile.in +++ b/content/events/src/Makefile.in @@ -61,16 +61,17 @@ CPPSRCS = \ nsDOMKeyboardEvent.cpp \ nsDOMTextEvent.cpp \ nsDOMMouseEvent.cpp \ nsDOMMouseScrollEvent.cpp \ nsDOMDragEvent.cpp \ nsDOMMutationEvent.cpp \ nsDOMPopupBlockedEvent.cpp \ nsDOMDeviceProximityEvent.cpp \ + nsDOMUserProximityEvent.cpp \ nsDOMDeviceLightEvent.cpp \ nsDOMDeviceOrientationEvent.cpp \ nsDOMDeviceMotionEvent.cpp \ nsDOMBeforeUnloadEvent.cpp \ nsDOMPageTransitionEvent.cpp \ nsDOMXULCommandEvent.cpp \ nsDOMCommandEvent.cpp \ nsDOMMessageEvent.cpp \
--- a/content/events/src/nsDOMDataContainerEvent.cpp +++ b/content/events/src/nsDOMDataContainerEvent.cpp @@ -84,17 +84,18 @@ nsDOMDataContainerEvent::GetData(const n NS_IMETHODIMP nsDOMDataContainerEvent::SetData(const nsAString& aKey, nsIVariant *aData) { NS_ENSURE_ARG(aData); // Make sure this event isn't already being dispatched. NS_ENSURE_STATE(!(NS_IS_EVENT_IN_DISPATCH(mEvent))); NS_ENSURE_STATE(mData.IsInitialized()); - return mData.Put(aKey, aData) ? NS_OK : NS_ERROR_OUT_OF_MEMORY; + mData.Put(aKey, aData); + return NS_OK; } nsresult NS_NewDOMDataContainerEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent) { nsDOMDataContainerEvent* it =
--- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -123,16 +123,17 @@ static const char* const sEventNames[] = "MozScrolledAreaChanged", "transitionend", "animationstart", "animationend", "animationiteration", "devicemotion", "deviceorientation", "deviceproximity", + "userproximity", "devicelight" }; static char *sPopupAllowedEvents; nsDOMEvent::nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent) { @@ -1552,16 +1553,18 @@ const char* nsDOMEvent::GetEventName(PRU case NS_ANIMATION_ITERATION: return sEventNames[eDOMEvents_animationiteration]; case NS_DEVICE_MOTION: return sEventNames[eDOMEvents_devicemotion]; case NS_DEVICE_ORIENTATION: return sEventNames[eDOMEvents_deviceorientation]; case NS_DEVICE_PROXIMITY: return sEventNames[eDOMEvents_deviceproximity]; + case NS_USER_PROXIMITY: + return sEventNames[eDOMEvents_userproximity]; case NS_DEVICE_LIGHT: return sEventNames[eDOMEvents_devicelight]; case NS_FULLSCREENCHANGE: return sEventNames[eDOMEvents_mozfullscreenchange]; case NS_FULLSCREENERROR: return sEventNames[eDOMEvents_mozfullscreenerror]; default: break;
--- a/content/events/src/nsDOMEvent.h +++ b/content/events/src/nsDOMEvent.h @@ -206,16 +206,17 @@ public: eDOMEvents_MozScrolledAreaChanged, eDOMEvents_transitionend, eDOMEvents_animationstart, eDOMEvents_animationend, eDOMEvents_animationiteration, eDOMEvents_devicemotion, eDOMEvents_deviceorientation, eDOMEvents_deviceproximity, + eDOMEvents_userproximity, eDOMEvents_devicelight }; nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent); virtual ~nsDOMEvent(); NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMEvent, nsIDOMEvent)
new file mode 100644 --- /dev/null +++ b/content/events/src/nsDOMUserProximityEvent.cpp @@ -0,0 +1,57 @@ +/* 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 "nsDOMUserProximityEvent.h" +#include "nsContentUtils.h" +#include "DictionaryHelpers.h" + +NS_IMPL_ADDREF_INHERITED(nsDOMUserProximityEvent, nsDOMEvent) +NS_IMPL_RELEASE_INHERITED(nsDOMUserProximityEvent, nsDOMEvent) + +DOMCI_DATA(UserProximityEvent, nsDOMUserProximityEvent) + +NS_INTERFACE_MAP_BEGIN(nsDOMUserProximityEvent) + NS_INTERFACE_MAP_ENTRY(nsIDOMUserProximityEvent) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(UserProximityEvent) +NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) + +NS_IMETHODIMP +nsDOMUserProximityEvent::InitUserProximityEvent(const nsAString & aEventTypeArg, + bool aCanBubbleArg, + bool aCancelableArg, + bool aNear) +{ + nsresult rv = nsDOMEvent::InitEvent(aEventTypeArg, aCanBubbleArg, aCancelableArg); + NS_ENSURE_SUCCESS(rv, rv); + mNear = aNear; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMUserProximityEvent::GetNear(bool *aNear) +{ + NS_ENSURE_ARG_POINTER(aNear); + *aNear = mNear; + return NS_OK; +} + +nsresult +nsDOMUserProximityEvent::InitFromCtor(const nsAString& aType, + JSContext* aCx, jsval* aVal) +{ + mozilla::dom::UserProximityEventInit d; + nsresult rv = d.Init(aCx, aVal); + NS_ENSURE_SUCCESS(rv, rv); + return InitUserProximityEvent(aType, d.bubbles, d.cancelable, d.near); +} + +nsresult +NS_NewDOMUserProximityEvent(nsIDOMEvent** aInstancePtrResult, + nsPresContext* aPresContext, + nsEvent *aEvent) +{ + NS_ENSURE_ARG_POINTER(aInstancePtrResult); + nsDOMUserProximityEvent* it = new nsDOMUserProximityEvent(aPresContext, aEvent); + return CallQueryInterface(it, aInstancePtrResult); +}
new file mode 100644 --- /dev/null +++ b/content/events/src/nsDOMUserProximityEvent.h @@ -0,0 +1,36 @@ +/* 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 nsDOMUserProximityEvent_h__ +#define nsDOMUserProximityEvent_h__ + +#include "nsIDOMUserProximityEvent.h" +#include "nsDOMEvent.h" + +class nsDOMUserProximityEvent + : public nsDOMEvent + , public nsIDOMUserProximityEvent +{ +public: + + nsDOMUserProximityEvent(nsPresContext* aPresContext, nsEvent* aEvent) + : nsDOMEvent(aPresContext, aEvent), + mNear(false) {} + + NS_DECL_ISUPPORTS_INHERITED + + // Forward to nsDOMEvent + NS_FORWARD_TO_NSDOMEVENT + + // nsIDOMUserProximityEvent Interface + NS_DECL_NSIDOMUSERPROXIMITYEVENT + + virtual nsresult InitFromCtor(const nsAString& aType, + JSContext* aCx, + jsval* aVal); +protected: + bool mNear; +}; + +#endif
--- a/content/events/src/nsEventListenerManager.cpp +++ b/content/events/src/nsEventListenerManager.cpp @@ -285,17 +285,17 @@ nsEventListenerManager::AddEventListener // If aType is NS_MUTATION_SUBTREEMODIFIED, we need to listen all // mutations. nsContentUtils::HasMutationListeners relies on this. window->SetMutationListeners((aType == NS_MUTATION_SUBTREEMODIFIED) ? kAllMutationBits : MutationBitForEventType(aType)); } } else if (aTypeAtom == nsGkAtoms::ondeviceorientation) { EnableDevice(NS_DEVICE_ORIENTATION); - } else if (aTypeAtom == nsGkAtoms::ondeviceproximity) { + } else if (aTypeAtom == nsGkAtoms::ondeviceproximity || aTypeAtom == nsGkAtoms::onuserproximity) { EnableDevice(NS_DEVICE_PROXIMITY); } else if (aTypeAtom == nsGkAtoms::ondevicelight) { EnableDevice(NS_DEVICE_LIGHT); } else if (aTypeAtom == nsGkAtoms::ondevicemotion) { EnableDevice(NS_DEVICE_MOTION); } else if ((aType >= NS_MOZTOUCH_DOWN && aType <= NS_MOZTOUCH_UP) || (aTypeAtom == nsGkAtoms::ontouchstart || aTypeAtom == nsGkAtoms::ontouchend || @@ -346,16 +346,17 @@ nsEventListenerManager::EnableDevice(PRU NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window"); switch (aType) { case NS_DEVICE_ORIENTATION: window->EnableDeviceSensor(SENSOR_ORIENTATION); break; case NS_DEVICE_PROXIMITY: + case NS_USER_PROXIMITY: window->EnableDeviceSensor(SENSOR_PROXIMITY); break; case NS_DEVICE_LIGHT: window->EnableDeviceSensor(SENSOR_LIGHT); break; case NS_DEVICE_MOTION: window->EnableDeviceSensor(SENSOR_ACCELERATION); window->EnableDeviceSensor(SENSOR_LINEAR_ACCELERATION); @@ -382,16 +383,17 @@ nsEventListenerManager::DisableDevice(PR window->DisableDeviceSensor(SENSOR_ORIENTATION); break; case NS_DEVICE_MOTION: window->DisableDeviceSensor(SENSOR_ACCELERATION); window->DisableDeviceSensor(SENSOR_LINEAR_ACCELERATION); window->DisableDeviceSensor(SENSOR_GYROSCOPE); break; case NS_DEVICE_PROXIMITY: + case NS_USER_PROXIMITY: window->DisableDeviceSensor(SENSOR_PROXIMITY); break; case NS_DEVICE_LIGHT: window->DisableDeviceSensor(SENSOR_LIGHT); break; default: NS_WARNING("Disabling an unknown device sensor."); break;
--- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -2217,16 +2217,18 @@ nsEventStateManager::DetermineDragTarget nsDOMDataTransfer* aDataTransfer, nsISelection** aSelection, nsIContent** aTargetNode) { *aTargetNode = nsnull; nsCOMPtr<nsISupports> container = aPresContext->GetContainer(); nsCOMPtr<nsIDOMWindow> window = do_GetInterface(container); + if (!window) + return; // GetDragData determines if a selection, link or image in the content // should be dragged, and places the data associated with the drag in the // data transfer. // mGestureDownContent is the node where the mousedown event for the drag // occurred, and aSelectionTarget is the node to use when a selection is used bool canDrag; nsCOMPtr<nsIContent> dragDataNode; @@ -3533,16 +3535,23 @@ nsEventStateManager::IsTargetCrossProces return false; return TabParent::GetIMETabParent() != nsnull; } void nsEventStateManager::NotifyDestroyPresContext(nsPresContext* aPresContext) { nsIMEStateManager::OnDestroyPresContext(aPresContext); + if (mHoverContent) { + // Bug 70855: Presentation is going away, possibly for a reframe. + // Reset the hover state so that if we're recreating the presentation, + // we won't have the old hover state still set in the new presentation, + // as if the new presentation is resized, a new element may be hovered. + SetContentState(nsnull, NS_EVENT_STATE_HOVER); + } } void nsEventStateManager::SetPresContext(nsPresContext* aPresContext) { mPresContext = aPresContext; }
--- a/content/events/test/test_eventctors.html +++ b/content/events/test/test_eventctors.html @@ -374,16 +374,24 @@ e = new DeviceProximityEvent("hello", {m ok(e.type, "hello", "Wrong event type!"); ok(!e.isTrusted, "Event should not be trusted"); is(e.value, 1, "value should be 1"); is(e.min, 0, "min should be 0"); is(e.max, 2, "max should be 2"); document.dispatchEvent(e); is(receivedEvent, e, "Wrong event!"); +// UserProximityEvent +e = new UserProximityEvent("hello", {near: true}); +ok(e.type, "hello", "Wrong event type!"); +ok(!e.isTrusted, "Event should not be trusted"); +is(e.near, true, "near should be true"); +document.dispatchEvent(e); +is(receivedEvent, e, "Wrong event!"); + // DeviceLightEvent e = new DeviceLightEvent("hello", {value: 1} ); ok(e.type, "hello", "Wrong event type!"); ok(!e.isTrusted, "Event should not be trusted"); is(e.value, 1, "value should be 1"); document.dispatchEvent(e); is(receivedEvent, e, "Wrong event!");
new file mode 100644 --- /dev/null +++ b/content/html/content/crashtests/616401.html @@ -0,0 +1,8 @@ +<!doctype html> +<script> +var c = document.createElement("canvas"); +c.getContext("experimental-webgl", { + get a() { throw 7; }, + get b() { throw 8; } +}); +</script>
--- a/content/html/content/crashtests/crashtests.list +++ b/content/html/content/crashtests/crashtests.list @@ -22,16 +22,17 @@ load 596785-1.html load 596785-2.html load 604807.html load 605264.html load 606430-1.html load 602117.html load 613027.html load 614279.html load 614988-1.html +load 616401.html load 620078-1.html load 620078-2.html load 680922-1.xul load 682058.xhtml load 682460.html load 673853.html load 738744.xhtml load 741250.xhtml
--- a/content/html/content/src/Makefile.in +++ b/content/html/content/src/Makefile.in @@ -144,13 +144,12 @@ INCLUDES += \ -I$(srcdir)/../../../../layout/style \ -I$(srcdir)/../../../../layout/tables \ -I$(srcdir)/../../../../layout/xul/base/src \ -I$(srcdir)/../../../../layout/generic \ -I$(srcdir)/../../../../dom/base \ -I$(srcdir)/../../../../editor/libeditor/base \ -I$(srcdir)/../../../../editor/libeditor/text \ -I$(srcdir) \ - -I$(topsrcdir)/js/xpconnect/src \ -I$(topsrcdir)/xpcom/ds \ $(NULL) DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -815,31 +815,31 @@ nsGenericHTMLElement::SetInnerHTML(const } return rv; } NS_IMETHODIMP nsGenericHTMLElement::SetOuterHTML(const nsAString& aOuterHTML) { - nsINode* parent = GetNodeParent(); + nsCOMPtr<nsINode> parent = GetNodeParent(); if (!parent) { return NS_OK; } if (parent->NodeType() == nsIDOMNode::DOCUMENT_NODE) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } if (OwnerDoc()->IsHTML()) { nsIAtom* localName; PRInt32 namespaceID; if (parent->IsElement()) { - localName = static_cast<nsIContent*>(parent)->Tag(); - namespaceID = static_cast<nsIContent*>(parent)->GetNameSpaceID(); + localName = static_cast<nsIContent*>(parent.get())->Tag(); + namespaceID = static_cast<nsIContent*>(parent.get())->GetNameSpaceID(); } else { NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE, "How come the parent isn't a document, a fragment or an element?"); localName = nsGkAtoms::body; namespaceID = kNameSpaceID_XHTML; } nsCOMPtr<nsIDOMDocumentFragment> df; nsresult rv = NS_NewDocumentFragment(getter_AddRefs(df),
--- a/content/html/content/src/nsHTMLCanvasElement.cpp +++ b/content/html/content/src/nsHTMLCanvasElement.cpp @@ -521,30 +521,29 @@ nsHTMLCanvasElement::GetContext(const ns return NS_ERROR_FAILURE; } // note: if any contexts end up supporting something other // than objects, e.g. plain strings, then we'll need to expand // this to know how to create nsISupportsStrings etc. nsCOMPtr<nsIWritablePropertyBag2> contextProps; - if (aContextOptions.isObject()) - { - JSContext *cx = nsContentUtils::GetCurrentJSContext(); + if (aContextOptions.isObject()) { + JSContext* cx = nsContentUtils::GetCurrentJSContext(); contextProps = do_CreateInstance("@mozilla.org/hash-property-bag;1"); - JSObject *opts = &aContextOptions.toObject(); - JS::AutoIdArray props(cx, JS_Enumerate(cx, opts)); + JSObject& opts = aContextOptions.toObject(); + JS::AutoIdArray props(cx, JS_Enumerate(cx, &opts)); for (size_t i = 0; !!props && i < props.length(); ++i) { jsid propid = props[i]; jsval propname, propval; if (!JS_IdToValue(cx, propid, &propname) || - !JS_GetPropertyById(cx, opts, propid, &propval)) { - continue; + !JS_GetPropertyById(cx, &opts, propid, &propval)) { + return NS_ERROR_FAILURE; } JSString *propnameString = JS_ValueToString(cx, propname); nsDependentJSString pstr; if (!propnameString || !pstr.init(cx, propnameString)) { mCurrentContext = nsnull; return NS_ERROR_FAILURE; }
--- a/content/html/content/src/nsHTMLFormElement.cpp +++ b/content/html/content/src/nsHTMLFormElement.cpp @@ -284,22 +284,19 @@ nsHTMLFormElement::Init() nsresult rv = mControls->Init(); if (NS_FAILED(rv)) { mControls = nsnull; return rv; } - NS_ENSURE_TRUE(mSelectedRadioButtons.Init(4), - NS_ERROR_OUT_OF_MEMORY); - NS_ENSURE_TRUE(mRequiredRadioButtonCounts.Init(4), - NS_ERROR_OUT_OF_MEMORY); - NS_ENSURE_TRUE(mValueMissingRadioGroups.Init(4), - NS_ERROR_OUT_OF_MEMORY); + mSelectedRadioButtons.Init(4); + mRequiredRadioButtonCounts.Init(4); + mValueMissingRadioGroups.Init(4); return NS_OK; } // nsISupports static PLDHashOperator @@ -1889,18 +1886,17 @@ nsHTMLFormElement::IndexOfControl(nsIFor PRInt32 index = nsnull; return mControls->IndexOfControl(aControl, &index) == NS_OK ? index : nsnull; } NS_IMETHODIMP nsHTMLFormElement::SetCurrentRadioButton(const nsAString& aName, nsIDOMHTMLInputElement* aRadio) { - NS_ENSURE_TRUE(mSelectedRadioButtons.Put(aName, aRadio), - NS_ERROR_OUT_OF_MEMORY); + mSelectedRadioButtons.Put(aName, aRadio); return NS_OK; } NS_IMETHODIMP nsHTMLFormElement::GetCurrentRadioButton(const nsAString& aName, nsIDOMHTMLInputElement** aRadio) { @@ -2139,20 +2135,17 @@ nsFormControlList::nsFormControlList(nsH nsFormControlList::~nsFormControlList() { mForm = nsnull; Clear(); } nsresult nsFormControlList::Init() { - NS_ENSURE_TRUE( - mNameLookupTable.Init(NS_FORM_CONTROL_LIST_HASHTABLE_SIZE), - NS_ERROR_OUT_OF_MEMORY); - + mNameLookupTable.Init(NS_FORM_CONTROL_LIST_HASHTABLE_SIZE); return NS_OK; } void nsFormControlList::DropFormReference() { mForm = nsnull; Clear(); @@ -2305,19 +2298,17 @@ nsFormControlList::AddElementToTable(nsG return NS_OK; } nsCOMPtr<nsISupports> supports; mNameLookupTable.Get(aName, getter_AddRefs(supports)); if (!supports) { // No entry found, add the form control - NS_ENSURE_TRUE(mNameLookupTable.Put(aName, - NS_ISUPPORTS_CAST(nsIContent*, aChild)), - NS_ERROR_FAILURE); + mNameLookupTable.Put(aName, NS_ISUPPORTS_CAST(nsIContent*, aChild)); } else { // Found something in the hash, check its type nsCOMPtr<nsIContent> content = do_QueryInterface(supports); if (content) { // Check if the new content is the same as the one we found in the // hash, if it is then we leave it in the hash as it is, this will // happen if a form control has both a name and an id with the same @@ -2340,18 +2331,17 @@ nsFormControlList::AddElementToTable(nsG list->AppendElement(newFirst ? aChild : content); list->AppendElement(newFirst ? content : aChild); nsCOMPtr<nsISupports> listSupports = do_QueryObject(list); // Replace the element with the list. - NS_ENSURE_TRUE(mNameLookupTable.Put(aName, listSupports), - NS_ERROR_FAILURE); + mNameLookupTable.Put(aName, listSupports); } else { // There's already a list in the hash, add the child to the list nsCOMPtr<nsIDOMNodeList> nodeList = do_QueryInterface(supports); NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE); // Upcast, uggly, but it works! nsSimpleContentList *list = static_cast<nsSimpleContentList*>(nodeList.get()); @@ -2450,17 +2440,17 @@ nsFormControlList::RemoveElementFromTabl // If the list is empty we remove if from our hash, this shouldn't // happen tho mNameLookupTable.Remove(aName); } else if (length == 1) { // Only one element left, replace the list in the hash with the // single element. nsIContent* node = list->GetNodeAt(0); if (node) { - NS_ENSURE_TRUE(mNameLookupTable.Put(aName, node),NS_ERROR_FAILURE); + mNameLookupTable.Put(aName, node); } } return NS_OK; } nsresult nsFormControlList::GetSortedControls(nsTArray<nsGenericHTMLFormElement*>& aControls) const
--- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -2189,16 +2189,20 @@ bool nsHTMLMediaElement::ShouldHandleMed #ifdef MOZ_OGG if (IsOggType(nsDependentCString(aMIMEType))) return true; #endif #ifdef MOZ_WEBM if (IsWebMType(nsDependentCString(aMIMEType))) return true; #endif +#ifdef MOZ_GSTREAMER + if (IsH264Type(nsDependentCString(aMIMEType))) + return true; +#endif // We should not return true for Wave types, since there are some // Wave codecs actually in use in the wild that we don't support, and // we should allow those to be handled by plugins or helper apps. // Furthermore people can play Wave files on most platforms by other // means. return false; }
--- a/content/html/content/src/nsTextEditorState.cpp +++ b/content/html/content/src/nsTextEditorState.cpp @@ -1858,17 +1858,17 @@ nsTextEditorState::SetValue(const nsAStr mTextListener->SettingValue(true); // Also don't enforce max-length here PRInt32 savedMaxLength; plaintextEditor->GetMaxTextLength(&savedMaxLength); plaintextEditor->SetMaxTextLength(-1); if (insertValue.IsEmpty()) { - mEditor->DeleteSelection(nsIEditor::eNone); + mEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip); } else { plaintextEditor->InsertText(insertValue); } mTextListener->SettingValue(false); if (!weakFrame.IsAlive()) { // If the frame was destroyed because of a flush somewhere inside
--- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -1349,17 +1349,26 @@ nsHTMLDocument::Open(const nsAString& aC NS_ParseContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy); if (!actualType.EqualsLiteral("text/html") && !type.EqualsLiteral("replace")) { contentType.AssignLiteral("text/plain"); } } // If we already have a parser we ignore the document.open call. - if (mParser) { + if (mParser || mParserAborted) { + // The WHATWG spec says: "If the document has an active parser that isn't + // a script-created parser, and the insertion point associated with that + // parser's input stream is not undefined (that is, it does point to + // somewhere in the input stream), then the method does nothing. Abort + // these steps and return the Document object on which the method was + // invoked." + // Note that aborting a parser leaves the parser "active" with its + // insertion point "not undefined". We track this using mParserAborted, + // because aborting a parser nulls out mParser. return NS_OK; } // No calling document.open() without a script global object if (!mScriptGlobalObject) { return NS_OK; } @@ -3072,16 +3081,25 @@ nsHTMLDocument::ExecCommand(const nsAStr { NS_ENSURE_ARG_POINTER(_retval); // for optional parameters see dom/src/base/nsHistory.cpp: HistoryImpl::Go() // this might add some ugly JS dependencies? *_retval = false; + nsCAutoString cmdToDispatch, paramStr; + bool isBool, boolVal; + if (!ConvertToMidasInternalCommand(commandID, value, + cmdToDispatch, paramStr, + isBool, boolVal)) { + // Return false + return NS_OK; + } + // if editing is not on, bail if (!IsEditingOnAfterFlush()) return NS_ERROR_FAILURE; // if they are requesting UI from us, let's fail since we have no UI if (doShowUI) return NS_OK; @@ -3105,22 +3123,16 @@ nsHTMLDocument::ExecCommand(const nsAStr GetMidasCommandManager(getter_AddRefs(cmdMgr)); if (!cmdMgr) return NS_ERROR_FAILURE; nsIDOMWindow *window = GetWindow(); if (!window) return NS_ERROR_FAILURE; - nsCAutoString cmdToDispatch, paramStr; - bool isBool, boolVal; - if (!ConvertToMidasInternalCommand(commandID, value, - cmdToDispatch, paramStr, isBool, boolVal)) - return NS_OK; - if ((cmdToDispatch.EqualsLiteral("cmd_paragraphState") || cmdToDispatch.EqualsLiteral("cmd_fontSize")) && paramStr.IsEmpty()) { // Invalid value return NS_OK; } if (!isBool && paramStr.IsEmpty()) { rv = cmdMgr->DoCommand(cmdToDispatch.get(), nsnull, window); @@ -3152,62 +3164,66 @@ nsHTMLDocument::ExecCommand(const nsAStr /* boolean queryCommandEnabled(in DOMString commandID); */ NS_IMETHODIMP nsHTMLDocument::QueryCommandEnabled(const nsAString & commandID, bool *_retval) { NS_ENSURE_ARG_POINTER(_retval); *_retval = false; - // if editing is not on, bail - if (!IsEditingOnAfterFlush()) - return NS_ERROR_FAILURE; - - // get command manager and dispatch command to our window if it's acceptable - nsCOMPtr<nsICommandManager> cmdMgr; - GetMidasCommandManager(getter_AddRefs(cmdMgr)); - if (!cmdMgr) - return NS_ERROR_FAILURE; - - nsIDOMWindow *window = GetWindow(); - if (!window) - return NS_ERROR_FAILURE; - nsCAutoString cmdToDispatch; - if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) - return NS_OK; // queryCommandEnabled returns false on unsupported commands - - return cmdMgr->IsCommandEnabled(cmdToDispatch.get(), window, _retval); -} - -/* boolean queryCommandIndeterm (in DOMString commandID); */ -NS_IMETHODIMP -nsHTMLDocument::QueryCommandIndeterm(const nsAString & commandID, - bool *_retval) -{ - NS_ENSURE_ARG_POINTER(_retval); - *_retval = false; + if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) { + // Return false + return NS_OK; + } // if editing is not on, bail if (!IsEditingOnAfterFlush()) return NS_ERROR_FAILURE; // get command manager and dispatch command to our window if it's acceptable nsCOMPtr<nsICommandManager> cmdMgr; GetMidasCommandManager(getter_AddRefs(cmdMgr)); if (!cmdMgr) return NS_ERROR_FAILURE; nsIDOMWindow *window = GetWindow(); if (!window) return NS_ERROR_FAILURE; + return cmdMgr->IsCommandEnabled(cmdToDispatch.get(), window, _retval); +} + +/* boolean queryCommandIndeterm (in DOMString commandID); */ +NS_IMETHODIMP +nsHTMLDocument::QueryCommandIndeterm(const nsAString & commandID, + bool *_retval) +{ + NS_ENSURE_ARG_POINTER(_retval); + *_retval = false; + nsCAutoString cmdToDispatch; - if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) - return NS_ERROR_NOT_IMPLEMENTED; + if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) { + // Return false + return NS_OK; + } + + // if editing is not on, bail + if (!IsEditingOnAfterFlush()) + return NS_ERROR_FAILURE; + + // get command manager and dispatch command to our window if it's acceptable + nsCOMPtr<nsICommandManager> cmdMgr; + GetMidasCommandManager(getter_AddRefs(cmdMgr)); + if (!cmdMgr) + return NS_ERROR_FAILURE; + + nsIDOMWindow *window = GetWindow(); + if (!window) + return NS_ERROR_FAILURE; nsresult rv; nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance( NS_COMMAND_PARAMS_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, cmdParams); if (NS_FAILED(rv)) @@ -3222,16 +3238,25 @@ nsHTMLDocument::QueryCommandIndeterm(con /* boolean queryCommandState(in DOMString commandID); */ NS_IMETHODIMP nsHTMLDocument::QueryCommandState(const nsAString & commandID, bool *_retval) { NS_ENSURE_ARG_POINTER(_retval); *_retval = false; + nsCAutoString cmdToDispatch, paramToCheck; + bool dummy, dummy2; + if (!ConvertToMidasInternalCommand(commandID, commandID, + cmdToDispatch, paramToCheck, + dummy, dummy2)) { + // Return false + return NS_OK; + } + // if editing is not on, bail if (!IsEditingOnAfterFlush()) return NS_ERROR_FAILURE; // get command manager and dispatch command to our window if it's acceptable nsCOMPtr<nsICommandManager> cmdMgr; GetMidasCommandManager(getter_AddRefs(cmdMgr)); if (!cmdMgr) @@ -3243,22 +3268,16 @@ nsHTMLDocument::QueryCommandState(const if (commandID.LowerCaseEqualsLiteral("usecss")) { // Per spec, state is supported for styleWithCSS but not useCSS, so we just // return false always. *_retval = false; return NS_OK; } - nsCAutoString cmdToDispatch, paramToCheck; - bool dummy, dummy2; - if (!ConvertToMidasInternalCommand(commandID, commandID, - cmdToDispatch, paramToCheck, dummy, dummy2)) - return NS_ERROR_NOT_IMPLEMENTED; - nsresult rv; nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance( NS_COMMAND_PARAMS_CONTRACTID, &rv); if (!cmdParams) return NS_ERROR_OUT_OF_MEMORY; rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, cmdParams); if (NS_FAILED(rv)) @@ -3289,61 +3308,51 @@ nsHTMLDocument::QueryCommandState(const } /* boolean queryCommandSupported(in DOMString commandID); */ NS_IMETHODIMP nsHTMLDocument::QueryCommandSupported(const nsAString & commandID, bool *_retval) { NS_ENSURE_ARG_POINTER(_retval); - *_retval = false; - - // if editing is not on, bail - if (!IsEditingOnAfterFlush()) - return NS_ERROR_FAILURE; - - // get command manager - nsCOMPtr<nsICommandManager> cmdMgr; - GetMidasCommandManager(getter_AddRefs(cmdMgr)); - if (!cmdMgr) - return NS_ERROR_FAILURE; // commandID is supported if it can be converted to a Midas command nsCAutoString cmdToDispatch; - if (ConvertToMidasInternalCommand(commandID, cmdToDispatch)) - *_retval = true; + *_retval = ConvertToMidasInternalCommand(commandID, cmdToDispatch); return NS_OK; } /* DOMString queryCommandValue(in DOMString commandID); */ NS_IMETHODIMP nsHTMLDocument::QueryCommandValue(const nsAString & commandID, nsAString &_retval) { _retval.SetLength(0); + nsCAutoString cmdToDispatch, paramStr; + if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) { + // Return empty string + return NS_OK; + } + // if editing is not on, bail if (!IsEditingOnAfterFlush()) return NS_ERROR_FAILURE; // get command manager and dispatch command to our window if it's acceptable nsCOMPtr<nsICommandManager> cmdMgr; GetMidasCommandManager(getter_AddRefs(cmdMgr)); if (!cmdMgr) return NS_ERROR_FAILURE; nsIDOMWindow *window = GetWindow(); if (!window) return NS_ERROR_FAILURE; - nsCAutoString cmdToDispatch, paramStr; - if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) - return NS_ERROR_NOT_IMPLEMENTED; - // create params nsresult rv; nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance( NS_COMMAND_PARAMS_CONTRACTID, &rv); if (!cmdParams) return NS_ERROR_OUT_OF_MEMORY; // this is a special command since we are calling "DoCommand rather than
--- a/content/media/AudioSegment.h +++ b/content/media/AudioSegment.h @@ -118,16 +118,17 @@ public: } void ApplyVolume(float aVolume); /** * aOutput must have a matching number of channels, but we will automatically * convert sample formats. */ void WriteTo(nsAudioStream* aOutput); + using MediaSegmentBase<AudioSegment, AudioChunk>::AppendFrom; void AppendFrom(AudioSegment* aSource) { NS_ASSERTION(aSource->mChannels == mChannels, "Non-matching channels"); MediaSegmentBase<AudioSegment, AudioChunk>::AppendFrom(aSource); } // Segment-generic methods not in MediaSegmentBase void InitFrom(const AudioSegment& aOther)
--- a/content/media/gstreamer/nsGStreamerReader.h +++ b/content/media/gstreamer/nsGStreamerReader.h @@ -29,16 +29,20 @@ public: PRInt64 aTimeThreshold); virtual nsresult ReadMetadata(nsVideoInfo* aInfo); virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime); virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime); + virtual bool IsSeekableInBufferedRanges() { + return true; + } + virtual bool HasAudio() { return mInfo.mHasAudio; } virtual bool HasVideo() { return mInfo.mHasVideo; }
--- a/content/media/nsBuiltinDecoder.cpp +++ b/content/media/nsBuiltinDecoder.cpp @@ -980,17 +980,23 @@ nsresult nsBuiltinDecoder::GetSeekable(n if (IsSeekable()) { double end = IsInfinite() ? std::numeric_limits<double>::infinity() : initialTime + GetDuration(); aSeekable->Add(initialTime, end); return NS_OK; } - return GetBuffered(aSeekable); + if (mDecoderStateMachine->IsSeekableInBufferedRanges()) { + return GetBuffered(aSeekable); + } else { + // The stream is not seekable using only buffered ranges, and is not + // seekable. Don't allow seeking (return no ranges in |seekable|). + return NS_OK; + } } void nsBuiltinDecoder::SetEndTime(double aTime) { NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mDecoderStateMachine) { ReentrantMonitorAutoEnter mon(mReentrantMonitor); mDecoderStateMachine->SetFragmentEndTime(static_cast<PRInt64>(aTime * USECS_PER_S));
--- a/content/media/nsBuiltinDecoder.h +++ b/content/media/nsBuiltinDecoder.h @@ -326,16 +326,19 @@ public: // and an invalidate of the frame being dispatched asynchronously if // there is no such event currently queued. // Only called on the decoder thread. Must be called with // the decode monitor held. virtual void UpdatePlaybackPosition(PRInt64 aTime) = 0; virtual nsresult GetBuffered(nsTimeRanges* aBuffered) = 0; + // Return true if the media is seekable using only buffered ranges. + virtual bool IsSeekableInBufferedRanges() = 0; + virtual PRInt64 VideoQueueMemoryInUse() = 0; virtual PRInt64 AudioQueueMemoryInUse() = 0; virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset) = 0; // Causes the state machine to switch to buffering state, and to // immediately stop playback and buffer downloaded data. Must be called // with the decode monitor held. Called on the state machine thread and
--- a/content/media/nsBuiltinDecoderReader.h +++ b/content/media/nsBuiltinDecoderReader.h @@ -475,16 +475,19 @@ public: // Populates aBuffered with the time ranges which are buffered. aStartTime // must be the presentation time of the first frame in the media, e.g. // the media time corresponding to playback time/position 0. This function // should only be called on the main thread. virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime) = 0; + // True if we can seek using only buffered ranges. This is backend dependant. + virtual bool IsSeekableInBufferedRanges() = 0; + class VideoQueueMemoryFunctor : public nsDequeFunctor { public: VideoQueueMemoryFunctor() : mResult(0) {} virtual void* operator()(void* anObject) { const VideoData* v = static_cast<const VideoData*>(anObject); if (!v->mImage) { return nsnull;
--- a/content/media/nsBuiltinDecoderStateMachine.cpp +++ b/content/media/nsBuiltinDecoderStateMachine.cpp @@ -431,19 +431,19 @@ nsBuiltinDecoderStateMachine::nsBuiltinD mDecodeThreadIdle(false), mStopAudioThread(true), mQuickBuffering(false), mIsRunning(false), mRunAgain(false), mDispatchedRunEvent(false), mDecodeThreadWaiting(false), mRealTime(aRealTime), - mRequestedNewDecodeThread(false), mDidThrottleAudioDecoding(false), mDidThrottleVideoDecoding(false), + mRequestedNewDecodeThread(false), mEventManager(aDecoder) { MOZ_COUNT_CTOR(nsBuiltinDecoderStateMachine); NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); StateMachineTracker::Instance().EnsureGlobalStateMachine(); // only enable realtime mode when "media.realtime_decoder.enabled" is true. @@ -534,17 +534,17 @@ void nsBuiltinDecoderStateMachine::SendO if (aAudio->mTime <= aStream->mLastAudioPacketTime) { // ignore packet that we've already processed return; } aStream->mLastAudioPacketTime = aAudio->mTime; aStream->mLastAudioPacketEndTime = aAudio->GetEnd(); - NS_ASSERTION(aOutput->GetChannels() == aAudio->mChannels, + NS_ASSERTION(aOutput->GetChannels() == PRInt32(aAudio->mChannels), "Wrong number of channels"); // This logic has to mimic AudioLoop closely to make sure we write // the exact same silences CheckedInt64 audioWrittenOffset = UsecsToFrames(mInfo.mAudioRate, aStream->mAudioFramesWrittenBaseTime + mStartTime) + aStream->mAudioFramesWritten; CheckedInt64 frameOffset = UsecsToFrames(mInfo.mAudioRate, aAudio->mTime); if (!audioWrittenOffset.isValid() || !frameOffset.isValid()) @@ -630,17 +630,16 @@ void nsBuiltinDecoderStateMachine::SendO if (mInfo.mHasAudio) { nsAutoTArray<AudioData*,10> audio; // It's OK to hold references to the AudioData because while audio // is captured, only the decoder thread pops from the queue (see below). mReader->mAudioQueue.GetElementsAfter(stream->mLastAudioPacketTime, &audio); AudioSegment output; output.Init(mInfo.mAudioChannels); for (PRUint32 i = 0; i < audio.Length(); ++i) { - AudioData* a = audio[i]; SendOutputStreamAudio(audio[i], stream, &output); } if (output.GetDuration() > 0) { mediaStream->AppendToTrack(TRACK_AUDIO, &output); } if (mReader->mAudioQueue.IsFinished() && !stream->mHaveSentFinishAudio) { mediaStream->EndTrack(TRACK_AUDIO); stream->mHaveSentFinishAudio = true; @@ -1121,18 +1120,17 @@ void nsBuiltinDecoderStateMachine::Audio } PRInt64 framesWritten = 0; if (missingFrames.value() > 0) { // The next audio chunk begins some time after the end of the last chunk // we pushed to the audio hardware. We must push silence into the audio // hardware so that the next audio chunk begins playback at the correct // time. - missingFrames = NS_MIN(static_cast<PRInt64>(PR_UINT32_MAX), - missingFrames.value()); + missingFrames = NS_MIN<int64_t>(UINT32_MAX, missingFrames.value()); LOG(PR_LOG_DEBUG, ("%p Decoder playing %d frames of silence", mDecoder.get(), PRInt32(missingFrames.value()))); framesWritten = PlaySilence(static_cast<PRUint32>(missingFrames.value()), channels, playedFrames.value()); } else { framesWritten = PlayFromAudioQueue(sampleTime.value(), channels); } audioDuration += framesWritten;
--- a/content/media/nsBuiltinDecoderStateMachine.h +++ b/content/media/nsBuiltinDecoderStateMachine.h @@ -238,16 +238,23 @@ public: return mEndTime; } bool IsSeekable() { mDecoder->GetReentrantMonitor().AssertCurrentThreadIn(); return mSeekable; } + bool IsSeekableInBufferedRanges() { + if (mReader) { + return mReader->IsSeekableInBufferedRanges(); + } + return false; + } + // Sets the current frame buffer length for the MozAudioAvailable event. // Accessed on the main and state machine threads. virtual void SetFrameBufferLength(PRUint32 aLength); // Returns the shared state machine thread. static nsIThread* GetStateMachineThread(); // Schedules the shared state machine thread to run the state machine.
--- a/content/media/ogg/nsOggCodecState.cpp +++ b/content/media/ogg/nsOggCodecState.cpp @@ -40,16 +40,19 @@ #include "nsOggCodecState.h" #include "nsOggDecoder.h" #include <string.h> #include "nsTraceRefcnt.h" #include "VideoUtils.h" #include "nsBuiltinDecoderReader.h" #include "mozilla/StandardInteger.h" +#include "mozilla/Util.h" // DebugOnly + +using namespace mozilla; #ifdef PR_LOGGING extern PRLogModuleInfo* gBuiltinDecoderLog; #define LOG(type, msg) PR_LOG(gBuiltinDecoderLog, type, msg) #else #define LOG(type, msg) #endif @@ -916,17 +919,17 @@ nsresult nsOpusState::PageIn(ogg_page* a } mUnstamped.Clear(); return NS_OK; } void nsOpusState::ReconstructGranulepos(void) { NS_ASSERTION(mUnstamped.Length() > 0, "Must have unstamped packets"); - ogg_packet* last = mUnstamped[mUnstamped.Length()-1]; + DebugOnly<ogg_packet*> last = mUnstamped[mUnstamped.Length()-1]; NS_ASSERTION(last->e_o_s || last->granulepos > 0, "Must know last granulepos!"); // Loop through the packets backwards, subtracting the next // packet's duration from its granulepos to get the value // for the current packet. for (PRUint32 i = mUnstamped.Length() - 1; i > 0; i--) { ogg_packet* next = mUnstamped[i]; @@ -1255,22 +1258,17 @@ bool nsSkeletonState::DecodeHeader(ogg_p } // Extract the segment length. mLength = LEInt64(aPacket->packet + SKELETON_FILE_LENGTH_OFFSET); LOG(PR_LOG_DEBUG, ("Skeleton segment length: %lld", mLength)); // Initialize the serianlno-to-index map. - bool init = mIndex.Init(); - if (!init) { - NS_WARNING("Failed to initialize Ogg skeleton serialno-to-index map"); - mActive = false; - return mDoneReadingHeaders = true; - } + mIndex.Init(); mActive = true; } else if (IsSkeletonIndex(aPacket) && mVersion >= SKELETON_VERSION(4,0)) { if (!DecodeIndex(aPacket)) { // Failed to parse index, or invalid/hostile index. DecodeIndex() will // have deactivated the track. return mDoneReadingHeaders = true; }
--- a/content/media/ogg/nsOggReader.cpp +++ b/content/media/ogg/nsOggReader.cpp @@ -121,21 +121,17 @@ nsOggReader::nsOggReader(nsBuiltinDecode nsOggReader::~nsOggReader() { ogg_sync_clear(&mOggState); MOZ_COUNT_DTOR(nsOggReader); } nsresult nsOggReader::Init(nsBuiltinDecoderReader* aCloneDonor) { - bool init = mCodecStates.Init(); - NS_ASSERTION(init, "Failed to initialize mCodecStates"); - if (!init) { - return NS_ERROR_FAILURE; - } + mCodecStates.Init(); int ret = ogg_sync_init(&mOggState); NS_ENSURE_TRUE(ret == 0, NS_ERROR_FAILURE); return NS_OK; } nsresult nsOggReader::ResetDecode() { NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); @@ -200,18 +196,17 @@ nsresult nsOggReader::ReadMetadata(nsVid // can follow in this Ogg segment, so there will be no other bitstreams // in the Ogg (unless it's invalid). readAllBOS = true; } else if (!mCodecStates.Get(serial, nsnull)) { // We've not encountered a stream with this serial number before. Create // an nsOggCodecState to demux it, and map that to the nsOggCodecState // in mCodecStates. codecState = nsOggCodecState::Create(&page); - DebugOnly<bool> r = mCodecStates.Put(serial, codecState); - NS_ASSERTION(r, "Failed to insert into mCodecStates"); + mCodecStates.Put(serial, codecState); bitstreams.AppendElement(codecState); mKnownStreams.AppendElement(serial); if (codecState && codecState->GetType() == nsOggCodecState::TYPE_VORBIS && !mVorbisState) { // First Vorbis bitstream, we'll play this one. Subsequent Vorbis // bitstreams will be ignored. @@ -446,17 +441,17 @@ nsresult nsOggReader::DecodeOpus(ogg_pac // Trim the initial samples. if (endTime < 0) return NS_OK; if (startTime < 0) { PRInt32 skip = mOpusState->mPreSkip; PRInt32 goodFrames = frames - skip; NS_ASSERTION(goodFrames > 0, "endTime calculation was wrong"); nsAutoArrayPtr<AudioDataValue> goodBuffer(new AudioDataValue[goodFrames * channels]); - for (int i = 0; i < goodFrames*channels; i++) + for (PRInt32 i = 0; i < goodFrames * PRInt32(channels); i++) goodBuffer[i] = buffer[skip*channels + i]; startTime = mOpusState->Time(endFrame - goodFrames); duration = endTime - startTime; frames = goodFrames; buffer = goodBuffer; }
--- a/content/media/ogg/nsOggReader.h +++ b/content/media/ogg/nsOggReader.h @@ -79,16 +79,21 @@ public: virtual bool HasVideo() { return mTheoraState != 0 && mTheoraState->mActive; } virtual nsresult ReadMetadata(nsVideoInfo* aInfo); virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime); virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime); + // We use bisection to seek in buffered range. + virtual bool IsSeekableInBufferedRanges() { + return true; + } + private: bool HasSkeleton() { return mSkeletonState != 0 && mSkeletonState->mActive; } // Seeks to the keyframe preceeding the target time using available // keyframe indexes.
--- a/content/media/raw/Makefile.in +++ b/content/media/raw/Makefile.in @@ -31,37 +31,37 @@ # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** -DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk -MODULE = content -LIBRARY_NAME = gkconraw_s -LIBXUL_LIBRARY = 1 +MODULE = content +LIBRARY_NAME = gkconraw_s +LIBXUL_LIBRARY = 1 -EXPORTS += \ - nsRawDecoder.h \ - nsRawReader.h \ - nsRawStructs.h \ - $(NULL) +EXPORTS += \ + nsRawDecoder.h \ + nsRawReader.h \ + nsRawStructs.h \ + $(NULL) -CPPSRCS += \ - nsRawDecoder.cpp \ - nsRawReader.cpp \ - $(NULL) +CPPSRCS += \ + nsRawDecoder.cpp \ + nsRawReader.cpp \ + $(NULL) FORCE_STATIC_LIB = 1 include $(topsrcdir)/config/rules.mk INCLUDES += \ -I$(srcdir)/../../base/src \ -I$(srcdir)/../../html/content/src \
--- a/content/media/raw/nsRawReader.h +++ b/content/media/raw/nsRawReader.h @@ -65,16 +65,21 @@ public: { return true; } virtual nsresult ReadMetadata(nsVideoInfo* aInfo); virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime); virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime); + // By seeking in the media resource, it is possible to seek. + bool IsSeekableInBufferedRanges() { + return true; + } + private: bool ReadFromResource(MediaResource *aResource, PRUint8 *aBuf, PRUint32 aLength); nsRawVideoHeader mMetadata; PRUint32 mCurrentFrame; double mFrameRate; PRUint32 mFrameSize; nsIntRect mPicture;
--- a/content/media/wave/nsWaveReader.h +++ b/content/media/wave/nsWaveReader.h @@ -63,16 +63,21 @@ public: { return false; } virtual nsresult ReadMetadata(nsVideoInfo* aInfo); virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime); virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime); + // To seek in a buffered range, we just have to seek the stream. + virtual bool IsSeekableInBufferedRanges() { + return true; + } + private: bool ReadAll(char* aBuf, PRInt64 aSize, PRInt64* aBytesRead = nsnull); bool LoadRIFFChunk(); bool ScanForwardUntil(PRUint32 aWantedChunk, PRUint32* aChunkSize); bool LoadFormatChunk(); bool FindDataOffset(); // Returns the number of seconds that aBytes represents based on the
--- a/content/media/webm/nsWebMReader.h +++ b/content/media/webm/nsWebMReader.h @@ -151,16 +151,21 @@ public: } virtual bool HasVideo() { NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); return mHasVideo; } + // Bug 575140, cannot seek in webm if no cue is present. + bool IsSeekableInBufferedRanges() { + return false; + } + virtual nsresult ReadMetadata(nsVideoInfo* aInfo); virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime); virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime); virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset); private: // Value passed to NextPacket to determine if we are reading a video or an // audio packet.
--- a/content/smil/nsSMILAnimationFunction.cpp +++ b/content/smil/nsSMILAnimationFunction.cpp @@ -210,26 +210,24 @@ nsSMILAnimationFunction::SampleLastValue } void nsSMILAnimationFunction::Activate(nsSMILTime aBeginTime) { mBeginTime = aBeginTime; mIsActive = true; mIsFrozen = false; - mFrozenValue = nsSMILValue(); mHasChanged = true; } void nsSMILAnimationFunction::Inactivate(bool aIsFrozen) { mIsActive = false; mIsFrozen = aIsFrozen; - mFrozenValue = nsSMILValue(); mHasChanged = true; } void nsSMILAnimationFunction::ComposeResult(const nsISMILAttr& aSMILAttr, nsSMILValue& aResult) { mHasChanged = false; @@ -281,33 +279,24 @@ nsSMILAnimationFunction::ComposeResult(c // See comment in AccumulateResult: to-animation does not accumulate if (!IsToAnimation() && GetAccumulate() && mRepeatIteration) { // If the target attribute type doesn't support addition Add will // fail leaving result = last result.Add(last, mRepeatIteration); } - } else if (!mFrozenValue.IsNull() && !mHasChanged) { - - // Frozen to animation - result = mFrozenValue; - } else { // Interpolation if (NS_FAILED(InterpolateResult(values, result, aResult))) return; if (NS_FAILED(AccumulateResult(values, result))) return; - - if (IsToAnimation() && mIsFrozen) { - mFrozenValue = result; - } } // If additive animation isn't required or isn't supported, set the value. if (!isAdditive || NS_FAILED(aResult.SandwichAdd(result))) { aResult.Swap(result); // Note: The old value of aResult is now in |result|, and it will get // cleaned up when |result| goes out of scope, when this function returns. } @@ -354,32 +343,32 @@ nsSMILAnimationFunction::CompareTo(const ? -1 : 1; } bool nsSMILAnimationFunction::WillReplace() const { /* * In IsAdditive() we don't consider to-animation to be additive as it is - * a special case that is dealt with differently in the compositing method but - * here we return false for to animation as it builds on the underlying value - * unless its a frozen to animation. + * a special case that is dealt with differently in the compositing method. + * Here, however, we return FALSE for to-animation (i.e. it will NOT replace + * the underlying value) as it builds on the underlying value. */ - return !mErrorFlags && (!(IsAdditive() || IsToAnimation()) || - (IsToAnimation() && mIsFrozen && !mHasChanged)); + return !mErrorFlags && !(IsAdditive() || IsToAnimation()); } bool nsSMILAnimationFunction::HasChanged() const { return mHasChanged || mValueNeedsReparsingEverySample; } bool -nsSMILAnimationFunction::UpdateCachedTarget(const nsSMILTargetIdentifier& aNewTarget) +nsSMILAnimationFunction::UpdateCachedTarget( + const nsSMILTargetIdentifier& aNewTarget) { if (!mLastTarget.Equals(aNewTarget)) { mLastTarget = aNewTarget; return true; } return false; } @@ -509,18 +498,17 @@ nsSMILAnimationFunction::InterpolateResu } return rv; } nsresult nsSMILAnimationFunction::AccumulateResult(const nsSMILValueArray& aValues, nsSMILValue& aResult) { - if (!IsToAnimation() && GetAccumulate() && mRepeatIteration) - { + if (!IsToAnimation() && GetAccumulate() && mRepeatIteration) { const nsSMILValue& lastValue = aValues[aValues.Length() - 1]; // If the target attribute type doesn't support addition, Add will // fail and we leave aResult untouched. aResult.Add(lastValue, mRepeatIteration); } return NS_OK; @@ -814,17 +802,17 @@ nsSMILAnimationFunction::GetValues(const bool parseOk = true; nsSMILValue to, from, by; parseOk &= ParseAttr(nsGkAtoms::to, aSMILAttr, to, preventCachingOfSandwich); parseOk &= ParseAttr(nsGkAtoms::from, aSMILAttr, from, preventCachingOfSandwich); parseOk &= ParseAttr(nsGkAtoms::by, aSMILAttr, by, preventCachingOfSandwich); - + if (preventCachingOfSandwich) { mValueNeedsReparsingEverySample = true; } if (!parseOk) return NS_ERROR_FAILURE; result.SetCapacity(2);
--- a/content/smil/nsSMILAnimationFunction.h +++ b/content/smil/nsSMILAnimationFunction.h @@ -448,41 +448,16 @@ protected: // its owning animation element. nsISMILAnimationElement* mAnimationElement; // Which attributes have been set but have had errors. This is not used for // all attributes but only those which have specified error behaviour // associated with them. PRUint16 mErrorFlags; - // This is for the very specific case where we have a 'to' animation that is - // frozen part way through the simple duration and there are other active - // lower-priority animations targetting the same attribute. In this case - // SMILANIM 3.3.6 says: - // - // The value for F(t) when a to-animation is frozen (at the end of the - // simple duration) is just the to value. If a to-animation is frozen - // anywhere within the simple duration (e.g., using a repeatCount of "2.5"), - // the value for F(t) when the animation is frozen is the value computed for - // the end of the active duration. Even if other, lower priority animations - // are active while a to-animation is frozen, the value for F(t) does not - // change. - // - // To implement this properly we'd need to force a resample of all the lower - // priority animations at the active end of this animation--something which - // would introduce unwanted coupling between the timing and animation model. - // Instead we just save the value calculated when this animation is frozen (in - // which case this animation will be sampled at the active end and the lower - // priority animations should be sampled at a time pretty close to this, - // provided we have a reasonable frame rate and we aren't seeking). - // - // @see - // http://www.w3.org/TR/2001/REC-smil-animation-20010904/#FromToByAndAdditive - nsSMILValue mFrozenValue; - // Allows us to check whether an animation function has changed target from // sample to sample (because if neither target nor animated value have // changed, we don't have to do anything). nsSMILWeakTargetIdentifier mLastTarget; // Boolean flags bool mIsActive:1; bool mIsFrozen:1;
--- a/content/smil/nsSMILCSSProperty.cpp +++ b/content/smil/nsSMILCSSProperty.cpp @@ -276,16 +276,17 @@ nsSMILCSSProperty::IsPropertyAnimatable( case eCSSProperty_stroke_miterlimit: case eCSSProperty_stroke_opacity: case eCSSProperty_stroke_width: case eCSSProperty_text_anchor: case eCSSProperty_text_blink: case eCSSProperty_text_decoration: case eCSSProperty_text_decoration_line: case eCSSProperty_text_rendering: + case eCSSProperty_vector_effect: case eCSSProperty_visibility: case eCSSProperty_word_spacing: return true; // EXPLICITLY NON-ANIMATABLE PROPERTIES: // (Some of these aren't supported at all in Gecko -- I've commented those // ones out. If/when we add support for them, uncomment their line here) // ----------------------------------------------------------------------
--- a/content/smil/nsSMILTimedElement.cpp +++ b/content/smil/nsSMILTimedElement.cpp @@ -350,16 +350,33 @@ nsSMILTimeValue nsSMILTimedElement::GetStartTime() const { return mElementState == STATE_WAITING || mElementState == STATE_ACTIVE ? mCurrentInterval->Begin()->Time() : nsSMILTimeValue(); } //---------------------------------------------------------------------- +// Hyperlinking support + +nsSMILTimeValue +nsSMILTimedElement::GetHyperlinkTime() const +{ + nsSMILTimeValue hyperlinkTime; // Default ctor creates unresolved time + + if (mElementState == STATE_ACTIVE) { + hyperlinkTime = mCurrentInterval->Begin()->Time(); + } else if (!mBeginInstances.IsEmpty()) { + hyperlinkTime = mBeginInstances[0]->Time(); + } + + return hyperlinkTime; +} + +//---------------------------------------------------------------------- // nsSMILTimedElement void nsSMILTimedElement::AddInstanceTime(nsSMILInstanceTime* aInstanceTime, bool aIsBegin) { NS_ABORT_IF_FALSE(aInstanceTime, "Attempting to add null instance time"); @@ -1487,39 +1504,50 @@ nsSMILTimedElement::FilterHistory() } void nsSMILTimedElement::FilterIntervals() { // We can filter old intervals that: // // a) are not the previous interval; AND - // b) are not in the middle of a dependency chain + // b) are not in the middle of a dependency chain; AND + // c) are not the first interval // // Condition (a) is necessary since the previous interval is used for applying // fill effects and updating the current interval. // // Condition (b) is necessary since even if this interval itself is not // active, it may be part of a dependency chain that includes active // intervals. Such chains are used to establish priorities within the // animation sandwich. // + // Condition (c) is necessary to support hyperlinks that target animations + // since in some cases the defined behavior is to seek the document back to + // the first resolved begin time. Presumably the intention here is not + // actually to use the first resolved begin time, the + // _the_first_resolved_begin_time_that_produced_an_interval. That is, + // if we have begin="-5s; -3s; 1s; 3s" with a duration on 1s, we should seek + // to 1s. The spec doesn't say this but I'm pretty sure that is the intention. + // It seems negative times were simply not considered. + // // Although the above conditions allow us to safely filter intervals for most // scenarios they do not cover all cases and there will still be scenarios // that generate intervals indefinitely. In such a case we simply set // a maximum number of intervals and drop any intervals beyond that threshold. PRUint32 threshold = mOldIntervals.Length() > sMaxNumIntervals ? mOldIntervals.Length() - sMaxNumIntervals : 0; IntervalList filteredList; for (PRUint32 i = 0; i < mOldIntervals.Length(); ++i) { nsSMILInterval* interval = mOldIntervals[i].get(); - if (i + 1 < mOldIntervals.Length() /*skip previous interval*/ && + if (i != 0 && /*skip first interval*/ + i + 1 < mOldIntervals.Length() && /*skip previous interval*/ (i < threshold || !interval->IsDependencyChainLink())) { interval->Unlink(true /*filtered, not deleted*/); } else { filteredList.AppendElement(mOldIntervals[i].forget()); } } mOldIntervals.Clear(); mOldIntervals.SwapElements(filteredList); @@ -1579,24 +1607,28 @@ nsSMILTimedElement::FilterInstanceTimes( // they're unpredictable due to the possibility of seeking the document which // may prevent some events from being generated). Therefore we introduce // a hard cutoff at which point we just drop the oldest instance times. if (aList.Length() > sMaxNumInstanceTimes) { PRUint32 threshold = aList.Length() - sMaxNumInstanceTimes; // There are a few instance times we should keep though, notably: // - the current interval begin time, // - the previous interval end time (see note in RemoveInstanceTimes) + // - the first interval begin time (see note in FilterIntervals) nsTArray<const nsSMILInstanceTime *> timesToKeep; if (mCurrentInterval) { timesToKeep.AppendElement(mCurrentInterval->Begin()); } const nsSMILInterval* prevInterval = GetPreviousInterval(); if (prevInterval) { timesToKeep.AppendElement(prevInterval->End()); } + if (!mOldIntervals.IsEmpty()) { + timesToKeep.AppendElement(mOldIntervals[0]->Begin()); + } RemoveBelowThreshold removeBelowThreshold(threshold, timesToKeep); RemoveInstanceTimes(aList, removeBelowThreshold); } } // // This method is based on the pseudocode given in the SMILANIM spec. //
--- a/content/smil/nsSMILTimedElement.h +++ b/content/smil/nsSMILTimedElement.h @@ -135,20 +135,39 @@ public: * @return the simple duration in milliseconds or INDEFINITE. */ nsSMILTimeValue GetSimpleDuration() const { return mSimpleDur; } /** + * Methods for supporting hyperlinking + */ + + /** * Internal SMIL methods */ /** + * Returns the time to seek the document to when this element is targetted by + * a hyperlink. + * + * The behavior is defined here: + * http://www.w3.org/TR/smil-animation/#HyperlinkSemantics + * + * It is very similar to GetStartTime() with the exception that when the + * element is not active, the begin time of the *first* interval is returned. + * + * @return the time to seek the documen to in milliseconds or an unresolved + * time if there is no resolved interval. + */ + nsSMILTimeValue GetHyperlinkTime() const; + + /** * Adds an instance time object this element's list of instance times. * These instance times are used when creating intervals. * * This method is typically called by an nsSMILTimeValueSpec. * * @param aInstanceTime The time to add, expressed in container time. * @param aIsBegin true if the time to be added represents a begin * time or false if it represents an end time.
--- a/content/smil/test/Makefile.in +++ b/content/smil/test/Makefile.in @@ -73,16 +73,17 @@ include $(topsrcdir)/config/rules.mk test_smilMappedAttrFromBy.xhtml \ test_smilMappedAttrPaced.xhtml \ test_smilReset.xhtml \ test_smilRestart.xhtml \ test_smilExtDoc.xhtml \ test_smilFillMode.xhtml \ test_smilGetStartTime.xhtml \ test_smilGetSimpleDuration.xhtml \ + test_smilHyperlinking.xhtml \ test_smilKeySplines.xhtml \ test_smilKeyTimes.xhtml \ test_smilKeyTimesPacedMode.xhtml \ test_smilRepeatTiming.xhtml \ test_smilSetCurrentTime.xhtml \ test_smilSync.xhtml \ test_smilSyncbaseTarget.xhtml \ test_smilSyncTransform.xhtml \
--- a/content/smil/test/db_smilCSSFromTo.js +++ b/content/smil/test/db_smilCSSFromTo.js @@ -458,16 +458,19 @@ var gFromToBundles = [ toComp: "geometricprecision" }), new AnimTestcaseFromTo("geometricPrecision", "optimizeLegibility", { fromComp: "geometricprecision", toComp: "optimizelegibility" }), ]), new TestcaseBundle(gPropList.unicode_bidi, [ new AnimTestcaseFromTo("embed", "bidi-override"), ]), + new TestcaseBundle(gPropList.vector_effect, [ + new AnimTestcaseFromTo("none", "non-scaling-stroke"), + ]), new TestcaseBundle(gPropList.visibility, [ new AnimTestcaseFromTo("visible", "hidden"), new AnimTestcaseFromTo("hidden", "collapse"), ]), new TestcaseBundle(gPropList.word_spacing, [].concat(_fromToTestLists.lengthNoUnits, _fromToTestLists.lengthPx, _fromToTestLists.lengthPxPctSVG)),
--- a/content/smil/test/db_smilCSSPropertyList.js +++ b/content/smil/test/db_smilCSSPropertyList.js @@ -111,14 +111,15 @@ var gPropList = stroke_linejoin: new NonAdditiveAttribute("stroke-linejoin", "CSS", "rect"), stroke_miterlimit: new AdditiveAttribute("stroke-miterlimit", "CSS", "rect"), stroke_opacity: new AdditiveAttribute("stroke-opacity", "CSS", "rect"), stroke_width: new AdditiveAttribute("stroke-width", "CSS", "rect"), text_anchor: new NonAdditiveAttribute("text-anchor", "CSS", "text"), text_decoration: new NonAdditiveAttribute("text-decoration", "CSS", "text"), text_rendering: new NonAdditiveAttribute("text-rendering", "CSS", "text"), unicode_bidi: new NonAnimatableAttribute("unicode-bidi", "CSS", "text"), + vector_effect: new NonAdditiveAttribute("vector-effect", "CSS", "rect"), visibility: new NonAdditiveAttribute("visibility", "CSS", "rect"), word_spacing: new AdditiveAttribute("word-spacing", "CSS", "text"), writing_mode: // NOTE: Not supported by Mozilla, but explicitly non-animatable new NonAnimatableAttribute("writing-mode", "CSS", "text"), };
new file mode 100644 --- /dev/null +++ b/content/smil/test/test_smilHyperlinking.xhtml @@ -0,0 +1,233 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>Test for hyperlinking</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<p id="display"></p> +<div id="content" style="display:none"> +<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px" + onload="this.pauseAnimations()"> + <circle cx="-100" cy="20" r="15" fill="blue" id="circle"/> +</svg> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> +<![CDATA[ +/** Test for SMIL keySplines **/ + +/* Global Variables */ +const SVGNS="http://www.w3.org/2000/svg"; +var gSvg = document.getElementById("svg"); +var gAnim; + +var gTestStages = + [ testActive, + testSeekToFirst, + testKickStart, + testKickStartWithUnresolved, + testFiltering + ]; + +SimpleTest.waitForExplicitFinish(); + +function continueTest() +{ + if (gTestStages.length == 0) { + SimpleTest.finish(); + return; + } + + window.location.hash = ""; + if (gAnim) { + gAnim.parentNode.removeChild(gAnim); + } + gAnim = createAnim(); + gSvg.setCurrentTime(0); + gTestStages.shift()(); +} + +function createAnim() { + var anim = document.createElementNS(SVGNS,'animate'); + anim.setAttribute('attributeName','cx'); + anim.setAttribute('from','0'); + anim.setAttribute('to','100'); + anim.setAttribute('dur','1s'); + anim.setAttribute('begin','indefinite'); + anim.setAttribute('id','anim'); + return document.getElementById('circle').appendChild(anim); +} + +// Traversing a hyperlink, condition 1: +// +// "If the target element is active, seek the document time back to the +// (current) begin time of the element. If there are multiple begin times, use +// the begin time that corresponds to the current "begin instance"." +// +function testActive() { + gAnim.setAttribute('begin','2s; 4s'); + gSvg.setCurrentTime(2.5); + fireLink(rewindActiveInterval1); +} + +function rewindActiveInterval1() { + is(gSvg.getCurrentTime(), 2, + "Unexpected time after activating link to animation in the middle of " + + "first active interval"); + + // Seek to second interval + gSvg.setCurrentTime(4.5); + fireLink(rewindActiveInterval2); +} + +function rewindActiveInterval2() { + is(gSvg.getCurrentTime(), 4, + "Unexpected time after activating link to animation in the middle of " + + "second active interval"); + + // Try a negative time + gAnim.setAttribute("begin", "-0.5"); + gSvg.setCurrentTime(0.2); + fireLink(rewindActiveIntervalAtZero); +} + +function rewindActiveIntervalAtZero() { + is(gSvg.getCurrentTime(), 0, + "Unexpected time after activating link to animation in the middle of " + + "an active interval that overlaps zero"); + + continueTest(); +} + +// Traversing a hyperlink, condition 2: +// +// "Else if the target element begin time is resolved (i.e., there is any +// resolved time in the list of begin times, or if the begin time was forced by +// an earlier hyperlink or a beginElement() method call), seek the document time +// (forward or back, as needed) to the earliest resolved begin time of the +// target element. Note that the begin time may be resolved as a result of an +// earlier hyperlink, DOM or event activation. Once the begin time is resolved, +// hyperlink traversal always seeks." +// +function testSeekToFirst() { + // Seek forwards + gAnim.setAttribute('begin','2s'); + gSvg.setCurrentTime(0); + fireLink(forwardToInterval1); +} + +function forwardToInterval1() { + is(gSvg.getCurrentTime(), 2, + "Unexpected time after activating link to animation scheduled to start " + + "the future"); + + // Seek backwards + gSvg.setCurrentTime(3.5); + fireLink(backwardToInterval1); +} + +function backwardToInterval1() { + is(gSvg.getCurrentTime(), 2, + "Unexpected time after activating link to animation that ran in the past"); + + // What if the first begin instance is negative? + gAnim.setAttribute('begin','-0.5s'); + gSvg.setCurrentTime(1); + fireLink(backwardToZero); +} + +function backwardToZero() { + is(gSvg.getCurrentTime(), 0, + "Unexpected time after activating link to animation that ran in the " + + "past with a negative time"); + + continueTest(); +} + +// Traversing a hyperlink, condition 3: +// +// "Else (animation begin time is unresolved) just resolve the target animation +// begin time at current document time. Disregard the sync-base or event base of +// the animation, and do not "back-propagate" any timing logic to resolve the +// child, but rather treat it as though it were defined with begin="indefinite" +// and just resolve begin time to the current document time." +// +function testKickStart() { + gSvg.setCurrentTime(1); + fireLink(startedAt1s); +} + +function startedAt1s() { + is(gSvg.getCurrentTime(), 1, + "Unexpected time after kick-starting animation with indefinite start " + + "by hyperlink"); + is(gAnim.getStartTime(), 1, + "Unexpected start time for kick-started animation"); + + continueTest(); +} + +function testKickStartWithUnresolved() { + gAnim.setAttribute("begin", "circle.click"); + gSvg.setCurrentTime(3); + fireLink(startedAt3s); +} + +function startedAt3s() { + is(gSvg.getCurrentTime(), 3, + "Unexpected time after kick-starting animation with unresolved start " + + "by hyperlink"); + is(gAnim.getStartTime(), 3, + "Unexpected start time for kick-started animation with unresolved begin " + + "condition"); + + continueTest(); +} + +function testFiltering() { + gAnim.setAttribute('begin','-3s; 1s; 2s; 3s; 4s; 5s; 6s; 7s; 8s; 9s; 10s'); + gSvg.setCurrentTime(12); + fireLink(rewindToFirst); +} + +function rewindToFirst() { + is(gSvg.getCurrentTime(), 1, + "Unexpected time after triggering animation with a hyperlink after " + + "numerous intervals have passed"); + + continueTest(); +} + +function fireLink(callback) { + // First we need to reset the hash because otherwise the redundant hashchange + // events will be suppressed + if (window.location.hash === '') { + fireLinkPart2(callback); + } else { + window.location.hash = ''; + window.addEventListener("hashchange", + function clearHash() { + window.removeEventListener("hashchange", clearHash, false); + window.setTimeout(fireLinkPart2, 0, callback); + }, + false); + } +} + +function fireLinkPart2(callback) { + window.addEventListener("hashchange", + function triggerCallback() { + window.removeEventListener("hashchange", triggerCallback, false); + window.setTimeout(callback, 0); + }, + false); + window.location.hash = '#anim'; +} + +window.addEventListener("load", continueTest, false); +]]> +</script> +</pre> +</body> +</html>
--- a/content/svg/content/src/DOMSVGStringList.cpp +++ b/content/svg/content/src/DOMSVGStringList.cpp @@ -213,14 +213,14 @@ DOMSVGStringList::AppendItem(const nsASt return InsertItemBefore(newItem, InternalList().Length(), _retval); } SVGStringList & DOMSVGStringList::InternalList() { if (mIsConditionalProcessingAttribute) { nsCOMPtr<DOMSVGTests> tests = do_QueryInterface(mElement); - return tests->mStringListAttributes[mAttrEnum]; + return *tests->GetStringListAttribute(mAttrEnum); } return mElement->GetStringListInfo().mStringLists[mAttrEnum]; } } // namespace mozilla
--- a/content/svg/content/src/DOMSVGTests.cpp +++ b/content/svg/content/src/DOMSVGTests.cpp @@ -32,16 +32,17 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "DOMSVGTests.h" #include "DOMSVGStringList.h" +#include "nsContentErrors.h" // For NS_PROPTABLE_PROP_OVERWRITTEN #include "nsSVGFeatures.h" #include "nsSVGSwitchElement.h" #include "nsCharSeparatedTokenizer.h" #include "nsStyleUtil.h" #include "nsSVGUtils.h" #include "mozilla/Preferences.h" using namespace mozilla; @@ -50,48 +51,43 @@ NS_IMPL_ISUPPORTS1(DOMSVGTests, nsIDOMSV nsIAtom** DOMSVGTests::sStringListNames[3] = { &nsGkAtoms::requiredFeatures, &nsGkAtoms::requiredExtensions, &nsGkAtoms::systemLanguage, }; -DOMSVGTests::DOMSVGTests() -{ - mStringListAttributes[LANGUAGE].SetIsCommaSeparated(true); -} - /* readonly attribute nsIDOMSVGStringList requiredFeatures; */ NS_IMETHODIMP DOMSVGTests::GetRequiredFeatures(nsIDOMSVGStringList * *aRequiredFeatures) { nsCOMPtr<nsSVGElement> element = do_QueryInterface(this); *aRequiredFeatures = DOMSVGStringList::GetDOMWrapper( - &mStringListAttributes[FEATURES], element, true, FEATURES).get(); + GetOrCreateStringListAttribute(FEATURES), element, true, FEATURES).get(); return NS_OK; } /* readonly attribute nsIDOMSVGStringList requiredExtensions; */ NS_IMETHODIMP DOMSVGTests::GetRequiredExtensions(nsIDOMSVGStringList * *aRequiredExtensions) { nsCOMPtr<nsSVGElement> element = do_QueryInterface(this); *aRequiredExtensions = DOMSVGStringList::GetDOMWrapper( - &mStringListAttributes[EXTENSIONS], element, true, EXTENSIONS).get(); + GetOrCreateStringListAttribute(EXTENSIONS), element, true, EXTENSIONS).get(); return NS_OK; } /* readonly attribute nsIDOMSVGStringList systemLanguage; */ NS_IMETHODIMP DOMSVGTests::GetSystemLanguage(nsIDOMSVGStringList * *aSystemLanguage) { nsCOMPtr<nsSVGElement> element = do_QueryInterface(this); *aSystemLanguage = DOMSVGStringList::GetDOMWrapper( - &mStringListAttributes[LANGUAGE], element, true, LANGUAGE).get(); + GetOrCreateStringListAttribute(LANGUAGE), element, true, LANGUAGE).get(); return NS_OK; } /* boolean hasExtension (in DOMString extension); */ NS_IMETHODIMP DOMSVGTests::HasExtension(const nsAString & extension, bool *_retval) { *_retval = nsSVGFeatures::HasExtension(extension); @@ -111,25 +107,29 @@ DOMSVGTests::IsConditionalProcessingAttr PRInt32 DOMSVGTests::GetBestLanguagePreferenceRank(const nsSubstring& aAcceptLangs) const { const nsDefaultStringComparator defaultComparator; PRInt32 lowestRank = -1; - for (PRUint32 i = 0; i < mStringListAttributes[LANGUAGE].Length(); i++) { + const SVGStringList *languageStringList = GetStringListAttribute(LANGUAGE); + if (!languageStringList) { + return lowestRank; + } + for (PRUint32 i = 0; i < languageStringList->Length(); i++) { nsCharSeparatedTokenizer languageTokenizer(aAcceptLangs, ','); PRInt32 index = 0; while (languageTokenizer.hasMoreTokens()) { const nsSubstring &languageToken = languageTokenizer.nextToken(); - bool exactMatch = (languageToken == mStringListAttributes[LANGUAGE][i]); + bool exactMatch = (languageToken == (*languageStringList)[i]); bool prefixOnlyMatch = !exactMatch && - nsStyleUtil::DashMatchCompare(mStringListAttributes[LANGUAGE][i], + nsStyleUtil::DashMatchCompare((*languageStringList)[i], languageTokenizer.nextToken(), defaultComparator); if (index == 0 && exactMatch) { // best possible match return 0; } if ((exactMatch || prefixOnlyMatch) && (lowestRank == -1 || 2 * index + prefixOnlyMatch < lowestRank)) { @@ -142,79 +142,82 @@ DOMSVGTests::GetBestLanguagePreferenceRa } const nsString * const DOMSVGTests::kIgnoreSystemLanguage = (nsString *) 0x01; bool DOMSVGTests::PassesConditionalProcessingTests(const nsString *aAcceptLangs) const { // Required Features - if (mStringListAttributes[FEATURES].IsExplicitlySet()) { - if (mStringListAttributes[FEATURES].IsEmpty()) { + const SVGStringList *featuresStringList = GetStringListAttribute(FEATURES); + if (featuresStringList && featuresStringList->IsExplicitlySet()) { + if (featuresStringList->IsEmpty()) { return false; } nsCOMPtr<nsIContent> content( do_QueryInterface(const_cast<DOMSVGTests*>(this))); - for (PRUint32 i = 0; i < mStringListAttributes[FEATURES].Length(); i++) { - if (!nsSVGFeatures::HasFeature(content, mStringListAttributes[FEATURES][i])) { + for (PRUint32 i = 0; i < featuresStringList->Length(); i++) { + if (!nsSVGFeatures::HasFeature(content, (*featuresStringList)[i])) { return false; } } } // Required Extensions // // The requiredExtensions attribute defines a list of required language // extensions. Language extensions are capabilities within a user agent that // go beyond the feature set defined in the SVG specification. // Each extension is identified by a URI reference. // For now, claim that mozilla's SVG implementation supports XHTML and MathML. - if (mStringListAttributes[EXTENSIONS].IsExplicitlySet()) { - if (mStringListAttributes[EXTENSIONS].IsEmpty()) { + const SVGStringList *extensionsStringList = GetStringListAttribute(EXTENSIONS); + if (extensionsStringList && extensionsStringList->IsExplicitlySet()) { + if (extensionsStringList->IsEmpty()) { return false; } - for (PRUint32 i = 0; i < mStringListAttributes[EXTENSIONS].Length(); i++) { - if (!nsSVGFeatures::HasExtension(mStringListAttributes[EXTENSIONS][i])) { + for (PRUint32 i = 0; i < extensionsStringList->Length(); i++) { + if (!nsSVGFeatures::HasExtension((*extensionsStringList)[i])) { return false; } } } if (aAcceptLangs == kIgnoreSystemLanguage) { return true; } // systemLanguage // // Evaluates to "true" if one of the languages indicated by user preferences // exactly equals one of the languages given in the value of this parameter, // or if one of the languages indicated by user preferences exactly equals a // prefix of one of the languages given in the value of this parameter such // that the first tag character following the prefix is "-". - if (mStringListAttributes[LANGUAGE].IsExplicitlySet()) { - if (mStringListAttributes[LANGUAGE].IsEmpty()) { + const SVGStringList *languageStringList = GetStringListAttribute(LANGUAGE); + if (languageStringList && languageStringList->IsExplicitlySet()) { + if (languageStringList->IsEmpty()) { return false; } // Get our language preferences const nsAutoString acceptLangs(aAcceptLangs ? *aAcceptLangs : Preferences::GetLocalizedString("intl.accept_languages")); if (acceptLangs.IsEmpty()) { NS_WARNING("no default language specified for systemLanguage conditional test"); return false; } const nsDefaultStringComparator defaultComparator; - for (PRUint32 i = 0; i < mStringListAttributes[LANGUAGE].Length(); i++) { + for (PRUint32 i = 0; i < languageStringList->Length(); i++) { nsCharSeparatedTokenizer languageTokenizer(acceptLangs, ','); while (languageTokenizer.hasMoreTokens()) { - if (nsStyleUtil::DashMatchCompare(mStringListAttributes[LANGUAGE][i], + if (nsStyleUtil::DashMatchCompare((*languageStringList)[i], languageTokenizer.nextToken(), defaultComparator)) { return true; } } } return false; } @@ -224,51 +227,109 @@ DOMSVGTests::PassesConditionalProcessing bool DOMSVGTests::ParseConditionalProcessingAttribute(nsIAtom* aAttribute, const nsAString& aValue, nsAttrValue& aResult) { for (PRUint32 i = 0; i < ArrayLength(sStringListNames); i++) { if (aAttribute == *sStringListNames[i]) { - nsresult rv = mStringListAttributes[i].SetValue(aValue); - if (NS_FAILED(rv)) { - mStringListAttributes[i].Clear(); + SVGStringList *stringList = GetOrCreateStringListAttribute(i); + if (stringList) { + nsresult rv = stringList->SetValue(aValue); + if (NS_FAILED(rv)) { + stringList->Clear(); + } } MaybeInvalidate(); return true; } } return false; } void DOMSVGTests::UnsetAttr(const nsIAtom* aAttribute) { for (PRUint32 i = 0; i < ArrayLength(sStringListNames); i++) { if (aAttribute == *sStringListNames[i]) { - mStringListAttributes[i].Clear(); - MaybeInvalidate(); + SVGStringList *stringList = GetStringListAttribute(i); + if (stringList) { + // don't destroy the property in case there are tear-offs + // referring to it + stringList->Clear(); + MaybeInvalidate(); + } return; } } } +// Callback function, for freeing PRUint64 values stored in property table +// when the element goes away +static void +ReleaseStringListPropertyValue(void* aObject, /* unused */ + nsIAtom* aPropertyName, /* unused */ + void* aPropertyValue, + void* aData /* unused */) +{ + SVGStringList* valPtr = + static_cast<SVGStringList*>(aPropertyValue); + delete valPtr; +} + +SVGStringList* +DOMSVGTests::GetStringListAttribute(PRUint8 aAttrEnum) const +{ + nsIAtom *attrName = GetAttrName(aAttrEnum); + const nsCOMPtr<nsSVGElement> element = + do_QueryInterface(const_cast<DOMSVGTests*>(this)); + + return static_cast<SVGStringList*>(element->GetProperty(attrName)); +} + +SVGStringList* +DOMSVGTests::GetOrCreateStringListAttribute(PRUint8 aAttrEnum) const +{ + SVGStringList* stringListPtr = GetStringListAttribute(aAttrEnum); + if (stringListPtr) { + return stringListPtr; + } + nsIAtom *attrName = GetAttrName(aAttrEnum); + const nsCOMPtr<nsSVGElement> element = + do_QueryInterface(const_cast<DOMSVGTests*>(this)); + + stringListPtr = new SVGStringList(); + stringListPtr->SetIsCommaSeparated(aAttrEnum == LANGUAGE); + nsresult rv = element->SetProperty(attrName, + stringListPtr, + ReleaseStringListPropertyValue); + NS_ABORT_IF_FALSE(rv != NS_PROPTABLE_PROP_OVERWRITTEN, + "Setting property value when it's already set...?"); + + if (NS_LIKELY(NS_SUCCEEDED(rv))) { + return stringListPtr; + } + // property-insertion failed (e.g. OOM in property-table code) + delete stringListPtr; + return nsnull; +} + nsIAtom* DOMSVGTests::GetAttrName(PRUint8 aAttrEnum) const { return *sStringListNames[aAttrEnum]; } void DOMSVGTests::GetAttrValue(PRUint8 aAttrEnum, nsAttrValue& aValue) const { MOZ_ASSERT(aAttrEnum < ArrayLength(sStringListNames), "aAttrEnum out of range"); - aValue.SetTo(mStringListAttributes[aAttrEnum], nsnull); + aValue.SetTo(*GetOrCreateStringListAttribute(aAttrEnum), nsnull); } void DOMSVGTests::MaybeInvalidate() { nsCOMPtr<nsSVGElement> element = do_QueryInterface(this); nsIContent* parent = element->GetFlattenedTreeParent();
--- a/content/svg/content/src/DOMSVGTests.h +++ b/content/svg/content/src/DOMSVGTests.h @@ -54,18 +54,16 @@ class DOMSVGTests : public nsIDOMSVGTest { public: NS_DECL_ISUPPORTS NS_DECL_NSIDOMSVGTESTS friend class mozilla::DOMSVGStringList; typedef mozilla::SVGStringList SVGStringList; - DOMSVGTests(); - /** * Compare the language name(s) in a systemLanguage attribute to the * user's language preferences, as defined in * http://www.w3.org/TR/SVG11/struct.html#SystemLanguageAttribute * We have a match if a language name in the users language preferences * exactly equals one of the language names or exactly equals a prefix of * one of the language names in the systemLanguage attribute. * @returns 2 * the lowest index in the aAcceptLangs that matches + 1 @@ -106,19 +104,20 @@ public: nsAttrValue& aResult); /** * Unsets a conditional processing attribute. */ void UnsetAttr(const nsIAtom* aAttribute); nsIAtom* GetAttrName(PRUint8 aAttrEnum) const; + SVGStringList* GetStringListAttribute(PRUint8 aAttrEnum) const; + SVGStringList* GetOrCreateStringListAttribute(PRUint8 aAttrEnum) const; void GetAttrValue(PRUint8 aAttrEnum, nsAttrValue &aValue) const; void MaybeInvalidate(); private: enum { FEATURES, EXTENSIONS, LANGUAGE }; - SVGStringList mStringListAttributes[3]; static nsIAtom** sStringListNames[3]; }; #endif // MOZILLA_DOMSVGTESTS_H__
--- a/content/svg/content/src/Makefile.in +++ b/content/svg/content/src/Makefile.in @@ -119,22 +119,24 @@ CPPSRCS = \ nsSVGTextContentElement.cpp \ nsSVGTextElement.cpp \ nsSVGTextPathElement.cpp \ nsSVGTextPositioningElement.cpp \ nsSVGTitleElement.cpp \ nsSVGUnknownElement.cpp \ nsSVGUseElement.cpp \ nsSVGViewBox.cpp \ + nsSVGViewElement.cpp \ SVGAnimatedLengthList.cpp \ SVGAnimatedNumberList.cpp \ SVGAnimatedPathSegList.cpp \ SVGAnimatedPointList.cpp \ SVGAnimatedPreserveAspectRatio.cpp \ SVGAnimatedTransformList.cpp \ + SVGFragmentIdentifier.cpp \ SVGLength.cpp \ SVGLengthList.cpp \ SVGNumberList.cpp \ SVGPathData.cpp \ SVGPathSegUtils.cpp \ SVGPointList.cpp \ SVGStringList.cpp \ SVGTransform.cpp \
--- a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp +++ b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp @@ -144,16 +144,24 @@ GetMeetOrSliceString(nsAString& aMeetOrS aMeetOrSlice <= nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE, "Unknown meetOrSlice"); aMeetOrSliceString.AssignASCII( sMeetOrSliceStrings[aMeetOrSlice - nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_MEET]); } +bool +SVGPreserveAspectRatio::operator==(const SVGPreserveAspectRatio& aOther) const +{ + return mAlign == aOther.mAlign && + mMeetOrSlice == aOther.mMeetOrSlice && + mDefer == aOther.mDefer; +} + nsresult SVGAnimatedPreserveAspectRatio::ToDOMBaseVal( nsIDOMSVGPreserveAspectRatio **aResult, nsSVGElement *aSVGElement) { *aResult = new DOMBaseVal(this, aSVGElement); if (!*aResult) return NS_ERROR_OUT_OF_MEMORY; @@ -268,58 +276,35 @@ SVGAnimatedPreserveAspectRatio::GetBaseV nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE) { aValueAsString.AppendLiteral(" "); GetMeetOrSliceString(tmpString, mBaseVal.mMeetOrSlice); aValueAsString.Append(tmpString); } } -nsresult -SVGAnimatedPreserveAspectRatio::SetBaseAlign(PRUint16 aAlign, +void +SVGAnimatedPreserveAspectRatio::SetBaseValue(const SVGPreserveAspectRatio &aValue, nsSVGElement *aSVGElement) { - if (mIsBaseSet && mBaseVal.GetAlign() == aAlign) { - return NS_OK; + if (mIsBaseSet && mBaseVal == aValue) { + return; } nsAttrValue emptyOrOldValue = aSVGElement->WillChangePreserveAspectRatio(); - nsresult rv = mBaseVal.SetAlign(aAlign); - NS_ENSURE_SUCCESS(rv, rv); + mBaseVal = aValue; mIsBaseSet = true; - mAnimVal.mAlign = mBaseVal.mAlign; + if (!mIsAnimated) { + mAnimVal = mBaseVal; + } aSVGElement->DidChangePreserveAspectRatio(emptyOrOldValue); if (mIsAnimated) { aSVGElement->AnimationNeedsResample(); } - - return NS_OK; -} - -nsresult -SVGAnimatedPreserveAspectRatio::SetBaseMeetOrSlice(PRUint16 aMeetOrSlice, - nsSVGElement *aSVGElement) -{ - if (mIsBaseSet && mBaseVal.GetMeetOrSlice() == aMeetOrSlice) { - return NS_OK; - } - - nsAttrValue emptyOrOldValue = aSVGElement->WillChangePreserveAspectRatio(); - nsresult rv = mBaseVal.SetMeetOrSlice(aMeetOrSlice); - NS_ENSURE_SUCCESS(rv, rv); - mIsBaseSet = true; - - mAnimVal.mMeetOrSlice = mBaseVal.mMeetOrSlice; - aSVGElement->DidChangePreserveAspectRatio(emptyOrOldValue); - if (mIsAnimated) { - aSVGElement->AnimationNeedsResample(); - } - - return NS_OK; } void SVGAnimatedPreserveAspectRatio::SetAnimValue(PRUint64 aPackedValue, nsSVGElement *aSVGElement) { mAnimVal.SetDefer(((aPackedValue & 0xff0000) >> 16) ? true : false); mAnimVal.SetAlign(PRUint16((aPackedValue & 0xff00) >> 8));
--- a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.h +++ b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.h @@ -55,22 +55,30 @@ namespace mozilla { class SVGAnimatedPreserveAspectRatio; class SVGPreserveAspectRatio { friend class SVGAnimatedPreserveAspectRatio; public: + SVGPreserveAspectRatio(PRUint16 aAlign, PRUint16 aMeetOrSlice, bool aDefer = false) + : mAlign(aAlign) + , mMeetOrSlice(aMeetOrSlice) + , mDefer(aDefer) + {}; + SVGPreserveAspectRatio() : mAlign(0) , mMeetOrSlice(0) , mDefer(false) {}; + bool operator==(const SVGPreserveAspectRatio& aOther) const; + nsresult SetAlign(PRUint16 aAlign) { if (aAlign < nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE || aAlign > nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX) return NS_ERROR_FAILURE; mAlign = static_cast<PRUint8>(aAlign); return NS_OK; }; @@ -115,18 +123,38 @@ public: mIsAnimated = false; mIsBaseSet = false; } nsresult SetBaseValueString(const nsAString& aValue, nsSVGElement *aSVGElement); void GetBaseValueString(nsAString& aValue) const; - nsresult SetBaseAlign(PRUint16 aAlign, nsSVGElement *aSVGElement); - nsresult SetBaseMeetOrSlice(PRUint16 aMeetOrSlice, nsSVGElement *aSVGElement); + void SetBaseValue(const SVGPreserveAspectRatio &aValue, + nsSVGElement *aSVGElement); + nsresult SetBaseAlign(PRUint16 aAlign, nsSVGElement *aSVGElement) { + if (aAlign < nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE || + aAlign > nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX) { + return NS_ERROR_FAILURE; + } + SetBaseValue(SVGPreserveAspectRatio( + aAlign, mBaseVal.GetMeetOrSlice(), mBaseVal.GetDefer()), + aSVGElement); + return NS_OK; + } + nsresult SetBaseMeetOrSlice(PRUint16 aMeetOrSlice, nsSVGElement *aSVGElement) { + if (aMeetOrSlice < nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_MEET || + aMeetOrSlice > nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE) { + return NS_ERROR_FAILURE; + } + SetBaseValue(SVGPreserveAspectRatio( + mBaseVal.GetAlign(), aMeetOrSlice, mBaseVal.GetDefer()), + aSVGElement); + return NS_OK; + } void SetAnimValue(PRUint64 aPackedValue, nsSVGElement *aSVGElement); const SVGPreserveAspectRatio &GetBaseValue() const { return mBaseVal; } const SVGPreserveAspectRatio &GetAnimValue() const { return mAnimVal; } bool IsAnimated() const { return mIsAnimated; }
new file mode 100644 --- /dev/null +++ b/content/svg/content/src/SVGFragmentIdentifier.cpp @@ -0,0 +1,262 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla SVG project. + * + * The Initial Developer of the Original Code is + * Robert Longson <longsonr@gmail.com> + * Portions created by the Initial Developer are Copyright (C) 2012 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "SVGFragmentIdentifier.h" +#include "mozilla/CharTokenizer.h" +#include "nsIDOMSVGDocument.h" +#include "nsSVGSVGElement.h" +#include "nsSVGViewElement.h" + +using namespace mozilla; + +static nsSVGEnumMapping sZoomAndPanMap[] = { + {&nsGkAtoms::disable, nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_DISABLE}, + {&nsGkAtoms::magnify, nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_MAGNIFY}, + {nsnull, 0} +}; + +static bool +IsMatchingParameter(const nsAString &aString, const nsAString &aParameterName) +{ + // The first two tests ensure aString.Length() > aParameterName.Length() + // so it's then safe to do the third test + return StringBeginsWith(aString, aParameterName) && + aString.Last() == ')' && + aString.CharAt(aParameterName.Length()) == '('; +} + +static nsSVGViewElement* +GetViewElement(nsIDocument *aDocument, const nsAString &aId) +{ + dom::Element* element = aDocument->GetElementById(aId); + return (element && element->IsSVG(nsGkAtoms::view)) ? + static_cast<nsSVGViewElement*>(element) : nsnull; +} + +void +SVGFragmentIdentifier::SaveOldPreserveAspectRatio(nsSVGSVGElement *root) +{ + const SVGPreserveAspectRatio *oldPARPtr = root->GetPreserveAspectRatioProperty(); + if (!oldPARPtr) { + root->SetPreserveAspectRatioProperty(root->mPreserveAspectRatio.GetBaseValue()); + } +} + +void +SVGFragmentIdentifier::RestoreOldPreserveAspectRatio(nsSVGSVGElement *root) +{ + const SVGPreserveAspectRatio *oldPARPtr = root->GetPreserveAspectRatioProperty(); + if (oldPARPtr) { + root->mPreserveAspectRatio.SetBaseValue(*oldPARPtr, root); + root->ClearPreserveAspectRatioProperty(); + } +} + +void +SVGFragmentIdentifier::SaveOldViewBox(nsSVGSVGElement *root) +{ + const nsSVGViewBoxRect *oldViewBoxPtr = root->GetViewBoxProperty(); + if (!oldViewBoxPtr) { + root->SetViewBoxProperty(root->mViewBox.GetBaseValue()); + } +} + +void +SVGFragmentIdentifier::RestoreOldViewBox(nsSVGSVGElement *root) +{ + const nsSVGViewBoxRect *oldViewBoxPtr = root->GetViewBoxProperty(); + if (oldViewBoxPtr) { + root->mViewBox.SetBaseValue(*oldViewBoxPtr, root); + root->ClearViewBoxProperty(); + } +} + +void +SVGFragmentIdentifier::SaveOldZoomAndPan(nsSVGSVGElement *root) +{ + const PRUint16 *oldZoomAndPanPtr = root->GetZoomAndPanProperty(); + if (!oldZoomAndPanPtr) { + root->SetZoomAndPanProperty(root->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].GetBaseValue()); + } +} + +void +SVGFragmentIdentifier::RestoreOldZoomAndPan(nsSVGSVGElement *root) +{ + const PRUint16 *oldZoomAndPanPtr = root->GetZoomAndPanProperty(); + if (oldZoomAndPanPtr) { + root->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].SetBaseValue(*oldZoomAndPanPtr, root); + root->ClearZoomAndPanProperty(); + } +} + +bool +SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString &aViewSpec, + nsSVGSVGElement *root) +{ + if (!IsMatchingParameter(aViewSpec, NS_LITERAL_STRING("svgView"))) { + return false; + } + + // SVGViewAttribute may occur in any order, but each type may only occur at most one time + // in a correctly formed SVGViewSpec. + // If we encounter any element more than once or get any syntax errors we're going to + // return without updating the root element + + const nsAString *viewBoxParams = nsnull; + const nsAString *preserveAspectRatioParams = nsnull; + const nsAString *zoomAndPanParams = nsnull; + + // Each token is a SVGViewAttribute + PRInt32 bracketPos = aViewSpec.FindChar('('); + CharTokenizer<';'>tokenizer( + Substring(aViewSpec, bracketPos + 1, aViewSpec.Length() - bracketPos - 2)); + + while (tokenizer.hasMoreTokens()) { + + nsAutoString token(tokenizer.nextToken()); + + bracketPos = token.FindChar('('); + if (bracketPos < 1 || token.Last() != ')') { + // invalid SVGViewAttribute syntax + return false; + } + + const nsAString ¶ms = + Substring(token, bracketPos + 1, token.Length() - bracketPos - 2); + + if (IsMatchingParameter(token, NS_LITERAL_STRING("viewBox"))) { + if (viewBoxParams) { + return false; + } + viewBoxParams = ¶ms; + } else if (IsMatchingParameter(token, NS_LITERAL_STRING("preserveAspectRatio"))) { + if (preserveAspectRatioParams) { + return false; + } + preserveAspectRatioParams = ¶ms; + } else if (IsMatchingParameter(token, NS_LITERAL_STRING("zoomAndPan"))) { + if (zoomAndPanParams) { + return false; + } + zoomAndPanParams = ¶ms; + } else { + // We don't support transform or viewTarget currently + return false; + } + } + + const nsSVGViewBoxRect *oldViewBoxPtr = root->GetViewBoxProperty(); + if (viewBoxParams) { + SaveOldViewBox(root); + root->mViewBox.SetBaseValueString(*viewBoxParams, root); + } else { + RestoreOldViewBox(root); + } + + const SVGPreserveAspectRatio *oldPARPtr = root->GetPreserveAspectRatioProperty(); + if (preserveAspectRatioParams) { + SaveOldPreserveAspectRatio(root); + root->mPreserveAspectRatio.SetBaseValueString(*preserveAspectRatioParams, root); + } else { + RestoreOldPreserveAspectRatio(root); + } + + const PRUint16 *oldZoomAndPanPtr = root->GetZoomAndPanProperty(); + if (zoomAndPanParams) { + SaveOldZoomAndPan(root); + nsCOMPtr<nsIAtom> valAtom = do_GetAtom(*zoomAndPanParams); + const nsSVGEnumMapping *mapping = root->sZoomAndPanMap; + while (mapping->mKey) { + if (valAtom == *(mapping->mKey)) { + root->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].SetBaseValue(mapping->mVal, root); + break; + } + mapping++; + } + } else { + RestoreOldZoomAndPan(root); + } + + return true; +} + +bool +SVGFragmentIdentifier::ProcessFragmentIdentifier(nsIDocument *aDocument, + const nsAString &aAnchorName) +{ + NS_ABORT_IF_FALSE(aDocument->GetRootElement()->IsSVG(nsGkAtoms::svg), + "expecting an SVG root element"); + + nsSVGSVGElement *rootElement = + static_cast<nsSVGSVGElement*>(aDocument->GetRootElement()); + + const nsSVGViewElement *viewElement = GetViewElement(aDocument, aAnchorName); + + if (viewElement) { + if (viewElement->mViewBox.IsExplicitlySet()) { + SaveOldViewBox(rootElement); + rootElement->mViewBox.SetBaseValue( + viewElement->mViewBox.GetBaseValue(), rootElement); + } else { + RestoreOldViewBox(rootElement); + } + if (viewElement->mPreserveAspectRatio.IsExplicitlySet()) { + SaveOldPreserveAspectRatio(rootElement); + rootElement->mPreserveAspectRatio.SetBaseValue( + viewElement->mPreserveAspectRatio.GetBaseValue(), rootElement); + } else { + RestoreOldPreserveAspectRatio(rootElement); + } + if (viewElement->mEnumAttributes[nsSVGViewElement::ZOOMANDPAN].IsExplicitlySet()) { + SaveOldZoomAndPan(rootElement); + rootElement->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].SetBaseValue( + viewElement->mEnumAttributes[nsSVGViewElement::ZOOMANDPAN].GetBaseValue(), rootElement); + } else { + RestoreOldZoomAndPan(rootElement); + } + return true; + } + + if (ProcessSVGViewSpec(aAnchorName, rootElement)) { + return true; + } + RestoreOldViewBox(rootElement); + RestoreOldPreserveAspectRatio(rootElement); + RestoreOldZoomAndPan(rootElement); + return false; +}
new file mode 100644 --- /dev/null +++ b/content/svg/content/src/SVGFragmentIdentifier.h @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla SVG project. + * + * The Initial Developer of the Original Code is + * Robert Longson <longsonr@gmail.com> + * Portions created by the Initial Developer are Copyright (C) 2012 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef MOZILLA_SVGFRAGMENTIDENTIFIER_H__ +#define MOZILLA_SVGFRAGMENTIDENTIFIER_H__ + +#include "nsString.h" + +class nsIDocument; +class nsSVGSVGElement; +class nsSVGViewElement; + +namespace mozilla { + +/** + * Implements support for parsing SVG fragment identifiers + * http://www.w3.org/TR/SVG/linking.html#SVGFragmentIdentifiers + */ +class SVGFragmentIdentifier +{ + // To prevent the class being instantiated + SVGFragmentIdentifier() MOZ_DELETE; + +public: + /** + * Process the SVG fragment identifier, if there is one. + * @return true if we found something we recognised + */ + static bool ProcessFragmentIdentifier(nsIDocument *aDocument, + const nsAString &aAnchorName); + +private: + /** + * Parse an SVG ViewSpec and set applicable attributes on the root element. + * @return true if there is a valid ViewSpec + */ + static bool ProcessSVGViewSpec(const nsAString &aViewSpec, nsSVGSVGElement *root); + + // Save and restore things we override in case we want to go back e.g. the + // user presses the back button + static void SaveOldPreserveAspectRatio(nsSVGSVGElement *root); + static void RestoreOldPreserveAspectRatio(nsSVGSVGElement *root); + static void SaveOldViewBox(nsSVGSVGElement *root); + static void RestoreOldViewBox(nsSVGSVGElement *root); + static void SaveOldZoomAndPan(nsSVGSVGElement *root); + static void RestoreOldZoomAndPan(nsSVGSVGElement *root); +}; + +} // namespace mozilla + +#endif // MOZILLA_SVGFRAGMENTIDENTIFIER_H__
--- a/content/svg/content/src/nsSVGAnimationElement.cpp +++ b/content/svg/content/src/nsSVGAnimationElement.cpp @@ -418,16 +418,44 @@ nsSVGAnimationElement::UnsetAttr(PRInt32 bool nsSVGAnimationElement::IsNodeOfType(PRUint32 aFlags) const { return !(aFlags & ~(eCONTENT | eANIMATION)); } //---------------------------------------------------------------------- +// SVG utility methods + +void +nsSVGAnimationElement::ActivateByHyperlink() +{ + FlushAnimations(); + + // The behavior for when the target is an animation element is defined in + // SMIL Animation: + // http://www.w3.org/TR/smil-animation/#HyperlinkSemantics + nsSMILTimeValue seekTime = mTimedElement.GetHyperlinkTime(); + if (seekTime.IsDefinite()) { + nsSMILTimeContainer* timeContainer = GetTimeContainer(); + if (timeContainer) { + timeContainer->SetCurrentTime(seekTime.GetMillis()); + AnimationNeedsResample(); + // As with nsSVGSVGElement::SetCurrentTime, we need to trigger + // a synchronous sample now. + FlushAnimations(); + } + // else, silently fail. We mustn't be part of an SVG document fragment that + // is attached to the document tree so there's nothing we can do here + } else { + BeginElement(); + } +} + +//---------------------------------------------------------------------- // Implementation helpers nsSMILTimeContainer* nsSVGAnimationElement::GetTimeContainer() { nsSVGSVGElement *element = nsSVGUtils::GetOuterSVGElement(this); if (element) {
--- a/content/svg/content/src/nsSVGAnimationElement.h +++ b/content/svg/content/src/nsSVGAnimationElement.h @@ -95,16 +95,19 @@ public: virtual bool HasAnimAttr(nsIAtom* aAttName) const; virtual Element* GetTargetElementContent(); virtual bool GetTargetAttributeName(PRInt32* aNamespaceID, nsIAtom** aLocalName) const; virtual nsSMILTargetAttrType GetTargetAttributeType() const; virtual nsSMILTimedElement& TimedElement(); virtual nsSMILTimeContainer* GetTimeContainer(); + // Utility methods for within SVG + void ActivateByHyperlink(); + protected: // nsSVGElement overrides bool IsEventName(nsIAtom* aName); void UpdateHrefTarget(nsIContent* aNodeForContext, const nsAString& aHrefStr); void AnimationTargetChanged();
--- a/content/svg/content/src/nsSVGAttrTearoffTable.h +++ b/content/svg/content/src/nsSVGAttrTearoffTable.h @@ -99,21 +99,17 @@ nsSVGAttrTearoffTable<SimpleType, Tearof // We shouldn't be adding a tear-off if there already is one. If that happens, // something is wrong. if (mTable.Get(aSimple, nsnull)) { NS_ABORT_IF_FALSE(false, "There is already a tear-off for this object."); return; } -#ifdef DEBUG - bool result = -#endif - mTable.Put(aSimple, aTearoff); - NS_ABORT_IF_FALSE(result, "Out of memory."); + mTable.Put(aSimple, aTearoff); } template<class SimpleType, class TearoffType> void nsSVGAttrTearoffTable<SimpleType, TearoffType>::RemoveTearoff( SimpleType* aSimple) { if (!mTable.IsInitialized()) {
--- a/content/svg/content/src/nsSVGElement.cpp +++ b/content/svg/content/src/nsSVGElement.cpp @@ -926,16 +926,17 @@ nsSVGElement::sFillStrokeMap[] = { { &nsGkAtoms::stroke }, { &nsGkAtoms::stroke_dasharray }, { &nsGkAtoms::stroke_dashoffset }, { &nsGkAtoms::stroke_linecap }, { &nsGkAtoms::stroke_linejoin }, { &nsGkAtoms::stroke_miterlimit }, { &nsGkAtoms::stroke_opacity }, { &nsGkAtoms::stroke_width }, + { &nsGkAtoms::vector_effect }, { nsnull } }; // PresentationAttributes-Graphics /* static */ const nsGenericElement::MappedAttributeEntry nsSVGElement::sGraphicsMap[] = { { &nsGkAtoms::clip_path }, { &nsGkAtoms::clip_rule },
--- a/content/svg/content/src/nsSVGElementFactory.cpp +++ b/content/svg/content/src/nsSVGElementFactory.cpp @@ -217,16 +217,19 @@ nsresult NS_NewSVGFESpecularLightingElement(nsIContent **aResult, already_AddRefed<nsINodeInfo> aNodeInfo); nsresult NS_NewSVGFEImageElement(nsIContent **aResult, already_AddRefed<nsINodeInfo> aNodeInfo); nsresult NS_NewSVGFEDisplacementMapElement(nsIContent **aResult, already_AddRefed<nsINodeInfo> aNodeInfo); +nsresult +NS_NewSVGViewElement(nsIContent **aResult, + already_AddRefed<nsINodeInfo> aNodeInfo); nsresult NS_NewSVGAnimateElement(nsIContent **aResult, already_AddRefed<nsINodeInfo> aNodeInfo); nsresult NS_NewSVGAnimateTransformElement(nsIContent **aResult, already_AddRefed<nsINodeInfo> aNodeInfo); nsresult @@ -365,16 +368,18 @@ NS_NewSVGElement(nsIContent** aResult, a if (name == nsGkAtoms::feDisplacementMap) return NS_NewSVGFEDisplacementMapElement(aResult, aNodeInfo); if (name == nsGkAtoms::pattern) return NS_NewSVGPatternElement(aResult, aNodeInfo); if (name == nsGkAtoms::mask) return NS_NewSVGMaskElement(aResult, aNodeInfo); if (name == nsGkAtoms::svgSwitch) return NS_NewSVGSwitchElement(aResult, aNodeInfo); + if (name == nsGkAtoms::view) + return NS_NewSVGViewElement(aResult, aNodeInfo); if (NS_SMILEnabled()) { if (name == nsGkAtoms::animate) return NS_NewSVGAnimateElement(aResult, aNodeInfo); if (name == nsGkAtoms::animateTransform) return NS_NewSVGAnimateTransformElement(aResult, aNodeInfo); if (name == nsGkAtoms::animateMotion) return NS_NewSVGAnimateMotionElement(aResult, aNodeInfo); if (name == nsGkAtoms::mpath)
--- a/content/svg/content/src/nsSVGGraphicElement.cpp +++ b/content/svg/content/src/nsSVGGraphicElement.cpp @@ -40,16 +40,17 @@ #include "mozilla/Util.h" #include "nsSVGGraphicElement.h" #include "nsSVGSVGElement.h" #include "DOMSVGAnimatedTransformList.h" #include "DOMSVGMatrix.h" #include "nsGkAtoms.h" #include "nsIDOMEventTarget.h" +#include "nsIDOMMutationEvent.h" #include "nsIFrame.h" #include "nsISVGChildFrame.h" #include "nsIDOMSVGPoint.h" #include "nsSVGUtils.h" #include "nsDOMError.h" #include "nsSVGRect.h" #include "nsContentUtils.h" @@ -174,16 +175,53 @@ nsSVGGraphicElement::IsAttributeMapped(c sFillStrokeMap, sGraphicsMap }; return FindAttributeDependence(name, map) || nsSVGGraphicElementBase::IsAttributeMapped(name); } +nsChangeHint +nsSVGGraphicElement::GetAttributeChangeHint(const nsIAtom* aAttribute, + PRInt32 aModType) const +{ + nsChangeHint retval = + nsSVGGraphicElementBase::GetAttributeChangeHint(aAttribute, aModType); + if (aAttribute == nsGkAtoms::transform) { + // We add nsChangeHint_UpdateOverflow so that nsFrame::UpdateOverflow() + // will be called on us and our ancestors. + nsIFrame* frame = + const_cast<nsSVGGraphicElement*>(this)->GetPrimaryFrame(); + if (frame && frame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD) { + // No need to do anything. + } else if (aModType == nsIDOMMutationEvent::ADDITION || + aModType == nsIDOMMutationEvent::REMOVAL) { + // In order to handle view creation/destruction and stacking context + // changes, the code in nsStyleDisplay::CalcDifference uses + // nsChangeHint_ReconstructFrame if the transform was added/removed. + // XXXSDL Currently we don't need to reconstruct SVG frames when their + // transform is set/unset since we don't currently create GFX layers for + // SVG transforms, but we will after bug 614732 is fixed. Also change the + // assertion in ApplyRenderingChangeToTree when we do that. + NS_UpdateHint(retval, nsChangeHint_UpdateOverflow); + } else { + NS_ABORT_IF_FALSE(aModType == nsIDOMMutationEvent::MODIFICATION, + "Unknown modification type."); + // We just assume the old and new transforms are different. + // XXXSDL Once we use GFX layers for SVG transforms, we will need to pass + // the nsChangeHint_UpdateTransformLayer hint too. Note that the + // assertion in ApplyRenderingChangeToTree will fail if that hint is + // passed on nsIDOMMutationEvent::REMOVAL though. + NS_UpdateHint(retval, nsChangeHint_UpdateOverflow); + } + } + return retval; +} + //---------------------------------------------------------------------- // nsSVGElement overrides bool nsSVGGraphicElement::IsEventName(nsIAtom* aName) { return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic); }
--- a/content/svg/content/src/nsSVGGraphicElement.h +++ b/content/svg/content/src/nsSVGGraphicElement.h @@ -57,16 +57,19 @@ public: // interfaces: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOMSVGLOCATABLE NS_DECL_NSIDOMSVGTRANSFORMABLE // nsIContent interface NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const; + nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute, + PRInt32 aModType) const; + virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix, TransformTypes aWhich = eAllTransforms) const; virtual void SetAnimateMotionTransform(const gfxMatrix* aMatrix); virtual mozilla::SVGAnimatedTransformList* GetAnimatedTransformList(); virtual nsIAtom* GetTransformListAttrName() const { return nsGkAtoms::transform; }
--- a/content/svg/content/src/nsSVGSVGElement.cpp +++ b/content/svg/content/src/nsSVGSVGElement.cpp @@ -36,16 +36,17 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "mozilla/Util.h" #include "nsGkAtoms.h" +#include "nsLayoutUtils.h" #include "DOMSVGNumber.h" #include "DOMSVGLength.h" #include "nsSVGAngle.h" #include "nsCOMPtr.h" #include "nsIPresShell.h" #include "nsContentUtils.h" #include "nsIDocument.h" #include "nsPresContext.h" @@ -199,17 +200,18 @@ nsSVGSVGElement::nsSVGSVGElement(already mViewportWidth(0), mViewportHeight(0), mCurrentTranslate(0.0f, 0.0f), mCurrentScale(1.0f), mPreviousTranslate(0.0f, 0.0f), mPreviousScale(1.0f), mStartAnimationOnBindToTree(!aFromParser), mImageNeedsTransformInvalidation(false), - mIsPaintingSVGImageElement(false) + mIsPaintingSVGImageElement(false), + mHasChildrenOnlyTransform(false) { } //---------------------------------------------------------------------- // nsIDOMNode methods // From NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGSVGElement) nsresult @@ -949,81 +951,69 @@ ComputeSynthesizedViewBoxDimension(const } //---------------------------------------------------------------------- // public helpers: gfxMatrix nsSVGSVGElement::GetViewBoxTransform() const { - // Do we have an override preserveAspectRatio value? - const SVGPreserveAspectRatio* overridePARPtr = - GetImageOverridePreserveAspectRatio(); - - // May assign this to overridePARPtr if we have no viewBox but are faking one: - SVGPreserveAspectRatio tmpPAR; - float viewportWidth, viewportHeight; if (IsInner()) { nsSVGSVGElement *ctx = GetCtx(); viewportWidth = mLengthAttributes[WIDTH].GetAnimValue(ctx); viewportHeight = mLengthAttributes[HEIGHT].GetAnimValue(ctx); } else { viewportWidth = mViewportWidth; viewportHeight = mViewportHeight; } if (viewportWidth <= 0.0f || viewportHeight <= 0.0f) { return gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // singular } - nsSVGViewBoxRect viewBox; - if (HasViewBox()) { - viewBox = mViewBox.GetAnimValue(); - } else { - viewBox.x = viewBox.y = 0.0f; - if (ShouldSynthesizeViewBox()) { - // Special case -- fake a viewBox, using height & width attrs. - // (Use |this| as context, since if we get here, we're outermost <svg>.) - viewBox.width = - ComputeSynthesizedViewBoxDimension(mLengthAttributes[WIDTH], - mViewportWidth, this); - viewBox.height = - ComputeSynthesizedViewBoxDimension(mLengthAttributes[HEIGHT], - mViewportHeight, this); - NS_ABORT_IF_FALSE(!overridePARPtr, - "shouldn't have overridePAR if we're " - "synthesizing a viewBox"); - - // If we're synthesizing a viewBox, use preserveAspectRatio="none"; - tmpPAR.SetAlign(nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE); - - // (set the other pAR attributes too, just so they're initialized): - tmpPAR.SetDefer(false); - tmpPAR.SetMeetOrSlice(nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE); - - overridePARPtr = &tmpPAR; - } else { - // No viewBox attribute, so we shouldn't auto-scale. This is equivalent - // to having a viewBox that exactly matches our viewport size. - viewBox.width = viewportWidth; - viewBox.height = viewportHeight; - } - } + nsSVGViewBoxRect viewBox = + GetViewBoxWithSynthesis(viewportWidth, viewportHeight); if (viewBox.width <= 0.0f || viewBox.height <= 0.0f) { return gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // singular } return nsSVGUtils::GetViewBoxTransform(this, viewportWidth, viewportHeight, viewBox.x, viewBox.y, viewBox.width, viewBox.height, - overridePARPtr ? *overridePARPtr : - mPreserveAspectRatio.GetAnimValue()); + GetPreserveAspectRatioWithOverride()); +} + +void +nsSVGSVGElement::ChildrenOnlyTransformChanged() +{ + // Avoid wasteful calls: + NS_ABORT_IF_FALSE(!(GetPrimaryFrame()->GetStateBits() & + NS_STATE_SVG_NONDISPLAY_CHILD), + "Non-display SVG frames don't maintain overflow rects"); + + bool hasChildrenOnlyTransform = HasViewBoxOrSyntheticViewBox() || + (IsRoot() && (mCurrentTranslate != nsSVGTranslatePoint(0.0f, 0.0f) || + mCurrentScale != 1.0f)); + + // XXXSDL Currently we don't destroy frames if + // hasChildrenOnlyTransform != mHasChildrenOnlyTransform + // but we should once we start using GFX layers for SVG transforms + // (see the comment in nsSVGGraphicElement::GetAttributeChangeHint). + + nsChangeHint changeHint = + nsChangeHint(nsChangeHint_RepaintFrame | + nsChangeHint_UpdateOverflow | + nsChangeHint_ChildrenOnlyTransform); + + nsLayoutUtils::PostRestyleEvent(this, nsRestyleHint(0), changeHint); + + mHasChildrenOnlyTransform = hasChildrenOnlyTransform; } nsresult nsSVGSVGElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, bool aCompileEventHandlers) { @@ -1115,16 +1105,60 @@ nsSVGSVGElement::InvalidateTransformNoti bool nsSVGSVGElement::HasPreserveAspectRatio() { return HasAttr(kNameSpaceID_None, nsGkAtoms::preserveAspectRatio) || mPreserveAspectRatio.IsAnimated(); } +nsSVGViewBoxRect +nsSVGSVGElement::GetViewBoxWithSynthesis( + float aViewportWidth, float aViewportHeight) const +{ + if (HasViewBox()) { + return mViewBox.GetAnimValue(); + } + + if (ShouldSynthesizeViewBox()) { + // Special case -- fake a viewBox, using height & width attrs. + // (Use |this| as context, since if we get here, we're outermost <svg>.) + return nsSVGViewBoxRect(0, 0, + ComputeSynthesizedViewBoxDimension(mLengthAttributes[WIDTH], + mViewportWidth, this), + ComputeSynthesizedViewBoxDimension(mLengthAttributes[HEIGHT], + mViewportHeight, this)); + + } + + // No viewBox attribute, so we shouldn't auto-scale. This is equivalent + // to having a viewBox that exactly matches our viewport size. + return nsSVGViewBoxRect(0, 0, aViewportWidth, aViewportHeight); +} + +SVGPreserveAspectRatio +nsSVGSVGElement::GetPreserveAspectRatioWithOverride() const +{ + if (GetCurrentDoc()->IsBeingUsedAsImage()) { + const SVGPreserveAspectRatio *pAROverridePtr = GetPreserveAspectRatioProperty(); + if (pAROverridePtr) { + return *pAROverridePtr; + } + } + + if (!HasViewBox() && ShouldSynthesizeViewBox()) { + // If we're synthesizing a viewBox, use preserveAspectRatio="none"; + return SVGPreserveAspectRatio( + nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE, + nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE); + } + + return mPreserveAspectRatio.GetAnimValue(); +} + //---------------------------------------------------------------------- // nsSVGSVGElement float nsSVGSVGElement::GetLength(PRUint8 aCtxType) { float h, w; @@ -1267,16 +1301,53 @@ ReleasePreserveAspectRatioPropertyValue( void* aPropertyValue, void* aData /* unused */) { SVGPreserveAspectRatio* valPtr = static_cast<SVGPreserveAspectRatio*>(aPropertyValue); delete valPtr; } +bool +nsSVGSVGElement:: + SetPreserveAspectRatioProperty(const SVGPreserveAspectRatio& aPAR) +{ + SVGPreserveAspectRatio* pAROverridePtr = new SVGPreserveAspectRatio(aPAR); + nsresult rv = SetProperty(nsGkAtoms::overridePreserveAspectRatio, + pAROverridePtr, + ReleasePreserveAspectRatioPropertyValue); + NS_ABORT_IF_FALSE(rv != NS_PROPTABLE_PROP_OVERWRITTEN, + "Setting override value when it's already set...?"); + + if (NS_UNLIKELY(NS_FAILED(rv))) { + // property-insertion failed (e.g. OOM in property-table code) + delete pAROverridePtr; + return false; + } + return true; +} + +const SVGPreserveAspectRatio* +nsSVGSVGElement::GetPreserveAspectRatioProperty() const +{ + void* valPtr = GetProperty(nsGkAtoms::overridePreserveAspectRatio); + if (valPtr) { + return static_cast<SVGPreserveAspectRatio*>(valPtr); + } + return nsnull; +} + +bool +nsSVGSVGElement::ClearPreserveAspectRatioProperty() +{ + void* valPtr = UnsetProperty(nsGkAtoms::overridePreserveAspectRatio); + delete static_cast<SVGPreserveAspectRatio*>(valPtr); + return valPtr; +} + void nsSVGSVGElement:: SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR) { #ifdef DEBUG NS_ABORT_IF_FALSE(GetCurrentDoc()->IsBeingUsedAsImage(), "should only override preserveAspectRatio in images"); #endif @@ -1292,72 +1363,121 @@ nsSVGSVGElement:: if (!HasViewBox()) { return; // preserveAspectRatio irrelevant (only matters if we have viewBox) } if (aPAR.GetDefer() && HasPreserveAspectRatio()) { return; // Referring element defers to my own preserveAspectRatio value. } - SVGPreserveAspectRatio* pAROverridePtr = new SVGPreserveAspectRatio(aPAR); - nsresult rv = SetProperty(nsGkAtoms::overridePreserveAspectRatio, - pAROverridePtr, - ReleasePreserveAspectRatioPropertyValue); - NS_ABORT_IF_FALSE(rv != NS_PROPTABLE_PROP_OVERWRITTEN, - "Setting override value when it's already set...?"); - - if (NS_LIKELY(NS_SUCCEEDED(rv))) { + if (SetPreserveAspectRatioProperty(aPAR)) { mImageNeedsTransformInvalidation = true; - } else { - // property-insertion failed (e.g. OOM in property-table code) - delete pAROverridePtr; } } void nsSVGSVGElement::ClearImageOverridePreserveAspectRatio() { #ifdef DEBUG NS_ABORT_IF_FALSE(GetCurrentDoc()->IsBeingUsedAsImage(), - "should only override preserveAspectRatio in images"); + "should only override image preserveAspectRatio in images"); #endif mIsPaintingSVGImageElement = false; if (!HasViewBox() && ShouldSynthesizeViewBox()) { // My non-<svg:image> clients will want to paint me with a synthesized // viewBox, but my <svg:image> client that just painted me did NOT // use that. Need to tell ourselves to flush our transform. mImageNeedsTransformInvalidation = true; } - void* valPtr = UnsetProperty(nsGkAtoms::overridePreserveAspectRatio); - if (valPtr) { + if (ClearPreserveAspectRatioProperty()) { mImageNeedsTransformInvalidation = true; - delete static_cast<SVGPreserveAspectRatio*>(valPtr); } } -const SVGPreserveAspectRatio* -nsSVGSVGElement::GetImageOverridePreserveAspectRatio() const -{ - void* valPtr = GetProperty(nsGkAtoms::overridePreserveAspectRatio); -#ifdef DEBUG - if (valPtr) { - NS_ABORT_IF_FALSE(GetCurrentDoc()->IsBeingUsedAsImage(), - "should only override preserveAspectRatio in images"); - } -#endif - - return static_cast<SVGPreserveAspectRatio*>(valPtr); -} - void nsSVGSVGElement::FlushImageTransformInvalidation() { NS_ABORT_IF_FALSE(!GetParent(), "Should only be called on root node"); NS_ABORT_IF_FALSE(GetCurrentDoc()->IsBeingUsedAsImage(), "Should only be called on image documents"); if (mImageNeedsTransformInvalidation) { InvalidateTransformNotifyFrame(); mImageNeedsTransformInvalidation = false; } } + +// Callback function, for freeing PRUint64 values stored in property table +static void +ReleaseViewBoxPropertyValue(void* aObject, /* unused */ + nsIAtom* aPropertyName, /* unused */ + void* aPropertyValue, + void* aData /* unused */) +{ + nsSVGViewBoxRect* valPtr = + static_cast<nsSVGViewBoxRect*>(aPropertyValue); + delete valPtr; +} + +bool +nsSVGSVGElement::SetViewBoxProperty(const nsSVGViewBoxRect& aViewBox) +{ + nsSVGViewBoxRect* pViewBoxOverridePtr = new nsSVGViewBoxRect(aViewBox); + nsresult rv = SetProperty(nsGkAtoms::viewBox, + pViewBoxOverridePtr, + ReleaseViewBoxPropertyValue); + NS_ABORT_IF_FALSE(rv != NS_PROPTABLE_PROP_OVERWRITTEN, + "Setting override value when it's already set...?"); + + if (NS_UNLIKELY(NS_FAILED(rv))) { + // property-insertion failed (e.g. OOM in property-table code) + delete pViewBoxOverridePtr; + return false; + } + return true; +} + +const nsSVGViewBoxRect* +nsSVGSVGElement::GetViewBoxProperty() const +{ + void* valPtr = GetProperty(nsGkAtoms::viewBox); + if (valPtr) { + return static_cast<nsSVGViewBoxRect*>(valPtr); + } + return nsnull; +} + +bool +nsSVGSVGElement::ClearViewBoxProperty() +{ + void* valPtr = UnsetProperty(nsGkAtoms::viewBox); + delete static_cast<nsSVGViewBoxRect*>(valPtr); + return valPtr; +} + +bool +nsSVGSVGElement::SetZoomAndPanProperty(PRUint16 aValue) +{ + nsresult rv = SetProperty(nsGkAtoms::zoomAndPan, reinterpret_cast<void*>(aValue)); + NS_ABORT_IF_FALSE(rv != NS_PROPTABLE_PROP_OVERWRITTEN, + "Setting override value when it's already set...?"); + + return NS_SUCCEEDED(rv); +} + +const PRUint16* +nsSVGSVGElement::GetZoomAndPanProperty() const +{ + void* valPtr = GetProperty(nsGkAtoms::zoomAndPan); + if (valPtr) { + return reinterpret_cast<PRUint16*>(valPtr); + } + return nsnull; +} + +bool +nsSVGSVGElement::ClearZoomAndPanProperty() +{ + return UnsetProperty(nsGkAtoms::viewBox); +} +
--- a/content/svg/content/src/nsSVGSVGElement.h +++ b/content/svg/content/src/nsSVGSVGElement.h @@ -50,37 +50,52 @@ #include "nsSVGEnum.h" #include "nsSVGLength2.h" #include "nsSVGStylableElement.h" #include "nsSVGViewBox.h" #include "SVGAnimatedPreserveAspectRatio.h" class nsIDOMSVGMatrix; class nsSMILTimeContainer; +class nsSVGViewElement; +namespace mozilla { + class SVGFragmentIdentifier; +} typedef nsSVGStylableElement nsSVGSVGElementBase; class nsSVGSVGElement; class nsSVGTranslatePoint { public: - nsSVGTranslatePoint(float aX, float aY) : - mX(aX), mY(aY) {} + nsSVGTranslatePoint() + : mX(0.0f) + , mY(0.0f) + {} + + nsSVGTranslatePoint(float aX, float aY) + : mX(aX) + , mY(aY) + {} void SetX(float aX) { mX = aX; } void SetY(float aY) { mY = aY; } float GetX() const { return mX; } float GetY() const { return mY; } nsresult ToDOMVal(nsSVGSVGElement *aElement, nsIDOMSVGPoint **aResult); + bool operator!=(const nsSVGTranslatePoint &rhs) const { + return mX != rhs.mX || mY != rhs.mY; + } + private: struct DOMVal : public nsIDOMSVGPoint { NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS(DOMVal) DOMVal(nsSVGTranslatePoint* aVal, nsSVGSVGElement *aElement) : mVal(aVal), mElement(aElement) {} @@ -122,18 +137,18 @@ class nsSVGSVGElement : public nsSVGSVGE public DOMSVGTests, public nsIDOMSVGFitToViewBox, public nsIDOMSVGLocatable, public nsIDOMSVGZoomAndPan { friend class nsSVGOuterSVGFrame; friend class nsSVGInnerSVGFrame; friend class nsSVGImageFrame; + friend class mozilla::SVGFragmentIdentifier; -protected: friend nsresult NS_NewSVGSVGElement(nsIContent **aResult, already_AddRefed<nsINodeInfo> aNodeInfo, mozilla::dom::FromParser aFromParser); nsSVGSVGElement(already_AddRefed<nsINodeInfo> aNodeInfo, mozilla::dom::FromParser aFromParser); public: typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio; @@ -215,18 +230,38 @@ public: * Returns true if we should synthesize a viewBox for ourselves (that is, if * we're the root element in an image document, and we're not currently being * painted for an <svg:image> element). * * Only call this method if HasViewBox() returns false. */ bool ShouldSynthesizeViewBox() const; + bool HasViewBoxOrSyntheticViewBox() const { + return HasViewBox() || ShouldSynthesizeViewBox(); + } + gfxMatrix GetViewBoxTransform() const; + bool HasChildrenOnlyTransform() const { + return mHasChildrenOnlyTransform; + } + + /** + * This method notifies the style system that the overflow rects of our + * immediate childrens' frames need to be updated. It is called by our own + * frame when changes (e.g. to currentScale) cause our children-only + * transform to change. + * + * The reason we have this method instead of overriding + * GetAttributeChangeHint is because we need to act on non-attribute (e.g. + * currentScale) changes in addition to attribute (e.g. viewBox) changes. + */ + void ChildrenOnlyTransformChanged(); + // This services any pending notifications for the transform on on this root // <svg> node needing to be recalculated. (Only applicable in // SVG-as-an-image documents.) virtual void FlushImageTransformInvalidation(); virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; svgFloatSize GetViewportSize() const { @@ -238,34 +273,43 @@ public: mViewportHeight = aSize.height; } virtual nsXPCClassInfo* GetClassInfo(); virtual nsIDOMNode* AsDOMNode() { return this; } private: - // Methods for <image> elements to override my "PreserveAspectRatio" value. - // These are private so that only our friends (nsSVGImageFrame in - // particular) have access. - void SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR); - void ClearImageOverridePreserveAspectRatio(); - const SVGPreserveAspectRatio* GetImageOverridePreserveAspectRatio() const; - -protected: // nsSVGElement overrides bool IsEventName(nsIAtom* aName); virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, bool aCompileEventHandlers); virtual void UnbindFromTree(bool aDeep, bool aNullParent); // implementation helpers: + // Methods for <image> elements to override my "PreserveAspectRatio" value. + // These are private so that only our friends (nsSVGImageFrame in + // particular) have access. + void SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR); + void ClearImageOverridePreserveAspectRatio(); + + // Set/Clear properties to hold old or override versions of attributes + bool SetPreserveAspectRatioProperty(const SVGPreserveAspectRatio& aPAR); + const SVGPreserveAspectRatio* GetPreserveAspectRatioProperty() const; + bool ClearPreserveAspectRatioProperty(); + bool SetViewBoxProperty(const nsSVGViewBoxRect& aViewBox); + const nsSVGViewBoxRect* GetViewBoxProperty() const; + bool ClearViewBoxProperty(); + bool SetZoomAndPanProperty(PRUint16 aValue); + const PRUint16* GetZoomAndPanProperty() const; + bool ClearZoomAndPanProperty(); + bool IsRoot() const { NS_ASSERTION((IsInDoc() && !GetParent()) == (OwnerDoc() && (OwnerDoc()->GetRootElement() == this)), "Can't determine if we're root"); return IsInDoc() && !GetParent(); } /** @@ -283,26 +327,39 @@ protected: * <svg> element _before_ the children are bound (as they want to know what * timed document root to register with) and therefore _before_ our parent is * set (both actions are performed by nsGenericElement::BindToTree) so we * can't use GetOwnerSVGElement() as it relies on GetParent(). This code is * basically a simplified version of GetOwnerSVGElement that uses the parent * parameters passed in instead. */ bool WillBeOutermostSVG(nsIContent* aParent, - nsIContent* aBindingParent) const; + nsIContent* aBindingParent) const; // invalidate viewbox -> viewport xform & inform frames void InvalidateTransformNotifyFrame(); // Returns true if we have at least one of the following: // - a (valid or invalid) value for the preserveAspectRatio attribute // - a SMIL-animated value for the preserveAspectRatio attribute bool HasPreserveAspectRatio(); + /** + * Returns the explicit viewBox rect, if specified, or else a synthesized + * viewBox, if appropriate, or else a viewBox matching the dimensions of the + * SVG viewport. + */ + nsSVGViewBoxRect GetViewBoxWithSynthesis( + float aViewportWidth, float aViewportHeight) const; + /** + * Returns the explicit or default preserveAspectRatio, unless we're + * synthesizing a viewBox, in which case it returns the "none" value. + */ + SVGPreserveAspectRatio GetPreserveAspectRatioWithOverride() const; + virtual LengthAttributesInfo GetLengthInfo(); enum { X, Y, WIDTH, HEIGHT }; nsSVGLength2 mLengthAttributes[4]; static LengthInfo sLengthInfo[4]; virtual EnumAttributesInfo GetEnumInfo(); @@ -344,11 +401,12 @@ protected: // For outermost <svg> elements created from parsing, animation is started by // the onload event in accordance with the SVG spec, but for <svg> elements // created by script or promoted from inner <svg> to outermost <svg> we need // to manually kick off animation when they are bound to the tree. bool mStartAnimationOnBindToTree; bool mImageNeedsTransformInvalidation; bool mIsPaintingSVGImageElement; + bool mHasChildrenOnlyTransform; }; #endif
--- a/content/svg/content/src/nsSVGViewBox.cpp +++ b/content/svg/content/src/nsSVGViewBox.cpp @@ -119,26 +119,26 @@ nsSVGViewBox::SetAnimValue(float aX, flo mAnimVal->y = aY; mAnimVal->width = aWidth; mAnimVal->height = aHeight; } aSVGElement->DidAnimateViewBox(); } void -nsSVGViewBox::SetBaseValue(float aX, float aY, float aWidth, float aHeight, +nsSVGViewBox::SetBaseValue(const nsSVGViewBoxRect& aRect, nsSVGElement *aSVGElement) { - if (mHasBaseVal && mBaseVal == nsSVGViewBoxRect(aX, aY, aWidth, aHeight)) { + if (mHasBaseVal && mBaseVal == aRect) { return; } nsAttrValue emptyOrOldValue = aSVGElement->WillChangeViewBox(); - mBaseVal = nsSVGViewBoxRect(aX, aY, aWidth, aHeight); + mBaseVal = aRect; mHasBaseVal = true; aSVGElement->DidChangeViewBox(emptyOrOldValue); if (mAnimVal) { aSVGElement->AnimationNeedsResample(); } }
--- a/content/svg/content/src/nsSVGViewBox.h +++ b/content/svg/content/src/nsSVGViewBox.h @@ -81,19 +81,21 @@ public: * positive, so callers must check whether the viewBox rect is valid where * necessary! */ bool IsExplicitlySet() const { return (mHasBaseVal || mAnimVal); } const nsSVGViewBoxRect& GetBaseValue() const { return mBaseVal; } - void SetBaseValue(float aX, float aY, float aWidth, float aHeight, + void SetBaseValue(const nsSVGViewBoxRect& aRect, nsSVGElement *aSVGElement); - + void SetBaseValue(float aX, float aY, float aWidth, float aHeight, + nsSVGElement *aSVGElement) + { SetBaseValue(nsSVGViewBoxRect(aX, aY, aWidth, aHeight), aSVGElement); } const nsSVGViewBoxRect& GetAnimValue() const { return mAnimVal ? *mAnimVal : mBaseVal; } void SetAnimValue(float aX, float aY, float aWidth, float aHeight, nsSVGElement *aSVGElement); nsresult SetBaseValueString(const nsAString& aValue, nsSVGElement *aSVGElement); void GetBaseValueString(nsAString& aValue) const;
new file mode 100644 --- /dev/null +++ b/content/svg/content/src/nsSVGViewElement.cpp @@ -0,0 +1,169 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla SVG project. + * + * The Initial Developer of the Original Code is Robert Longson. + * Portions created by the Initial Developer are Copyright (C) 2012 + * the Initial Developer. All Rights Reserved. + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsSVGViewElement.h" +#include "DOMSVGStringList.h" + +using namespace mozilla; + +nsSVGElement::StringListInfo nsSVGViewElement::sStringListInfo[1] = +{ + { &nsGkAtoms::viewTarget } +}; + +nsSVGEnumMapping nsSVGViewElement::sZoomAndPanMap[] = { + {&nsGkAtoms::disable, nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_DISABLE}, + {&nsGkAtoms::magnify, nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_MAGNIFY}, + {nsnull, 0} +}; + +nsSVGElement::EnumInfo nsSVGViewElement::sEnumInfo[1] = +{ + { &nsGkAtoms::zoomAndPan, + sZoomAndPanMap, + nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_MAGNIFY + } +}; + +NS_IMPL_NS_NEW_SVG_ELEMENT(View) + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGViewElement,nsSVGViewElementBase) +NS_IMPL_RELEASE_INHERITED(nsSVGViewElement,nsSVGViewElementBase) + +DOMCI_NODE_DATA(SVGViewElement, nsSVGViewElement) + +NS_INTERFACE_TABLE_HEAD(nsSVGViewElement) + NS_NODE_INTERFACE_TABLE6(nsSVGViewElement, nsIDOMNode, nsIDOMElement, + nsIDOMSVGElement, nsIDOMSVGViewElement, + nsIDOMSVGFitToViewBox, + nsIDOMSVGZoomAndPan) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGViewElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGViewElementBase) + +//---------------------------------------------------------------------- +// Implementation + +nsSVGViewElement::nsSVGViewElement(already_AddRefed<nsINodeInfo> aNodeInfo) + : nsSVGViewElementBase(aNodeInfo) +{ +} + +//---------------------------------------------------------------------- +// nsIDOMNode methods + +NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGViewElement) + +//---------------------------------------------------------------------- +// nsIDOMSVGZoomAndPan methods + +/* attribute unsigned short zoomAndPan; */ +NS_IMETHODIMP +nsSVGViewElement::GetZoomAndPan(PRUint16 *aZoomAndPan) +{ + *aZoomAndPan = mEnumAttributes[ZOOMANDPAN].GetAnimValue(); + return NS_OK; +} + +NS_IMETHODIMP +nsSVGViewElement::SetZoomAndPan(PRUint16 aZoomAndPan) +{ + if (aZoomAndPan == nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_DISABLE || + aZoomAndPan == nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_MAGNIFY) { + mEnumAttributes[ZOOMANDPAN].SetBaseValue(aZoomAndPan, this); + return NS_OK; + } + + return NS_ERROR_DOM_SVG_INVALID_VALUE_ERR; +} + +//---------------------------------------------------------------------- +// nsIDOMSVGFitToViewBox methods + +/* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ +NS_IMETHODIMP +nsSVGViewElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) +{ + return mViewBox.ToDOMAnimatedRect(aViewBox, this); +} + +/* readonly attribute nsIDOMSVGAnimatedPreserveAspectRatio preserveAspectRatio; */ +NS_IMETHODIMP +nsSVGViewElement::GetPreserveAspectRatio(nsIDOMSVGAnimatedPreserveAspectRatio + **aPreserveAspectRatio) +{ + return mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(aPreserveAspectRatio, this); +} + +//---------------------------------------------------------------------- +// nsIDOMSVGViewElement methods + +/* readonly attribute nsIDOMSVGStringList viewTarget; */ +NS_IMETHODIMP nsSVGViewElement::GetViewTarget(nsIDOMSVGStringList * *aViewTarget) +{ + *aViewTarget = DOMSVGStringList::GetDOMWrapper( + &mStringListAttributes[VIEW_TARGET], this, false, VIEW_TARGET).get(); + return NS_OK; +} + +//---------------------------------------------------------------------- +// nsSVGElement methods + +nsSVGElement::EnumAttributesInfo +nsSVGViewElement::GetEnumInfo() +{ + return EnumAttributesInfo(mEnumAttributes, sEnumInfo, + ArrayLength(sEnumInfo)); +} + +nsSVGViewBox * +nsSVGViewElement::GetViewBox() +{ + return &mViewBox; +} + +SVGAnimatedPreserveAspectRatio * +nsSVGViewElement::GetPreserveAspectRatio() +{ + return &mPreserveAspectRatio; +} + +nsSVGElement::StringListAttributesInfo +nsSVGViewElement::GetStringListInfo() +{ + return StringListAttributesInfo(mStringListAttributes, sStringListInfo, + ArrayLength(sStringListInfo)); +}
new file mode 100644 --- /dev/null +++ b/content/svg/content/src/nsSVGViewElement.h @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla SVG project. + * + * The Initial Developer of the Original Code is Robert Longson. + * Portions created by the Initial Developer are Copyright (C) 2012 + * the Initial Developer. All Rights Reserved. + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __NS_SVGVIEWELEMENT_H__ +#define __NS_SVGVIEWELEMENT_H__ + +#include "nsIDOMSVGViewElement.h" +#include "nsIDOMSVGFitToViewBox.h" +#include "nsIDOMSVGZoomAndPan.h" +#include "nsSVGElement.h" +#include "nsSVGEnum.h" +#include "nsSVGViewBox.h" +#include "SVGAnimatedPreserveAspectRatio.h" +#include "SVGStringList.h" + +namespace mozilla { + class SVGFragmentIdentifier; +} + +typedef nsSVGElement nsSVGViewElementBase; + +class nsSVGViewElement : public nsSVGViewElementBase, + public nsIDOMSVGViewElement, + public nsIDOMSVGFitToViewBox, + public nsIDOMSVGZoomAndPan +{ + friend class mozilla::SVGFragmentIdentifier; + friend nsresult NS_NewSVGViewElement(nsIContent **aResult, + already_AddRefed<nsINodeInfo> aNodeInfo); + nsSVGViewElement(already_AddRefed<nsINodeInfo> aNodeInfo); + +public: + // interfaces: + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIDOMSVGVIEWELEMENT + NS_DECL_NSIDOMSVGFITTOVIEWBOX + NS_DECL_NSIDOMSVGZOOMANDPAN + + // xxx If xpcom allowed virtual inheritance we wouldn't need to + // forward here :-( + NS_FORWARD_NSIDOMNODE(nsSVGViewElementBase::) + NS_FORWARD_NSIDOMELEMENT(nsSVGViewElementBase::) + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGViewElementBase::) + + virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; + + virtual nsXPCClassInfo* GetClassInfo(); + + virtual nsIDOMNode* AsDOMNode() { return this; } +private: + + // nsSVGElement overrides + + virtual EnumAttributesInfo GetEnumInfo(); + + enum { ZOOMANDPAN }; + nsSVGEnum mEnumAttributes[1]; + static nsSVGEnumMapping sZoomAndPanMap[]; + static EnumInfo sEnumInfo[1]; + + virtual nsSVGViewBox *GetViewBox(); + virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio(); + + nsSVGViewBox mViewBox; + SVGAnimatedPreserveAspectRatio mPreserveAspectRatio; + + virtual StringListAttributesInfo GetStringListInfo(); + + enum { VIEW_TARGET }; + SVGStringList mStringListAttributes[1]; + static StringListInfo sStringListInfo[1]; +}; + +#endif
--- a/content/svg/content/test/bounds-helper.svg +++ b/content/svg/content/test/bounds-helper.svg @@ -15,15 +15,16 @@ text { font: 20px monospace; } <g transform="rotate(45 175 75)"> <rect id="rect2" x="150" y="50" width="50" height="50" fill="yellow"/> <rect id="rect2a" x="150" y="50" width="50" height="50" fill="none" stroke-width="4" stroke="blue"/> <text id="text3" x="150" y="50" text-anchor="middle">abc</text> </g> <g transform="scale(2)"> <rect id="rect3" x="25" y="80" width="50" height="50" fill="green"/> <rect id="rect3a" x="25" y="80" width="50" height="50" fill="none" stroke-width="4" stroke="blue"/> + <rect id="rect3b" vector-effect="non-scaling-stroke" x="100" y="100" width="25" height="25" fill="orange" stroke-width="4" stroke="yellow"/> </g> <g transform="scale(2) rotate(45 175 75)"> <rect id="rect4" x="150" y="50" width="50" height="50" fill="yellow"/> <rect id="rect4a" x="150" y="50" width="50" height="50" fill="none" stroke-width="4" stroke="blue"/> </g> </g> </svg>
--- a/content/svg/content/test/test_bounds.html +++ b/content/svg/content/test/test_bounds.html @@ -88,16 +88,17 @@ function runTest() isWithAbsTolerance(rect4Bounds.left, rect.left, 0.1, "rect4.getBoundingClientRect().left"); isWithAbsTolerance(rect4Bounds.top, rect.top, 0.1, "rect4.getBoundingClientRect().top"); isWithAbsTolerance(rect4Bounds.width, rect.width, 0.1, "rect4.getBoundingClientRect().width"); isWithAbsTolerance(rect4Bounds.height, rect.height, 0.1, "rect4.getBoundingClientRect().height"); var rect1aBounds = doc.getElementById("rect1a").getBoundingClientRect(); var rect2aBounds = doc.getElementById("rect2a").getBoundingClientRect(); var rect3aBounds = doc.getElementById("rect3a").getBoundingClientRect(); + var rect3bBounds = doc.getElementById("rect3b").getBoundingClientRect(); var rect4aBounds = doc.getElementById("rect4a").getBoundingClientRect(); is(rect1aBounds.left, 48, "rect1a.getBoundingClientRect().left"); is(rect1aBounds.top, 48, "rect1a.getBoundingClientRect().top"); is(rect1aBounds.width, 54, "rect1a.getBoundingClientRect().width"); is(rect1aBounds.height, 54, "rect1a.getBoundingClientRect().height"); rect = new Rect(175 - 54 * sin45, 75 - 54 * sin45, 54 * sin45 * 2, 54 * sin45 * 2); @@ -106,16 +107,21 @@ function runTest() isWithAbsTolerance(rect2aBounds.width, rect.width, 0.1, "rect2a.getBoundingClientRect().width"); isWithAbsTolerance(rect2aBounds.height, rect.height, 0.1, "rect2a.getBoundingClientRect().height"); is(rect3aBounds.left, 46, "rect3a.getBoundingClientRect().left"); is(rect3aBounds.top, 156, "rect3a.getBoundingClientRect().top"); is(rect3aBounds.width, 108, "rect3a.getBoundingClientRect().width"); is(rect3aBounds.height, 108, "rect3a.getBoundingClientRect().height"); + is(rect3bBounds.left, 198, "rect3b.getBoundingClientRect().left"); + is(rect3bBounds.top, 198, "rect3b.getBoundingClientRect().top"); + is(rect3bBounds.width, 54, "rect3b.getBoundingClientRect().width"); + is(rect3bBounds.height, 54, "rect3b.getBoundingClientRect().height"); + rect = new Rect(350 - 108 * sin45, 150 - 108 * sin45, 108 * sin45 * 2, 108 * sin45 * 2); isWithAbsTolerance(rect4aBounds.left, rect.left, 0.1, "rect4a.getBoundingClientRect().left"); isWithAbsTolerance(rect4aBounds.top, rect.top, 0.1, "rect4a.getBoundingClientRect().top"); isWithAbsTolerance(rect4aBounds.width, rect.width, 0.1, "rect4a.getBoundingClientRect().width"); isWithAbsTolerance(rect4aBounds.height, rect.height, 0.1, "rect4a.getBoundingClientRect().height"); var text1a = doc.getElementById("text1a");
--- a/content/xbl/src/Makefile.in +++ b/content/xbl/src/Makefile.in @@ -84,12 +84,11 @@ LOCAL_INCLUDES = \ -I$(srcdir)/../../html/document/src \ -I$(srcdir)/../../xml/document/src \ -I$(srcdir)/../../xul/content/src \ -I$(srcdir)/../../xul/document/src \ -I$(srcdir)/../../events/src \ -I$(srcdir)/../../../layout/style \ -I$(srcdir)/../../../dom/base \ -I$(topsrcdir)/xpcom/ds \ - -I$(topsrcdir)/js/xpconnect/src \ $(NULL) DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/xbl/src/nsBindingManager.cpp +++ b/content/xbl/src/nsBindingManager.cpp @@ -549,18 +549,17 @@ nsBindingManager::GetBinding(nsIContent* return nsnull; } nsresult nsBindingManager::SetBinding(nsIContent* aContent, nsXBLBinding* aBinding) { if (!mBindingTable.IsInitialized()) { - if (!mBindingTable.Init()) - return NS_ERROR_OUT_OF_MEMORY; + mBindingTable.Init(); } // After this point, aBinding will be the most-derived binding for aContent. // If we already have a binding for aContent in our table, make sure to // remove it from the attached stack. Otherwise we might end up firing its // constructor twice (if aBinding inherits from it) or firing its constructor // after aContent has been deleted (if aBinding is null and the content node // dies before we process mAttachedStack). @@ -579,36 +578,34 @@ nsBindingManager::SetBinding(nsIContent* // Don't remove items here as that could mess up an executing // ProcessAttachedQueue PRUint32 index = mAttachedStack.IndexOf(oldBinding); if (index != mAttachedStack.NoIndex) { mAttachedStack[index] = nsnull; } } - bool result = true; - if (aBinding) { aContent->SetFlags(NODE_MAY_BE_IN_BINDING_MNGR); - result = mBindingTable.Put(aContent, aBinding); + mBindingTable.Put(aContent, aBinding); } else { mBindingTable.Remove(aContent); // The death of the bindings means the death of the JS wrapper, // and the flushing of our explicit and anonymous insertion point // lists. SetWrappedJS(aContent, nsnull); SetContentListFor(aContent, nsnull); SetAnonymousNodesFor(aContent, nsnull); if (oldBinding) { oldBinding->SetBoundElement(nsnull); } } - return result ? NS_OK : NS_ERROR_FAILURE; + return NS_OK; } nsIContent* nsBindingManager::GetInsertionParent(nsIContent* aContent) { if (mInsertionParentTable.ops) { return static_cast<nsIContent*> (LookupObject(mInsertionParentTable, aContent)); @@ -1096,22 +1093,21 @@ nsBindingManager::ExecuteDetachedHandler } } nsresult nsBindingManager::PutXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo) { NS_PRECONDITION(aDocumentInfo, "Must have a non-null documentinfo!"); - NS_ENSURE_TRUE(mDocumentTable.IsInitialized() || mDocumentTable.Init(16), - NS_ERROR_OUT_OF_MEMORY); + if (!mDocumentTable.IsInitialized()) + mDocumentTable.Init(16); - NS_ENSURE_TRUE(mDocumentTable.Put(aDocumentInfo->DocumentURI(), - aDocumentInfo), - NS_ERROR_OUT_OF_MEMORY); + mDocumentTable.Put(aDocumentInfo->DocumentURI(), + aDocumentInfo); return NS_OK; } void nsBindingManager::RemoveXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo) { if (mDocumentTable.IsInitialized()) { @@ -1128,21 +1124,20 @@ nsBindingManager::GetXBLDocumentInfo(nsI return mDocumentTable.GetWeak(aURL); } nsresult nsBindingManager::PutLoadingDocListener(nsIURI* aURL, nsIStreamListener* aListener) { NS_PRECONDITION(aListener, "Must have a non-null listener!"); - NS_ENSURE_TRUE(mLoadingDocTable.IsInitialized() || mLoadingDocTable.Init(16), - NS_ERROR_OUT_OF_MEMORY); + if (!mLoadingDocTable.IsInitialized()) + mLoadingDocTable.Init(16); - NS_ENSURE_TRUE(mLoadingDocTable.Put(aURL, aListener), - NS_ERROR_OUT_OF_MEMORY); + mLoadingDocTable.Put(aURL, aListener); return NS_OK; } nsIStreamListener* nsBindingManager::GetLoadingDocListener(nsIURI* aURL) { if (!mLoadingDocTable.IsInitialized()) @@ -1350,18 +1345,19 @@ static PLDHashOperator EnumRuleProcessors(nsISupports *aKey, nsXBLBinding *aBinding, void* aClosure) { RuleProcessorSet *set = static_cast<RuleProcessorSet*>(aClosure); for (nsXBLBinding *binding = aBinding; binding; binding = binding->GetBaseBinding()) { nsIStyleRuleProcessor *ruleProc = binding->PrototypeBinding()->GetRuleProcessor(); if (ruleProc) { - if (!set->IsInitialized() && !set->Init(16)) - return PL_DHASH_STOP; + if (!set->IsInitialized()) { + set->Init(16); + } set->PutEntry(ruleProc); } } return PL_DHASH_NEXT; } struct WalkAllRulesData { nsIStyleRuleProcessor::EnumFunc mFunc;
--- a/content/xbl/src/nsXBLBinding.cpp +++ b/content/xbl/src/nsXBLBinding.cpp @@ -108,17 +108,17 @@ XBLFinalize(JSFreeOp *fop, JSObject *obj static_cast<nsXBLDocumentInfo*>(::JS_GetPrivate(obj)); NS_RELEASE(docInfo); nsXBLJSClass* c = static_cast<nsXBLJSClass*>(::JS_GetClass(obj)); c->Drop(); } static JSBool -XBLResolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags, +XBLResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags, JSObject **objp) { // Note: if we get here, that means that the implementation for some binding // was installed, which means that AllowScripts() tested true. Hence no need // to do checks like that here. // Default to not resolving things. NS_ASSERTION(*objp, "Must have starting object"); @@ -1433,32 +1433,24 @@ nsXBLBinding::HasInsertionParent(nsICont nsresult nsXBLBinding::GetInsertionPointsFor(nsIContent* aParent, nsInsertionPointList** aResult) { if (!mInsertionPointTable) { mInsertionPointTable = new nsClassHashtable<nsISupportsHashKey, nsInsertionPointList>; - if (!mInsertionPointTable || !mInsertionPointTable->Init(4)) { - delete mInsertionPointTable; - mInsertionPointTable = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } + mInsertionPointTable->Init(4); } mInsertionPointTable->Get(aParent, aResult); if (!*aResult) { *aResult = new nsInsertionPointList; - if (!*aResult || !mInsertionPointTable->Put(aParent, *aResult)) { - delete *aResult; - *aResult = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } + mInsertionPointTable->Put(aParent, *aResult); if (aParent) { aParent->SetFlags(NODE_IS_INSERTION_PARENT); } } return NS_OK; }
--- a/content/xbl/src/nsXBLDocumentInfo.cpp +++ b/content/xbl/src/nsXBLDocumentInfo.cpp @@ -138,33 +138,33 @@ nsXBLDocGlobalObject::doCheckAccess(JSCo } nsresult rv = ssm->CheckPropertyAccess(cx, obj, JS_GetClass(obj)->name, id, accessType); return NS_SUCCEEDED(rv); } static JSBool -nsXBLDocGlobalObject_getProperty(JSContext *cx, JSObject *obj, - jsid id, jsval *vp) +nsXBLDocGlobalObject_getProperty(JSContext *cx, JSHandleObject obj, + JSHandleId id, jsval *vp) { return nsXBLDocGlobalObject:: doCheckAccess(cx, obj, id, nsIXPCSecurityManager::ACCESS_GET_PROPERTY); } static JSBool -nsXBLDocGlobalObject_setProperty(JSContext *cx, JSObject *obj, - jsid id, JSBool strict, jsval *vp) +nsXBLDocGlobalObject_setProperty(JSContext *cx, JSHandleObject obj, + JSHandleId id, JSBool strict, jsval *vp) { return nsXBLDocGlobalObject:: doCheckAccess(cx, obj, id, nsIXPCSecurityManager::ACCESS_SET_PROPERTY); } static JSBool -nsXBLDocGlobalObject_checkAccess(JSContext *cx, JSObject *obj, jsid id, +nsXBLDocGlobalObject_checkAccess(JSContext *cx, JSHandleObject obj, JSHandleId id, JSAccessMode mode, jsval *vp) { PRUint32 translated; if (mode & JSACC_WRITE) { translated = nsIXPCSecurityManager::ACCESS_SET_PROPERTY; } else { translated = nsIXPCSecurityManager::ACCESS_GET_PROPERTY; } @@ -185,17 +185,17 @@ nsXBLDocGlobalObject_finalize(JSFreeOp * // The addref was part of JSObject construction NS_RELEASE(nativeThis); DestroyProtoOrIfaceCache(obj); } static JSBool -nsXBLDocGlobalObject_resolve(JSContext *cx, JSObject *obj, jsid id) +nsXBLDocGlobalObject_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id) { JSBool did_resolve = JS_FALSE; return JS_ResolveStandardClass(cx, obj, id, &did_resolve); } JSClass nsXBLDocGlobalObject::gSharedGlobalClass = { "nsXBLPrototypeScript compilation scope",
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp +++ b/content/xbl/src/nsXBLPrototypeHandler.cpp @@ -642,136 +642,20 @@ struct keyCodeData { PRUint32 keycode; }; // All of these must be uppercase, since the function below does // case-insensitive comparison by converting to uppercase. // XXX: be sure to check this periodically for new symbol additions! static const keyCodeData gKeyCodes[] = { -#define KEYCODE_ENTRY(str) {#str, sizeof(#str) - 1, nsIDOMKeyEvent::DOM_##str} -#define KEYCODE_ENTRY2(str, code) {str, sizeof(str) - 1, code} - - KEYCODE_ENTRY(VK_CANCEL), - KEYCODE_ENTRY2("VK_BACK", nsIDOMKeyEvent::DOM_VK_BACK_SPACE), - KEYCODE_ENTRY(VK_TAB), - KEYCODE_ENTRY(VK_CLEAR), - KEYCODE_ENTRY(VK_RETURN), - KEYCODE_ENTRY(VK_ENTER), - KEYCODE_ENTRY(VK_SHIFT), - KEYCODE_ENTRY(VK_CONTROL), - KEYCODE_ENTRY(VK_ALT), - KEYCODE_ENTRY(VK_PAUSE), - KEYCODE_ENTRY(VK_CAPS_LOCK), - KEYCODE_ENTRY(VK_ESCAPE), - KEYCODE_ENTRY(VK_SPACE), - KEYCODE_ENTRY(VK_PAGE_UP), - KEYCODE_ENTRY(VK_PAGE_DOWN), - KEYCODE_ENTRY(VK_END), - KEYCODE_ENTRY(VK_HOME), - KEYCODE_ENTRY(VK_LEFT), - KEYCODE_ENTRY(VK_UP), - KEYCODE_ENTRY(VK_RIGHT), - KEYCODE_ENTRY(VK_DOWN), - KEYCODE_ENTRY(VK_PRINTSCREEN), - KEYCODE_ENTRY(VK_INSERT), - KEYCODE_ENTRY(VK_HELP), - KEYCODE_ENTRY(VK_DELETE), - KEYCODE_ENTRY(VK_0), - KEYCODE_ENTRY(VK_1), - KEYCODE_ENTRY(VK_2), - KEYCODE_ENTRY(VK_3), - KEYCODE_ENTRY(VK_4), - KEYCODE_ENTRY(VK_5), - KEYCODE_ENTRY(VK_6), - KEYCODE_ENTRY(VK_7), - KEYCODE_ENTRY(VK_8), - KEYCODE_ENTRY(VK_9), - KEYCODE_ENTRY(VK_SEMICOLON), - KEYCODE_ENTRY(VK_EQUALS), - KEYCODE_ENTRY(VK_A), - KEYCODE_ENTRY(VK_B), - KEYCODE_ENTRY(VK_C), - KEYCODE_ENTRY(VK_D), - KEYCODE_ENTRY(VK_E), - KEYCODE_ENTRY(VK_F), - KEYCODE_ENTRY(VK_G), - KEYCODE_ENTRY(VK_H), - KEYCODE_ENTRY(VK_I), - KEYCODE_ENTRY(VK_J), - KEYCODE_ENTRY(VK_K), - KEYCODE_ENTRY(VK_L), - KEYCODE_ENTRY(VK_M), - KEYCODE_ENTRY(VK_N), - KEYCODE_ENTRY(VK_O), - KEYCODE_ENTRY(VK_P), - KEYCODE_ENTRY(VK_Q), - KEYCODE_ENTRY(VK_R), - KEYCODE_ENTRY(VK_S), - KEYCODE_ENTRY(VK_T), - KEYCODE_ENTRY(VK_U), - KEYCODE_ENTRY(VK_V), - KEYCODE_ENTRY(VK_W), - KEYCODE_ENTRY(VK_X), - KEYCODE_ENTRY(VK_Y), - KEYCODE_ENTRY(VK_Z), - KEYCODE_ENTRY(VK_NUMPAD0), - KEYCODE_ENTRY(VK_NUMPAD1), - KEYCODE_ENTRY(VK_NUMPAD2), - KEYCODE_ENTRY(VK_NUMPAD3), - KEYCODE_ENTRY(VK_NUMPAD4), - KEYCODE_ENTRY(VK_NUMPAD5), - KEYCODE_ENTRY(VK_NUMPAD6), - KEYCODE_ENTRY(VK_NUMPAD7), - KEYCODE_ENTRY(VK_NUMPAD8), - KEYCODE_ENTRY(VK_NUMPAD9), - KEYCODE_ENTRY(VK_MULTIPLY), - KEYCODE_ENTRY(VK_ADD), - KEYCODE_ENTRY(VK_SEPARATOR), - KEYCODE_ENTRY(VK_SUBTRACT), - KEYCODE_ENTRY(VK_DECIMAL), - KEYCODE_ENTRY(VK_DIVIDE), - KEYCODE_ENTRY(VK_F1), - KEYCODE_ENTRY(VK_F2), - KEYCODE_ENTRY(VK_F3), - KEYCODE_ENTRY(VK_F4), - KEYCODE_ENTRY(VK_F5), - KEYCODE_ENTRY(VK_F6), - KEYCODE_ENTRY(VK_F7), - KEYCODE_ENTRY(VK_F8), - KEYCODE_ENTRY(VK_F9), - KEYCODE_ENTRY(VK_F10), - KEYCODE_ENTRY(VK_F11), - KEYCODE_ENTRY(VK_F12), - KEYCODE_ENTRY(VK_F13), - KEYCODE_ENTRY(VK_F14), - KEYCODE_ENTRY(VK_F15), - KEYCODE_ENTRY(VK_F16), - KEYCODE_ENTRY(VK_F17), - KEYCODE_ENTRY(VK_F18), - KEYCODE_ENTRY(VK_F19), - KEYCODE_ENTRY(VK_F20), - KEYCODE_ENTRY(VK_F21), - KEYCODE_ENTRY(VK_F22), - KEYCODE_ENTRY(VK_F23), - KEYCODE_ENTRY(VK_F24), - KEYCODE_ENTRY(VK_NUM_LOCK), - KEYCODE_ENTRY(VK_SCROLL_LOCK), - KEYCODE_ENTRY(VK_COMMA), - KEYCODE_ENTRY(VK_PERIOD), - KEYCODE_ENTRY(VK_SLASH), - KEYCODE_ENTRY(VK_BACK_QUOTE), - KEYCODE_ENTRY(VK_OPEN_BRACKET), - KEYCODE_ENTRY(VK_BACK_SLASH), - KEYCODE_ENTRY(VK_CLOSE_BRACKET), - KEYCODE_ENTRY(VK_QUOTE) - -#undef KEYCODE_ENTRY -#undef KEYCODE_ENTRY2 - +#define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) \ + { #aDOMKeyName, sizeof(#aDOMKeyName) - 1, aDOMKeyCode } +#include "nsVKList.h" +#undef NS_DEFINE_VK }; PRInt32 nsXBLPrototypeHandler::GetMatchingKeyCode(const nsAString& aKeyName) { nsCAutoString keyName; keyName.AssignWithConversion(aKeyName); ToUpperCase(keyName); // We want case-insensitive comparison with data // stored as uppercase.
--- a/content/xslt/src/xslt/txEXSLTFunctions.cpp +++ b/content/xslt/src/xslt/txEXSLTFunctions.cpp @@ -402,29 +402,25 @@ txEXSLTFunctionCall::evaluate(txIEvalCon getter_AddRefs(nodes)); NS_ENSURE_SUCCESS(rv, rv); nsRefPtr<txNodeSet> resultSet; rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet)); NS_ENSURE_SUCCESS(rv, rv); nsTHashtable<nsStringHashKey> hash; - if (!hash.Init()) { - return NS_ERROR_OUT_OF_MEMORY; - } + hash.Init(); PRInt32 i, len = nodes->size(); for (i = 0; i < len; ++i) { nsAutoString str; const txXPathNode& node = nodes->get(i); txXPathNodeUtils::appendNodeValue(node, str); if (!hash.GetEntry(str)) { - if (!hash.PutEntry(str)) { - return NS_ERROR_OUT_OF_MEMORY; - } + hash.PutEntry(str); rv = resultSet->append(node); NS_ENSURE_SUCCESS(rv, rv); } } NS_ADDREF(*aResult = resultSet); return NS_OK;
--- a/content/xslt/src/xslt/txExecutionState.cpp +++ b/content/xslt/src/xslt/txExecutionState.cpp @@ -46,18 +46,17 @@ #include "txLog.h" #include "txURIUtils.h" #include "txXMLParser.h" const PRInt32 txExecutionState::kMaxRecursionDepth = 20000; nsresult txLoadedDocumentsHash::init(txXPathNode* aSourceDocument) { - nsresult rv = Init(8); - NS_ENSURE_SUCCESS(rv, rv); + Init(8); mSourceDocument = aSourceDocument; nsAutoString baseURI; txXPathNodeUtils::getBaseURI(*mSourceDocument, baseURI); txLoadedDocumentEntry* entry = PutEntry(baseURI); if (!entry) {
--- a/content/xslt/src/xslt/txKeyFunctionCall.cpp +++ b/content/xslt/src/xslt/txKeyFunctionCall.cpp @@ -267,25 +267,20 @@ txKeyHash::getKeyNodes(const txExpandedN } return NS_OK; } nsresult txKeyHash::init() { - nsresult rv = mKeyValues.Init(8); - NS_ENSURE_SUCCESS(rv, rv); + mKeyValues.Init(8); + mIndexedKeys.Init(1); + mEmptyNodeSet = new txNodeSet(nsnull); - rv = mIndexedKeys.Init(1); - NS_ENSURE_SUCCESS(rv, rv); - - mEmptyNodeSet = new txNodeSet(nsnull); - NS_ENSURE_TRUE(mEmptyNodeSet, NS_ERROR_OUT_OF_MEMORY); - return NS_OK; } /** * Adds a match/use pair. * @param aMatch match-pattern * @param aUse use-expression
--- a/content/xul/content/test/Makefile.in +++ b/content/xul/content/test/Makefile.in @@ -45,17 +45,16 @@ include $(DEPTH)/config/autoconf.mk include $(topsrcdir)/config/rules.mk _TEST_FILES = \ test_bug486990.xul \ test_bug749367.xul \ $(NULL) _CHROME_FILES = \ - test_bug330705-2.xul \ test_bug233643.xul \ test_bug398289.html \ 398289-resource.xul \ $(NULL) libs:: $(_TEST_FILES) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
deleted file mode 100644 --- a/content/xul/content/test/test_bug330705-2.xul +++ /dev/null @@ -1,50 +0,0 @@ -<?xml version="1.0"?> -<?xml-stylesheet href="chrome://global/skin" type="text/css"?> -<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?> -<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml" - title="Test for Bug 330705"> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=330705 ---> - <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> - <body xmlns="http://www.w3.org/1999/xhtml"> - <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=330705">Mozilla Bug 330705</a> - <p id="display"> - <box tabindex="1" style="-moz-user-focus:normal;" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/> - <box tabindex="1" style="-moz-user-focus:normal;" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/> - </p> - <div id="content" style="display: none"> - <script class="testbody" type="text/javascript"> - <![CDATA[ - SimpleTest.waitForExplicitFinish(); - - var isFocused = false; - - function doTest() { - document.getElementsByTagName('box')[1].blur(); - setTimeout(function () { - ok(isFocused, - "The first box element is still focused after blur() has been called on the second box element"); - SimpleTest.finish(); - }, 0); - } - - function onLoad() { - var box = document.getElementsByTagName('box')[0]; - box.addEventListener('focus', function() { - isFocused = true; - setTimeout(doTest, 0); - box.removeEventListener('focus', arguments.callee, true); - }, true); - box.addEventListener('blur', function() { isFocused = false;}, true); - box.focus(); - } - - addLoadEvent(onLoad); - ]]> - </script> - <pre id="test"> - </pre> - </div> - </body> -</window>
--- a/content/xul/document/src/Makefile.in +++ b/content/xul/document/src/Makefile.in @@ -71,13 +71,12 @@ LOCAL_INCLUDES = -I$(srcdir)/../../../ba -I$(srcdir)/../../../../layout/base \ -I$(srcdir)/../../../../layout/generic \ -I$(srcdir)/../../../../layout/style \ -I$(srcdir)/../../../../layout/xul/base/src \ -I$(srcdir)/../../../xml/document/src \ -I$(srcdir)/../../../xbl/src \ -I$(srcdir)/../../../events/src \ -I$(topsrcdir)/xpcom/ds \ - -I$(topsrcdir)/js/xpconnect/src \ -I$(topsrcdir)/dom/base \ $(NULL) DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -1868,20 +1868,17 @@ NS_IMETHODIMP nsXULDocument::SetTemplateBuilderFor(nsIContent* aContent, nsIXULTemplateBuilder* aBuilder) { if (! mTemplateBuilderTable) { if (!aBuilder) { return NS_OK; } mTemplateBuilderTable = new BuilderTable; - if (! mTemplateBuilderTable || !mTemplateBuilderTable->Init()) { - mTemplateBuilderTable = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } + mTemplateBuilderTable->Init(); } if (aBuilder) { mTemplateBuilderTable->Put(aContent, aBuilder); } else { mTemplateBuilderTable->Remove(aContent); } @@ -2644,19 +2641,19 @@ nsXULDocument::LoadOverlay(const nsAStri nsresult rv; nsCOMPtr<nsIURI> uri; rv = NS_NewURI(getter_AddRefs(uri), aURL, nsnull); if (NS_FAILED(rv)) return rv; if (aObserver) { nsIObserver* obs = nsnull; - NS_ENSURE_TRUE(mOverlayLoadObservers.IsInitialized() || mOverlayLoadObservers.Init(), - NS_ERROR_OUT_OF_MEMORY); - + if (!mOverlayLoadObservers.IsInitialized()) { + mOverlayLoadObservers.Init(); + } obs = mOverlayLoadObservers.GetWeak(uri); if (obs) { // We don't support loading the same overlay twice into the same // document - that doesn't make sense anyway. return NS_ERROR_FAILURE; } mOverlayLoadObservers.Put(uri, aObserver); @@ -3243,18 +3240,19 @@ nsXULDocument::DoneWalking() // yet been attached. This can be a race condition because dynamic // overlay loading can take varying amounts of time depending on // whether or not the overlay prototype is in the XUL cache. The // most likely effect of this bug is odd UI initialization due to // methods and properties that do not work. // XXXbz really, we shouldn't be firing binding constructors // until after StartLayout returns! - NS_ENSURE_TRUE(mPendingOverlayLoadNotifications.IsInitialized() || mPendingOverlayLoadNotifications.Init(), - NS_ERROR_OUT_OF_MEMORY); + if (!mPendingOverlayLoadNotifications.IsInitialized()) { + mPendingOverlayLoadNotifications.Init(); + } mPendingOverlayLoadNotifications.Get(overlayURI, getter_AddRefs(obs)); if (!obs) { mOverlayLoadObservers.Get(overlayURI, getter_AddRefs(obs)); NS_ASSERTION(obs, "null overlay load observer?"); mPendingOverlayLoadNotifications.Put(overlayURI, obs); } }
--- a/content/xul/document/src/nsXULPrototypeCache.cpp +++ b/content/xul/document/src/nsXULPrototypeCache.cpp @@ -204,28 +204,27 @@ nsXULPrototypeCache::GetPrototype(nsIURI return newProto; } nsresult nsXULPrototypeCache::PutPrototype(nsXULPrototypeDocument* aDocument) { nsCOMPtr<nsIURI> uri = aDocument->GetURI(); // Put() releases any old value and addrefs the new one - NS_ENSURE_TRUE(mPrototypeTable.Put(uri, aDocument), NS_ERROR_OUT_OF_MEMORY); + mPrototypeTable.Put(uri, aDocument); return NS_OK; } nsresult nsXULPrototypeCache::PutStyleSheet(nsCSSStyleSheet* aStyleSheet) { nsIURI* uri = aStyleSheet->GetSheetURI(); - NS_ENSURE_TRUE(mStyleSheetTable.Put(uri, aStyleSheet), - NS_ERROR_OUT_OF_MEMORY); + mStyleSheetTable.Put(uri, aStyleSheet); return NS_OK; } JSScript* nsXULPrototypeCache::GetScript(nsIURI* aURI) { @@ -261,17 +260,17 @@ nsXULPrototypeCache::PutScript(nsIURI* a NS_WARNING(message.get()); #endif // Reuse the callback used for enumeration in FlushScripts ReleaseScriptObjectCallback(aURI, existingEntry, nsnull); } CacheScriptEntry entry = {aScriptObject}; - NS_ENSURE_TRUE(mScriptTable.Put(aURI, entry), NS_ERROR_OUT_OF_MEMORY); + mScriptTable.Put(aURI, entry); // Lock the object from being gc'd until it is removed from the cache nsCOMPtr<nsIScriptRuntime> rt; nsresult rv = NS_GetJSRuntime(getter_AddRefs(rt)); if (NS_SUCCEEDED(rv)) rv = rt->HoldScriptObject(aScriptObject); NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to GC lock the object"); @@ -291,18 +290,17 @@ nsXULPrototypeCache::FlushScripts() nsresult nsXULPrototypeCache::PutXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo) { nsIURI* uri = aDocumentInfo->DocumentURI(); nsRefPtr<nsXBLDocumentInfo> info; mXBLDocTable.Get(uri, getter_AddRefs(info)); if (!info) { - NS_ENSURE_TRUE(mXBLDocTable.Put(uri, aDocumentInfo), - NS_ERROR_OUT_OF_MEMORY); + mXBLDocTable.Put(uri, aDocumentInfo); } return NS_OK; } static PLDHashOperator FlushSkinXBL(nsIURI* aKey, nsRefPtr<nsXBLDocumentInfo>& aDocInfo, void* aClosure) { nsCAutoString str;
--- a/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -132,17 +132,17 @@ nsXULPDGlobalObject_finalize(JSFreeOp *f // The addref was part of JSObject construction NS_RELEASE(nativeThis); DestroyProtoOrIfaceCache(obj); } JSBool -nsXULPDGlobalObject_resolve(JSContext *cx, JSObject *obj, jsid id) +nsXULPDGlobalObject_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id) { JSBool did_resolve = JS_FALSE; return JS_ResolveStandardClass(cx, obj, id, &did_resolve); } JSClass nsXULPDGlobalObject::gSharedGlobalClass = {
--- a/content/xul/templates/src/nsXULContentBuilder.cpp +++ b/content/xul/templates/src/nsXULContentBuilder.cpp @@ -1236,19 +1236,18 @@ nsXULContentBuilder::CreateContainerCont } if (mFlags & eLoggingEnabled) OutputMatchToLog(resultid, newmatch, true); if (prevmatch) { prevmatch->mNext = newmatch; } - else if (!mMatchMap.Put(resultid, newmatch)) { - nsTemplateMatch::Destroy(mPool, newmatch, true); - return NS_ERROR_OUT_OF_MEMORY; + else { + mMatchMap.Put(resultid, newmatch); } if (removematch) { newmatch->mNext = removematch->mNext; nsTemplateMatch::Destroy(mPool, removematch, true); } else { newmatch->mNext = existingmatch;
--- a/content/xul/templates/src/nsXULTemplateBuilder.cpp +++ b/content/xul/templates/src/nsXULTemplateBuilder.cpp @@ -206,18 +206,18 @@ nsXULTemplateBuilder::InitGlobals() return rv; } #ifdef PR_LOGGING if (! gXULTemplateLog) gXULTemplateLog = PR_NewLogModule("nsXULTemplateBuilder"); #endif - if (!mMatchMap.IsInitialized() && !mMatchMap.Init()) - return NS_ERROR_OUT_OF_MEMORY; + if (!mMatchMap.IsInitialized()) + mMatchMap.Init(); const size_t bucketsizes[] = { sizeof(nsTemplateMatch) }; return mPool.Init("nsXULTemplateBuilder", bucketsizes, 1, 256); } void nsXULTemplateBuilder::CleanUp(bool aIsFinal) { @@ -786,18 +786,17 @@ nsXULTemplateBuilder::UpdateResultInCont findmatch = findmatch->mNext; } } if (oldmatch == firstmatch) { // the match to remove is at the beginning if (oldmatch->mNext) { - if (!mMatchMap.Put(aOldId, oldmatch->mNext)) - return NS_ERROR_OUT_OF_MEMORY; + mMatchMap.Put(aOldId, oldmatch->mNext); } else { mMatchMap.Remove(aOldId); } } if (prevmatch) prevmatch->mNext = nextmatch; @@ -960,23 +959,17 @@ nsXULTemplateBuilder::UpdateResultInCont } newmatch = newmatch->mNext; } } // put the match in the map if there isn't a previous match if (! prevmatch) { - if (!mMatchMap.Put(aNewId, newmatch)) { - // The match may have already matched a rule above, so - // HasBeenRemoved should be called to indicate that it - // is being removed again. - nsTemplateMatch::Destroy(mPool, newmatch, true); - return rv; - } + mMatchMap.Put(aNewId, newmatch); } } // hook up the match last in case an error occurs if (prevmatch) prevmatch->mNext = newmatch; } else { @@ -995,20 +988,17 @@ nsXULTemplateBuilder::UpdateResultInCont if (NS_FAILED(rv)) { nsTemplateMatch::Destroy(mPool, newmatch, false); return rv; } acceptedmatch = newmatch; } - if (!mMatchMap.Put(aNewId, newmatch)) { - nsTemplateMatch::Destroy(mPool, newmatch, true); - return NS_ERROR_OUT_OF_MEMORY; - } + mMatchMap.Put(aNewId, newmatch); } } // The ReplaceMatch method is builder specific and removes the generated // content for a match. // Remove the content for a match that was active and needs to be replaced. if (replacedmatch) {
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp +++ b/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp @@ -337,25 +337,22 @@ nsXULTemplateQueryProcessorRDF::Initiali nsIXULTemplateBuilder* aBuilder, nsIDOMNode* aRootNode) { if (!mQueryProcessorRDFInited) { nsresult rv = InitGlobals(); if (NS_FAILED(rv)) return rv; - if (!mMemoryElementToResultMap.IsInitialized() && - !mMemoryElementToResultMap.Init()) - return NS_ERROR_OUT_OF_MEMORY; - if (!mBindingDependencies.IsInitialized() && - !mBindingDependencies.Init()) - return NS_ERROR_OUT_OF_MEMORY; - if (!mRuleToBindingsMap.IsInitialized() && - !mRuleToBindingsMap.Init()) - return NS_ERROR_OUT_OF_MEMORY; + if (!mMemoryElementToResultMap.IsInitialized()) + mMemoryElementToResultMap.Init(); + if (!mBindingDependencies.IsInitialized()) + mBindingDependencies.Init(); + if (!mRuleToBindingsMap.IsInitialized()) + mRuleToBindingsMap.Init(); mQueryProcessorRDFInited = true; } // don't do anything if generation has already been done if (mGenerationStarted) return NS_ERROR_UNEXPECTED; @@ -615,18 +612,17 @@ nsXULTemplateQueryProcessorRDF::AddBindi nsCOMPtr<nsIRDFResource> property; nsresult rv = gRDFService->GetUnicodeResource(aExpr, getter_AddRefs(property)); if (NS_FAILED(rv)) return rv; nsRefPtr<RDFBindingSet> bindings = mRuleToBindingsMap.GetWeak(aRuleNode); if (!bindings) { bindings = new RDFBindingSet(); - if (!bindings || !mRuleToBindingsMap.Put(aRuleNode, bindings)) - return NS_ERROR_OUT_OF_MEMORY; + mRuleToBindingsMap.Put(aRuleNode, bindings); } return bindings->AddBinding(aVar, aRef, property); } NS_IMETHODIMP nsXULTemplateQueryProcessorRDF::TranslateRef(nsISupports* aDatasource, const nsAString& aRefString, @@ -1761,20 +1757,17 @@ nsXULTemplateQueryProcessorRDF::AddBindi nsIRDFResource* aResource) { nsCOMArray<nsXULTemplateResultRDF>* arr; if (!mBindingDependencies.Get(aResource, &arr)) { arr = new nsCOMArray<nsXULTemplateResultRDF>(); if (!arr) return NS_ERROR_OUT_OF_MEMORY; - if (!mBindingDependencies.Put(aResource, arr)) { - delete arr; - return NS_ERROR_OUT_OF_MEMORY; - } + mBindingDependencies.Put(aResource, arr); } PRInt32 index = arr->IndexOf(aResult); if (index == -1) return arr->AppendObject(aResult); return NS_OK; } @@ -1806,20 +1799,17 @@ nsXULTemplateQueryProcessorRDF::AddMemor PLHashNumber hash = (element.operator->())->Hash(); nsCOMArray<nsXULTemplateResultRDF>* arr; if (!mMemoryElementToResultMap.Get(hash, &arr)) { arr = new nsCOMArray<nsXULTemplateResultRDF>(); if (!arr) return NS_ERROR_OUT_OF_MEMORY; - if (!mMemoryElementToResultMap.Put(hash, arr)) { - delete arr; - return NS_ERROR_OUT_OF_MEMORY; - } + mMemoryElementToResultMap.Put(hash, arr); } // results may be added more than once so they will all get deleted properly arr->AppendObject(aResult); } return NS_OK; }
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp +++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp @@ -250,19 +250,18 @@ nsXULTemplateQueryProcessorXML::Initiali doc->GetDocumentElement(getter_AddRefs(mRoot)); else mRoot = do_QueryInterface(aDatasource); NS_ENSURE_STATE(mRoot); mEvaluator = do_CreateInstance("@mozilla.org/dom/xpath-evaluator;1"); NS_ENSURE_TRUE(mEvaluator, NS_ERROR_OUT_OF_MEMORY); - if (!mRuleToBindingsMap.IsInitialized() && - !mRuleToBindingsMap.Init()) - return NS_ERROR_OUT_OF_MEMORY; + if (!mRuleToBindingsMap.IsInitialized()) + mRuleToBindingsMap.Init(); return NS_OK; } NS_IMETHODIMP nsXULTemplateQueryProcessorXML::Done() { mGenerationStarted = false; @@ -395,18 +394,17 @@ nsXULTemplateQueryProcessorXML::AddBindi const nsAString& aExpr) { if (mGenerationStarted) return NS_ERROR_FAILURE; nsRefPtr<nsXMLBindingSet> bindings = mRuleToBindingsMap.GetWeak(aRuleNode); if (!bindings) { bindings = new nsXMLBindingSet(); - if (!bindings || !mRuleToBindingsMap.Put(aRuleNode, bindings)) - return NS_ERROR_OUT_OF_MEMORY; + mRuleToBindingsMap.Put(aRuleNode, bindings); } nsCOMPtr<nsIDOMXPathExpression> compiledexpr; nsresult rv = CreateExpression(aExpr, aRuleNode, getter_AddRefs(compiledexpr)); if (NS_FAILED(rv)) { nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_BINDING_XPATH); return NS_OK;
--- a/content/xul/templates/src/nsXULTreeBuilder.cpp +++ b/content/xul/templates/src/nsXULTreeBuilder.cpp @@ -1738,19 +1738,18 @@ nsXULTreeBuilder::OpenSubtreeForQuerySet if (mFlags & eLoggingEnabled) OutputMatchToLog(resultid, newmatch, true); } if (prevmatch) { prevmatch->mNext = newmatch; } - else if (!mMatchMap.Put(resultid, newmatch)) { - nsTemplateMatch::Destroy(mPool, newmatch, true); - return NS_ERROR_OUT_OF_MEMORY; + else { + mMatchMap.Put(resultid, newmatch); } } *aDelta = count; return rv; } nsresult
--- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -872,18 +872,17 @@ nsDocShell::Init() NS_ASSERTION(mLoadGroup, "Something went wrong!"); mContentListener = new nsDSURIContentListener(this); NS_ENSURE_TRUE(mContentListener, NS_ERROR_OUT_OF_MEMORY); rv = mContentListener->Init(); NS_ENSURE_SUCCESS(rv, rv); - if (!mStorages.Init()) - return NS_ERROR_OUT_OF_MEMORY; + mStorages.Init(); // We want to hold a strong ref to the loadgroup, so it better hold a weak // ref to us... use an InterfaceRequestorProxy to do this. nsCOMPtr<InterfaceRequestorProxy> proxy = new InterfaceRequestorProxy(static_cast<nsIInterfaceRequestor*> (this)); NS_ENSURE_TRUE(proxy, NS_ERROR_OUT_OF_MEMORY); mLoadGroup->SetNotificationCallbacks(proxy); @@ -2437,18 +2436,17 @@ nsDocShell::GetSessionStorageForPrincipa nsCOMPtr<nsPIDOMStorage> pistorage = do_QueryInterface(newstorage); if (!pistorage) return NS_ERROR_FAILURE; rv = pistorage->InitAsSessionStorage(aPrincipal, aDocumentURI); if (NS_FAILED(rv)) return rv; - if (!mStorages.Put(origin, newstorage)) - return NS_ERROR_OUT_OF_MEMORY; + mStorages.Put(origin, newstorage); newstorage.swap(*aStorage); #if defined(PR_LOGGING) && defined(DEBUG) PR_LOG(gDocShellLog, PR_LOG_DEBUG, ("nsDocShell[%p]: created a new sessionStorage %p", this, *aStorage)); #endif } @@ -2575,18 +2573,17 @@ nsDocShell::AddSessionStorage(nsIPrincip if (mStorages.GetWeak(origin)) return NS_ERROR_NOT_AVAILABLE; #if defined(PR_LOGGING) && defined(DEBUG) PR_LOG(gDocShellLog, PR_LOG_DEBUG, ("nsDocShell[%p]: was added a sessionStorage %p", this, aStorage)); #endif - if (!mStorages.Put(origin, aStorage)) - return NS_ERROR_OUT_OF_MEMORY; + mStorages.Put(origin, aStorage); } else { return topDocShell->AddSessionStorage(aPrincipal, aStorage); } } return NS_OK; }
--- a/dom/base/BrowserElementChild.js +++ b/dom/base/BrowserElementChild.js @@ -70,16 +70,19 @@ BrowserElementChild.prototype = { this._titleChangedHandler.bind(this), /* useCapture = */ true, /* wantsUntrusted = */ false); addEventListener('DOMLinkAdded', this._iconChangedHandler.bind(this), /* useCapture = */ true, /* wantsUntrusted = */ false); + + addMessageListener("browser-element-api:get-screenshot", + this._recvGetScreenshot.bind(this)); }, _titleChangedHandler: function(e) { debug("Got titlechanged: (" + e.target.title + ")"); var win = e.target.defaultView; // Ignore titlechanges which don't come from the top-level // <iframe mozbrowser> window. @@ -105,16 +108,32 @@ BrowserElementChild.prototype = { sendAsyncMsg('iconchange', e.target.href); } else { debug("Not top level!"); } } }, + _recvGetScreenshot: function(data) { + debug("Received getScreenshot message: (" + data.json.id + ")"); + var canvas = content.document + .createElementNS("http://www.w3.org/1999/xhtml", "canvas"); + var ctx = canvas.getContext("2d"); + canvas.mozOpaque = true; + canvas.height = content.innerHeight; + canvas.width = content.innerWidth; + ctx.drawWindow(content, 0, 0, content.innerWidth, + content.innerHeight, "rgb(255,255,255)"); + sendAsyncMsg('got-screenshot', { + id: data.json.id, + screenshot: canvas.toDataURL("image/png") + }); + }, + // The docShell keeps a weak reference to the progress listener, so we need // to keep a strong ref to it ourselves. _progressListener: { QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference, Ci.nsISupports]), _seenLoadStart: false,
--- a/dom/base/BrowserElementParent.js +++ b/dom/base/BrowserElementParent.js @@ -2,16 +2,18 @@ * 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/. */ "use strict"; let Cu = Components.utils; let Ci = Components.interfaces; let Cc = Components.classes; + +Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; const BROWSER_FRAMES_ENABLED_PREF = "dom.mozBrowserFramesEnabled"; function debug(msg) { //dump("BrowserElementParent - " + msg + "\n"); } @@ -47,16 +49,19 @@ BrowserElementParent.prototype = { if (!this._browserFramesPrefEnabled()) { var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); prefs.addObserver(BROWSER_FRAMES_ENABLED_PREF, this, /* ownsWeak = */ true); return; } this._initialized = true; + this._screenshotListeners = {}; + this._screenshotReqCounter = 0; + var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); os.addObserver(this, 'remote-browser-frame-shown', /* ownsWeak = */ true); os.addObserver(this, 'in-process-browser-frame-shown', /* ownsWeak = */ true); }, _browserFramesPrefEnabled: function() { var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); try { @@ -96,16 +101,21 @@ BrowserElementParent.prototype = { addMessageListener("hello", this._recvHello); addMessageListener("locationchange", this._fireEventFromMsg); addMessageListener("loadstart", this._fireEventFromMsg); addMessageListener("loadend", this._fireEventFromMsg); addMessageListener("titlechange", this._fireEventFromMsg); addMessageListener("iconchange", this._fireEventFromMsg); addMessageListener("get-mozapp-manifest-url", this._sendMozAppManifestURL); + mm.addMessageListener('browser-element-api:got-screenshot', + this._recvGotScreenshot.bind(this)); + + XPCNativeWrapper.unwrap(frameElement).getScreenshot = + this._getScreenshot.bind(this, mm, frameElement); mm.loadFrameScript("chrome://global/content/BrowserElementChild.js", /* allowDelayedLoad = */ true); }, _recvHello: function(frameElement, data) { debug("recvHello " + frameElement); }, @@ -134,16 +144,31 @@ BrowserElementParent.prototype = { frameElement.dispatchEvent(evt); }, _sendMozAppManifestURL: function(frameElement, data) { return frameElement.getAttribute('mozapp'); }, + _recvGotScreenshot: function(data) { + var req = this._screenshotListeners[data.json.id]; + delete this._screenshotListeners[data.json.id]; + Services.DOMRequest.fireSuccess(req, data.json.screenshot); + }, + + _getScreenshot: function(mm, frameElement) { + let id = 'req_' + this._screenshotReqCounter++; + let req = Services.DOMRequest + .createRequest(frameElement.ownerDocument.defaultView); + this._screenshotListeners[id] = req; + mm.sendAsyncMessage('browser-element-api:get-screenshot', {id: id}); + return req; + }, + observe: function(subject, topic, data) { switch(topic) { case 'app-startup': this._init(); break; case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: if (data == BROWSER_FRAMES_ENABLED_PREF) { this._init();
--- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -321,16 +321,17 @@ #include "nsIDOMCSSMozDocumentRule.h" #include "nsIDOMMozCSSKeyframeRule.h" #include "nsIDOMMozCSSKeyframesRule.h" #include "nsIDOMCSSPrimitiveValue.h" #include "nsIDOMCSSStyleRule.h" #include "nsIDOMCSSStyleSheet.h" #include "nsDOMCSSValueList.h" #include "nsIDOMDeviceProximityEvent.h" +#include "nsIDOMUserProximityEvent.h" #include "nsIDOMDeviceLightEvent.h" #include "nsIDOMDeviceOrientationEvent.h" #include "nsIDOMDeviceMotionEvent.h" #include "nsIDOMRange.h" #include "nsIDOMNodeIterator.h" #include "nsIDOMTreeWalker.h" #include "nsIDOMXULDocument.h" #include "nsIDOMXULElement.h" @@ -430,16 +431,17 @@ #include "nsIDOMSVGTitleElement.h" #include "nsIDOMSVGTransform.h" #include "nsIDOMSVGTransformable.h" #include "nsIDOMSVGTransformList.h" #include "nsIDOMSVGTSpanElement.h" #include "nsIDOMSVGUnitTypes.h" #include "nsIDOMSVGURIReference.h" #include "nsIDOMSVGUseElement.h" +#include "nsIDOMSVGViewElement.h" #include "nsIDOMSVGZoomAndPan.h" #include "nsIDOMSVGZoomEvent.h" #include "nsIDOMCanvasRenderingContext2D.h" #include "nsIDOMWebGLRenderingContext.h" #include "nsIImageDocument.h" @@ -816,16 +818,19 @@ static nsDOMClassInfoData sClassInfoData NS_DEFINE_CLASSINFO_DATA(PopupBlockedEvent, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) // Device Light NS_DEFINE_CLASSINFO_DATA(DeviceLightEvent, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) // Device Proximity NS_DEFINE_CLASSINFO_DATA(DeviceProximityEvent, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) + // User Proximity + NS_DEFINE_CLASSINFO_DATA(UserProximityEvent, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) // Device Orientation NS_DEFINE_CLASSINFO_DATA(DeviceOrientationEvent, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(DeviceMotionEvent, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(DeviceAcceleration, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(DeviceRotationRate, nsDOMGenericSH, @@ -1206,16 +1211,18 @@ static nsDOMClassInfoData sClassInfoData NS_DEFINE_CLASSINFO_DATA(SVGTitleElement, nsElementSH, ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGTSpanElement, nsElementSH, ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA_WITH_NAME(SVGUnknownElement, SVGElement, nsElementSH, ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGUseElement, nsElementSH, ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGViewElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) // other SVG classes NS_DEFINE_CLASSINFO_DATA(SVGAngle, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGAnimatedAngle, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGAnimatedBoolean, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) @@ -1692,16 +1699,17 @@ NS_DEFINE_EVENT_CTOR(PopStateEvent) NS_DEFINE_EVENT_CTOR(HashChangeEvent) NS_DEFINE_EVENT_CTOR(PageTransitionEvent) NS_DEFINE_EVENT_CTOR(CloseEvent) NS_DEFINE_EVENT_CTOR(MozSettingsEvent) NS_DEFINE_EVENT_CTOR(UIEvent) NS_DEFINE_EVENT_CTOR(MouseEvent) NS_DEFINE_EVENT_CTOR(DeviceLightEvent) NS_DEFINE_EVENT_CTOR(DeviceProximityEvent) +NS_DEFINE_EVENT_CTOR(UserProximityEvent) nsresult NS_DOMStorageEventCtor(nsISupports** aInstancePtrResult) { nsDOMStorageEvent* e = new nsDOMStorageEvent(); return CallQueryInterface(e, aInstancePtrResult); } @@ -1727,16 +1735,17 @@ static const nsConstructorFuncMapData kC NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(PopStateEvent) NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(HashChangeEvent) NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(PageTransitionEvent) NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(CloseEvent) NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(MozSettingsEvent) NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(UIEvent) NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(MouseEvent) NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(DeviceProximityEvent) + NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(UserProximityEvent) NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(DeviceLightEvent) NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(StorageEvent) NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozSmsFilter, sms::SmsFilter::NewSmsFilter) }; nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull; nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nsnull; bool nsDOMClassInfo::sIsInitialized = false; @@ -2616,16 +2625,21 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_EVENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(DeviceProximityEvent, nsIDOMDeviceProximityEvent) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDeviceProximityEvent) DOM_CLASSINFO_EVENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(UserProximityEvent, nsIDOMUserProximityEvent) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMUserProximityEvent) + DOM_CLASSINFO_EVENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(DeviceOrientationEvent, nsIDOMDeviceOrientationEvent) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDeviceOrientationEvent) DOM_CLASSINFO_EVENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(DeviceMotionEvent, nsIDOMDeviceMotionEvent) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDeviceMotionEvent) DOM_CLASSINFO_EVENT_MAP_ENTRIES @@ -3661,16 +3675,22 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGUseElement, nsIDOMSVGUseElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGUseElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference) DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(SVGViewElement, nsIDOMSVGViewElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGZoomAndPan) + DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + // other SVG classes DOM_CLASSINFO_MAP_BEGIN(SVGAngle, nsIDOMSVGAngle) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAngle) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(SVGAnimatedAngle, nsIDOMSVGAnimatedAngle) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimatedAngle) @@ -5221,18 +5241,18 @@ static JSClass sGlobalScopePolluterClass (JSResolveOp)nsWindowSH::GlobalScopePolluterNewResolve, JS_ConvertStub, nsHTMLDocumentSH::ReleaseDocument }; // static JSBool -nsWindowSH::GlobalScopePolluterGetProperty(JSContext *cx, JSObject *obj, - jsid id, jsval *vp) +nsWindowSH::GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj, + JSHandleId id, jsval *vp) { // Someone is accessing a element by referencing its name/id in the // global scope, do a security check to make sure that's ok. nsresult rv = sSecMan->CheckPropertyAccess(cx, ::JS_GetGlobalForObject(cx, obj), "Window", id, nsIXPCSecurityManager::ACCESS_GET_PROPERTY); @@ -5248,17 +5268,17 @@ nsWindowSH::GlobalScopePolluterGetProper // catch and fix these mistakes. PrintWarningOnConsole(cx, "GlobalScopeElementReference"); return JS_TRUE; } // static JSBool -nsWindowSH::SecurityCheckOnAddDelProp(JSContext *cx, JSObject *obj, jsid id, +nsWindowSH::SecurityCheckOnAddDelProp(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp) { // Someone is accessing a element by referencing its name/id in the // global scope, do a security check to make sure that's ok. nsresult rv = sSecMan->CheckPropertyAccess(cx, ::JS_GetGlobalForObject(cx, obj), "Window", id, @@ -5266,33 +5286,33 @@ nsWindowSH::SecurityCheckOnAddDelProp(JS // If !NS_SUCCEEDED(rv) the security check failed. The security // manager set a JS exception for us. return NS_SUCCEEDED(rv); } // static JSBool -nsWindowSH::SecurityCheckOnSetProp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, +nsWindowSH::SecurityCheckOnSetProp(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp) { return SecurityCheckOnAddDelProp(cx, obj, id, vp); } static nsHTMLDocument* GetDocument(JSObject *obj) { return static_cast<nsHTMLDocument*>( static_cast<nsIHTMLDocument*>(::JS_GetPrivate(obj))); } // static JSBool -nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj, - jsid id, unsigned flags, +nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj, + JSHandleId id, unsigned flags, JSObject **objp) { if (flags & (JSRESOLVE_ASSIGNING | JSRESOLVE_DECLARING | JSRESOLVE_CLASSNAME | JSRESOLVE_QUALIFIED) || !JSID_IS_STRING(id)) { // Nothing to do here if we're either assigning or declaring, // resolving a class name, doing a qualified resolve, or // resolving a number. @@ -5771,17 +5791,17 @@ static const IDBConstant sIDBConstants[] { IDBConstant::IDBRequest, "LOADING", "pending" }, { IDBConstant::IDBRequest, "DONE", "done" }, { IDBConstant::IDBTransaction, "READ_ONLY", "readonly" }, { IDBConstant::IDBTransaction, "READ_WRITE", "readwrite" }, { IDBConstant::IDBTransaction, "VERSION_CHANGE", "versionchange" }, }; static JSBool -IDBConstantGetter(JSContext *cx, JSObject *obj, jsid id, jsval* vp) +IDBConstantGetter(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval* vp) { MOZ_ASSERT(JSID_IS_INT(id)); int8_t index = JSID_TO_INT(id); MOZ_ASSERT((uint8_t)index < mozilla::ArrayLength(sIDBConstants)); const IDBConstant& c = sIDBConstants[index]; @@ -6906,47 +6926,52 @@ LocationSetterGuts(JSContext *cx, JSObje nsDependentJSString depStr; NS_ENSURE_TRUE(depStr.init(cx, val), NS_ERROR_UNEXPECTED); return location->SetHref(depStr); } template<class Interface> static JSBool -LocationSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, +LocationSetter(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp) { nsresult rv = LocationSetterGuts<Interface>(cx, obj, vp); if (NS_FAILED(rv)) { if (!::JS_IsExceptionPending(cx)) { nsDOMClassInfo::ThrowJSException(cx, rv); } return JS_FALSE; } return JS_TRUE; } static JSBool -LocationSetterUnwrapper(JSContext *cx, JSObject *obj, jsid id, JSBool strict, +LocationSetterUnwrapper(JSContext *cx, JSHandleObject obj_, JSHandleId id, JSBool strict, jsval *vp) { + JS::RootedVarObject obj(cx, obj_); + JSObject *wrapped = XPCWrapper::UnsafeUnwrapSecurityWrapper(obj); if (wrapped) { obj = wrapped; } return LocationSetter<nsIDOMWindow>(cx, obj, id, strict, vp); } NS_IMETHODIMP nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, - JSObject *obj, jsid id, PRUint32 flags, + JSObject *obj_, jsid id_, PRUint32 flags, JSObject **objp, bool *_retval) { + JS::RootedVarObject obj(cx, obj_); + JS::RootedVarId id(cx, id_); + nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper); if (!JSID_IS_STRING(id)) { if (JSID_IS_INT(id) && JSID_TO_INT(id) >= 0 && !(flags & JSRESOLVE_ASSIGNING)) { // If we're resolving a numeric property, treat that as if // window.frames[n] is resolved (since window.frames === // wind