From e39f9f88f797ada2f161cc9dbeccdd89f051787a Mon Sep 17 00:00:00 2001 From: Roy Tam Date: Fri, 12 Jun 2020 21:48:57 +0800 Subject: [PATCH] import changes from `dev' branch of rmottola/Arctic-Fox: - Bug 1152171 part 2 - Rename AnimationTimeline to DocumentTimeline; r=smaug (26c118319) - Bug 1152171 part 3 - Update web-platform-tests expectations; r=jgraham (b7b4032aa) - Bug 1153734 part 1 - Remove AnimationEffect; r=smaug (9cf67a02e) - Bug 1153734 part 2 - Rename Animation to KeyframeEffectReadonly; r=smaug (b69556ee6) - Bug 1153734 part 3 - Rename AnimationPlayer.source to AnimationPlayer.effect; r=smaug (50d3130ee) - Bug 1153734 part 4 - Rename other uses of 'source' and 'source content'; r=jwatt (b02c4ba36) - Bug 1153734 part 5 - Add AnimationEffectReadonly as a superinterface of KeyframeEffectReadonly; r=smaug (c3395d3f5) - Bug 1149990 - Support replaying of finished CSS transitions by supporting setting of currentTime/startTime. r=birtles (3fb2cb401) - Bug 1154615 part 1 - Rename AnimationPlayer to Animation in WebIDL; r=smaug (6c2125b49) - Bug 1154615 part 2 - Rename PendingPlayerTracker to PendingAnimationTracker; r=jwatt (8d6804def) - Bug 1154615 part 3 - Rename internal members of PendingAnimationTracker; r=jwatt (f348f6355) - Bug 1154615 part 4 - Rename references to players in dom/animation; r=jwatt (0250572e8) - Bug 1117603 part 1 - Don't assume style rules have been refreshed in GetAnimationRule; r=dbaron (a5d340d0f) - remove kungFuDeathGrip (49df758e6) - Bug 1117603 part 2 - Don't unregister from the refresh driver unless we are also queueing events; r=dbaron (715c9caa1) - Bug 1154615 part 5 - Rename AnimationPlayerCollection to AnimationCollection; r=jwatt (4c596f089) - Bug 1154615 part 6 - Rename references to players within layout/; r=jwatt (42405f3fc) - Bug 1154615 part 7 - Rename CSSAnimationPlayer and CSSTransitionPlayer; r=jwatt (49ab272ed) - Bug 1154615 part 8 - Rename references to players in animation observers; r=jwatt (c3fa26d7a) - Bug 1154615 part 9 - Rename test files; r=jwatt (9d9f03e7b) - Bug 1145439 (Part 1) - Throttle requestAnimationFrame for non-visible iframes. r=mstange,mchang (be7d183d6) - Bug 1145439 (Part 2) - Make test_scroll_event_ordering.html wait for rAF to unthrottle. r=roc (9ac8317c9) - Bug 1144324 - Try to register for, and handle, touch events when APZ is enabled. r=dvander,jimm (fb75d1665) - Bug 1144324 - Remove the codepaths that conditionally enable touch events based on touch the presence of touch listeners. r=smaug,jimm (710617e6b) - Bug 1003991 - Disable https:// only load for ServiceWorkers when Developer Tools are open. r=nsm, r=miker (9d6669814) - Bug 1153267 - part 1 - use smart-pointer .forget() instead of NS_ADDREF+assign; r=ehsan (e4555c90c) - Bug 1153267 - part 2 - use smart pointers instead of manual NS_ADDREF'ing outparams; r=ehsan (ae8b60d5a) - Bug 1153267 - fix typo that broke OS X builds on a CLOSED TREE; r=bustage (08fdb3c4f) - Bug 1146843 - Revert part of cset 33c30e283fa8 because the code is used in Fennec. r=snorp (407248257) - Bug 1151940 part 1. Make some readonly properties defined on Window by CSSOM-view replaceable. r=smaug (5cb9b91f0) - Bug 1151940 part 2. Add a convenience function in nsGlobalWindow for replacing a property on the window with a new value. r=smaug (2ba39331c) - Bug 1151940 part 3. Make some writable cssom-view attributes that we only allow setting from chrome act the way readonly replaceables would when called from content. r=smaug (b485e1b44) - Goanna -> Gecko (2c539d7be) - Goanna -> Gecko (25d34e213) - Bug 1148962 - Use TakeOwnershipOfErrorReporting in CPOW code (r=bholley) (96c997639) - pointer style (a07fbffaa) - Bug 1152577: Add 'aReason' argument to AutoEntryScript constructor, and provide plausible names for its instantiations. r=bholley (512fa27e2) - bug 1155691 - Expose WindowRoot to chrome from window in webidl. r=smaug (235281924) - Bug 404828 - No need to assert that the top window isn't reachable. r=smaug (d73154fa0) - Bug 404828 - Followup: remove assertion expectations on a CLOSED TREE. a=tomcat (a5dabe1b7) - Bug 1156102 - Mark nsGlobalWindowObserver::mWindow as MOZ_NON_OWNING_REF; r=baku (c0d4208b7) - Bug 1107801 - Improve gamepad support on MacOS. r=ted (c591bd5ac) - Goanna -> Gecko (d9b81bc9e) - Bug 852944 - Gamepad API IPC; r=ted, r=baku (521892538) - Bug 1143529 part 1. Stop manually calling WrapObject in DataStoreService::GetDataStoresResolve. r=baku (056ad6bfe) - Bug 1143529 part 2. Tighten up the assert in binding Wrap methods. r=peterv (765a13325) - Bug 1152169 - DataStoreService should check if the first revision exists, r=bent (ee371cc5d) - Bug 1152169 followup: Mark FirstRevisionIdCallback methods Run() and HandleEvent() as 'override'. rs=ehsan (8186c4168) - Bug 1143651 - don't use CallQueryInterface when the compiler can do the cast for us; r=ehsan (a50f0a54b) - Bug 1144322 - Handle tabindex in overridden IsInteractiveHTMLContent methods. r=smaug (fd4b9beed) - Bug 1086684 - Stash the full path for file inputs to avoid doing IPC at inopportune times. r=ehsan/bent/gps (b843b1efc) - Bug 1143934 - Disallow mozSetFileNameArray in content processes. r=ehsan (42e5c8c6d) - Bug 1143934 - Fix assorted forms mochitests for e10s-compatibility. r=smaug (7a3babfed) - Bug 1143934 - Work around SessionStore dependency on current brokenness. r=ttaubert (5b0fcb5ce) - Bug 956530 - Clear the delayed caret data when clicking on a selected part of a text control if the focus event handler selects the control; r=roc (2859f07b4) - Bug 956530 follow-up: Fix the test failure on Windows 8 caused by the text box having a glowing outline as a result of being clicked on (d34e8da1a) - Bug 1157898 part 1. Make code of the form "return rv.ErrorCode();" where rv is an ErrorResult use StealNSResult instead. r=peterv (800da50e2) - Bug 1157898 part 2. Make code of the form "NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());" use Failed and StealNSResult instead. r=peterv (472432a83) - Bug 1157898 part 3. Fix the remaining consumers of rv.ErrorCode() in NS_ENSURE_* expressions to not do that. r=peterv (d452807e7) - Bug 1122238 part 1. Switch to using the new stackframe APIs in JSStackFrame. r=bholley (9d87b261a) - Bug 1122238 part 2. Stop caching things in JSStackFrame when we're called over Xrays. r=bholley (83eda7275) - Bug 1122238 part 3. Drop all the DOMException-cloning and sanitization gunk we added in bug 1107592 and bug 1107953 and bug 1117242 . r=bholley (f237aa948) - add support for NetBSD/SPARC64 (065783b70) - Bug 1153484 - Fetch should ignore invalid headers, but still process later headers. r=nsm (8925ddd77) - Bug 1157754 part 2. Convert consumers of ErrorResult::ClearMessage() to the new better APIs we have for suppressing exceptions on ErrorResult. r=bkelly (6519fbd5e) - Bug 1157754 part 3. Make ClearMessage private on ErrorResult. r=peterv (3fb218692) - Bug 1157898 part 4. Add ErrorResult::ErrorCodeIs() and use it in various places to get rid of ErrorCode(). r=peterv (bed7bfb4c) - Bug 1130686 - Refactor PromiseHolder in the service worker clients code. r=nsm (b3dbdcbfe) - Bug 1130686 - Implement client.focus. r=baku (5dee6d850) - Bug 1149163 part 1 - Clean up nsHTMLEditRules::GetInnerContent; r=froydnj (cc8f65b54) - Bug 1149163 part 2 - Make nsDOMIterator infallible; r=froydnj (d975f6c62) - Bug 1149163 part 3 - Clean up nsHTMLEditRules::BustUpInlinesAtBRs; r=froydnj (58155adad) - Bug 1149163 part 4 - Allow use of temporary nsBoolDomIterFunctor; r=froydnj (dbafec00f) - Bug 1149163 part 5 - Clean up nsHTMLEditRules::GetNodesForOperation; r=froydnj (41179d810) - Bug 1149163 part 6 - Clean up nsHTMLEditRules::LookInsideDivBQandList; r=froydnj (0b757bf14) - Bug 1149163 part 7 - Clean up nsHTMLEditRules::PromoteRange; r=froydnj (c49c714b1) - Bug 1149163 part 8 - Clean up nsHTMLEditRules::GetPromotedRanges; r=froydnj (5163a0026) - Bug 1148228 - Stop checking ul twice (43a22088c) - Bug 1141017 - resurrect serif and monospace. r=ehsan (95a1b6fcf) - Bug 1147412 part 1 - Make methods take nsINode*, not just nsIContent*; r=ehsan (7f762cdbe) - Bug 1147412 part 2 - Clean up nsHTMLEditor::SetInlinePropertyOnTextNode; r=ehsan (faf805587) - Bug 1147412 part 3 - Fix completely broken nsHTMLCSSUtils::IsCSSEquivalentToHTMLInlineStyleSet implementation; r=ehsan (73fea67c1) - Bug 1147412 part 4 - Clean up nsHTMLEditor::GetInlinePropertyBase; r=ehsan (3265bfbce) - Bug 1147412 part 5 - Clean up nsHTMLEditor::RemoveInlinePropertyImpl; r=ehsan (0f402bd7e) - Bug 1147412 part 6 - Remove nsHTMLCSSUtils::IsCSSEditableProperty(nsIDOMNode*,...); r=ehsan (100e4038a) - Bug 1147412 part 7 - Remove nsHTMLCSSUtils::GetComputedStyle(nsIDOMElement*); r=ehsan (6c51103bc) - Bug 1147412 part 8 - Clean up nsHTMLCSSUtils::IsCSSInvertible; r=ehsan (01e60c446) - Bug 1147412 part 9 - Convert some nsHTMLEditor members to Element; r=ehsan (e7efb1ac4) - Bug 1147412 part 10 - Clean up nsHTMLCSSUtils::Get*Property, GetCSSInlinePropertyBase; r=ehsan (54154143d) - Bug 1149163 part 9 - Clean up nsHTMLEditRules::GetNodesFromSelection; r=froydnj (5186308b9) - Bug 1154701 part 1 - Clean up nsHTMLEditor::CreateListOfNodesToPaste; r=ehsan (ea95238d5) - Bug 1153629 part 1 - Clean up nsHTMLEditRules::GetListActionNodes; r=ehsan (51f3b3e95) - Bug 1153629 part 2 - Clean up nsHTMLEditRules::GetParagraphFormatNodes; r=ehsan (a27bd7751) - Bug 1153629 part 3 - Clean up nsHTMLEditRules::GetNodesFromPoint; r=ehsan (edc7e4561) - Bug 1153629 part 4 - Clean up nsHTMLEditRules::ListIsEmptyLine; r=ehsan (ce3289bc7) - Bug 1153629 part 5 - Clean up nsHTMLEditRules::GetChildNodesForOperation; r=ehsan (b3a509dbf) - Bug 1153629 part 6 - Clean up nsHTMLEditRules::MakeBlockquote; r=ehsan (cb3808182) - Bug 1153629 part 7 - Clean up nsHTMLEditRules::RemoveBlockStyle, RemovePartOfBlock; r=ehsan (660b9f76e) - Bug 1153629 part 8 - Clean up nsHTMLEditRules::ApplyBlockStyle; r=ehsan (f54f9538c) - Bug 1153629 part 9 - Clean up nsHTMLEditRules::MakeTransitionList; r=ehsan (fb63cf6d8) - Bug 1153629 part 10 - Clean up nsHTMLEditRules::AlignInnerBlocks; r=ehsan (752d2df7a) - Bug 1153629 part 11 - Clean up nsHTMLEditRules::AdjustSpecialBreaks; r=ehsan (16ef0416b) - Bug 1153629 part 12 - Clean up nsHTMLEditRules::RemoveEmptyNodes; r=ehsan (d528e70e6) - Bug 1154701 part 2 - Use more OwningNonNull in editor; r=ehsan (85b1929e6) - Bug 1154701 part 3 - Clean up nsHTMLEditor::GetListAndTableParents, DiscoverPartialListsAndTables, ScanForListAndTableStructure, ReplaceOrphanedStructure; r=ehsan (7fe31f058) - Bug 1154701 part 4 - Switch nsHTMLEditor::mContentFilters to nsTArray; r=ehsan (64e6dd160) - Bug 1154701 part 5 - Switch nsHTMLEditor::objectResizeEventListeners to nsTArray; r=ehsan (036bc65fe) - Bug 1154701 part 6 - Clean up nsHTMLEditor::SetInlinePropertyOnNodeImpl; r=ehsan (2d619ca16) - Bug 1154701 part 7 - Clean up nsHTMLEditor::SetInlineProperty; r=ehsan (7a367d31b) - Bug 1154701 part 8 - Clean up nsHTMLEditor::SetInlinePropertyOnNode; r=ehsan (707c07d93) - Bug 1154701 part 9 - Clean up nsHTMLEditor::RelativeFontChange; r=ehsan (273ae9c64) - Bug 1154701 part 10 - Switch nsEditor::mActionListeners to nsTArray; r=ehsan (d2b5732fe) - Bug 1154701 part 11 - Switch nsEditor::mEditorObservers to nsTArray; r=ehsan (25a5af12e) - Bug 1154701 part 12 - Switch nsEditor::mDocStateListeners to nsTArray; r=ehsan (665af0792) - Bug 1154701 part 13 - Clean up nsHTMLEditor::SetCSSBackgroundColor; r=ehsan (ba424ade8) - Bug 1154701 part 14 - Remove unused nsCOMArray cruft; r=ehsan (3a8679a67) - Bug 1101651 - Part 1: xpcomrt version of dom media library need for standalone webrtcs. r=jesup (ae37b5464) - Bug 1137447 - New app update telemetry for patch type (complete or partial), extended error codes, and general cleanup. r=bbondy (c736ae502) --- .../components/preferences/applications.js | 4 +- build/mobile/robocop/Actions.java | 8 +- build/mobile/robocop/FennecNativeActions.java | 62 +- build/mobile/robocop/FennecNativeDriver.java | 4 +- configure.in | 7 +- docshell/base/nsDocShell.cpp | 2 +- docshell/base/nsIDocShell.idl | 2 +- docshell/base/nsIDocumentLoaderFactory.idl | 2 +- docshell/base/nsWebNavigationInfo.cpp | 2 +- docshell/shistory/src/nsSHistory.cpp | 9 +- dom/animation/Animation.cpp | 1183 ++++++--- dom/animation/Animation.h | 596 +++-- dom/animation/AnimationEffect.cpp | 24 - dom/animation/AnimationEffect.h | 46 - dom/animation/AnimationEffectReadonly.cpp | 23 + dom/animation/AnimationEffectReadonly.h | 42 + dom/animation/AnimationPlayer.cpp | 886 ------- dom/animation/AnimationPlayer.h | 348 --- dom/animation/AnimationTimeline.cpp | 113 +- dom/animation/AnimationTimeline.h | 62 +- dom/animation/DocumentTimeline.cpp | 123 + dom/animation/DocumentTimeline.h | 76 + dom/animation/KeyframeEffect.cpp | 396 +++ dom/animation/KeyframeEffect.h | 353 +++ ...racker.cpp => PendingAnimationTracker.cpp} | 56 +- dom/animation/PendingAnimationTracker.h | 83 + dom/animation/PendingPlayerTracker.h | 86 - dom/animation/moz.build | 15 +- ...e.html => test_animation-currenttime.html} | 37 +- ...shed.html => test_animation-finished.html} | 0 ...ate.html => test_animation-playstate.html} | 0 ...r-ready.html => test_animation-ready.html} | 0 ...ime.html => test_animation-starttime.html} | 27 +- ...effect-name.html => test_effect-name.html} | 8 +- ...on-target.html => test_effect-target.html} | 2 +- ....html => test_element-get-animations.html} | 2 +- ...e.html => test_animation-currenttime.html} | 14 +- .../test_animation-player-ready.html | 735 +++++- .../css-transitions/test_animation-ready.html | 96 + .../test_animation-starttime.html | 403 +++ ...effect-name.html => test_effect-name.html} | 2 +- ...on-target.html => test_effect-target.html} | 2 +- ....html => test_element-get-animations.html} | 0 .../test_document-timeline.html} | 2 +- .../test_request_animation_frame.html | 0 dom/animation/test/mochitest.ini | 33 +- dom/animation/test/testcommon.js | 11 + dom/archivereader/ArchiveReader.cpp | 2 +- dom/archivereader/ArchiveZipFile.cpp | 2 +- dom/base/Attr.cpp | 2 +- dom/base/DOMCursor.cpp | 2 +- dom/base/DOMException.cpp | 26 - dom/base/DOMException.h | 9 - dom/base/DOMImplementation.cpp | 2 +- dom/base/DocumentType.cpp | 2 +- dom/base/Element.cpp | 24 +- dom/base/Element.h | 22 +- dom/base/File.cpp | 16 +- dom/base/MultipartFileImpl.cpp | 3 +- dom/base/NodeIterator.h | 2 +- dom/base/ScriptSettings.cpp | 3 +- dom/base/ScriptSettings.h | 7 +- dom/base/TreeWalker.cpp | 2 +- dom/base/TreeWalker.h | 2 +- dom/base/nsContentPermissionHelper.cpp | 2 +- dom/base/nsContentUtils.cpp | 6 +- dom/base/nsDOMAttributeMap.cpp | 8 +- dom/base/nsDOMFileReader.cpp | 10 +- dom/base/nsDOMMutationObserver.cpp | 40 +- dom/base/nsDOMMutationObserver.h | 42 +- dom/base/nsDOMSerializer.cpp | 3 +- dom/base/nsDOMWindowUtils.cpp | 56 +- dom/base/nsDocument.cpp | 102 +- dom/base/nsDocument.h | 22 +- dom/base/nsFocusManager.cpp | 18 +- dom/base/nsFrameLoader.cpp | 4 +- dom/base/nsFrameMessageManager.cpp | 22 +- dom/base/nsGenericDOMDataNode.cpp | 2 +- dom/base/nsGkAtomList.h | 4 + dom/base/nsGlobalWindow.cpp | 536 ++-- dom/base/nsGlobalWindow.h | 78 +- dom/base/nsGlobalWindowCommands.cpp | 3 +- dom/base/nsHTMLContentSerializer.cpp | 12 +- dom/base/nsHostObjectProtocolHandler.cpp | 2 +- dom/base/nsIAnimationObserver.h | 20 +- dom/base/nsIDocument.h | 24 +- dom/base/nsINode.cpp | 10 +- dom/base/nsINode.h | 10 +- dom/base/nsImageLoadingContent.cpp | 10 +- dom/base/nsJSTimeoutHandler.cpp | 2 +- dom/base/nsNodeUtils.cpp | 30 +- dom/base/nsNodeUtils.h | 8 +- dom/base/nsPIDOMWindow.h | 32 +- dom/base/nsPlainTextSerializer.cpp | 12 +- dom/base/nsRange.cpp | 60 +- dom/base/nsScreen.cpp | 2 +- dom/base/nsScriptLoader.cpp | 3 +- dom/base/nsTraversal.cpp | 5 +- dom/base/nsXHTMLContentSerializer.cpp | 12 +- dom/base/nsXMLContentSerializer.cpp | 12 +- dom/base/nsXMLHttpRequest.cpp | 18 +- dom/base/test/chrome/chrome.ini | 1 + dom/base/test/chrome/test_windowroot.xul | 19 + dom/base/test/test_bug345339.html | 39 +- dom/base/test/test_innersize_scrollport.html | 9 +- dom/base/test/test_writable-replaceable.html | 23 +- dom/bindings/BindingUtils.cpp | 40 +- dom/bindings/BindingUtils.h | 2 +- dom/bindings/Bindings.conf | 8 + dom/bindings/CallbackObject.cpp | 4 +- dom/bindings/CallbackObject.h | 1 + dom/bindings/Codegen.py | 32 +- dom/bindings/ErrorResult.h | 10 +- dom/bindings/Exceptions.cpp | 345 ++- dom/cache/CacheOpParent.cpp | 2 +- dom/cache/DBSchema.cpp | 6 +- dom/cache/FetchPut.cpp | 7 +- dom/datastore/DataStoreCursorImpl.jsm | 6 + dom/datastore/DataStoreDB.cpp | 16 +- dom/datastore/DataStoreRevision.cpp | 2 +- dom/datastore/DataStoreService.cpp | 132 +- dom/devicestorage/nsDeviceStorage.cpp | 18 +- dom/events/ClipboardEvent.cpp | 2 +- dom/events/DataTransfer.cpp | 23 +- dom/events/JSEventHandler.cpp | 6 +- dom/events/MessageEvent.cpp | 2 +- dom/events/SpeechRecognitionError.cpp | 2 +- dom/events/test/bug648573.html | 5 - dom/fetch/FetchDriver.cpp | 15 +- dom/filehandle/FileHandle.cpp | 2 +- dom/gamepad/GamepadFunctions.cpp | 105 + dom/gamepad/GamepadFunctions.h | 45 + dom/gamepad/GamepadMonitoring.cpp | 31 + dom/gamepad/GamepadMonitoring.h | 22 + dom/gamepad/GamepadService.cpp | 252 +- dom/gamepad/GamepadService.h | 46 +- dom/gamepad/GamepadServiceTest.cpp | 92 + dom/gamepad/GamepadServiceTest.h | 42 + .../gamepad}/android/AndroidGamepad.cpp | 19 +- {hal => dom/gamepad}/cocoa/CocoaGamepad.cpp | 254 +- .../gamepad}/fallback/FallbackGamepad.cpp | 15 +- {hal => dom/gamepad}/linux/LinuxGamepad.cpp | 54 +- {hal => dom/gamepad}/linux/udev.h | 0 dom/gamepad/moz.build | 31 + .../gamepad}/windows/WindowsGamepad.cpp | 80 +- dom/geolocation/nsGeolocationSettings.cpp | 4 +- dom/html/HTMLAudioElement.cpp | 3 +- dom/html/HTMLBodyElement.cpp | 12 +- dom/html/HTMLCanvasElement.cpp | 4 +- dom/html/HTMLDivElement.h | 2 +- dom/html/HTMLFormElement.cpp | 5 +- dom/html/HTMLFrameSetElement.cpp | 4 +- dom/html/HTMLImageElement.cpp | 7 +- dom/html/HTMLInputElement.cpp | 84 +- dom/html/HTMLInputElement.h | 10 +- dom/html/HTMLLabelElement.cpp | 2 +- dom/html/HTMLMediaElement.cpp | 22 +- dom/html/HTMLObjectElement.cpp | 3 +- dom/html/HTMLOptionsCollection.cpp | 6 +- dom/html/HTMLScriptElement.cpp | 4 +- dom/html/HTMLSelectElement.cpp | 8 +- dom/html/HTMLTableCellElement.cpp | 28 +- dom/html/HTMLTextAreaElement.cpp | 18 +- dom/html/HTMLVideoElement.cpp | 3 +- dom/html/ImageDocument.cpp | 2 +- dom/html/TimeRanges.cpp | 4 +- dom/html/nsGenericHTMLElement.cpp | 8 +- dom/html/nsGenericHTMLElement.h | 32 +- dom/html/nsHTMLDocument.cpp | 28 +- dom/html/test/formSubmission_chrome.js | 6 + dom/html/test/forms/mochitest.ini | 4 - .../test_interactive_content_in_label.html | 76 +- dom/html/test/forms/test_max_attribute.html | 9 +- dom/html/test/forms/test_min_attribute.html | 9 +- .../test/forms/test_pattern_attribute.html | 10 +- .../test/forms/test_required_attribute.html | 17 +- dom/html/test/forms/test_step_attribute.html | 9 +- dom/html/test/mochitest.ini | 3 +- dom/html/test/test_bug143220.html | 72 +- dom/html/test/test_formSubmission.html | 73 +- .../conformancetest/test_runtest.html.json | 114 - dom/inputport/InputPortManager.cpp | 4 +- dom/interfaces/base/nsIDOMWindowUtils.idl | 12 +- .../gamepad/nsIGamepadServiceTest.idl | 7 +- dom/ipc/Blob.cpp | 2 +- dom/ipc/ContentChild.cpp | 16 + dom/ipc/ContentChild.h | 2 + dom/ipc/ContentParent.cpp | 35 +- dom/ipc/ContentParent.h | 7 + dom/ipc/PContent.ipdl | 46 + dom/ipc/moz.build | 4 - dom/jsurl/nsJSProtocolHandler.cpp | 2 +- dom/media/AudioSegment.cpp | 2 + dom/media/AudioSegment.h | 6 + dom/media/SimpleImageBuffer.cpp | 53 + dom/media/SimpleImageBuffer.h | 50 + dom/media/VideoSegment.cpp | 2 + dom/media/VideoSegment.h | 14 + dom/media/moz.build | 1 + dom/media/standalone/moz.build | 47 + dom/media/webaudio/AudioProcessingEvent.cpp | 2 +- dom/network/UDPSocket.cpp | 6 +- dom/notification/Notification.cpp | 4 +- dom/offline/nsDOMOfflineResourceList.cpp | 2 +- dom/plugins/base/android/ANPSystem.cpp | 2 +- dom/plugins/base/nsJSNPRuntime.cpp | 12 +- dom/plugins/base/nsNPAPIPlugin.cpp | 4 +- dom/plugins/base/nsNPAPIPluginInstance.cpp | 6 +- dom/plugins/base/nsPluginHost.cpp | 8 +- dom/plugins/base/nsPluginInstanceOwner.cpp | 2 +- dom/power/PowerManagerService.cpp | 2 +- dom/promise/Promise.cpp | 54 +- dom/promise/PromiseCallback.cpp | 13 +- dom/promise/PromiseWorkerProxy.h | 45 +- dom/quota/QuotaManager.cpp | 2 +- dom/storage/DOMStorage.cpp | 6 +- dom/svg/DOMSVGLength.cpp | 12 +- .../android/AndroidLocationProvider.cpp | 6 +- dom/system/android/nsHapticFeedback.cpp | 2 +- dom/system/gonk/nsVolumeMountLock.cpp | 2 +- dom/system/gonk/nsVolumeService.cpp | 2 +- dom/tests/mochitest/bugs/test_bug400204.html | 18 +- dom/tests/mochitest/bugs/test_bug61098.html | 1 - .../bugs/test_resize_move_windows.html | 38 +- dom/tests/mochitest/gamepad/mochitest.ini | 7 +- .../gamepad/test_check_timestamp.html | 1 + dom/tests/mochitest/gamepad/test_gamepad.html | 12 +- .../gamepad/test_navigator_gamepads.html | 28 +- .../mochitest/general/test_interfaces.html | 10 +- dom/webidl/Animatable.webidl | 2 +- dom/webidl/Animation.webidl | 44 +- dom/webidl/AnimationEffectReadonly.webidl | 18 + dom/webidl/AnimationPlayer.webidl | 50 - dom/webidl/AnimationTimeline.webidl | 8 +- dom/webidl/Client.webidl | 2 + dom/webidl/Document.webidl | 4 +- ...nEffect.webidl => DocumentTimeline.webidl} | 9 +- dom/webidl/HTMLInputElement.webidl | 2 +- dom/webidl/KeyframeEffect.webidl | 24 + dom/webidl/MutationObserver.webidl | 6 +- dom/webidl/Window.webidl | 62 +- dom/webidl/moz.build | 5 +- dom/workers/RuntimeService.cpp | 2 +- dom/workers/ScriptLoader.cpp | 6 +- dom/workers/ServiceWorkerClient.cpp | 2 +- dom/workers/ServiceWorkerClient.h | 12 +- dom/workers/ServiceWorkerClients.cpp | 144 +- dom/workers/ServiceWorkerManager.cpp | 16 +- dom/workers/ServiceWorkerScriptCache.cpp | 8 +- dom/workers/ServiceWorkerWindowClient.cpp | 130 +- dom/workers/ServiceWorkerWindowClient.h | 2 +- dom/workers/WorkerRunnable.cpp | 10 +- dom/workers/XMLHttpRequest.cpp | 2 +- dom/xbl/nsXBLContentSink.cpp | 7 +- dom/xbl/nsXBLProtoImplField.cpp | 2 +- dom/xbl/nsXBLProtoImplMethod.cpp | 2 +- dom/xml/XMLDocument.cpp | 2 +- dom/xml/nsXMLContentSink.cpp | 8 +- dom/xslt/xpath/XPathEvaluator.cpp | 9 +- dom/xul/XULDocument.cpp | 19 +- dom/xul/nsXULCommandDispatcher.cpp | 2 +- dom/xul/nsXULControllers.cpp | 3 +- dom/xul/nsXULElement.cpp | 14 +- dom/xul/nsXULPrototypeCache.cpp | 4 +- dom/xul/nsXULPrototypeDocument.cpp | 13 +- dom/xul/templates/nsXULContentBuilder.cpp | 3 +- dom/xul/templates/nsXULTemplateBuilder.cpp | 2 +- .../nsXULTemplateQueryProcessorRDF.cpp | 12 +- .../nsXULTemplateQueryProcessorStorage.cpp | 2 +- .../nsXULTemplateQueryProcessorXML.cpp | 20 +- .../templates/nsXULTemplateResultSetRDF.cpp | 3 +- editor/libeditor/CreateElementTxn.cpp | 8 +- editor/libeditor/DeleteNodeTxn.cpp | 6 +- editor/libeditor/InsertNodeTxn.cpp | 4 +- editor/libeditor/JoinNodeTxn.cpp | 4 +- editor/libeditor/SplitNodeTxn.cpp | 10 +- editor/libeditor/nsEditor.cpp | 191 +- editor/libeditor/nsEditor.h | 11 +- editor/libeditor/nsEditorUtils.cpp | 92 +- editor/libeditor/nsEditorUtils.h | 31 +- editor/libeditor/nsHTMLAbsPosition.cpp | 144 +- editor/libeditor/nsHTMLAnonymousUtils.cpp | 15 +- editor/libeditor/nsHTMLCSSUtils.cpp | 172 +- editor/libeditor/nsHTMLCSSUtils.h | 30 +- editor/libeditor/nsHTMLDataTransfer.cpp | 429 ++- editor/libeditor/nsHTMLEditRules.cpp | 2320 +++++++---------- editor/libeditor/nsHTMLEditRules.h | 89 +- editor/libeditor/nsHTMLEditor.cpp | 321 +-- editor/libeditor/nsHTMLEditor.h | 146 +- editor/libeditor/nsHTMLEditorStyle.cpp | 790 +++--- editor/libeditor/nsHTMLInlineTableEditor.cpp | 2 +- editor/libeditor/nsHTMLObjectResizer.cpp | 290 +-- editor/libeditor/tests/test_bug408231.html | 2 +- .../spellcheck/src/mozInlineSpellChecker.cpp | 2 +- gfx/gl/AndroidSurfaceTexture.cpp | 6 +- gfx/layers/Layers.cpp | 2 +- gfx/layers/apz/src/AsyncPanZoomController.cpp | 2 +- gfx/layers/apz/src/Axis.cpp | 2 +- gfx/layers/apz/util/APZCCallbackHelper.cpp | 1 + .../composite/AsyncCompositionManager.cpp | 4 +- gfx/thebes/gfxSVGGlyphs.cpp | 2 +- hal/Hal.cpp | 10 - hal/Hal.h | 11 - hal/android/AndroidHal.cpp | 18 +- hal/android/AndroidSensor.cpp | 4 +- hal/moz.build | 21 - hal/sandbox/SandboxHal.cpp | 7 - image/SVGDocumentWrapper.cpp | 2 +- image/build/nsImageModule.cpp | 28 +- image/imgTools.cpp | 3 +- ipc/glue/MessageChannel.h | 2 +- ipc/glue/MessagePump.cpp | 2 +- ipc/glue/WindowsMessageLoop.cpp | 2 +- ipc/testshell/TestShellParent.cpp | 3 +- js/ipc/WrapperAnswer.cpp | 166 +- js/ipc/WrapperAnswer.h | 11 +- js/xpconnect/loader/mozJSComponentLoader.cpp | 12 +- js/xpconnect/src/Sandbox.cpp | 6 +- js/xpconnect/src/XPCShellImpl.cpp | 7 +- js/xpconnect/src/XPCWrappedJSClass.cpp | 6 +- layout/base/RestyleManager.cpp | 4 +- layout/base/nsDisplayList.cpp | 64 +- layout/base/nsLayoutUtils.cpp | 31 +- layout/base/nsRefreshDriver.cpp | 173 +- layout/base/nsRefreshDriver.h | 11 +- layout/base/tests/bug956530-1-ref.html | 23 + layout/base/tests/bug956530-1.html | 32 + layout/base/tests/mochitest.ini | 2 + .../base/tests/test_reftests_with_caret.html | 1 + .../tests/test_scroll_event_ordering.html | 13 +- layout/build/nsContentDLF.h | 48 +- layout/build/nsLayoutModule.cpp | 2 +- layout/generic/nsFrame.cpp | 8 +- layout/generic/nsFrameSelection.h | 7 + layout/generic/nsIFrame.h | 20 +- layout/generic/nsSelection.cpp | 38 +- layout/inspector/inDOMUtils.cpp | 13 +- layout/style/AnimationCommon.cpp | 218 +- layout/style/AnimationCommon.h | 49 +- layout/style/CSSStyleSheet.cpp | 2 +- layout/style/nsAnimationManager.cpp | 247 +- layout/style/nsAnimationManager.h | 30 +- layout/style/nsComputedDOMStyle.cpp | 4 +- layout/style/nsICSSDeclaration.h | 2 +- layout/style/nsROCSSPrimitiveValue.cpp | 4 +- layout/style/nsTransitionManager.cpp | 142 +- layout/style/nsTransitionManager.h | 40 +- layout/xul/tree/nsTreeBodyFrame.cpp | 2 +- .../videoengine/VideoCaptureAndroid.java | 10 +- modules/libjar/nsJARURI.cpp | 6 +- modules/libpref/Preferences.cpp | 8 +- netwerk/base/Tickler.cpp | 2 +- netwerk/base/nsDirectoryIndexStream.cpp | 9 +- netwerk/base/nsNetUtil.h | 32 +- netwerk/base/nsURLHelperOSX.cpp | 2 +- netwerk/base/nsURLHelperUnix.cpp | 2 +- netwerk/base/nsURLHelperWin.cpp | 2 +- netwerk/protocol/data/nsDataChannel.cpp | 2 +- .../device/AndroidCaptureProvider.cpp | 3 +- netwerk/protocol/device/CameraStreamImpl.cpp | 6 +- .../device/nsDeviceProtocolHandler.cpp | 6 +- netwerk/protocol/http/nsHttpConnectionMgr.cpp | 2 +- netwerk/protocol/http/nsHttpDigestAuth.cpp | 2 +- netwerk/protocol/res/nsResProtocolHandler.cpp | 9 +- .../websocket/BaseWebSocketChannel.cpp | 2 +- .../wyciwyg/nsWyciwygProtocolHandler.cpp | 3 +- .../streamconv/nsStreamConverterService.cpp | 12 +- .../android/nsAndroidNetworkLinkService.cpp | 6 +- .../manager/ssl/src/nsProtectedAuthThread.cpp | 7 +- testing/mozbase/mozcrash/mozcrash/mozcrash.py | 8 +- testing/mozbase/mozcrash/tests/test.py | 12 +- .../window-properties.html.ini | 39 - .../animation-timeline/idlharness.html.ini | 7 + .../the-window-object/window-properties.html | 39 +- toolkit/components/alerts/nsAlertsService.cpp | 6 +- .../components/commandlines/nsCommandLine.cpp | 6 +- .../downloads/nsDownloadManager.cpp | 4 +- toolkit/components/filepicker/nsFileView.cpp | 2 +- toolkit/components/places/SQLFunctions.cpp | 6 +- .../components/places/nsAnnotationService.cpp | 10 +- .../components/places/nsNavHistoryQuery.cpp | 6 +- .../typeaheadfind/nsTypeAheadFind.cpp | 7 +- toolkit/devtools/framework/test/browser.ini | 4 + ...options_enable_serviceworkers_testing.html | 58 + ...x_options_enable_serviceworkers_testing.js | 124 + .../devtools/framework/test/serviceworker.js | 1 + toolkit/devtools/framework/toolbox-options.js | 2 +- .../devtools/framework/toolbox-options.xul | 4 + toolkit/devtools/framework/toolbox.js | 33 +- .../browser_profiler_shared-connection-01.js | 23 +- toolkit/devtools/server/actors/animation.js | 8 +- toolkit/devtools/server/actors/webbrowser.js | 41 +- .../en-US/chrome/global/devtools/toolbox.dtd | 6 + toolkit/modules/sessionstore/FormData.jsm | 7 +- toolkit/mozapps/update/common/errors.h | 28 +- toolkit/profile/nsToolkitProfileService.cpp | 9 +- toolkit/system/gnome/nsGConfService.cpp | 2 +- toolkit/system/gnome/nsGIOService.cpp | 2 +- toolkit/system/gnome/nsGSettingsService.cpp | 4 +- toolkit/xre/nsAndroidStartup.cpp | 2 +- toolkit/xre/nsAppRunner.cpp | 6 +- toolkit/xre/nsUpdateDriver.cpp | 2 +- toolkit/xre/nsXREDirProvider.cpp | 22 +- tools/profiler/platform.cpp | 6 +- .../android/nsAndroidHandlerApp.cpp | 4 +- .../android/nsExternalSharingAppService.cpp | 2 +- .../exthandler/android/nsMIMEInfoAndroid.cpp | 2 +- widget/cocoa/nsAppShell.h | 2 +- widget/cocoa/nsAppShell.mm | 40 +- widget/cocoa/nsChildView.mm | 214 +- widget/nsBaseAppShell.cpp | 10 +- widget/nsBaseAppShell.h | 6 +- widget/nsBaseWidget.cpp | 10 - widget/nsBaseWidget.h | 2 - widget/nsIWidget.h | 3 - widget/windows/WinMouseScrollHandler.cpp.bak | 1595 ++++++++++++ widget/windows/nsAppShell.cpp | 6 +- widget/windows/nsAppShell.h | 2 +- widget/windows/nsWindow.cpp | 39 +- widget/windows/nsWindow.h | 4 +- xpcom/base/nsIException.idl | 10 - xpcom/base/nsSystemInfo.cpp | 2 +- xpcom/components/ManifestParser.cpp | 2 +- xpcom/io/nsLocalFileUnix.cpp | 2 +- xpcom/reflect/xptcall/md/unix/moz.build | 2 +- xpfe/appshell/nsContentTreeOwner.cpp | 2 +- xpfe/appshell/nsWindowMediator.cpp | 14 +- .../directory/nsDirectoryViewer.cpp | 14 +- .../windowds/nsWindowDataSource.cpp | 3 +- 429 files changed, 12037 insertions(+), 8560 deletions(-) delete mode 100644 dom/animation/AnimationEffect.cpp delete mode 100644 dom/animation/AnimationEffect.h create mode 100644 dom/animation/AnimationEffectReadonly.cpp create mode 100644 dom/animation/AnimationEffectReadonly.h delete mode 100644 dom/animation/AnimationPlayer.cpp delete mode 100644 dom/animation/AnimationPlayer.h create mode 100644 dom/animation/DocumentTimeline.cpp create mode 100644 dom/animation/DocumentTimeline.h create mode 100644 dom/animation/KeyframeEffect.cpp create mode 100644 dom/animation/KeyframeEffect.h rename dom/animation/{PendingPlayerTracker.cpp => PendingAnimationTracker.cpp} (53%) create mode 100644 dom/animation/PendingAnimationTracker.h delete mode 100644 dom/animation/PendingPlayerTracker.h rename dom/animation/test/css-animations/{test_animation-player-currenttime.html => test_animation-currenttime.html} (95%) rename dom/animation/test/css-animations/{test_animation-player-finished.html => test_animation-finished.html} (100%) rename dom/animation/test/css-animations/{test_animation-player-playstate.html => test_animation-playstate.html} (100%) rename dom/animation/test/css-animations/{test_animation-player-ready.html => test_animation-ready.html} (100%) rename dom/animation/test/css-animations/{test_animation-player-starttime.html => test_animation-starttime.html} (96%) rename dom/animation/test/css-animations/{test_animation-effect-name.html => test_effect-name.html} (75%) rename dom/animation/test/css-animations/{test_animation-target.html => test_effect-target.html} (91%) rename dom/animation/test/css-animations/{test_element-get-animation-players.html => test_element-get-animations.html} (99%) rename dom/animation/test/css-transitions/{test_animation-player-currenttime.html => test_animation-currenttime.html} (97%) create mode 100644 dom/animation/test/css-transitions/test_animation-ready.html create mode 100644 dom/animation/test/css-transitions/test_animation-starttime.html rename dom/animation/test/css-transitions/{test_animation-effect-name.html => test_effect-name.html} (89%) rename dom/animation/test/css-transitions/{test_animation-target.html => test_effect-target.html} (92%) rename dom/animation/test/css-transitions/{test_element-get-animation-players.html => test_element-get-animations.html} (100%) rename dom/animation/test/{animation-timeline/test_animation-timeline.html => document-timeline/test_document-timeline.html} (98%) rename dom/animation/test/{animation-timeline => document-timeline}/test_request_animation_frame.html (100%) create mode 100644 dom/base/test/chrome/test_windowroot.xul create mode 100644 dom/gamepad/GamepadFunctions.cpp create mode 100644 dom/gamepad/GamepadFunctions.h create mode 100644 dom/gamepad/GamepadMonitoring.cpp create mode 100644 dom/gamepad/GamepadMonitoring.h create mode 100644 dom/gamepad/GamepadServiceTest.cpp create mode 100644 dom/gamepad/GamepadServiceTest.h rename {hal => dom/gamepad}/android/AndroidGamepad.cpp (56%) rename {hal => dom/gamepad}/cocoa/CocoaGamepad.cpp (57%) rename {hal => dom/gamepad}/fallback/FallbackGamepad.cpp (74%) rename {hal => dom/gamepad}/linux/LinuxGamepad.cpp (89%) rename {hal => dom/gamepad}/linux/udev.h (100%) rename {hal => dom/gamepad}/windows/WindowsGamepad.cpp (92%) create mode 100644 dom/html/test/formSubmission_chrome.js create mode 100644 dom/media/SimpleImageBuffer.cpp create mode 100644 dom/media/SimpleImageBuffer.h create mode 100644 dom/media/standalone/moz.build create mode 100644 dom/webidl/AnimationEffectReadonly.webidl delete mode 100644 dom/webidl/AnimationPlayer.webidl rename dom/webidl/{AnimationEffect.webidl => DocumentTimeline.webidl} (64%) create mode 100644 dom/webidl/KeyframeEffect.webidl create mode 100644 layout/base/tests/bug956530-1-ref.html create mode 100644 layout/base/tests/bug956530-1.html create mode 100644 testing/web-platform/meta/web-animations/animation-timeline/idlharness.html.ini create mode 100644 toolkit/devtools/framework/test/browser_toolbox_options_enable_serviceworkers_testing.html create mode 100644 toolkit/devtools/framework/test/browser_toolbox_options_enable_serviceworkers_testing.js create mode 100644 toolkit/devtools/framework/test/serviceworker.js create mode 100644 widget/windows/WinMouseScrollHandler.cpp.bak diff --git a/browser/components/preferences/applications.js b/browser/components/preferences/applications.js index 5768de7089..61c8af62b2 100644 --- a/browser/components/preferences/applications.js +++ b/browser/components/preferences/applications.js @@ -400,7 +400,7 @@ HandlerInfoWrapper.prototype = { disabledPluginTypes.join(",")); // Update the category manager so existing browser windows update. - this._categoryMgr.deleteCategoryEntry("Goanna-Content-Viewers", + this._categoryMgr.deleteCategoryEntry("Gecko-Content-Viewers", this.type, false); }, @@ -416,7 +416,7 @@ HandlerInfoWrapper.prototype = { // Update the category manager so existing browser windows update. this._categoryMgr. - addCategoryEntry("Goanna-Content-Viewers", + addCategoryEntry("Gecko-Content-Viewers", this.type, "@mozilla.org/content/plugin/document-loader-factory;1", false, diff --git a/build/mobile/robocop/Actions.java b/build/mobile/robocop/Actions.java index aef83503de..e5eb9dcf68 100644 --- a/build/mobile/robocop/Actions.java +++ b/build/mobile/robocop/Actions.java @@ -41,9 +41,9 @@ public interface Actions { /** * Sends an event to Goanna. * - * @param goannaEvent The goannaEvent JSONObject's type + * @param geckoEvent The geckoEvent JSONObject's type */ - void sendGoannaEvent(String goannaEvent, String data); + void sendGeckoEvent(String geckoEvent, String data); /** * Sends a preferences get event to Goanna. @@ -73,9 +73,9 @@ public interface Actions { * The returned object can be used to test if the event has been * received. Note that only one event is listened for. * - * @param goannaEvent The goannaEvent JSONObject's type + * @param geckoEvent The geckoEvent JSONObject's type */ - RepeatedEventExpecter expectGoannaEvent(String goannaEvent); + RepeatedEventExpecter expectGeckoEvent(String geckoEvent); /** * Listens for a paint event. Note that calling expectPaint() will diff --git a/build/mobile/robocop/FennecNativeActions.java b/build/mobile/robocop/FennecNativeActions.java index 0e005b2234..c655b64a82 100644 --- a/build/mobile/robocop/FennecNativeActions.java +++ b/build/mobile/robocop/FennecNativeActions.java @@ -14,7 +14,7 @@ import org.mozilla.goanna.gfx.LayerView; import org.mozilla.goanna.gfx.LayerView.DrawListener; import org.mozilla.goanna.mozglue.GoannaLoader; import org.mozilla.goanna.sqlite.SQLiteBridge; -import org.mozilla.goanna.util.GoannaEventListener; +import org.mozilla.goanna.util.GeckoEventListener; import android.app.Activity; import android.app.Instrumentation; @@ -40,39 +40,39 @@ public class FennecNativeActions implements Actions { GoannaLoader.loadSQLiteLibs(activity, activity.getApplication().getPackageResourcePath()); } - class GoannaEventExpecter implements RepeatedEventExpecter { + class GeckoEventExpecter implements RepeatedEventExpecter { private static final int MAX_WAIT_MS = 180000; private volatile boolean mIsRegistered; - private final String mGoannaEvent; - private final GoannaEventListener mListener; + private final String mGeckoEvent; + private final GeckoEventListener mListener; private volatile boolean mEventEverReceived; private String mEventData; private BlockingQueue mEventDataQueue; - GoannaEventExpecter(final String goannaEvent) { - if (TextUtils.isEmpty(goannaEvent)) { - throw new IllegalArgumentException("goannaEvent must not be empty"); + GeckoEventExpecter(final String geckoEvent) { + if (TextUtils.isEmpty(geckoEvent)) { + throw new IllegalArgumentException("geckoEvent must not be empty"); } - mGoannaEvent = goannaEvent; + mGeckoEvent = geckoEvent; mEventDataQueue = new LinkedBlockingQueue(); - final GoannaEventExpecter expecter = this; - mListener = new GoannaEventListener() { + final GeckoEventExpecter expecter = this; + mListener = new GeckoEventListener() { @Override public void handleMessage(final String event, final JSONObject message) { FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, - "handleMessage called for: " + event + "; expecting: " + mGoannaEvent); - mAsserter.is(event, mGoannaEvent, "Given message occurred for registered event: " + message); + "handleMessage called for: " + event + "; expecting: " + mGeckoEvent); + mAsserter.is(event, mGeckoEvent, "Given message occurred for registered event: " + message); expecter.notifyOfEvent(message); } }; - EventDispatcher.getInstance().registerGoannaThreadListener(mListener, mGoannaEvent); + EventDispatcher.getInstance().registerGeckoThreadListener(mListener, mGeckoEvent); mIsRegistered = true; } @@ -93,15 +93,15 @@ public class FennecNativeActions implements Actions { if (mEventData == null) { if (failOnTimeout) { FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR); - mAsserter.ok(false, "GoannaEventExpecter", - "blockForEvent timeout: "+mGoannaEvent); + mAsserter.ok(false, "GeckoEventExpecter", + "blockForEvent timeout: "+mGeckoEvent); } else { FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, - "blockForEvent timeout: "+mGoannaEvent); + "blockForEvent timeout: "+mGeckoEvent); } } else { FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, - "unblocked on expecter for " + mGoannaEvent); + "unblocked on expecter for " + mGeckoEvent); } } @@ -121,7 +121,7 @@ public class FennecNativeActions implements Actions { } if (mEventData == null) { FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR); - mAsserter.ok(false, "GoannaEventExpecter", "blockUntilClear timeout"); + mAsserter.ok(false, "GeckoEventExpecter", "blockUntilClear timeout"); return; } // now wait for a period of millis where we don't get an event @@ -137,7 +137,7 @@ public class FennecNativeActions implements Actions { } } FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, - "unblocked on expecter for " + mGoannaEvent); + "unblocked on expecter for " + mGeckoEvent); } public String blockForEventData() { @@ -156,9 +156,9 @@ public class FennecNativeActions implements Actions { } FennecNativeDriver.log(LogLevel.INFO, - "EventExpecter: no longer listening for " + mGoannaEvent); + "EventExpecter: no longer listening for " + mGeckoEvent); - EventDispatcher.getInstance().unregisterGoannaThreadListener(mListener, mGoannaEvent); + EventDispatcher.getInstance().unregisterGeckoThreadListener(mListener, mGeckoEvent); mIsRegistered = false; } @@ -168,7 +168,7 @@ public class FennecNativeActions implements Actions { void notifyOfEvent(final JSONObject message) { FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, - "received event " + mGoannaEvent); + "received event " + mGeckoEvent); mEventEverReceived = true; @@ -181,25 +181,25 @@ public class FennecNativeActions implements Actions { } } - public RepeatedEventExpecter expectGoannaEvent(final String goannaEvent) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, "waiting for " + goannaEvent); - return new GoannaEventExpecter(goannaEvent); + public RepeatedEventExpecter expectGeckoEvent(final String geckoEvent) { + FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, "waiting for " + geckoEvent); + return new GeckoEventExpecter(geckoEvent); } - public void sendGoannaEvent(final String goannaEvent, final String data) { - GoannaAppShell.sendEventToGoanna(GoannaEvent.createBroadcastEvent(goannaEvent, data)); + public void sendGeckoEvent(final String geckoEvent, final String data) { + GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(geckoEvent, data)); } public void sendPreferencesGetEvent(int requestId, String[] prefNames) { - GoannaAppShell.sendEventToGoanna(GoannaEvent.createPreferencesGetEvent(requestId, prefNames)); + GeckoAppShell.sendEventToGecko(GeckoEvent.createPreferencesGetEvent(requestId, prefNames)); } public void sendPreferencesObserveEvent(int requestId, String[] prefNames) { - GoannaAppShell.sendEventToGoanna(GoannaEvent.createPreferencesObserveEvent(requestId, prefNames)); + GeckoAppShell.sendEventToGecko(GeckoEvent.createPreferencesObserveEvent(requestId, prefNames)); } public void sendPreferencesRemoveObserversEvent(int requestId) { - GoannaAppShell.sendEventToGoanna(GoannaEvent.createPreferencesRemoveObserversEvent(requestId)); + GeckoAppShell.sendEventToGecko(GeckoEvent.createPreferencesRemoveObserversEvent(requestId)); } class PaintExpecter implements RepeatedEventExpecter { @@ -213,7 +213,7 @@ public class FennecNativeActions implements Actions { PaintExpecter() { final PaintExpecter expecter = this; - mLayerView = GoannaAppShell.getLayerView(); + mLayerView = GeckoAppShell.getLayerView(); mDrawListener = new DrawListener() { @Override public void drawFinished() { diff --git a/build/mobile/robocop/FennecNativeDriver.java b/build/mobile/robocop/FennecNativeDriver.java index 097a8f6df9..01edd8af58 100644 --- a/build/mobile/robocop/FennecNativeDriver.java +++ b/build/mobile/robocop/FennecNativeDriver.java @@ -22,7 +22,7 @@ import org.json.JSONException; import org.json.JSONObject; import org.mozilla.goanna.gfx.LayerView; import org.mozilla.goanna.gfx.PanningPerfAPI; -import org.mozilla.goanna.util.GoannaEventListener; +import org.mozilla.goanna.util.GeckoEventListener; import android.app.Activity; import android.util.Log; @@ -248,7 +248,7 @@ public class FennecNativeDriver implements Driver { @Override public void setupScrollHandling() { - EventDispatcher.getInstance().registerGoannaThreadListener(new GoannaEventListener() { + EventDispatcher.getInstance().registerGeckoThreadListener(new GeckoEventListener() { @Override public void handleMessage(final String event, final JSONObject message) { try { diff --git a/configure.in b/configure.in index 42d9077a09..12e0513063 100644 --- a/configure.in +++ b/configure.in @@ -5480,12 +5480,18 @@ MOZ_ARG_DISABLE_BOOL(permissions, MOZ_PERMISSIONS=1 ) +AC_SUBST(MOZ_PERMISSIONS) +if test -n "$MOZ_PERMISSIONS"; then + AC_DEFINE(MOZ_PERMISSIONS) +fi + dnl ======================================================== dnl Child permissions, currently only used for b2g dnl ======================================================== if test -n "$MOZ_B2G"; then if test -n "$MOZ_PERMISSIONS"; then MOZ_CHILD_PERMISSIONS=1 + AC_DEFINE(MOZ_CHILD_PERMISSIONS) else AC_MSG_ERROR([You need to enable MOZ_PERMISSIONS for MOZ_CHILD_PERMISSIONS]) fi @@ -8123,7 +8129,6 @@ AC_SUBST(BIN_FLAGS) AC_SUBST(MOZ_WIDGET_TOOLKIT) AC_SUBST(MOZ_UPDATE_XTERM) AC_SUBST(MOZ_AUTH_EXTENSION) -AC_SUBST(MOZ_PERMISSIONS) AC_SUBST(MOZ_PREF_EXTENSIONS) AC_SUBST(MOZ_DEBUG) AC_SUBST(MOZ_DEBUG_SYMBOLS) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index a26a30452a..844489f94e 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -14130,7 +14130,7 @@ nsDocShell::GetURLSearchParams() } void -nsDocShell::NotifyJSRunToCompletionStart() +nsDocShell::NotifyJSRunToCompletionStart(const char *aReason) { bool timelineOn = nsIDocShell::GetRecordProfileTimelineMarkers(); diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl index 8d6ff32054..51950860dc 100644 --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -1033,7 +1033,7 @@ interface nsIDocShell : nsIDocShellTreeItem * that execution has stopped. This only occurs when the Timeline devtool * is collecting information. */ - [noscript,notxpcom,nostdcall] void notifyJSRunToCompletionStart(); + [noscript,notxpcom,nostdcall] void notifyJSRunToCompletionStart(in string aReason); [noscript,notxpcom,nostdcall] void notifyJSRunToCompletionStop(); /** diff --git a/docshell/base/nsIDocumentLoaderFactory.idl b/docshell/base/nsIDocumentLoaderFactory.idl index 929667c4c4..7e0df1fd7d 100644 --- a/docshell/base/nsIDocumentLoaderFactory.idl +++ b/docshell/base/nsIDocumentLoaderFactory.idl @@ -17,7 +17,7 @@ interface nsIPrincipal; /** * To get a component that implements nsIDocumentLoaderFactory * for a given mimetype, use nsICategoryManager to find an entry - * with the mimetype as its name in the category "Goanna-Content-Viewers". + * with the mimetype as its name in the category "Gecko-Content-Viewers". * The value of the entry is the contractid of the component. * The component is a service, so use GetService, not CreateInstance to get it. */ diff --git a/docshell/base/nsWebNavigationInfo.cpp b/docshell/base/nsWebNavigationInfo.cpp index 9cc2a4a570..95ef8d950d 100644 --- a/docshell/base/nsWebNavigationInfo.cpp +++ b/docshell/base/nsWebNavigationInfo.cpp @@ -40,7 +40,7 @@ nsWebNavigationInfo::IsTypeSupported(const nsACString& aType, // an nsSHistory, but not much we can do with that). So if we start using // it here, we need to be careful to get to the docshell correctly. - // For now just report what the Goanna-Content-Viewers category has + // For now just report what the Gecko-Content-Viewers category has // to say for itself. *aIsTypeSupported = nsIWebNavigationInfo::UNSUPPORTED; diff --git a/docshell/shistory/src/nsSHistory.cpp b/docshell/shistory/src/nsSHistory.cpp index a2d6b07cfd..4a7481e122 100644 --- a/docshell/shistory/src/nsSHistory.cpp +++ b/docshell/shistory/src/nsSHistory.cpp @@ -1814,13 +1814,10 @@ nsSHistory::SetRootDocShell(nsIDocShell * aDocShell) NS_IMETHODIMP nsSHistory::GetSHistoryEnumerator(nsISimpleEnumerator** aEnumerator) { - nsresult status = NS_OK; - NS_ENSURE_ARG_POINTER(aEnumerator); - nsSHEnumerator * iterator = new nsSHEnumerator(this); - if (iterator && NS_FAILED(status = CallQueryInterface(iterator, aEnumerator))) - delete iterator; - return status; + nsRefPtr iterator = new nsSHEnumerator(this); + iterator.forget(aEnumerator); + return NS_OK; } diff --git a/dom/animation/Animation.cpp b/dom/animation/Animation.cpp index 577e8a341b..43683926e5 100644 --- a/dom/animation/Animation.cpp +++ b/dom/animation/Animation.cpp @@ -1,390 +1,889 @@ /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ /* 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/. */ + * 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 "mozilla/dom/Animation.h" +#include "Animation.h" +#include "AnimationUtils.h" #include "mozilla/dom/AnimationBinding.h" -#include "mozilla/dom/AnimationEffect.h" -#include "mozilla/FloatingPoint.h" -#include "AnimationCommon.h" -#include "nsCSSPropertySet.h" +#include "mozilla/AutoRestore.h" +#include "AnimationCommon.h" // For AnimationCollection, + // CommonAnimationManager +#include "nsIDocument.h" // For nsIDocument +#include "nsIPresShell.h" // For nsIPresShell +#include "nsLayoutUtils.h" // For PostRestyleEvent (remove after bug 1073336) +#include "PendingAnimationTracker.h" // For PendingAnimationTracker namespace mozilla { - -void -ComputedTimingFunction::Init(const nsTimingFunction &aFunction) -{ - mType = aFunction.mType; - if (mType == nsTimingFunction::Function) { - mTimingFunction.Init(aFunction.mFunc.mX1, aFunction.mFunc.mY1, - aFunction.mFunc.mX2, aFunction.mFunc.mY2); - } else { - mSteps = aFunction.mSteps; - } -} - -static inline double -StepEnd(uint32_t aSteps, double aPortion) -{ - MOZ_ASSERT(0.0 <= aPortion && aPortion <= 1.0, "out of range"); - uint32_t step = uint32_t(aPortion * aSteps); // floor - return double(step) / double(aSteps); -} - -double -ComputedTimingFunction::GetValue(double aPortion) const -{ - switch (mType) { - case nsTimingFunction::Function: - return mTimingFunction.GetSplineValue(aPortion); - case nsTimingFunction::StepStart: - // There are diagrams in the spec that seem to suggest this check - // and the bounds point should not be symmetric with StepEnd, but - // should actually step up at rather than immediately after the - // fraction points. However, we rely on rounding negative values - // up to zero, so we can't do that. And it's not clear the spec - // really meant it. - return 1.0 - StepEnd(mSteps, 1.0 - aPortion); - default: - MOZ_ASSERT(false, "bad type"); - // fall through - case nsTimingFunction::StepEnd: - return StepEnd(mSteps, aPortion); - } -} - -// In the Web Animations model, the time fraction can be outside the range -// [0.0, 1.0] but it shouldn't be Infinity. -const double ComputedTiming::kNullTimeFraction = PositiveInfinity(); - namespace dom { -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Animation, mDocument, mTarget) - -NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(Animation, AddRef) -NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(Animation, Release) +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Animation, mTimeline, + mEffect, mReady, mFinished) +NS_IMPL_CYCLE_COLLECTING_ADDREF(Animation) +NS_IMPL_CYCLE_COLLECTING_RELEASE(Animation) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Animation) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END JSObject* Animation::WrapObject(JSContext* aCx, JS::Handle aGivenProto) { - return AnimationBinding::Wrap(aCx, this, aGivenProto); -} - -already_AddRefed -Animation::GetEffect() -{ - nsRefPtr effect = new AnimationEffect(this); - return effect.forget(); + return dom::AnimationBinding::Wrap(aCx, this, aGivenProto); } void -Animation::SetParentTime(Nullable aParentTime) +Animation::SetStartTime(const Nullable& aNewStartTime) { - mParentTime = aParentTime; +#if 1 + // Bug 1096776: once we support inactive/missing timelines we'll want to take + // the disabled branch. + MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(), + "We don't support inactive/missing timelines yet"); +#else + Nullable timelineTime = mTimeline->GetCurrentTime(); + if (mTimeline) { + // The spec says to check if the timeline is active (has a resolved time) + // before using it here, but we don't need to since it's harmless to set + // the already null time to null. + timelineTime = mTimeline->GetCurrentTime(); + } + if (timelineTime.IsNull() && !aNewStartTime.IsNull()) { + mHoldTime.SetNull(); + } +#endif + Nullable previousCurrentTime = GetCurrentTime(); + mStartTime = aNewStartTime; + if (!aNewStartTime.IsNull()) { + if (mPlaybackRate != 0.0) { + mHoldTime.SetNull(); + } + } else { + mHoldTime = previousCurrentTime; + } + + CancelPendingTasks(); + if (mReady) { + // We may have already resolved mReady, but in that case calling + // MaybeResolve is a no-op, so that's okay. + mReady->MaybeResolve(this); + } + + UpdateTiming(); + PostUpdate(); } -ComputedTiming -Animation::GetComputedTimingAt(const Nullable& aLocalTime, - const AnimationTiming& aTiming) +Nullable +Animation::GetCurrentTime() const { - const TimeDuration zeroDuration; - - // Currently we expect negative durations to be picked up during CSS - // parsing but when we start receiving timing parameters from other sources - // we will need to clamp negative durations here. - // For now, if we're hitting this it probably means we're overflowing - // integer arithmetic in mozilla::TimeStamp. - MOZ_ASSERT(aTiming.mIterationDuration >= zeroDuration, - "Expecting iteration duration >= 0"); - - // Always return the same object to benefit from return-value optimization. - ComputedTiming result; - - result.mActiveDuration = ActiveDuration(aTiming); - - // The default constructor for ComputedTiming sets all other members to - // values consistent with an animation that has not been sampled. - if (aLocalTime.IsNull()) { + Nullable result; + if (!mHoldTime.IsNull()) { + result = mHoldTime; return result; } - const TimeDuration& localTime = aLocalTime.Value(); - // When we finish exactly at the end of an iteration we need to report - // the end of the final iteration and not the start of the next iteration - // so we set up a flag for that case. - bool isEndOfFinalIteration = false; - - // Get the normalized time within the active interval. - StickyTimeDuration activeTime; - if (localTime >= aTiming.mDelay + result.mActiveDuration) { - result.mPhase = ComputedTiming::AnimationPhase_After; - if (!aTiming.FillsForwards()) { - // The animation isn't active or filling at this time. - result.mTimeFraction = ComputedTiming::kNullTimeFraction; - return result; + if (!mStartTime.IsNull()) { + Nullable timelineTime = mTimeline->GetCurrentTime(); + if (!timelineTime.IsNull()) { + result.SetValue((timelineTime.Value() - mStartTime.Value()) + .MultDouble(mPlaybackRate)); } - activeTime = result.mActiveDuration; - // Note that infinity == floor(infinity) so this will also be true when we - // have finished an infinitely repeating animation of zero duration. - isEndOfFinalIteration = - aTiming.mIterationCount != 0.0 && - aTiming.mIterationCount == floor(aTiming.mIterationCount); - } else if (localTime < aTiming.mDelay) { - result.mPhase = ComputedTiming::AnimationPhase_Before; - if (!aTiming.FillsBackwards()) { - // The animation isn't active or filling at this time. - result.mTimeFraction = ComputedTiming::kNullTimeFraction; - return result; - } - // activeTime is zero - } else { - MOZ_ASSERT(result.mActiveDuration != zeroDuration, - "How can we be in the middle of a zero-duration interval?"); - result.mPhase = ComputedTiming::AnimationPhase_Active; - activeTime = localTime - aTiming.mDelay; } - - // Get the position within the current iteration. - StickyTimeDuration iterationTime; - if (aTiming.mIterationDuration != zeroDuration) { - iterationTime = isEndOfFinalIteration - ? StickyTimeDuration(aTiming.mIterationDuration) - : activeTime % aTiming.mIterationDuration; - } /* else, iterationTime is zero */ - - // Determine the 0-based index of the current iteration. - if (isEndOfFinalIteration) { - result.mCurrentIteration = - aTiming.mIterationCount == NS_IEEEPositiveInfinity() - ? UINT64_MAX // FIXME: When we return this via the API we'll need - // to make sure it ends up being infinity. - : static_cast(aTiming.mIterationCount) - 1; - } else if (activeTime == zeroDuration) { - // If the active time is zero we're either in the first iteration - // (including filling backwards) or we have finished an animation with an - // iteration duration of zero that is filling forwards (but we're not at - // the exact end of an iteration since we deal with that above). - result.mCurrentIteration = - result.mPhase == ComputedTiming::AnimationPhase_After - ? static_cast(aTiming.mIterationCount) // floor - : 0; - } else { - result.mCurrentIteration = - static_cast(activeTime / aTiming.mIterationDuration); // floor - } - - // Normalize the iteration time into a fraction of the iteration duration. - if (result.mPhase == ComputedTiming::AnimationPhase_Before) { - result.mTimeFraction = 0.0; - } else if (result.mPhase == ComputedTiming::AnimationPhase_After) { - result.mTimeFraction = isEndOfFinalIteration - ? 1.0 - : fmod(aTiming.mIterationCount, 1.0f); - } else { - // We are in the active phase so the iteration duration can't be zero. - MOZ_ASSERT(aTiming.mIterationDuration != zeroDuration, - "In the active phase of a zero-duration animation?"); - result.mTimeFraction = - aTiming.mIterationDuration == TimeDuration::Forever() - ? 0.0 - : iterationTime / aTiming.mIterationDuration; - } - - bool thisIterationReverse = false; - switch (aTiming.mDirection) { - case NS_STYLE_ANIMATION_DIRECTION_NORMAL: - thisIterationReverse = false; - break; - case NS_STYLE_ANIMATION_DIRECTION_REVERSE: - thisIterationReverse = true; - break; - case NS_STYLE_ANIMATION_DIRECTION_ALTERNATE: - thisIterationReverse = (result.mCurrentIteration & 1) == 1; - break; - case NS_STYLE_ANIMATION_DIRECTION_ALTERNATE_REVERSE: - thisIterationReverse = (result.mCurrentIteration & 1) == 0; - break; - } - if (thisIterationReverse) { - result.mTimeFraction = 1.0 - result.mTimeFraction; - } - return result; } -StickyTimeDuration -Animation::ActiveDuration(const AnimationTiming& aTiming) +// Implements http://w3c.github.io/web-animations/#silently-set-the-current-time +void +Animation::SilentlySetCurrentTime(const TimeDuration& aSeekTime) { - if (aTiming.mIterationCount == mozilla::PositiveInfinity()) { - // An animation that repeats forever has an infinite active duration - // unless its iteration duration is zero, in which case it has a zero - // active duration. - const StickyTimeDuration zeroDuration; - return aTiming.mIterationDuration == zeroDuration - ? zeroDuration - : StickyTimeDuration::Forever(); - } - return StickyTimeDuration( - aTiming.mIterationDuration.MultDouble(aTiming.mIterationCount)); -} - -// http://w3c.github.io/web-animations/#in-play -bool -Animation::IsInPlay(const AnimationPlayer& aPlayer) const -{ - if (IsFinishedTransition() || - aPlayer.PlayState() == AnimationPlayState::Finished) { - return false; - } - - return GetComputedTiming().mPhase == ComputedTiming::AnimationPhase_Active; -} - -// http://w3c.github.io/web-animations/#current -bool -Animation::IsCurrent(const AnimationPlayer& aPlayer) const -{ - if (IsFinishedTransition() || - aPlayer.PlayState() == AnimationPlayState::Finished) { - return false; - } - - ComputedTiming computedTiming = GetComputedTiming(); - return computedTiming.mPhase == ComputedTiming::AnimationPhase_Before || - computedTiming.mPhase == ComputedTiming::AnimationPhase_Active; -} - -bool -Animation::IsInEffect() const -{ - if (IsFinishedTransition()) { - return false; - } - - ComputedTiming computedTiming = GetComputedTiming(); - return computedTiming.mTimeFraction != ComputedTiming::kNullTimeFraction; -} - -const AnimationProperty* -Animation::GetAnimationOfProperty(nsCSSProperty aProperty) const -{ - for (size_t propIdx = 0, propEnd = mProperties.Length(); - propIdx != propEnd; ++propIdx) { - if (aProperty == mProperties[propIdx].mProperty) { - const AnimationProperty* result = &mProperties[propIdx]; - if (!result->mWinsInCascade) { - result = nullptr; - } - return result; + if (!mHoldTime.IsNull() || + !mTimeline || + mTimeline->GetCurrentTime().IsNull() || + mPlaybackRate == 0.0 + /*or, once supported, if we have a pending pause task*/) { + mHoldTime.SetValue(aSeekTime); + if (!mTimeline || mTimeline->GetCurrentTime().IsNull()) { + mStartTime.SetNull(); } + } else { + mStartTime.SetValue(mTimeline->GetCurrentTime().Value() - + (aSeekTime.MultDouble(1 / mPlaybackRate))); + } + + mPreviousCurrentTime.SetNull(); +} + +// Implements http://w3c.github.io/web-animations/#set-the-current-time +void +Animation::SetCurrentTime(const TimeDuration& aSeekTime) +{ + SilentlySetCurrentTime(aSeekTime); + + if (mPendingState == PendingState::PausePending) { + CancelPendingTasks(); + if (mReady) { + mReady->MaybeResolve(this); + } + } + + UpdateFinishedState(true); + UpdateEffect(); + PostUpdate(); +} + +void +Animation::SetPlaybackRate(double aPlaybackRate) +{ + Nullable previousTime = GetCurrentTime(); + mPlaybackRate = aPlaybackRate; + if (!previousTime.IsNull()) { + ErrorResult rv; + SetCurrentTime(previousTime.Value()); + MOZ_ASSERT(!rv.Failed(), "Should not assert for non-null time"); + } +} + +void +Animation::SilentlySetPlaybackRate(double aPlaybackRate) +{ + Nullable previousTime = GetCurrentTime(); + mPlaybackRate = aPlaybackRate; + if (!previousTime.IsNull()) { + ErrorResult rv; + SilentlySetCurrentTime(previousTime.Value()); + MOZ_ASSERT(!rv.Failed(), "Should not assert for non-null time"); + } +} + +AnimationPlayState +Animation::PlayState() const +{ + if (mPendingState != PendingState::NotPending) { + return AnimationPlayState::Pending; + } + + Nullable currentTime = GetCurrentTime(); + if (currentTime.IsNull()) { + return AnimationPlayState::Idle; + } + + if (mStartTime.IsNull()) { + return AnimationPlayState::Paused; + } + + if ((mPlaybackRate > 0.0 && currentTime.Value() >= EffectEnd()) || + (mPlaybackRate < 0.0 && currentTime.Value().ToMilliseconds() <= 0.0)) { + return AnimationPlayState::Finished; + } + + return AnimationPlayState::Running; +} + +static inline already_AddRefed +CreatePromise(DocumentTimeline* aTimeline, ErrorResult& aRv) +{ + nsIGlobalObject* global = aTimeline->GetParentObject(); + if (global) { + return Promise::Create(global, aRv); } return nullptr; } -bool -Animation::HasAnimationOfProperties(const nsCSSProperty* aProperties, - size_t aPropertyCount) const +Promise* +Animation::GetReady(ErrorResult& aRv) { - for (size_t i = 0; i < aPropertyCount; i++) { - if (HasAnimationOfProperty(aProperties[i])) { - return true; + if (!mReady) { + mReady = CreatePromise(mTimeline, aRv); // Lazily create on demand + } + if (!mReady) { + aRv.Throw(NS_ERROR_FAILURE); + } else if (PlayState() != AnimationPlayState::Pending) { + mReady->MaybeResolve(this); + } + return mReady; +} + +Promise* +Animation::GetFinished(ErrorResult& aRv) +{ + if (!mFinished) { + mFinished = CreatePromise(mTimeline, aRv); // Lazily create on demand + } + if (!mFinished) { + aRv.Throw(NS_ERROR_FAILURE); + } else if (IsFinished()) { + mFinished->MaybeResolve(this); + } + return mFinished; +} + +void +Animation::Play(LimitBehavior aLimitBehavior) +{ + DoPlay(aLimitBehavior); + PostUpdate(); +} + +void +Animation::Pause() +{ + // TODO: The DoPause() call should not be synchronous (bug 1109390). See + // http://w3c.github.io/web-animations/#pausing-an-animation-section + DoPause(); + PostUpdate(); +} + +Nullable +Animation::GetStartTimeAsDouble() const +{ + return AnimationUtils::TimeDurationToDouble(mStartTime); +} + +void +Animation::SetStartTimeAsDouble(const Nullable& aStartTime) +{ + return SetStartTime(AnimationUtils::DoubleToTimeDuration(aStartTime)); +} + +Nullable +Animation::GetCurrentTimeAsDouble() const +{ + return AnimationUtils::TimeDurationToDouble(GetCurrentTime()); +} + +void +Animation::SetCurrentTimeAsDouble(const Nullable& aCurrentTime, + ErrorResult& aRv) +{ + if (aCurrentTime.IsNull()) { + if (!GetCurrentTime().IsNull()) { + aRv.Throw(NS_ERROR_DOM_TYPE_ERR); + } + return; + } + + return SetCurrentTime(TimeDuration::FromMilliseconds(aCurrentTime.Value())); +} + +void +Animation::SetEffect(KeyframeEffectReadonly* aEffect) +{ + if (mEffect) { + mEffect->SetParentTime(Nullable()); + } + mEffect = aEffect; + if (mEffect) { + mEffect->SetParentTime(GetCurrentTime()); + } + UpdateRelevance(); +} + +void +Animation::Tick() +{ + // Since we are not guaranteed to get only one call per refresh driver tick, + // it's possible that mPendingReadyTime is set to a time in the future. + // In that case, we should wait until the next refresh driver tick before + // resuming. + if (mPendingState != PendingState::NotPending && + !mPendingReadyTime.IsNull() && + mPendingReadyTime.Value() <= mTimeline->GetCurrentTime().Value()) { + FinishPendingAt(mPendingReadyTime.Value()); + mPendingReadyTime.SetNull(); + } + + if (IsPossiblyOrphanedPendingAnimation()) { + MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(), + "Orphaned pending animtaions should have an active timeline"); + FinishPendingAt(mTimeline->GetCurrentTime().Value()); + } + + UpdateTiming(); +} + +void +Animation::TriggerOnNextTick(const Nullable& aReadyTime) +{ + // Normally we expect the play state to be pending but it's possible that, + // due to the handling of possibly orphaned animations in Tick(), this + // animation got started whilst still being in another document's pending + // animation map. + if (PlayState() != AnimationPlayState::Pending) { + return; + } + + // If aReadyTime.IsNull() we'll detect this in Tick() where we check for + // orphaned animations and trigger this animation anyway + mPendingReadyTime = aReadyTime; +} + +void +Animation::TriggerNow() +{ + MOZ_ASSERT(PlayState() == AnimationPlayState::Pending, + "Expected to start a pending animation"); + MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(), + "Expected an active timeline"); + + FinishPendingAt(mTimeline->GetCurrentTime().Value()); +} + +Nullable +Animation::GetCurrentOrPendingStartTime() const +{ + Nullable result; + + if (!mStartTime.IsNull()) { + result = mStartTime; + return result; + } + + if (mPendingReadyTime.IsNull() || mHoldTime.IsNull()) { + return result; + } + + // Calculate the equivalent start time from the pending ready time. + // This is the same as the calculation performed in ResumeAt and will + // need to incorporate the playbackRate when implemented (bug 1127380). + result.SetValue(mPendingReadyTime.Value() - mHoldTime.Value()); + return result; +} + +void +Animation::Cancel() +{ + if (mPendingState != PendingState::NotPending) { + CancelPendingTasks(); + if (mReady) { + mReady->MaybeReject(NS_ERROR_DOM_ABORT_ERR); } } - return false; + + if (mFinished) { + mFinished->MaybeReject(NS_ERROR_DOM_ABORT_ERR); + } + // Clear finished promise. We'll create a new one lazily. + mFinished = nullptr; + + mHoldTime.SetNull(); + mStartTime.SetNull(); + + UpdateEffect(); +} + +void +Animation::UpdateRelevance() +{ + bool wasRelevant = mIsRelevant; + mIsRelevant = HasCurrentEffect() || IsInEffect(); + + // Notify animation observers. + if (wasRelevant && !mIsRelevant) { + nsNodeUtils::AnimationRemoved(this); + } else if (!wasRelevant && mIsRelevant) { + nsNodeUtils::AnimationAdded(this); + } +} + +bool +Animation::CanThrottle() const +{ + if (!mEffect || + mEffect->IsFinishedTransition() || + mEffect->Properties().IsEmpty()) { + return true; + } + + if (!mIsRunningOnCompositor) { + return false; + } + + if (PlayState() != AnimationPlayState::Finished) { + // Unfinished animations can be throttled. + return true; + } + + // The animation has finished but, if this is the first sample since + // finishing, we need an unthrottled sample so we can apply the correct + // end-of-animation behavior on the main thread (either removing the + // animation style or applying the fill mode). + return mFinishedAtLastComposeStyle; } void Animation::ComposeStyle(nsRefPtr& aStyleRule, - nsCSSPropertySet& aSetProperties) + nsCSSPropertySet& aSetProperties, + bool& aNeedsRefreshes) { - ComputedTiming computedTiming = GetComputedTiming(); - - // If the time fraction is null, we don't have fill data for the current - // time so we shouldn't animate. - if (computedTiming.mTimeFraction == ComputedTiming::kNullTimeFraction) { + if (!mEffect || mEffect->IsFinishedTransition()) { return; } - MOZ_ASSERT(0.0 <= computedTiming.mTimeFraction && - computedTiming.mTimeFraction <= 1.0, - "timing fraction should be in [0-1]"); - - for (size_t propIdx = 0, propEnd = mProperties.Length(); - propIdx != propEnd; ++propIdx) - { - const AnimationProperty& prop = mProperties[propIdx]; - - MOZ_ASSERT(prop.mSegments[0].mFromKey == 0.0, "incorrect first from key"); - MOZ_ASSERT(prop.mSegments[prop.mSegments.Length() - 1].mToKey == 1.0, - "incorrect last to key"); - - if (aSetProperties.HasProperty(prop.mProperty)) { - // Animations are composed by AnimationPlayerCollection by iterating - // from the last animation to first. For animations targetting the - // same property, the later one wins. So if this property is already set, - // we should not override it. - continue; - } - - if (!prop.mWinsInCascade) { - // This isn't the winning declaration, so don't add it to style. - // For transitions, this is important, because it's how we - // implement the rule that CSS transitions don't run when a CSS - // animation is running on the same property and element. For - // animations, this is only skipping things that will otherwise be - // overridden. - continue; - } - - aSetProperties.AddProperty(prop.mProperty); - - MOZ_ASSERT(prop.mSegments.Length() > 0, - "property should not be in animations if it has no segments"); - - // FIXME: Maybe cache the current segment? - const AnimationPropertySegment *segment = prop.mSegments.Elements(), - *segmentEnd = segment + prop.mSegments.Length(); - while (segment->mToKey < computedTiming.mTimeFraction) { - MOZ_ASSERT(segment->mFromKey < segment->mToKey, "incorrect keys"); - ++segment; - if (segment == segmentEnd) { - MOZ_ASSERT_UNREACHABLE("incorrect time fraction"); - break; // in order to continue in outer loop (just below) - } - MOZ_ASSERT(segment->mFromKey == (segment-1)->mToKey, "incorrect keys"); - } - if (segment == segmentEnd) { - continue; - } - MOZ_ASSERT(segment->mFromKey < segment->mToKey, "incorrect keys"); - MOZ_ASSERT(segment >= prop.mSegments.Elements() && - size_t(segment - prop.mSegments.Elements()) < - prop.mSegments.Length(), - "out of array bounds"); - - if (!aStyleRule) { - // Allocate the style rule now that we know we have animation data. - aStyleRule = new css::AnimValuesStyleRule(); - } - - double positionInSegment = - (computedTiming.mTimeFraction - segment->mFromKey) / - (segment->mToKey - segment->mFromKey); - double valuePosition = - segment->mTimingFunction.GetValue(positionInSegment); - - StyleAnimationValue *val = aStyleRule->AddEmptyValue(prop.mProperty); - -#ifdef DEBUG - bool result = -#endif - StyleAnimationValue::Interpolate(prop.mProperty, - segment->mFromValue, - segment->mToValue, - valuePosition, *val); - MOZ_ASSERT(result, "interpolate must succeed now"); + AnimationPlayState playState = PlayState(); + if (playState == AnimationPlayState::Running || + playState == AnimationPlayState::Pending) { + aNeedsRefreshes = true; } + + // In order to prevent flicker, there are a few cases where we want to use + // a different time for rendering that would otherwise be returned by + // GetCurrentTime. These are: + // + // (a) For animations that are pausing but which are still running on the + // compositor. In this case we send a layer transaction that removes the + // animation but which also contains the animation values calculated on + // the main thread. To prevent flicker when this occurs we want to ensure + // the timeline time used to calculate the main thread animation values + // does not lag far behind the time used on the compositor. Ideally we + // would like to use the "animation ready time" calculated at the end of + // the layer transaction as the timeline time but it will be too late to + // update the style rule at that point so instead we just use the current + // wallclock time. + // + // (b) For animations that are pausing that we have already taken off the + // compositor. In this case we record a pending ready time but we don't + // apply it until the next tick. However, while waiting for the next tick, + // we should still use the pending ready time as the timeline time. If we + // use the regular timeline time the animation may appear jump backwards + // if the main thread's timeline time lags behind the compositor. + // + // (c) For animations that are play-pending due to an aborted pause operation + // (i.e. a pause operation that was interrupted before we entered the + // paused state). When we cancel a pending pause we might momentarily take + // the animation off the compositor, only to re-add it moments later. In + // that case the compositor might have been ahead of the main thread so we + // should use the current wallclock time to ensure the animation doesn't + // temporarily jump backwards. + // + // To address each of these cases we temporarily tweak the hold time + // immediately before updating the style rule and then restore it immediately + // afterwards. This is purely to prevent visual flicker. Other behavior + // such as dispatching events continues to rely on the regular timeline time. + { + AutoRestore> restoreHoldTime(mHoldTime); + bool updatedHoldTime = false; + + AnimationPlayState playState = PlayState(); + + if (playState == AnimationPlayState::Pending && + mHoldTime.IsNull() && + !mStartTime.IsNull()) { + Nullable timeToUse = mPendingReadyTime; + if (timeToUse.IsNull() && + mTimeline && + !mTimeline->IsUnderTestControl()) { + timeToUse = mTimeline->ToTimelineTime(TimeStamp::Now()); + } + if (!timeToUse.IsNull()) { + mHoldTime.SetValue((timeToUse.Value() - mStartTime.Value()) + .MultDouble(mPlaybackRate)); + // Push the change down to the effect + UpdateEffect(); + updatedHoldTime = true; + } + } + + mEffect->ComposeStyle(aStyleRule, aSetProperties); + + if (updatedHoldTime) { + UpdateTiming(); + } + + mFinishedAtLastComposeStyle = (playState == AnimationPlayState::Finished); + } +} + +void +Animation::DoPlay(LimitBehavior aLimitBehavior) +{ + bool abortedPause = mPendingState == PendingState::PausePending; + + bool reuseReadyPromise = false; + if (mPendingState != PendingState::NotPending) { + CancelPendingTasks(); + reuseReadyPromise = true; + } + + Nullable currentTime = GetCurrentTime(); + if (mPlaybackRate > 0.0 && + (currentTime.IsNull() || + (aLimitBehavior == LimitBehavior::AutoRewind && + (currentTime.Value().ToMilliseconds() < 0.0 || + currentTime.Value() >= EffectEnd())))) { + mHoldTime.SetValue(TimeDuration(0)); + } else if (mPlaybackRate < 0.0 && + (currentTime.IsNull() || + (aLimitBehavior == LimitBehavior::AutoRewind && + (currentTime.Value().ToMilliseconds() <= 0.0 || + currentTime.Value() > EffectEnd())))) { + mHoldTime.SetValue(TimeDuration(EffectEnd())); + } else if (mPlaybackRate == 0.0 && currentTime.IsNull()) { + mHoldTime.SetValue(TimeDuration(0)); + } + + // If the hold time is null then we're either already playing normally (and + // we can ignore this call) or we aborted a pending pause operation (in which + // case, for consistency, we need to go through the motions of doing an + // asynchronous start even though we already have a resolved start time). + if (mHoldTime.IsNull() && !abortedPause) { + return; + } + + // Clear the start time until we resolve a new one (unless we are aborting + // a pending pause operation, in which case we keep the old start time so + // that the animation continues moving uninterrupted by the aborted pause). + if (!abortedPause) { + mStartTime.SetNull(); + } + + if (!reuseReadyPromise) { + // Clear ready promise. We'll create a new one lazily. + mReady = nullptr; + } + + mPendingState = PendingState::PlayPending; + + nsIDocument* doc = GetRenderedDocument(); + if (!doc) { + TriggerOnNextTick(Nullable()); + return; + } + + PendingAnimationTracker* tracker = doc->GetOrCreatePendingAnimationTracker(); + tracker->AddPlayPending(*this); + + // We may have updated the current time when we set the hold time above. + UpdateTiming(); +} + +void +Animation::DoPause() +{ + if (mPendingState == PendingState::PausePending) { + return; + } + + bool reuseReadyPromise = false; + if (mPendingState == PendingState::PlayPending) { + CancelPendingTasks(); + reuseReadyPromise = true; + } + + // Mark this as no longer running on the compositor so that next time + // we update animations we won't throttle them and will have a chance + // to remove the animation from any layer it might be on. + mIsRunningOnCompositor = false; + + if (!reuseReadyPromise) { + // Clear ready promise. We'll create a new one lazily. + mReady = nullptr; + } + + mPendingState = PendingState::PausePending; + + nsIDocument* doc = GetRenderedDocument(); + if (!doc) { + TriggerOnNextTick(Nullable()); + return; + } + + PendingAnimationTracker* tracker = doc->GetOrCreatePendingAnimationTracker(); + tracker->AddPausePending(*this); + + UpdateFinishedState(); +} + +void +Animation::ResumeAt(const TimeDuration& aReadyTime) +{ + // This method is only expected to be called for an animation that is + // waiting to play. We can easily adapt it to handle other states + // but it's currently not necessary. + MOZ_ASSERT(mPendingState == PendingState::PlayPending, + "Expected to resume a play-pending animation"); + MOZ_ASSERT(mHoldTime.IsNull() != mStartTime.IsNull(), + "An animation in the play-pending state should have either a" + " resolved hold time or resolved start time (but not both)"); + + // If we aborted a pending pause operation we will already have a start time + // we should use. In all other cases, we resolve it from the ready time. + if (mStartTime.IsNull()) { + if (mPlaybackRate != 0) { + mStartTime.SetValue(aReadyTime - + (mHoldTime.Value().MultDouble(1 / mPlaybackRate))); + mHoldTime.SetNull(); + } else { + mStartTime.SetValue(aReadyTime); + } + } + mPendingState = PendingState::NotPending; + + UpdateTiming(); + + if (mReady) { + mReady->MaybeResolve(this); + } +} + +void +Animation::PauseAt(const TimeDuration& aReadyTime) +{ + MOZ_ASSERT(mPendingState == PendingState::PausePending, + "Expected to pause a pause-pending animation"); + + if (!mStartTime.IsNull()) { + mHoldTime.SetValue((aReadyTime - mStartTime.Value()) + .MultDouble(mPlaybackRate)); + } + mStartTime.SetNull(); + mPendingState = PendingState::NotPending; + + UpdateTiming(); + + if (mReady) { + mReady->MaybeResolve(this); + } +} + +void +Animation::UpdateTiming() +{ + // We call UpdateFinishedState before UpdateEffect because the former + // can change the current time, which is used by the latter. + UpdateFinishedState(); + UpdateEffect(); +} + +void +Animation::UpdateFinishedState(bool aSeekFlag) +{ + Nullable currentTime = GetCurrentTime(); + TimeDuration effectEnd = TimeDuration(EffectEnd()); + + if (!mStartTime.IsNull() && + mPendingState == PendingState::NotPending) { + if (mPlaybackRate > 0.0 && + !currentTime.IsNull() && + currentTime.Value() >= effectEnd) { + if (aSeekFlag) { + mHoldTime = currentTime; + } else if (!mPreviousCurrentTime.IsNull()) { + mHoldTime.SetValue(std::max(mPreviousCurrentTime.Value(), effectEnd)); + } else { + mHoldTime.SetValue(effectEnd); + } + } else if (mPlaybackRate < 0.0 && + !currentTime.IsNull() && + currentTime.Value().ToMilliseconds() <= 0.0) { + if (aSeekFlag) { + mHoldTime = currentTime; + } else { + mHoldTime.SetValue(0); + } + } else if (mPlaybackRate != 0.0 && + !currentTime.IsNull()) { + if (aSeekFlag && !mHoldTime.IsNull()) { + mStartTime.SetValue(mTimeline->GetCurrentTime().Value() - + (mHoldTime.Value().MultDouble(1 / mPlaybackRate))); + } + mHoldTime.SetNull(); + } + } + + bool currentFinishedState = IsFinished(); + if (currentFinishedState && !mIsPreviousStateFinished) { + if (mFinished) { + mFinished->MaybeResolve(this); + } + } else if (!currentFinishedState && mIsPreviousStateFinished) { + // Clear finished promise. We'll create a new one lazily. + mFinished = nullptr; + if (mEffect->AsTransition()) { + mEffect->SetIsFinishedTransition(false); + } + } + mIsPreviousStateFinished = currentFinishedState; + // We must recalculate the current time to take account of any mHoldTime + // changes the code above made. + mPreviousCurrentTime = GetCurrentTime(); +} + +void +Animation::UpdateEffect() +{ + if (mEffect) { + mEffect->SetParentTime(GetCurrentTime()); + UpdateRelevance(); + } +} + +void +Animation::FlushStyle() const +{ + nsIDocument* doc = GetRenderedDocument(); + if (doc) { + doc->FlushPendingNotifications(Flush_Style); + } +} + +void +Animation::PostUpdate() +{ + AnimationCollection* collection = GetCollection(); + if (collection) { + collection->NotifyAnimationUpdated(); + } +} + +void +Animation::CancelPendingTasks() +{ + if (mPendingState == PendingState::NotPending) { + return; + } + + nsIDocument* doc = GetRenderedDocument(); + if (doc) { + PendingAnimationTracker* tracker = doc->GetPendingAnimationTracker(); + if (tracker) { + if (mPendingState == PendingState::PlayPending) { + tracker->RemovePlayPending(*this); + } else { + tracker->RemovePausePending(*this); + } + } + } + + mPendingState = PendingState::NotPending; + mPendingReadyTime.SetNull(); +} + +bool +Animation::IsFinished() const +{ + // Unfortunately there's some weirdness in the spec at the moment where if + // you're finished and paused, the playState is paused. This prevents us + // from just checking |PlayState() == AnimationPlayState::Finished| here, + // and we need this much more messy check to see if we're finished. + Nullable currentTime = GetCurrentTime(); + return !currentTime.IsNull() && + ((mPlaybackRate > 0.0 && currentTime.Value() >= EffectEnd()) || + (mPlaybackRate < 0.0 && currentTime.Value().ToMilliseconds() <= 0.0)); +} + +bool +Animation::IsPossiblyOrphanedPendingAnimation() const +{ + // Check if we are pending but might never start because we are not being + // tracked. + // + // This covers the following cases: + // + // * We started playing but our effect's target element was orphaned + // or bound to a different document. + // (note that for the case of our effect changing we should handle + // that in SetEffect) + // * We started playing but our timeline became inactive. + // In this case the pending animation tracker will drop us from its hashmap + // when we have been painted. + // * When we started playing we couldn't find a PendingAnimationTracker to + // register with (perhaps the effect had no document) so we simply + // set mPendingState in DoPlay and relied on this method to catch us on the + // next tick. + + // If we're not pending we're ok. + if (mPendingState == PendingState::NotPending) { + return false; + } + + // If we have a pending ready time then we will be started on the next + // tick. + if (!mPendingReadyTime.IsNull()) { + return false; + } + + // If we don't have an active timeline then we shouldn't start until + // we do. + if (!mTimeline || mTimeline->GetCurrentTime().IsNull()) { + return false; + } + + // If we have no rendered document, or we're not in our rendered document's + // PendingAnimationTracker then there's a good chance no one is tracking us. + // + // If we're wrong and another document is tracking us then, at worst, we'll + // simply start/pause the animation one tick too soon. That's better than + // never starting/pausing the animation and is unlikely. + nsIDocument* doc = GetRenderedDocument(); + if (!doc) { + return false; + } + + PendingAnimationTracker* tracker = doc->GetPendingAnimationTracker(); + return !tracker || + (!tracker->IsWaitingToPlay(*this) && + !tracker->IsWaitingToPause(*this)); +} + +StickyTimeDuration +Animation::EffectEnd() const +{ + if (!mEffect) { + return StickyTimeDuration(0); + } + + return mEffect->Timing().mDelay + + mEffect->GetComputedTiming().mActiveDuration; +} + +nsIDocument* +Animation::GetRenderedDocument() const +{ + if (!mEffect) { + return nullptr; + } + + Element* targetElement; + nsCSSPseudoElements::Type pseudoType; + mEffect->GetTarget(targetElement, pseudoType); + if (!targetElement) { + return nullptr; + } + + return targetElement->GetComposedDoc(); +} + +nsPresContext* +Animation::GetPresContext() const +{ + nsIDocument* doc = GetRenderedDocument(); + if (!doc) { + return nullptr; + } + nsIPresShell* shell = doc->GetShell(); + if (!shell) { + return nullptr; + } + return shell->GetPresContext(); +} + +AnimationCollection* +Animation::GetCollection() const +{ + css::CommonAnimationManager* manager = GetAnimationManager(); + if (!manager) { + return nullptr; + } + MOZ_ASSERT(mEffect, + "An animation with an animation manager must have an effect"); + + Element* targetElement; + nsCSSPseudoElements::Type targetPseudoType; + mEffect->GetTarget(targetElement, targetPseudoType); + MOZ_ASSERT(targetElement, + "An animation with an animation manager must have a target"); + + return manager->GetAnimations(targetElement, targetPseudoType, false); } } // namespace dom diff --git a/dom/animation/Animation.h b/dom/animation/Animation.h index 0fe71ad68d..2e746ff426 100644 --- a/dom/animation/Animation.h +++ b/dom/animation/Animation.h @@ -1,353 +1,347 @@ /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ /* 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/. */ + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_Animation_h #define mozilla_dom_Animation_h -#include "nsAutoPtr.h" -#include "nsCycleCollectionParticipant.h" -#include "nsCSSPseudoElements.h" -#include "nsIDocument.h" #include "nsWrapperCache.h" +#include "nsCycleCollectionParticipant.h" #include "mozilla/Attributes.h" -#include "mozilla/StickyTimeDuration.h" -#include "mozilla/StyleAnimationValue.h" -#include "mozilla/TimeStamp.h" -#include "mozilla/dom/Element.h" -#include "mozilla/dom/Nullable.h" -#include "nsSMILKeySpline.h" -#include "nsStyleStruct.h" // for nsTimingFunction +#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration +#include "mozilla/dom/AnimationBinding.h" // for AnimationPlayState +#include "mozilla/dom/DocumentTimeline.h" // for DocumentTimeline +#include "mozilla/dom/KeyframeEffect.h" // for KeyframeEffectReadonly +#include "mozilla/dom/Promise.h" // for Promise +#include "nsCSSProperty.h" // for nsCSSProperty + +// X11 has a #define for CurrentTime. +#ifdef CurrentTime +#undef CurrentTime +#endif + +// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to +// GetTickCount(). +#ifdef GetCurrentTime +#undef GetCurrentTime +#endif struct JSContext; class nsCSSPropertySet; +class nsIDocument; +class nsPresContext; namespace mozilla { +struct AnimationCollection; namespace css { class AnimValuesStyleRule; +class CommonAnimationManager; } // namespace css -/** - * Input timing parameters. - * - * Eventually this will represent all the input timing parameters specified - * by content but for now it encapsulates just the subset of those - * parameters passed to GetPositionInIteration. - */ -struct AnimationTiming -{ - TimeDuration mIterationDuration; - TimeDuration mDelay; - float mIterationCount; // mozilla::PositiveInfinity() means infinite - uint8_t mDirection; - uint8_t mFillMode; - - bool FillsForwards() const { - return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH || - mFillMode == NS_STYLE_ANIMATION_FILL_MODE_FORWARDS; - } - bool FillsBackwards() const { - return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH || - mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BACKWARDS; - } - bool operator==(const AnimationTiming& aOther) const { - return mIterationDuration == aOther.mIterationDuration && - mDelay == aOther.mDelay && - mIterationCount == aOther.mIterationCount && - mDirection == aOther.mDirection && - mFillMode == aOther.mFillMode; - } - bool operator!=(const AnimationTiming& aOther) const { - return !(*this == aOther); - } -}; - -/** - * Stores the results of calculating the timing properties of an animation - * at a given sample time. - */ -struct ComputedTiming -{ - ComputedTiming() - : mTimeFraction(kNullTimeFraction) - , mCurrentIteration(0) - , mPhase(AnimationPhase_Null) - { } - - static const double kNullTimeFraction; - - // The total duration of the animation including all iterations. - // Will equal StickyTimeDuration::Forever() if the animation repeats - // indefinitely. - StickyTimeDuration mActiveDuration; - - // Will be kNullTimeFraction if the animation is neither animating nor - // filling at the sampled time. - double mTimeFraction; - - // Zero-based iteration index (meaningless if mTimeFraction is - // kNullTimeFraction). - uint64_t mCurrentIteration; - - enum { - // Not sampled (null sample time) - AnimationPhase_Null, - // Sampled prior to the start of the active interval - AnimationPhase_Before, - // Sampled within the active interval - AnimationPhase_Active, - // Sampled after (or at) the end of the active interval - AnimationPhase_After - } mPhase; -}; - -class ComputedTimingFunction -{ -public: - typedef nsTimingFunction::Type Type; - void Init(const nsTimingFunction &aFunction); - double GetValue(double aPortion) const; - const nsSMILKeySpline* GetFunction() const { - NS_ASSERTION(mType == nsTimingFunction::Function, "Type mismatch"); - return &mTimingFunction; - } - Type GetType() const { return mType; } - uint32_t GetSteps() const { return mSteps; } - bool operator==(const ComputedTimingFunction& aOther) const { - return mType == aOther.mType && - (mType == nsTimingFunction::Function ? - mTimingFunction == aOther.mTimingFunction : - mSteps == aOther.mSteps); - } - bool operator!=(const ComputedTimingFunction& aOther) const { - return !(*this == aOther); - } - -private: - Type mType; - nsSMILKeySpline mTimingFunction; - uint32_t mSteps; -}; - -struct AnimationPropertySegment -{ - float mFromKey, mToKey; - StyleAnimationValue mFromValue, mToValue; - ComputedTimingFunction mTimingFunction; - - bool operator==(const AnimationPropertySegment& aOther) const { - return mFromKey == aOther.mFromKey && - mToKey == aOther.mToKey && - mFromValue == aOther.mFromValue && - mToValue == aOther.mToValue && - mTimingFunction == aOther.mTimingFunction; - } - bool operator!=(const AnimationPropertySegment& aOther) const { - return !(*this == aOther); - } -}; - -struct AnimationProperty -{ - nsCSSProperty mProperty; - - // Does this property win in the CSS Cascade? - // - // For CSS transitions, this is true as long as a CSS animation on the - // same property and element is not running, in which case we set this - // to false so that the animation (lower in the cascade) can win. We - // then use this to decide whether to apply the style both in the CSS - // cascade and for OMTA. - // - // For CSS Animations, which are overridden by !important rules in the - // cascade, we actually determine this from the CSS cascade - // computations, and then use it for OMTA. - // **NOTE**: For CSS animations, we only bother setting mWinsInCascade - // accurately for properties that we can animate on the compositor. - // For other properties, we make it always be true. - bool mWinsInCascade; - - InfallibleTArray mSegments; - - bool operator==(const AnimationProperty& aOther) const { - return mProperty == aOther.mProperty && - mWinsInCascade == aOther.mWinsInCascade && - mSegments == aOther.mSegments; - } - bool operator!=(const AnimationProperty& aOther) const { - return !(*this == aOther); - } -}; - -struct ElementPropertyTransition; +class CSSAnimation; +class CSSTransition; namespace dom { -class AnimationEffect; - -class Animation : public nsWrapperCache +class Animation + : public nsISupports + , public nsWrapperCache { +protected: + virtual ~Animation() {} + public: - Animation(nsIDocument* aDocument, - Element* aTarget, - nsCSSPseudoElements::Type aPseudoType, - const AnimationTiming &aTiming, - const nsSubstring& aName) - : mDocument(aDocument) - , mTarget(aTarget) - , mTiming(aTiming) - , mName(aName) - , mIsFinishedTransition(false) - , mPseudoType(aPseudoType) + explicit Animation(DocumentTimeline* aTimeline) + : mTimeline(aTimeline) + , mPlaybackRate(1.0) + , mPendingState(PendingState::NotPending) + , mIsRunningOnCompositor(false) + , mIsPreviousStateFinished(false) + , mFinishedAtLastComposeStyle(false) + , mIsRelevant(false) { - MOZ_ASSERT(aTarget, "null animation target is not yet supported"); } - NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(Animation) - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(Animation) + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Animation) - nsIDocument* GetParentObject() const { return mDocument; } - virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + DocumentTimeline* GetParentObject() const { return mTimeline; } + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; - // FIXME: If we succeed in moving transition-specific code to a type of - // AnimationEffect (as per the Web Animations API) we should remove these - // virtual methods. - virtual ElementPropertyTransition* AsTransition() { return nullptr; } - virtual const ElementPropertyTransition* AsTransition() const { - return nullptr; - } + virtual CSSAnimation* AsCSSAnimation() { return nullptr; } + virtual CSSTransition* AsCSSTransition() { return nullptr; } - // Animation interface - // This currently returns a new object each time when used from C++ but is - // cached when used from JS. - already_AddRefed GetEffect(); - Element* GetTarget() const { - // Currently we only implement Element.getAnimations() which only - // returns animations targetting Elements so this should never - // be called for an animation that targets a pseudo-element. - MOZ_ASSERT(mPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement, - "Requesting the target of an Animation that targets a" - " pseudo-element is not yet supported."); - return mTarget; - } + // Flag to pass to DoPlay to indicate that it should not carry out finishing + // behavior (reset the current time to the beginning of the active duration). + enum LimitBehavior { + AutoRewind = 0, + Continue = 1 + }; - // Temporary workaround to return both the target element and pseudo-type - // until we implement PseudoElement. - void GetTarget(Element*& aTarget, - nsCSSPseudoElements::Type& aPseudoType) const { - aTarget = mTarget; - aPseudoType = mPseudoType; - } + // Animation methods + KeyframeEffectReadonly* GetEffect() const { return mEffect; } + DocumentTimeline* Timeline() const { return mTimeline; } + Nullable GetStartTime() const { return mStartTime; } + void SetStartTime(const Nullable& aNewStartTime); + Nullable GetCurrentTime() const; + void SilentlySetCurrentTime(const TimeDuration& aNewCurrentTime); + void SetCurrentTime(const TimeDuration& aNewCurrentTime); + double PlaybackRate() const { return mPlaybackRate; } + void SetPlaybackRate(double aPlaybackRate); + void SilentlySetPlaybackRate(double aPlaybackRate); + AnimationPlayState PlayState() const; + virtual Promise* GetReady(ErrorResult& aRv); + virtual Promise* GetFinished(ErrorResult& aRv); + virtual void Play(LimitBehavior aLimitBehavior); + virtual void Pause(); + bool IsRunningOnCompositor() const { return mIsRunningOnCompositor; } - void SetParentTime(Nullable aParentTime); + // Wrapper functions for Animation DOM methods when called + // from script. We often use the same methods internally and from + // script but when called from script we (or one of our subclasses) perform + // extra steps such as flushing style or converting the return type. + Nullable GetStartTimeAsDouble() const; + void SetStartTimeAsDouble(const Nullable& aStartTime); + Nullable GetCurrentTimeAsDouble() const; + void SetCurrentTimeAsDouble(const Nullable& aCurrentTime, + ErrorResult& aRv); + virtual AnimationPlayState PlayStateFromJS() const { return PlayState(); } + virtual void PlayFromJS() { Play(LimitBehavior::AutoRewind); } + // PauseFromJS is currently only here for symmetry with PlayFromJS but + // in future we will likely have to flush style in + // CSSAnimation::PauseFromJS so we leave it for now. + void PauseFromJS() { Pause(); } - const AnimationTiming& Timing() const { - return mTiming; - } - AnimationTiming& Timing() { - return mTiming; - } + void SetEffect(KeyframeEffectReadonly* aEffect); + void Tick(); - virtual const nsString& Name() const { - return mName; - } + /** + * Set the time to use for starting or pausing a pending animation. + * + * Typically, when an animation is played, it does not start immediately but + * is added to a table of pending animations on the document of its effect. + * In the meantime it sets its hold time to the time from which playback + * should begin. + * + * When the document finishes painting, any pending animations in its table + * are marked as being ready to start by calling StartOnNextTick. + * The moment when the paint completed is also recorded, converted to a + * timeline time, and passed to StartOnTick. This is so that when these + * animations do start, they can be timed from the point when painting + * completed. + * + * After calling TriggerOnNextTick, animations remain in the pending state + * until the next refresh driver tick. At that time they transition out of + * the pending state using the time passed to TriggerOnNextTick as the + * effective time at which they resumed. + * + * This approach means that any setup time required for performing the + * initial paint of an animation such as layerization is not deducted from + * the running time of the animation. Without this we can easily drop the + * first few frames of an animation, or, on slower devices, the whole + * animation. + * + * Furthermore: + * + * - Starting the animation immediately when painting finishes is problematic + * because the start time of the animation will be ahead of its timeline + * (since the timeline time is based on the refresh driver time). + * That's a problem because the animation is playing but its timing + * suggests it starts in the future. We could update the timeline to match + * the start time of the animation but then we'd also have to update the + * timing and style of all animations connected to that timeline or else be + * stuck in an inconsistent state until the next refresh driver tick. + * + * - If we simply use the refresh driver time on its next tick, the lag + * between triggering an animation and its effective start is unacceptably + * long. + * + * For pausing, we apply the same asynchronous approach. This is so that we + * synchronize with animations that are running on the compositor. Otherwise + * if the main thread lags behind the compositor there will be a noticeable + * jump backwards when the main thread takes over. Even though main thread + * animations could be paused immediately, we do it asynchronously for + * consistency and so that animations paused together end up in step. + * + * Note that the caller of this method is responsible for removing the + * animation from any PendingAnimationTracker it may have been added to. + */ + void TriggerOnNextTick(const Nullable& aReadyTime); - // Return the duration from the start the active interval to the point where - // the animation begins playback. This is zero unless the animation has - // a negative delay in which case it is the absolute value of the delay. - // This is used for setting the elapsedTime member of CSS AnimationEvents. - TimeDuration InitialAdvance() const { - return std::max(TimeDuration(), mTiming.mDelay * -1); - } - - Nullable GetLocalTime() const { - // Since the *animation* start time is currently always zero, the local - // time is equal to the parent time. - return mParentTime; - } - - // This function takes as input the timing parameters of an animation and - // returns the computed timing at the specified local time. + // Testing only: Start or pause a pending animation using the current timeline + // time. This is used to support existing tests that expect animations to + // begin immediately. Ideally we would rewrite the those tests and get rid of + // this method, but there are a lot of them. // - // The local time may be null in which case only static parameters such as the - // active duration are calculated. All other members of the returned object - // are given a null/initial value. - // - // This function returns ComputedTiming::kNullTimeFraction for the - // mTimeFraction member of the return value if the animation should not be - // run (because it is not currently active and is not filling at this time). - static ComputedTiming - GetComputedTimingAt(const Nullable& aLocalTime, - const AnimationTiming& aTiming); + // As with TriggerOnNextTick, the caller of this method is responsible for + // removing the animation from any PendingAnimationTracker it may have been + // added to. + void TriggerNow(); - // Shortcut for that gets the computed timing using the current local time as - // calculated from the timeline time. - ComputedTiming GetComputedTiming(const AnimationTiming* aTiming - = nullptr) const { - return GetComputedTimingAt(GetLocalTime(), aTiming ? *aTiming : mTiming); + /** + * When StartOnNextTick is called, we store the ready time but we don't apply + * it until the next tick. In the meantime, GetStartTime() will return null. + * + * However, if we build layer animations again before the next tick, we + * should initialize them with the start time that GetStartTime() will return + * on the next tick. + * + * If we were to simply set the start time of layer animations to null, their + * start time would be updated to the current wallclock time when rendering + * finishes, thus making them out of sync with the start time stored here. + * This, in turn, will make the animation jump backwards when we build + * animations on the next tick and apply the start time stored here. + * + * This method returns the start time, if resolved. Otherwise, if we have + * a pending ready time, it returns the corresponding start time. If neither + * of those are available, it returns null. + */ + Nullable GetCurrentOrPendingStartTime() const; + + void Cancel(); + + const nsString& Name() const + { + return mEffect ? mEffect->Name() : EmptyString(); } - // Return the duration of the active interval for the given timing parameters. - static StickyTimeDuration - ActiveDuration(const AnimationTiming& aTiming); - - // After transitions finish they need to be retained in order to - // address the issue described in - // https://lists.w3.org/Archives/Public/www-style/2015Jan/0444.html . - // However, finished transitions are ignored for many purposes. - bool IsFinishedTransition() const { - return mIsFinishedTransition; + bool IsPausedOrPausing() const + { + return PlayState() == AnimationPlayState::Paused || + mPendingState == PendingState::PausePending; } - void SetIsFinishedTransition() { - MOZ_ASSERT(AsTransition(), - "Calling SetIsFinishedTransition but it's not a transition"); - mIsFinishedTransition = true; + bool HasInPlayEffect() const + { + return GetEffect() && GetEffect()->IsInPlay(*this); + } + bool HasCurrentEffect() const + { + return GetEffect() && GetEffect()->IsCurrent(*this); + } + bool IsInEffect() const + { + return GetEffect() && GetEffect()->IsInEffect(); } - bool IsInPlay(const AnimationPlayer& aPlayer) const; - bool IsCurrent(const AnimationPlayer& aPlayer) const; - bool IsInEffect() const; - - const AnimationProperty* - GetAnimationOfProperty(nsCSSProperty aProperty) const; - bool HasAnimationOfProperty(nsCSSProperty aProperty) const { - return GetAnimationOfProperty(aProperty) != nullptr; - } - bool HasAnimationOfProperties(const nsCSSProperty* aProperties, - size_t aPropertyCount) const; - const InfallibleTArray& Properties() const { - return mProperties; - } - InfallibleTArray& Properties() { - return mProperties; + /** + * "Playing" is different to "running". An animation in its delay phase is + * still running but we only consider it playing when it is in its active + * interval. This definition is used for fetching the animations that are + * are candidates for running on the compositor (since we don't ship + * animations to the compositor when they are in their delay phase or + * paused). + */ + bool IsPlaying() const + { + // We need to have an effect in its active interval, and + // be either running or waiting to run. + return HasInPlayEffect() && + (PlayState() == AnimationPlayState::Running || + mPendingState == PendingState::PlayPending); } - // Updates |aStyleRule| with the animation values produced by this - // Animation for the current time except any properties already contained - // in |aSetProperties|. - // Any updated properties are added to |aSetProperties|. + bool IsRelevant() const { return mIsRelevant; } + void UpdateRelevance(); + + void SetIsRunningOnCompositor() { mIsRunningOnCompositor = true; } + void ClearIsRunningOnCompositor() { mIsRunningOnCompositor = false; } + + // Returns true if this animation does not currently need to update + // style on the main thread (e.g. because it is empty, or is + // running on the compositor). + bool CanThrottle() const; + + // Updates |aStyleRule| with the animation values of this animation's effect, + // if any. + // Any properties already contained in |aSetProperties| are not changed. Any + // properties that are changed are added to |aSetProperties|. + // |aNeedsRefreshes| will be set to true if this animation expects to update + // the style rule on the next refresh driver tick as well (because it + // is running and has an effect to sample). void ComposeStyle(nsRefPtr& aStyleRule, - nsCSSPropertySet& aSetProperties); + nsCSSPropertySet& aSetProperties, + bool& aNeedsRefreshes); protected: - virtual ~Animation() { } + void DoPlay(LimitBehavior aLimitBehavior); + void DoPause(); + void ResumeAt(const TimeDuration& aReadyTime); + void PauseAt(const TimeDuration& aReadyTime); + void FinishPendingAt(const TimeDuration& aReadyTime) + { + if (mPendingState == PendingState::PlayPending) { + ResumeAt(aReadyTime); + } else if (mPendingState == PendingState::PausePending) { + PauseAt(aReadyTime); + } else { + NS_NOTREACHED("Can't finish pending if we're not in a pending state"); + } + } - // We use a document for a parent object since the other likely candidate, - // the target element, can be empty. - nsCOMPtr mDocument; - nsCOMPtr mTarget; - Nullable mParentTime; + void UpdateTiming(); + void UpdateFinishedState(bool aSeekFlag = false); + void UpdateEffect(); + void FlushStyle() const; + void PostUpdate(); + /** + * Remove this animation from the pending animation tracker and reset + * mPendingState as necessary. The caller is responsible for resolving or + * aborting the mReady promise as necessary. + */ + void CancelPendingTasks(); - AnimationTiming mTiming; - nsString mName; - // A flag to mark transitions that have finished and are due to - // be removed on the next throttle-able cycle. - bool mIsFinishedTransition; - nsCSSPseudoElements::Type mPseudoType; + bool IsFinished() const; - InfallibleTArray mProperties; + bool IsPossiblyOrphanedPendingAnimation() const; + StickyTimeDuration EffectEnd() const; + + nsIDocument* GetRenderedDocument() const; + nsPresContext* GetPresContext() const; + virtual css::CommonAnimationManager* GetAnimationManager() const = 0; + AnimationCollection* GetCollection() const; + + nsRefPtr mTimeline; + nsRefPtr mEffect; + // The beginning of the delay period. + Nullable mStartTime; // Timeline timescale + Nullable mHoldTime; // Animation timescale + Nullable mPendingReadyTime; // Timeline timescale + Nullable mPreviousCurrentTime; // Animation timescale + double mPlaybackRate; + + // A Promise that is replaced on each call to Play() (and in future Pause()) + // and fulfilled when Play() is successfully completed. + // This object is lazily created by GetReady. + // See http://w3c.github.io/web-animations/#current-ready-promise + nsRefPtr mReady; + + // A Promise that is resolved when we reach the end of the effect, or + // 0 when playing backwards. The Promise is replaced if the animation is + // finished but then a state change makes it not finished. + // This object is lazily created by GetFinished. + // See http://w3c.github.io/web-animations/#current-finished-promise + nsRefPtr mFinished; + + // Indicates if the animation is in the pending state (and what state it is + // waiting to enter when it finished pending). We use this rather than + // checking if this animation is tracked by a PendingAnimationTracker because + // the animation will continue to be pending even after it has been removed + // from the PendingAnimationTracker while it is waiting for the next tick + // (see TriggerOnNextTick for details). + enum class PendingState { NotPending, PlayPending, PausePending }; + PendingState mPendingState; + + bool mIsRunningOnCompositor; + // Indicates whether we were in the finished state during our + // most recent unthrottled sample (our last ComposeStyle call). + bool mIsPreviousStateFinished; // Spec calls this "previous finished state" + bool mFinishedAtLastComposeStyle; + // Indicates that the animation should be exposed in an element's + // getAnimations() list. + bool mIsRelevant; }; } // namespace dom diff --git a/dom/animation/AnimationEffect.cpp b/dom/animation/AnimationEffect.cpp deleted file mode 100644 index 0aed86fbab..0000000000 --- a/dom/animation/AnimationEffect.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ -/* 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 "mozilla/dom/AnimationEffect.h" -#include "mozilla/dom/AnimationEffectBinding.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationEffect, mAnimation) - -NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnimationEffect, AddRef) -NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AnimationEffect, Release) - -JSObject* -AnimationEffect::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return AnimationEffectBinding::Wrap(aCx, this, aGivenProto); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/animation/AnimationEffect.h b/dom/animation/AnimationEffect.h deleted file mode 100644 index 3c07e746b4..0000000000 --- a/dom/animation/AnimationEffect.h +++ /dev/null @@ -1,46 +0,0 @@ -/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_AnimationEffect_h -#define mozilla_dom_AnimationEffect_h - -#include "nsCycleCollectionParticipant.h" -#include "nsWrapperCache.h" -#include "mozilla/dom/Animation.h" - -struct JSContext; - -namespace mozilla { -namespace dom { - -class AnimationEffect final : public nsWrapperCache -{ -public: - explicit AnimationEffect(Animation* aAnimation) - : mAnimation(aAnimation) - { - } - - NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnimationEffect) - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AnimationEffect) - - Animation* GetParentObject() const { return mAnimation; } - virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - // AnimationEffect interface - void GetName(nsString& aRetVal) const { - aRetVal = mAnimation->Name(); - } - -private: - ~AnimationEffect() { } - - nsRefPtr mAnimation; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_AnimationEffect_h diff --git a/dom/animation/AnimationEffectReadonly.cpp b/dom/animation/AnimationEffectReadonly.cpp new file mode 100644 index 0000000000..20d6b65dda --- /dev/null +++ b/dom/animation/AnimationEffectReadonly.cpp @@ -0,0 +1,23 @@ +/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ +/* 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 "mozilla/dom/AnimationEffectReadonly.h" +#include "mozilla/dom/AnimationEffectReadonlyBinding.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationEffectReadonly, mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(AnimationEffectReadonly) +NS_IMPL_CYCLE_COLLECTING_RELEASE(AnimationEffectReadonly) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AnimationEffectReadonly) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +} // namespace dom +} // namespace mozilla diff --git a/dom/animation/AnimationEffectReadonly.h b/dom/animation/AnimationEffectReadonly.h new file mode 100644 index 0000000000..a79dfedfb3 --- /dev/null +++ b/dom/animation/AnimationEffectReadonly.h @@ -0,0 +1,42 @@ +/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_AnimationEffect_h +#define mozilla_dom_AnimationEffect_h + +#include "nsISupports.h" +#include "nsWrapperCache.h" +#include "nsCycleCollectionParticipant.h" +#include "nsCOMPtr.h" + +namespace mozilla { +namespace dom { + +class AnimationEffectReadonly + : public nsISupports + , public nsWrapperCache +{ +protected: + virtual ~AnimationEffectReadonly() { } + +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AnimationEffectReadonly) + + explicit AnimationEffectReadonly(nsISupports* aParent) + : mParent(aParent) + { + } + + nsISupports* GetParentObject() const { return mParent; } + +protected: + nsCOMPtr mParent; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_AnimationEffect_h diff --git a/dom/animation/AnimationPlayer.cpp b/dom/animation/AnimationPlayer.cpp deleted file mode 100644 index 625399469a..0000000000 --- a/dom/animation/AnimationPlayer.cpp +++ /dev/null @@ -1,886 +0,0 @@ -/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ -/* 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 "AnimationPlayer.h" -#include "AnimationUtils.h" -#include "mozilla/dom/AnimationPlayerBinding.h" -#include "mozilla/AutoRestore.h" -#include "AnimationCommon.h" // For AnimationPlayerCollection, - // CommonAnimationManager -#include "nsIDocument.h" // For nsIDocument -#include "nsIPresShell.h" // For nsIPresShell -#include "nsLayoutUtils.h" // For PostRestyleEvent (remove after bug 1073336) -#include "PendingPlayerTracker.h" // For PendingPlayerTracker - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationPlayer, mTimeline, - mSource, mReady, mFinished) -NS_IMPL_CYCLE_COLLECTING_ADDREF(AnimationPlayer) -NS_IMPL_CYCLE_COLLECTING_RELEASE(AnimationPlayer) -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AnimationPlayer) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -JSObject* -AnimationPlayer::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return dom::AnimationPlayerBinding::Wrap(aCx, this, aGivenProto); -} - -void -AnimationPlayer::SetStartTime(const Nullable& aNewStartTime) -{ -#if 1 - // Bug 1096776: once we support inactive/missing timelines we'll want to take - // the disabled branch. - MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(), - "We don't support inactive/missing timelines yet"); -#else - Nullable timelineTime = mTimeline->GetCurrentTime(); - if (mTimeline) { - // The spec says to check if the timeline is active (has a resolved time) - // before using it here, but we don't need to since it's harmless to set - // the already null time to null. - timelineTime = mTimeline->GetCurrentTime(); - } - if (timelineTime.IsNull() && !aNewStartTime.IsNull()) { - mHoldTime.SetNull(); - } -#endif - Nullable previousCurrentTime = GetCurrentTime(); - mStartTime = aNewStartTime; - if (!aNewStartTime.IsNull()) { - if (mPlaybackRate != 0.0) { - mHoldTime.SetNull(); - } - } else { - mHoldTime = previousCurrentTime; - } - - CancelPendingTasks(); - if (mReady) { - // We may have already resolved mReady, but in that case calling - // MaybeResolve is a no-op, so that's okay. - mReady->MaybeResolve(this); - } - - UpdateTiming(); - PostUpdate(); -} - -Nullable -AnimationPlayer::GetCurrentTime() const -{ - Nullable result; - if (!mHoldTime.IsNull()) { - result = mHoldTime; - return result; - } - - if (!mStartTime.IsNull()) { - Nullable timelineTime = mTimeline->GetCurrentTime(); - if (!timelineTime.IsNull()) { - result.SetValue((timelineTime.Value() - mStartTime.Value()) - .MultDouble(mPlaybackRate)); - } - } - return result; -} - -// Implements http://w3c.github.io/web-animations/#silently-set-the-current-time -void -AnimationPlayer::SilentlySetCurrentTime(const TimeDuration& aSeekTime) -{ - if (!mHoldTime.IsNull() || - !mTimeline || - mTimeline->GetCurrentTime().IsNull() || - mPlaybackRate == 0.0 - /*or, once supported, if we have a pending pause task*/) { - mHoldTime.SetValue(aSeekTime); - if (!mTimeline || mTimeline->GetCurrentTime().IsNull()) { - mStartTime.SetNull(); - } - } else { - mStartTime.SetValue(mTimeline->GetCurrentTime().Value() - - (aSeekTime.MultDouble(1 / mPlaybackRate))); - } - - mPreviousCurrentTime.SetNull(); -} - -// Implements http://w3c.github.io/web-animations/#set-the-current-time -void -AnimationPlayer::SetCurrentTime(const TimeDuration& aSeekTime) -{ - SilentlySetCurrentTime(aSeekTime); - - if (mPendingState == PendingState::PausePending) { - CancelPendingTasks(); - if (mReady) { - mReady->MaybeResolve(this); - } - } - - UpdateFinishedState(true); - UpdateSourceContent(); - PostUpdate(); -} - -void -AnimationPlayer::SetPlaybackRate(double aPlaybackRate) -{ - Nullable previousTime = GetCurrentTime(); - mPlaybackRate = aPlaybackRate; - if (!previousTime.IsNull()) { - ErrorResult rv; - SetCurrentTime(previousTime.Value()); - MOZ_ASSERT(!rv.Failed(), "Should not assert for non-null time"); - } -} - -void -AnimationPlayer::SilentlySetPlaybackRate(double aPlaybackRate) -{ - Nullable previousTime = GetCurrentTime(); - mPlaybackRate = aPlaybackRate; - if (!previousTime.IsNull()) { - ErrorResult rv; - SilentlySetCurrentTime(previousTime.Value()); - MOZ_ASSERT(!rv.Failed(), "Should not assert for non-null time"); - } -} - -AnimationPlayState -AnimationPlayer::PlayState() const -{ - if (mPendingState != PendingState::NotPending) { - return AnimationPlayState::Pending; - } - - Nullable currentTime = GetCurrentTime(); - if (currentTime.IsNull()) { - return AnimationPlayState::Idle; - } - - if (mStartTime.IsNull()) { - return AnimationPlayState::Paused; - } - - if ((mPlaybackRate > 0.0 && currentTime.Value() >= SourceContentEnd()) || - (mPlaybackRate < 0.0 && currentTime.Value().ToMilliseconds() <= 0.0)) { - return AnimationPlayState::Finished; - } - - return AnimationPlayState::Running; -} - -static inline already_AddRefed -CreatePromise(AnimationTimeline* aTimeline, ErrorResult& aRv) -{ - nsIGlobalObject* global = aTimeline->GetParentObject(); - if (global) { - return Promise::Create(global, aRv); - } - return nullptr; -} - -Promise* -AnimationPlayer::GetReady(ErrorResult& aRv) -{ - if (!mReady) { - mReady = CreatePromise(mTimeline, aRv); // Lazily create on demand - } - if (!mReady) { - aRv.Throw(NS_ERROR_FAILURE); - } else if (PlayState() != AnimationPlayState::Pending) { - mReady->MaybeResolve(this); - } - return mReady; -} - -Promise* -AnimationPlayer::GetFinished(ErrorResult& aRv) -{ - if (!mFinished) { - mFinished = CreatePromise(mTimeline, aRv); // Lazily create on demand - } - if (!mFinished) { - aRv.Throw(NS_ERROR_FAILURE); - } else if (IsFinished()) { - mFinished->MaybeResolve(this); - } - return mFinished; -} - -void -AnimationPlayer::Play(LimitBehavior aLimitBehavior) -{ - DoPlay(aLimitBehavior); - PostUpdate(); -} - -void -AnimationPlayer::Pause() -{ - // TODO: The DoPause() call should not be synchronous (bug 1109390). See - // http://w3c.github.io/web-animations/#pausing-an-animation-section - DoPause(); - PostUpdate(); -} - -Nullable -AnimationPlayer::GetStartTimeAsDouble() const -{ - return AnimationUtils::TimeDurationToDouble(mStartTime); -} - -void -AnimationPlayer::SetStartTimeAsDouble(const Nullable& aStartTime) -{ - return SetStartTime(AnimationUtils::DoubleToTimeDuration(aStartTime)); -} - -Nullable -AnimationPlayer::GetCurrentTimeAsDouble() const -{ - return AnimationUtils::TimeDurationToDouble(GetCurrentTime()); -} - -void -AnimationPlayer::SetCurrentTimeAsDouble(const Nullable& aCurrentTime, - ErrorResult& aRv) -{ - if (aCurrentTime.IsNull()) { - if (!GetCurrentTime().IsNull()) { - aRv.Throw(NS_ERROR_DOM_TYPE_ERR); - } - return; - } - - return SetCurrentTime(TimeDuration::FromMilliseconds(aCurrentTime.Value())); -} - -void -AnimationPlayer::SetSource(Animation* aSource) -{ - if (mSource) { - mSource->SetParentTime(Nullable()); - } - mSource = aSource; - if (mSource) { - mSource->SetParentTime(GetCurrentTime()); - } - UpdateRelevance(); -} - -void -AnimationPlayer::Tick() -{ - // Since we are not guaranteed to get only one call per refresh driver tick, - // it's possible that mPendingReadyTime is set to a time in the future. - // In that case, we should wait until the next refresh driver tick before - // resuming. - if (mPendingState != PendingState::NotPending && - !mPendingReadyTime.IsNull() && - mPendingReadyTime.Value() <= mTimeline->GetCurrentTime().Value()) { - FinishPendingAt(mPendingReadyTime.Value()); - mPendingReadyTime.SetNull(); - } - - if (IsPossiblyOrphanedPendingPlayer()) { - MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(), - "Orphaned pending players should have an active timeline"); - FinishPendingAt(mTimeline->GetCurrentTime().Value()); - } - - UpdateTiming(); -} - -void -AnimationPlayer::TriggerOnNextTick(const Nullable& aReadyTime) -{ - // Normally we expect the play state to be pending but it's possible that, - // due to the handling of possibly orphaned players in Tick(), this player got - // started whilst still being in another document's pending player map. - if (PlayState() != AnimationPlayState::Pending) { - return; - } - - // If aReadyTime.IsNull() we'll detect this in Tick() where we check for - // orphaned players and trigger this animation anyway - mPendingReadyTime = aReadyTime; -} - -void -AnimationPlayer::TriggerNow() -{ - MOZ_ASSERT(PlayState() == AnimationPlayState::Pending, - "Expected to start a pending player"); - MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(), - "Expected an active timeline"); - - FinishPendingAt(mTimeline->GetCurrentTime().Value()); -} - -Nullable -AnimationPlayer::GetCurrentOrPendingStartTime() const -{ - Nullable result; - - if (!mStartTime.IsNull()) { - result = mStartTime; - return result; - } - - if (mPendingReadyTime.IsNull() || mHoldTime.IsNull()) { - return result; - } - - // Calculate the equivalent start time from the pending ready time. - // This is the same as the calculation performed in ResumeAt and will - // need to incorporate the playbackRate when implemented (bug 1127380). - result.SetValue(mPendingReadyTime.Value() - mHoldTime.Value()); - return result; -} - -void -AnimationPlayer::Cancel() -{ - if (mPendingState != PendingState::NotPending) { - CancelPendingTasks(); - if (mReady) { - mReady->MaybeReject(NS_ERROR_DOM_ABORT_ERR); - } - } - - if (mFinished) { - mFinished->MaybeReject(NS_ERROR_DOM_ABORT_ERR); - } - // Clear finished promise. We'll create a new one lazily. - mFinished = nullptr; - - mHoldTime.SetNull(); - mStartTime.SetNull(); - - UpdateSourceContent(); -} - -void -AnimationPlayer::UpdateRelevance() -{ - bool wasRelevant = mIsRelevant; - mIsRelevant = HasCurrentSource() || HasInEffectSource(); - - // Notify animation observers. - if (wasRelevant && !mIsRelevant) { - nsNodeUtils::AnimationRemoved(this); - } else if (!wasRelevant && mIsRelevant) { - nsNodeUtils::AnimationAdded(this); - } -} - -bool -AnimationPlayer::CanThrottle() const -{ - if (!mSource || - mSource->IsFinishedTransition() || - mSource->Properties().IsEmpty()) { - return true; - } - - if (!mIsRunningOnCompositor) { - return false; - } - - if (PlayState() != AnimationPlayState::Finished) { - // Unfinished animations can be throttled. - return true; - } - - // The animation has finished but, if this is the first sample since - // finishing, we need an unthrottled sample so we can apply the correct - // end-of-animation behavior on the main thread (either removing the - // animation style or applying the fill mode). - return mFinishedAtLastComposeStyle; -} - -void -AnimationPlayer::ComposeStyle(nsRefPtr& aStyleRule, - nsCSSPropertySet& aSetProperties, - bool& aNeedsRefreshes) -{ - if (!mSource || mSource->IsFinishedTransition()) { - return; - } - - AnimationPlayState playState = PlayState(); - if (playState == AnimationPlayState::Running || - playState == AnimationPlayState::Pending) { - aNeedsRefreshes = true; - } - - // In order to prevent flicker, there are a few cases where we want to use - // a different time for rendering that would otherwise be returned by - // GetCurrentTime. These are: - // - // (a) For animations that are pausing but which are still running on the - // compositor. In this case we send a layer transaction that removes the - // animation but which also contains the animation values calculated on - // the main thread. To prevent flicker when this occurs we want to ensure - // the timeline time used to calculate the main thread animation values - // does not lag far behind the time used on the compositor. Ideally we - // would like to use the "animation ready time" calculated at the end of - // the layer transaction as the timeline time but it will be too late to - // update the style rule at that point so instead we just use the current - // wallclock time. - // - // (b) For animations that are pausing that we have already taken off the - // compositor. In this case we record a pending ready time but we don't - // apply it until the next tick. However, while waiting for the next tick, - // we should still use the pending ready time as the timeline time. If we - // use the regular timeline time the animation may appear jump backwards - // if the main thread's timeline time lags behind the compositor. - // - // (c) For animations that are play-pending due to an aborted pause operation - // (i.e. a pause operation that was interrupted before we entered the - // paused state). When we cancel a pending pause we might momentarily take - // the animation off the compositor, only to re-add it moments later. In - // that case the compositor might have been ahead of the main thread so we - // should use the current wallclock time to ensure the animation doesn't - // temporarily jump backwards. - // - // To address each of these cases we temporarily tweak the hold time - // immediately before updating the style rule and then restore it immediately - // afterwards. This is purely to prevent visual flicker. Other behavior - // such as dispatching events continues to rely on the regular timeline time. - { - AutoRestore> restoreHoldTime(mHoldTime); - bool updatedHoldTime = false; - - AnimationPlayState playState = PlayState(); - - if (playState == AnimationPlayState::Pending && - mHoldTime.IsNull() && - !mStartTime.IsNull()) { - Nullable timeToUse = mPendingReadyTime; - if (timeToUse.IsNull() && - mTimeline && - !mTimeline->IsUnderTestControl()) { - timeToUse = mTimeline->ToTimelineTime(TimeStamp::Now()); - } - if (!timeToUse.IsNull()) { - mHoldTime.SetValue((timeToUse.Value() - mStartTime.Value()) - .MultDouble(mPlaybackRate)); - // Push the change down to the source content - UpdateSourceContent(); - updatedHoldTime = true; - } - } - - mSource->ComposeStyle(aStyleRule, aSetProperties); - - if (updatedHoldTime) { - UpdateTiming(); - } - - mFinishedAtLastComposeStyle = (playState == AnimationPlayState::Finished); - } -} - -void -AnimationPlayer::DoPlay(LimitBehavior aLimitBehavior) -{ - bool abortedPause = mPendingState == PendingState::PausePending; - - bool reuseReadyPromise = false; - if (mPendingState != PendingState::NotPending) { - CancelPendingTasks(); - reuseReadyPromise = true; - } - - Nullable currentTime = GetCurrentTime(); - if (mPlaybackRate > 0.0 && - (currentTime.IsNull() || - (aLimitBehavior == LimitBehavior::AutoRewind && - (currentTime.Value().ToMilliseconds() < 0.0 || - currentTime.Value() >= SourceContentEnd())))) { - mHoldTime.SetValue(TimeDuration(0)); - } else if (mPlaybackRate < 0.0 && - (currentTime.IsNull() || - (aLimitBehavior == LimitBehavior::AutoRewind && - (currentTime.Value().ToMilliseconds() <= 0.0 || - currentTime.Value() > SourceContentEnd())))) { - mHoldTime.SetValue(TimeDuration(SourceContentEnd())); - } else if (mPlaybackRate == 0.0 && currentTime.IsNull()) { - mHoldTime.SetValue(TimeDuration(0)); - } - - // If the hold time is null then we're either already playing normally (and - // we can ignore this call) or we aborted a pending pause operation (in which - // case, for consistency, we need to go through the motions of doing an - // asynchronous start even though we already have a resolved start time). - if (mHoldTime.IsNull() && !abortedPause) { - return; - } - - // Clear the start time until we resolve a new one (unless we are aborting - // a pending pause operation, in which case we keep the old start time so - // that the animation continues moving uninterrupted by the aborted pause). - if (!abortedPause) { - mStartTime.SetNull(); - } - - if (!reuseReadyPromise) { - // Clear ready promise. We'll create a new one lazily. - mReady = nullptr; - } - - mPendingState = PendingState::PlayPending; - - nsIDocument* doc = GetRenderedDocument(); - if (!doc) { - TriggerOnNextTick(Nullable()); - return; - } - - PendingPlayerTracker* tracker = doc->GetOrCreatePendingPlayerTracker(); - tracker->AddPlayPending(*this); - - // We may have updated the current time when we set the hold time above. - UpdateTiming(); -} - -void -AnimationPlayer::DoPause() -{ - if (mPendingState == PendingState::PausePending) { - return; - } - - bool reuseReadyPromise = false; - if (mPendingState == PendingState::PlayPending) { - CancelPendingTasks(); - reuseReadyPromise = true; - } - - // Mark this as no longer running on the compositor so that next time - // we update animations we won't throttle them and will have a chance - // to remove the animation from any layer it might be on. - mIsRunningOnCompositor = false; - - if (!reuseReadyPromise) { - // Clear ready promise. We'll create a new one lazily. - mReady = nullptr; - } - - mPendingState = PendingState::PausePending; - - nsIDocument* doc = GetRenderedDocument(); - if (!doc) { - TriggerOnNextTick(Nullable()); - return; - } - - PendingPlayerTracker* tracker = doc->GetOrCreatePendingPlayerTracker(); - tracker->AddPausePending(*this); - - UpdateFinishedState(); -} - -void -AnimationPlayer::ResumeAt(const TimeDuration& aReadyTime) -{ - // This method is only expected to be called for a player that is - // waiting to play. We can easily adapt it to handle other states - // but it's currently not necessary. - MOZ_ASSERT(mPendingState == PendingState::PlayPending, - "Expected to resume a play-pending player"); - MOZ_ASSERT(mHoldTime.IsNull() != mStartTime.IsNull(), - "A player in the play-pending state should have either a" - " resolved hold time or resolved start time (but not both)"); - - // If we aborted a pending pause operation we will already have a start time - // we should use. In all other cases, we resolve it from the ready time. - if (mStartTime.IsNull()) { - if (mPlaybackRate != 0) { - mStartTime.SetValue(aReadyTime - - (mHoldTime.Value().MultDouble(1 / mPlaybackRate))); - mHoldTime.SetNull(); - } else { - mStartTime.SetValue(aReadyTime); - } - } - mPendingState = PendingState::NotPending; - - UpdateTiming(); - - if (mReady) { - mReady->MaybeResolve(this); - } -} - -void -AnimationPlayer::PauseAt(const TimeDuration& aReadyTime) -{ - MOZ_ASSERT(mPendingState == PendingState::PausePending, - "Expected to pause a pause-pending player"); - - if (!mStartTime.IsNull()) { - mHoldTime.SetValue((aReadyTime - mStartTime.Value()) - .MultDouble(mPlaybackRate)); - } - mStartTime.SetNull(); - mPendingState = PendingState::NotPending; - - UpdateTiming(); - - if (mReady) { - mReady->MaybeResolve(this); - } -} - -void -AnimationPlayer::UpdateTiming() -{ - // We call UpdateFinishedState before UpdateSourceContent because the former - // can change the current time, which is used by the latter. - UpdateFinishedState(); - UpdateSourceContent(); -} - -void -AnimationPlayer::UpdateFinishedState(bool aSeekFlag) -{ - Nullable currentTime = GetCurrentTime(); - TimeDuration targetEffectEnd = TimeDuration(SourceContentEnd()); - - if (!mStartTime.IsNull() && - mPendingState == PendingState::NotPending) { - if (mPlaybackRate > 0.0 && - !currentTime.IsNull() && - currentTime.Value() >= targetEffectEnd) { - if (aSeekFlag) { - mHoldTime = currentTime; - } else if (!mPreviousCurrentTime.IsNull()) { - mHoldTime.SetValue(std::max(mPreviousCurrentTime.Value(), - targetEffectEnd)); - } else { - mHoldTime.SetValue(targetEffectEnd); - } - } else if (mPlaybackRate < 0.0 && - !currentTime.IsNull() && - currentTime.Value().ToMilliseconds() <= 0.0) { - if (aSeekFlag) { - mHoldTime = currentTime; - } else { - mHoldTime.SetValue(0); - } - } else if (mPlaybackRate != 0.0 && - !currentTime.IsNull()) { - if (aSeekFlag && !mHoldTime.IsNull()) { - mStartTime.SetValue(mTimeline->GetCurrentTime().Value() - - (mHoldTime.Value().MultDouble(1 / mPlaybackRate))); - } - mHoldTime.SetNull(); - } - } - - bool currentFinishedState = IsFinished(); - if (currentFinishedState && !mIsPreviousStateFinished) { - if (mFinished) { - mFinished->MaybeResolve(this); - } - } else if (!currentFinishedState && mIsPreviousStateFinished) { - // Clear finished promise. We'll create a new one lazily. - mFinished = nullptr; - } - mIsPreviousStateFinished = currentFinishedState; - // We must recalculate the current time to take account of any mHoldTime - // changes the code above made. - mPreviousCurrentTime = GetCurrentTime(); -} - -void -AnimationPlayer::UpdateSourceContent() -{ - if (mSource) { - mSource->SetParentTime(GetCurrentTime()); - UpdateRelevance(); - } -} - -void -AnimationPlayer::FlushStyle() const -{ - nsIDocument* doc = GetRenderedDocument(); - if (doc) { - doc->FlushPendingNotifications(Flush_Style); - } -} - -void -AnimationPlayer::PostUpdate() -{ - AnimationPlayerCollection* collection = GetCollection(); - if (collection) { - collection->NotifyPlayerUpdated(); - } -} - -void -AnimationPlayer::CancelPendingTasks() -{ - if (mPendingState == PendingState::NotPending) { - return; - } - - nsIDocument* doc = GetRenderedDocument(); - if (doc) { - PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker(); - if (tracker) { - if (mPendingState == PendingState::PlayPending) { - tracker->RemovePlayPending(*this); - } else { - tracker->RemovePausePending(*this); - } - } - } - - mPendingState = PendingState::NotPending; - mPendingReadyTime.SetNull(); -} - -bool -AnimationPlayer::IsFinished() const -{ - // Unfortunately there's some weirdness in the spec at the moment where if - // you're finished and paused, the playState is paused. This prevents us - // from just checking |PlayState() == AnimationPlayState::Finished| here, - // and we need this much more messy check to see if we're finished. - Nullable currentTime = GetCurrentTime(); - return !currentTime.IsNull() && - ((mPlaybackRate > 0.0 && currentTime.Value() >= SourceContentEnd()) || - (mPlaybackRate < 0.0 && currentTime.Value().ToMilliseconds() <= 0.0)); -} - -bool -AnimationPlayer::IsPossiblyOrphanedPendingPlayer() const -{ - // Check if we are pending but might never start because we are not being - // tracked. - // - // This covers the following cases: - // - // * We started playing but our source content's target element was orphaned - // or bound to a different document. - // (note that for the case of our source content changing we should handle - // that in SetSource) - // * We started playing but our timeline became inactive. - // In this case the pending player tracker will drop us from its hashmap - // when we have been painted. - // * When we started playing we couldn't find a PendingPlayerTracker to - // register with (perhaps the source content had no document) so we simply - // set mPendingState in DoPlay and relied on this method to catch us on the - // next tick. - - // If we're not pending we're ok. - if (mPendingState == PendingState::NotPending) { - return false; - } - - // If we have a pending ready time then we will be started on the next - // tick. - if (!mPendingReadyTime.IsNull()) { - return false; - } - - // If we don't have an active timeline then we shouldn't start until - // we do. - if (!mTimeline || mTimeline->GetCurrentTime().IsNull()) { - return false; - } - - // If we have no rendered document, or we're not in our rendered document's - // PendingPlayerTracker then there's a good chance no one is tracking us. - // - // If we're wrong and another document is tracking us then, at worst, we'll - // simply start/pause the animation one tick too soon. That's better than - // never starting/pausing the animation and is unlikely. - nsIDocument* doc = GetRenderedDocument(); - if (!doc) { - return false; - } - - PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker(); - return !tracker || - (!tracker->IsWaitingToPlay(*this) && - !tracker->IsWaitingToPause(*this)); -} - -StickyTimeDuration -AnimationPlayer::SourceContentEnd() const -{ - if (!mSource) { - return StickyTimeDuration(0); - } - - return mSource->Timing().mDelay - + mSource->GetComputedTiming().mActiveDuration; -} - -nsIDocument* -AnimationPlayer::GetRenderedDocument() const -{ - if (!mSource) { - return nullptr; - } - - Element* targetElement; - nsCSSPseudoElements::Type pseudoType; - mSource->GetTarget(targetElement, pseudoType); - if (!targetElement) { - return nullptr; - } - - return targetElement->GetComposedDoc(); -} - -nsPresContext* -AnimationPlayer::GetPresContext() const -{ - nsIDocument* doc = GetRenderedDocument(); - if (!doc) { - return nullptr; - } - nsIPresShell* shell = doc->GetShell(); - if (!shell) { - return nullptr; - } - return shell->GetPresContext(); -} - -AnimationPlayerCollection* -AnimationPlayer::GetCollection() const -{ - css::CommonAnimationManager* manager = GetAnimationManager(); - if (!manager) { - return nullptr; - } - MOZ_ASSERT(mSource, "A player with an animation manager must have a source"); - - Element* targetElement; - nsCSSPseudoElements::Type targetPseudoType; - mSource->GetTarget(targetElement, targetPseudoType); - MOZ_ASSERT(targetElement, - "A player with an animation manager must have a target"); - - return manager->GetAnimations(targetElement, targetPseudoType, false); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/animation/AnimationPlayer.h b/dom/animation/AnimationPlayer.h deleted file mode 100644 index fb29b68d1a..0000000000 --- a/dom/animation/AnimationPlayer.h +++ /dev/null @@ -1,348 +0,0 @@ -/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_AnimationPlayer_h -#define mozilla_dom_AnimationPlayer_h - -#include "nsWrapperCache.h" -#include "nsCycleCollectionParticipant.h" -#include "mozilla/Attributes.h" -#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration -#include "mozilla/dom/Animation.h" // for Animation -#include "mozilla/dom/AnimationPlayerBinding.h" // for AnimationPlayState -#include "mozilla/dom/AnimationTimeline.h" // for AnimationTimeline -#include "mozilla/dom/Promise.h" // for Promise -#include "nsCSSProperty.h" // for nsCSSProperty - -// X11 has a #define for CurrentTime. -#ifdef CurrentTime -#undef CurrentTime -#endif - -// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to -// GetTickCount(). -#ifdef GetCurrentTime -#undef GetCurrentTime -#endif - -struct JSContext; -class nsCSSPropertySet; -class nsIDocument; -class nsPresContext; - -namespace mozilla { -struct AnimationPlayerCollection; -namespace css { -class AnimValuesStyleRule; -class CommonAnimationManager; -} // namespace css - -class CSSAnimationPlayer; -class CSSTransitionPlayer; - -namespace dom { - -class AnimationPlayer : public nsISupports, - public nsWrapperCache -{ -protected: - virtual ~AnimationPlayer() {} - -public: - explicit AnimationPlayer(AnimationTimeline* aTimeline) - : mTimeline(aTimeline) - , mPlaybackRate(1.0) - , mPendingState(PendingState::NotPending) - , mIsRunningOnCompositor(false) - , mIsPreviousStateFinished(false) - , mFinishedAtLastComposeStyle(false) - , mIsRelevant(false) - { - } - - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AnimationPlayer) - - AnimationTimeline* GetParentObject() const { return mTimeline; } - virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - virtual CSSAnimationPlayer* AsCSSAnimationPlayer() { return nullptr; } - virtual CSSTransitionPlayer* AsCSSTransitionPlayer() { return nullptr; } - - // Flag to pass to DoPlay to indicate that it should not carry out finishing - // behavior (reset the current time to the beginning of the active duration). - enum LimitBehavior { - AutoRewind = 0, - Continue = 1 - }; - - // AnimationPlayer methods - Animation* GetSource() const { return mSource; } - AnimationTimeline* Timeline() const { return mTimeline; } - Nullable GetStartTime() const { return mStartTime; } - void SetStartTime(const Nullable& aNewStartTime); - Nullable GetCurrentTime() const; - void SilentlySetCurrentTime(const TimeDuration& aNewCurrentTime); - void SetCurrentTime(const TimeDuration& aNewCurrentTime); - double PlaybackRate() const { return mPlaybackRate; } - void SetPlaybackRate(double aPlaybackRate); - void SilentlySetPlaybackRate(double aPlaybackRate); - AnimationPlayState PlayState() const; - virtual Promise* GetReady(ErrorResult& aRv); - virtual Promise* GetFinished(ErrorResult& aRv); - virtual void Play(LimitBehavior aLimitBehavior); - virtual void Pause(); - bool IsRunningOnCompositor() const { return mIsRunningOnCompositor; } - - // Wrapper functions for AnimationPlayer DOM methods when called - // from script. We often use the same methods internally and from - // script but when called from script we (or one of our subclasses) perform - // extra steps such as flushing style or converting the return type. - Nullable GetStartTimeAsDouble() const; - void SetStartTimeAsDouble(const Nullable& aStartTime); - Nullable GetCurrentTimeAsDouble() const; - void SetCurrentTimeAsDouble(const Nullable& aCurrentTime, - ErrorResult& aRv); - virtual AnimationPlayState PlayStateFromJS() const { return PlayState(); } - virtual void PlayFromJS() { Play(LimitBehavior::AutoRewind); } - // PauseFromJS is currently only here for symmetry with PlayFromJS but - // in future we will likely have to flush style in - // CSSAnimationPlayer::PauseFromJS so we leave it for now. - void PauseFromJS() { Pause(); } - - void SetSource(Animation* aSource); - void Tick(); - - /** - * Set the time to use for starting or pausing a pending player. - * - * Typically, when a player is played, it does not start immediately but is - * added to a table of pending players on the document of its source content. - * In the meantime it sets its hold time to the time from which playback - * should begin. - * - * When the document finishes painting, any pending players in its table - * are marked as being ready to start by calling StartOnNextTick. - * The moment when the paint completed is also recorded, converted to a - * timeline time, and passed to StartOnTick. This is so that when these - * players do start, they can be timed from the point when painting - * completed. - * - * After calling TriggerOnNextTick, players remain in the pending state until - * the next refresh driver tick. At that time they transition out of the - * pending state using the time passed to TriggerOnNextTick as the effective - * time at which they resumed. - * - * This approach means that any setup time required for performing the - * initial paint of an animation such as layerization is not deducted from - * the running time of the animation. Without this we can easily drop the - * first few frames of an animation, or, on slower devices, the whole - * animation. - * - * Furthermore: - * - * - Starting the player immediately when painting finishes is problematic - * because the start time of the player will be ahead of its timeline - * (since the timeline time is based on the refresh driver time). - * That's a problem because the player is playing but its timing suggests - * it starts in the future. We could update the timeline to match the start - * time of the player but then we'd also have to update the timing and style - * of all animations connected to that timeline or else be stuck in an - * inconsistent state until the next refresh driver tick. - * - * - If we simply use the refresh driver time on its next tick, the lag - * between triggering an animation and its effective start is unacceptably - * long. - * - * For pausing, we apply the same asynchronous approach. This is so that we - * synchronize with animations that are running on the compositor. Otherwise - * if the main thread lags behind the compositor there will be a noticeable - * jump backwards when the main thread takes over. Even though main thread - * animations could be paused immediately, we do it asynchronously for - * consistency and so that animations paused together end up in step. - * - * Note that the caller of this method is responsible for removing the player - * from any PendingPlayerTracker it may have been added to. - */ - void TriggerOnNextTick(const Nullable& aReadyTime); - - // Testing only: Start or pause a pending player using the current timeline - // time. This is used to support existing tests that expect animations to - // begin immediately. Ideally we would rewrite the those tests and get rid of - // this method, but there are a lot of them. - // - // As with TriggerOnNextTick, the caller of this method is responsible for - // removing the player from any PendingPlayerTracker it may have been added - // to. - void TriggerNow(); - - /** - * When StartOnNextTick is called, we store the ready time but we don't apply - * it until the next tick. In the meantime, GetStartTime() will return null. - * - * However, if we build layer animations again before the next tick, we - * should initialize them with the start time that GetStartTime() will return - * on the next tick. - * - * If we were to simply set the start time of layer animations to null, their - * start time would be updated to the current wallclock time when rendering - * finishes, thus making them out of sync with the start time stored here. - * This, in turn, will make the animation jump backwards when we build - * animations on the next tick and apply the start time stored here. - * - * This method returns the start time, if resolved. Otherwise, if we have - * a pending ready time, it returns the corresponding start time. If neither - * of those are available, it returns null. - */ - Nullable GetCurrentOrPendingStartTime() const; - - void Cancel(); - - const nsString& Name() const - { - return mSource ? mSource->Name() : EmptyString(); - } - - bool IsPausedOrPausing() const - { - return PlayState() == AnimationPlayState::Paused || - mPendingState == PendingState::PausePending; - } - - bool HasInPlaySource() const - { - return GetSource() && GetSource()->IsInPlay(*this); - } - bool HasCurrentSource() const - { - return GetSource() && GetSource()->IsCurrent(*this); - } - bool HasInEffectSource() const - { - return GetSource() && GetSource()->IsInEffect(); - } - - /** - * "Playing" is different to "running". An animation in its delay phase is - * still running but we only consider it playing when it is in its active - * interval. This definition is used for fetching the animations that are - * are candidates for running on the compositor (since we don't ship - * animations to the compositor when they are in their delay phase or - * paused). - */ - bool IsPlaying() const - { - // We need to have a source animation in its active interval, and - // be either running or waiting to run. - return HasInPlaySource() && - (PlayState() == AnimationPlayState::Running || - mPendingState == PendingState::PlayPending); - } - - bool IsRelevant() const { return mIsRelevant; } - void UpdateRelevance(); - - void SetIsRunningOnCompositor() { mIsRunningOnCompositor = true; } - void ClearIsRunningOnCompositor() { mIsRunningOnCompositor = false; } - - // Returns true if this animation does not currently need to update - // style on the main thread (e.g. because it is empty, or is - // running on the compositor). - bool CanThrottle() const; - - // Updates |aStyleRule| with the animation values of this player's source - // content, if any. - // Any properties already contained in |aSetProperties| are not changed. Any - // properties that are changed are added to |aSetProperties|. - // |aNeedsRefreshes| will be set to true if this player expects to update - // the style rule on the next refresh driver tick as well (because it - // is running and has source content to sample). - void ComposeStyle(nsRefPtr& aStyleRule, - nsCSSPropertySet& aSetProperties, - bool& aNeedsRefreshes); - -protected: - void DoPlay(LimitBehavior aLimitBehavior); - void DoPause(); - void ResumeAt(const TimeDuration& aReadyTime); - void PauseAt(const TimeDuration& aReadyTime); - void FinishPendingAt(const TimeDuration& aReadyTime) - { - if (mPendingState == PendingState::PlayPending) { - ResumeAt(aReadyTime); - } else if (mPendingState == PendingState::PausePending) { - PauseAt(aReadyTime); - } else { - NS_NOTREACHED("Can't finish pending if we're not in a pending state"); - } - } - - void UpdateTiming(); - void UpdateFinishedState(bool aSeekFlag = false); - void UpdateSourceContent(); - void FlushStyle() const; - void PostUpdate(); - /** - * Remove this player from the pending player tracker and reset - * mPendingState as necessary. The caller is responsible for resolving or - * aborting the mReady promise as necessary. - */ - void CancelPendingTasks(); - - bool IsFinished() const; - - bool IsPossiblyOrphanedPendingPlayer() const; - StickyTimeDuration SourceContentEnd() const; - - nsIDocument* GetRenderedDocument() const; - nsPresContext* GetPresContext() const; - virtual css::CommonAnimationManager* GetAnimationManager() const = 0; - AnimationPlayerCollection* GetCollection() const; - - nsRefPtr mTimeline; - nsRefPtr mSource; - // The beginning of the delay period. - Nullable mStartTime; // Timeline timescale - Nullable mHoldTime; // Player timescale - Nullable mPendingReadyTime; // Timeline timescale - Nullable mPreviousCurrentTime; // Player timescale - double mPlaybackRate; - - // A Promise that is replaced on each call to Play() (and in future Pause()) - // and fulfilled when Play() is successfully completed. - // This object is lazily created by GetReady. - // See http://w3c.github.io/web-animations/#current-ready-promise - nsRefPtr mReady; - - // A Promise that is resolved when we reach the end of the source content, or - // 0 when playing backwards. The Promise is replaced if the animation is - // finished but then a state change makes it not finished. - // This object is lazily created by GetFinished. - // See http://w3c.github.io/web-animations/#current-finished-promise - nsRefPtr mFinished; - - // Indicates if the player is in the pending state (and what state it is - // waiting to enter when it finished pending). We use this rather than - // checking if this player is tracked by a PendingPlayerTracker because the - // player will continue to be pending even after it has been removed from the - // PendingPlayerTracker while it is waiting for the next tick - // (see TriggerOnNextTick for details). - enum class PendingState { NotPending, PlayPending, PausePending }; - PendingState mPendingState; - - bool mIsRunningOnCompositor; - // Indicates whether we were in the finished state during our - // most recent unthrottled sample (our last ComposeStyle call). - bool mIsPreviousStateFinished; // Spec calls this "previous finished state" - bool mFinishedAtLastComposeStyle; - // Indicates that the animation should be exposed in an element's - // getAnimations() list. - bool mIsRelevant; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_AnimationPlayer_h diff --git a/dom/animation/AnimationTimeline.cpp b/dom/animation/AnimationTimeline.cpp index d83ae7389b..73033a5de5 100644 --- a/dom/animation/AnimationTimeline.cpp +++ b/dom/animation/AnimationTimeline.cpp @@ -4,118 +4,19 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AnimationTimeline.h" -#include "mozilla/dom/AnimationTimelineBinding.h" -#include "AnimationUtils.h" -#include "nsContentUtils.h" -#include "nsIPresShell.h" -#include "nsPresContext.h" -#include "nsRefreshDriver.h" -#include "nsDOMNavigationTiming.h" namespace mozilla { namespace dom { -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationTimeline, mDocument, mWindow) +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationTimeline, mWindow) -NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnimationTimeline, AddRef) -NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AnimationTimeline, Release) +NS_IMPL_CYCLE_COLLECTING_ADDREF(AnimationTimeline) +NS_IMPL_CYCLE_COLLECTING_RELEASE(AnimationTimeline) -JSObject* -AnimationTimeline::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return AnimationTimelineBinding::Wrap(aCx, this, aGivenProto); -} - -Nullable -AnimationTimeline::GetCurrentTime() const -{ - return ToTimelineTime(GetCurrentTimeStamp()); -} - -Nullable -AnimationTimeline::GetCurrentTimeAsDouble() const -{ - return AnimationUtils::TimeDurationToDouble(GetCurrentTime()); -} - -TimeStamp -AnimationTimeline::GetCurrentTimeStamp() const -{ - nsRefreshDriver* refreshDriver = GetRefreshDriver(); - TimeStamp refreshTime = refreshDriver - ? refreshDriver->MostRecentRefresh() - : TimeStamp(); - - // Always return the same object to benefit from return-value optimization. - TimeStamp result = !refreshTime.IsNull() - ? refreshTime - : mLastRefreshDriverTime; - - // If we don't have a refresh driver and we've never had one use the - // timeline's zero time. - if (result.IsNull()) { - nsRefPtr timing = mDocument->GetNavigationTiming(); - if (timing) { - result = timing->GetNavigationStartTimeStamp(); - // Also, let this time represent the current refresh time. This way - // we'll save it as the last refresh time and skip looking up - // navigation timing each time. - refreshTime = result; - } - } - - if (!refreshTime.IsNull()) { - mLastRefreshDriverTime = refreshTime; - } - - return result; -} - -Nullable -AnimationTimeline::ToTimelineTime(const TimeStamp& aTimeStamp) const -{ - Nullable result; // Initializes to null - if (aTimeStamp.IsNull()) { - return result; - } - - nsRefPtr timing = mDocument->GetNavigationTiming(); - if (MOZ_UNLIKELY(!timing)) { - return result; - } - - result.SetValue(aTimeStamp - timing->GetNavigationStartTimeStamp()); - return result; -} - -TimeStamp -AnimationTimeline::ToTimeStamp(const TimeDuration& aTimeDuration) const -{ - TimeStamp result; - nsRefPtr timing = mDocument->GetNavigationTiming(); - if (MOZ_UNLIKELY(!timing)) { - return result; - } - - result = timing->GetNavigationStartTimeStamp() + aTimeDuration; - return result; -} - -nsRefreshDriver* -AnimationTimeline::GetRefreshDriver() const -{ - nsIPresShell* presShell = mDocument->GetShell(); - if (MOZ_UNLIKELY(!presShell)) { - return nullptr; - } - - nsPresContext* presContext = presShell->GetPresContext(); - if (MOZ_UNLIKELY(!presContext)) { - return nullptr; - } - - return presContext->RefreshDriver(); -} +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AnimationTimeline) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END } // namespace dom } // namespace mozilla diff --git a/dom/animation/AnimationTimeline.h b/dom/animation/AnimationTimeline.h index 6a1f320ab0..8faaf54f75 100644 --- a/dom/animation/AnimationTimeline.h +++ b/dom/animation/AnimationTimeline.h @@ -6,26 +6,24 @@ #ifndef mozilla_dom_AnimationTimeline_h #define mozilla_dom_AnimationTimeline_h +#include "nsISupports.h" #include "nsWrapperCache.h" #include "nsCycleCollectionParticipant.h" +#include "mozilla/AnimationUtils.h" #include "mozilla/Attributes.h" -#include "mozilla/TimeStamp.h" #include "nsIGlobalObject.h" #include "js/TypeDecls.h" -#include "nsIDocument.h" -#include "nsRefreshDriver.h" - -struct JSContext; namespace mozilla { namespace dom { -class AnimationTimeline final : public nsWrapperCache +class AnimationTimeline + : public nsISupports + , public nsWrapperCache { public: - explicit AnimationTimeline(nsIDocument* aDocument) - : mDocument(aDocument) - , mWindow(aDocument->GetParentObject()) + explicit AnimationTimeline(nsIGlobalObject* aWindow) + : mWindow(aWindow) { MOZ_ASSERT(mWindow); } @@ -34,56 +32,22 @@ protected: virtual ~AnimationTimeline() { } public: - NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnimationTimeline) - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AnimationTimeline) + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AnimationTimeline) - nsIGlobalObject* GetParentObject() const - { - return mWindow; - } - virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + nsIGlobalObject* GetParentObject() const { return mWindow; } // AnimationTimeline methods - Nullable GetCurrentTime() const; + virtual Nullable GetCurrentTime() const = 0; // Wrapper functions for AnimationTimeline DOM methods when called from // script. - Nullable GetCurrentTimeAsDouble() const; - - // Converts a TimeStamp to the equivalent value in timeline time. - // Note that when IsUnderTestControl() is true, there is no correspondence - // between timeline time and wallclock time. In such a case, passing a - // timestamp from TimeStamp::Now() to this method will not return a - // meaningful result. - Nullable ToTimelineTime(const TimeStamp& aTimeStamp) const; - TimeStamp ToTimeStamp(const TimeDuration& aTimelineTime) const; - - nsRefreshDriver* GetRefreshDriver() const; - // Returns true if this timeline is driven by a refresh driver that is - // under test control. In such a case, there is no correspondence between - // TimeStamp values returned by the refresh driver and wallclock time. - // As a result, passing a value from TimeStamp::Now() to ToTimelineTime() - // would not return a meaningful result. - bool IsUnderTestControl() const - { - nsRefreshDriver* refreshDriver = GetRefreshDriver(); - return refreshDriver && refreshDriver->IsTestControllingRefreshesEnabled(); + Nullable GetCurrentTimeAsDouble() const { + return AnimationUtils::TimeDurationToDouble(GetCurrentTime()); } protected: - TimeStamp GetCurrentTimeStamp() const; - - // Sometimes documents can be given a new window, or windows can be given a - // new document (e.g. document.open()). Since GetParentObject is required to - // _always_ return the same object it can't get the window from our - // mDocument, which is why we have pointers to both our document and window. - nsCOMPtr mDocument; nsCOMPtr mWindow; - - // The most recently used refresh driver time. This is used in cases where - // we don't have a refresh driver (e.g. because we are in a display:none - // iframe). - mutable TimeStamp mLastRefreshDriverTime; }; } // namespace dom diff --git a/dom/animation/DocumentTimeline.cpp b/dom/animation/DocumentTimeline.cpp new file mode 100644 index 0000000000..1ed91d9a89 --- /dev/null +++ b/dom/animation/DocumentTimeline.cpp @@ -0,0 +1,123 @@ +/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ +/* 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 "DocumentTimeline.h" +#include "mozilla/dom/DocumentTimelineBinding.h" +#include "AnimationUtils.h" +#include "nsContentUtils.h" +#include "nsIPresShell.h" +#include "nsPresContext.h" +#include "nsRefreshDriver.h" +#include "nsDOMNavigationTiming.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_INHERITED(DocumentTimeline, AnimationTimeline, + mDocument) + +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(DocumentTimeline, + AnimationTimeline) +NS_IMPL_CYCLE_COLLECTION_TRACE_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DocumentTimeline) +NS_INTERFACE_MAP_END_INHERITING(AnimationTimeline) + +NS_IMPL_ADDREF_INHERITED(DocumentTimeline, AnimationTimeline) +NS_IMPL_RELEASE_INHERITED(DocumentTimeline, AnimationTimeline) + +JSObject* +DocumentTimeline::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + return DocumentTimelineBinding::Wrap(aCx, this, aGivenProto); +} + +Nullable +DocumentTimeline::GetCurrentTime() const +{ + return ToTimelineTime(GetCurrentTimeStamp()); +} + +TimeStamp +DocumentTimeline::GetCurrentTimeStamp() const +{ + nsRefreshDriver* refreshDriver = GetRefreshDriver(); + TimeStamp refreshTime = refreshDriver + ? refreshDriver->MostRecentRefresh() + : TimeStamp(); + + // Always return the same object to benefit from return-value optimization. + TimeStamp result = !refreshTime.IsNull() + ? refreshTime + : mLastRefreshDriverTime; + + // If we don't have a refresh driver and we've never had one use the + // timeline's zero time. + if (result.IsNull()) { + nsRefPtr timing = mDocument->GetNavigationTiming(); + if (timing) { + result = timing->GetNavigationStartTimeStamp(); + // Also, let this time represent the current refresh time. This way + // we'll save it as the last refresh time and skip looking up + // navigation timing each time. + refreshTime = result; + } + } + + if (!refreshTime.IsNull()) { + mLastRefreshDriverTime = refreshTime; + } + + return result; +} + +Nullable +DocumentTimeline::ToTimelineTime(const TimeStamp& aTimeStamp) const +{ + Nullable result; // Initializes to null + if (aTimeStamp.IsNull()) { + return result; + } + + nsRefPtr timing = mDocument->GetNavigationTiming(); + if (MOZ_UNLIKELY(!timing)) { + return result; + } + + result.SetValue(aTimeStamp - timing->GetNavigationStartTimeStamp()); + return result; +} + +TimeStamp +DocumentTimeline::ToTimeStamp(const TimeDuration& aTimeDuration) const +{ + TimeStamp result; + nsRefPtr timing = mDocument->GetNavigationTiming(); + if (MOZ_UNLIKELY(!timing)) { + return result; + } + + result = timing->GetNavigationStartTimeStamp() + aTimeDuration; + return result; +} + +nsRefreshDriver* +DocumentTimeline::GetRefreshDriver() const +{ + nsIPresShell* presShell = mDocument->GetShell(); + if (MOZ_UNLIKELY(!presShell)) { + return nullptr; + } + + nsPresContext* presContext = presShell->GetPresContext(); + if (MOZ_UNLIKELY(!presContext)) { + return nullptr; + } + + return presContext->RefreshDriver(); +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/animation/DocumentTimeline.h b/dom/animation/DocumentTimeline.h new file mode 100644 index 0000000000..20dedff2ac --- /dev/null +++ b/dom/animation/DocumentTimeline.h @@ -0,0 +1,76 @@ +/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_DocumentTimeline_h +#define mozilla_dom_DocumentTimeline_h + +#include "mozilla/TimeStamp.h" +#include "AnimationTimeline.h" +#include "nsIDocument.h" +#include "nsRefreshDriver.h" + +struct JSContext; + +namespace mozilla { +namespace dom { + +class DocumentTimeline final : public AnimationTimeline +{ +public: + explicit DocumentTimeline(nsIDocument* aDocument) + : AnimationTimeline(aDocument->GetParentObject()) + , mDocument(aDocument) + { + } + +protected: + virtual ~DocumentTimeline() { } + +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(DocumentTimeline, + AnimationTimeline) + + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + + // DocumentTimeline methods + virtual Nullable GetCurrentTime() const override; + + // Converts a TimeStamp to the equivalent value in timeline time. + // Note that when IsUnderTestControl() is true, there is no correspondence + // between timeline time and wallclock time. In such a case, passing a + // timestamp from TimeStamp::Now() to this method will not return a + // meaningful result. + Nullable ToTimelineTime(const TimeStamp& aTimeStamp) const; + TimeStamp ToTimeStamp(const TimeDuration& aTimelineTime) const; + + nsRefreshDriver* GetRefreshDriver() const; + // Returns true if this timeline is driven by a refresh driver that is + // under test control. In such a case, there is no correspondence between + // TimeStamp values returned by the refresh driver and wallclock time. + // As a result, passing a value from TimeStamp::Now() to ToTimelineTime() + // would not return a meaningful result. + bool IsUnderTestControl() const + { + nsRefreshDriver* refreshDriver = GetRefreshDriver(); + return refreshDriver && refreshDriver->IsTestControllingRefreshesEnabled(); + } + +protected: + TimeStamp GetCurrentTimeStamp() const; + + nsCOMPtr mDocument; + + // The most recently used refresh driver time. This is used in cases where + // we don't have a refresh driver (e.g. because we are in a display:none + // iframe). + mutable TimeStamp mLastRefreshDriverTime; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_DocumentTimeline_h diff --git a/dom/animation/KeyframeEffect.cpp b/dom/animation/KeyframeEffect.cpp new file mode 100644 index 0000000000..5671d1844a --- /dev/null +++ b/dom/animation/KeyframeEffect.cpp @@ -0,0 +1,396 @@ +/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ +/* 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 "mozilla/dom/KeyframeEffect.h" +#include "mozilla/dom/KeyframeEffectBinding.h" +#include "mozilla/FloatingPoint.h" +#include "AnimationCommon.h" +#include "nsCSSPropertySet.h" + +namespace mozilla { + +void +ComputedTimingFunction::Init(const nsTimingFunction &aFunction) +{ + mType = aFunction.mType; + if (mType == nsTimingFunction::Function) { + mTimingFunction.Init(aFunction.mFunc.mX1, aFunction.mFunc.mY1, + aFunction.mFunc.mX2, aFunction.mFunc.mY2); + } else { + mSteps = aFunction.mSteps; + } +} + +static inline double +StepEnd(uint32_t aSteps, double aPortion) +{ + MOZ_ASSERT(0.0 <= aPortion && aPortion <= 1.0, "out of range"); + uint32_t step = uint32_t(aPortion * aSteps); // floor + return double(step) / double(aSteps); +} + +double +ComputedTimingFunction::GetValue(double aPortion) const +{ + switch (mType) { + case nsTimingFunction::Function: + return mTimingFunction.GetSplineValue(aPortion); + case nsTimingFunction::StepStart: + // There are diagrams in the spec that seem to suggest this check + // and the bounds point should not be symmetric with StepEnd, but + // should actually step up at rather than immediately after the + // fraction points. However, we rely on rounding negative values + // up to zero, so we can't do that. And it's not clear the spec + // really meant it. + return 1.0 - StepEnd(mSteps, 1.0 - aPortion); + default: + MOZ_ASSERT(false, "bad type"); + // fall through + case nsTimingFunction::StepEnd: + return StepEnd(mSteps, aPortion); + } +} + +// In the Web Animations model, the time fraction can be outside the range +// [0.0, 1.0] but it shouldn't be Infinity. +const double ComputedTiming::kNullTimeFraction = PositiveInfinity(); + +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_INHERITED(KeyframeEffectReadonly, + AnimationEffectReadonly, + mTarget) + +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(KeyframeEffectReadonly, + AnimationEffectReadonly) +NS_IMPL_CYCLE_COLLECTION_TRACE_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(KeyframeEffectReadonly) +NS_INTERFACE_MAP_END_INHERITING(AnimationEffectReadonly) + +NS_IMPL_ADDREF_INHERITED(KeyframeEffectReadonly, AnimationEffectReadonly) +NS_IMPL_RELEASE_INHERITED(KeyframeEffectReadonly, AnimationEffectReadonly) + +JSObject* +KeyframeEffectReadonly::WrapObject(JSContext* aCx, + JS::Handle aGivenProto) +{ + return KeyframeEffectReadonlyBinding::Wrap(aCx, this, aGivenProto); +} + +void +KeyframeEffectReadonly::SetParentTime(Nullable aParentTime) +{ + mParentTime = aParentTime; +} + +ComputedTiming +KeyframeEffectReadonly::GetComputedTimingAt( + const Nullable& aLocalTime, + const AnimationTiming& aTiming) +{ + const TimeDuration zeroDuration; + + // Currently we expect negative durations to be picked up during CSS + // parsing but when we start receiving timing parameters from other sources + // we will need to clamp negative durations here. + // For now, if we're hitting this it probably means we're overflowing + // integer arithmetic in mozilla::TimeStamp. + MOZ_ASSERT(aTiming.mIterationDuration >= zeroDuration, + "Expecting iteration duration >= 0"); + + // Always return the same object to benefit from return-value optimization. + ComputedTiming result; + + result.mActiveDuration = ActiveDuration(aTiming); + + // The default constructor for ComputedTiming sets all other members to + // values consistent with an animation that has not been sampled. + if (aLocalTime.IsNull()) { + return result; + } + const TimeDuration& localTime = aLocalTime.Value(); + + // When we finish exactly at the end of an iteration we need to report + // the end of the final iteration and not the start of the next iteration + // so we set up a flag for that case. + bool isEndOfFinalIteration = false; + + // Get the normalized time within the active interval. + StickyTimeDuration activeTime; + if (localTime >= aTiming.mDelay + result.mActiveDuration) { + result.mPhase = ComputedTiming::AnimationPhase_After; + if (!aTiming.FillsForwards()) { + // The animation isn't active or filling at this time. + result.mTimeFraction = ComputedTiming::kNullTimeFraction; + return result; + } + activeTime = result.mActiveDuration; + // Note that infinity == floor(infinity) so this will also be true when we + // have finished an infinitely repeating animation of zero duration. + isEndOfFinalIteration = + aTiming.mIterationCount != 0.0 && + aTiming.mIterationCount == floor(aTiming.mIterationCount); + } else if (localTime < aTiming.mDelay) { + result.mPhase = ComputedTiming::AnimationPhase_Before; + if (!aTiming.FillsBackwards()) { + // The animation isn't active or filling at this time. + result.mTimeFraction = ComputedTiming::kNullTimeFraction; + return result; + } + // activeTime is zero + } else { + MOZ_ASSERT(result.mActiveDuration != zeroDuration, + "How can we be in the middle of a zero-duration interval?"); + result.mPhase = ComputedTiming::AnimationPhase_Active; + activeTime = localTime - aTiming.mDelay; + } + + // Get the position within the current iteration. + StickyTimeDuration iterationTime; + if (aTiming.mIterationDuration != zeroDuration) { + iterationTime = isEndOfFinalIteration + ? StickyTimeDuration(aTiming.mIterationDuration) + : activeTime % aTiming.mIterationDuration; + } /* else, iterationTime is zero */ + + // Determine the 0-based index of the current iteration. + if (isEndOfFinalIteration) { + result.mCurrentIteration = + aTiming.mIterationCount == NS_IEEEPositiveInfinity() + ? UINT64_MAX // FIXME: When we return this via the API we'll need + // to make sure it ends up being infinity. + : static_cast(aTiming.mIterationCount) - 1; + } else if (activeTime == zeroDuration) { + // If the active time is zero we're either in the first iteration + // (including filling backwards) or we have finished an animation with an + // iteration duration of zero that is filling forwards (but we're not at + // the exact end of an iteration since we deal with that above). + result.mCurrentIteration = + result.mPhase == ComputedTiming::AnimationPhase_After + ? static_cast(aTiming.mIterationCount) // floor + : 0; + } else { + result.mCurrentIteration = + static_cast(activeTime / aTiming.mIterationDuration); // floor + } + + // Normalize the iteration time into a fraction of the iteration duration. + if (result.mPhase == ComputedTiming::AnimationPhase_Before) { + result.mTimeFraction = 0.0; + } else if (result.mPhase == ComputedTiming::AnimationPhase_After) { + result.mTimeFraction = isEndOfFinalIteration + ? 1.0 + : fmod(aTiming.mIterationCount, 1.0f); + } else { + // We are in the active phase so the iteration duration can't be zero. + MOZ_ASSERT(aTiming.mIterationDuration != zeroDuration, + "In the active phase of a zero-duration animation?"); + result.mTimeFraction = + aTiming.mIterationDuration == TimeDuration::Forever() + ? 0.0 + : iterationTime / aTiming.mIterationDuration; + } + + bool thisIterationReverse = false; + switch (aTiming.mDirection) { + case NS_STYLE_ANIMATION_DIRECTION_NORMAL: + thisIterationReverse = false; + break; + case NS_STYLE_ANIMATION_DIRECTION_REVERSE: + thisIterationReverse = true; + break; + case NS_STYLE_ANIMATION_DIRECTION_ALTERNATE: + thisIterationReverse = (result.mCurrentIteration & 1) == 1; + break; + case NS_STYLE_ANIMATION_DIRECTION_ALTERNATE_REVERSE: + thisIterationReverse = (result.mCurrentIteration & 1) == 0; + break; + } + if (thisIterationReverse) { + result.mTimeFraction = 1.0 - result.mTimeFraction; + } + + return result; +} + +StickyTimeDuration +KeyframeEffectReadonly::ActiveDuration(const AnimationTiming& aTiming) +{ + if (aTiming.mIterationCount == mozilla::PositiveInfinity()) { + // An animation that repeats forever has an infinite active duration + // unless its iteration duration is zero, in which case it has a zero + // active duration. + const StickyTimeDuration zeroDuration; + return aTiming.mIterationDuration == zeroDuration + ? zeroDuration + : StickyTimeDuration::Forever(); + } + return StickyTimeDuration( + aTiming.mIterationDuration.MultDouble(aTiming.mIterationCount)); +} + +// http://w3c.github.io/web-animations/#in-play +bool +KeyframeEffectReadonly::IsInPlay(const Animation& aAnimation) const +{ + if (IsFinishedTransition() || + aAnimation.PlayState() == AnimationPlayState::Finished) { + return false; + } + + return GetComputedTiming().mPhase == ComputedTiming::AnimationPhase_Active; +} + +// http://w3c.github.io/web-animations/#current +bool +KeyframeEffectReadonly::IsCurrent(const Animation& aAnimation) const +{ + if (IsFinishedTransition() || + aAnimation.PlayState() == AnimationPlayState::Finished) { + return false; + } + + ComputedTiming computedTiming = GetComputedTiming(); + return computedTiming.mPhase == ComputedTiming::AnimationPhase_Before || + computedTiming.mPhase == ComputedTiming::AnimationPhase_Active; +} + +bool +KeyframeEffectReadonly::IsInEffect() const +{ + if (IsFinishedTransition()) { + return false; + } + + ComputedTiming computedTiming = GetComputedTiming(); + return computedTiming.mTimeFraction != ComputedTiming::kNullTimeFraction; +} + +const AnimationProperty* +KeyframeEffectReadonly::GetAnimationOfProperty(nsCSSProperty aProperty) const +{ + for (size_t propIdx = 0, propEnd = mProperties.Length(); + propIdx != propEnd; ++propIdx) { + if (aProperty == mProperties[propIdx].mProperty) { + const AnimationProperty* result = &mProperties[propIdx]; + if (!result->mWinsInCascade) { + result = nullptr; + } + return result; + } + } + return nullptr; +} + +bool +KeyframeEffectReadonly::HasAnimationOfProperties( + const nsCSSProperty* aProperties, + size_t aPropertyCount) const +{ + for (size_t i = 0; i < aPropertyCount; i++) { + if (HasAnimationOfProperty(aProperties[i])) { + return true; + } + } + return false; +} + +void +KeyframeEffectReadonly::ComposeStyle( + nsRefPtr& aStyleRule, + nsCSSPropertySet& aSetProperties) +{ + ComputedTiming computedTiming = GetComputedTiming(); + + // If the time fraction is null, we don't have fill data for the current + // time so we shouldn't animate. + if (computedTiming.mTimeFraction == ComputedTiming::kNullTimeFraction) { + return; + } + + MOZ_ASSERT(0.0 <= computedTiming.mTimeFraction && + computedTiming.mTimeFraction <= 1.0, + "timing fraction should be in [0-1]"); + + for (size_t propIdx = 0, propEnd = mProperties.Length(); + propIdx != propEnd; ++propIdx) + { + const AnimationProperty& prop = mProperties[propIdx]; + + MOZ_ASSERT(prop.mSegments[0].mFromKey == 0.0, "incorrect first from key"); + MOZ_ASSERT(prop.mSegments[prop.mSegments.Length() - 1].mToKey == 1.0, + "incorrect last to key"); + + if (aSetProperties.HasProperty(prop.mProperty)) { + // Animations are composed by AnimationCollection by iterating + // from the last animation to first. For animations targetting the + // same property, the later one wins. So if this property is already set, + // we should not override it. + continue; + } + + if (!prop.mWinsInCascade) { + // This isn't the winning declaration, so don't add it to style. + // For transitions, this is important, because it's how we + // implement the rule that CSS transitions don't run when a CSS + // animation is running on the same property and element. For + // animations, this is only skipping things that will otherwise be + // overridden. + continue; + } + + aSetProperties.AddProperty(prop.mProperty); + + MOZ_ASSERT(prop.mSegments.Length() > 0, + "property should not be in animations if it has no segments"); + + // FIXME: Maybe cache the current segment? + const AnimationPropertySegment *segment = prop.mSegments.Elements(), + *segmentEnd = segment + prop.mSegments.Length(); + while (segment->mToKey < computedTiming.mTimeFraction) { + MOZ_ASSERT(segment->mFromKey < segment->mToKey, "incorrect keys"); + ++segment; + if (segment == segmentEnd) { + MOZ_ASSERT_UNREACHABLE("incorrect time fraction"); + break; // in order to continue in outer loop (just below) + } + MOZ_ASSERT(segment->mFromKey == (segment-1)->mToKey, "incorrect keys"); + } + if (segment == segmentEnd) { + continue; + } + MOZ_ASSERT(segment->mFromKey < segment->mToKey, "incorrect keys"); + MOZ_ASSERT(segment >= prop.mSegments.Elements() && + size_t(segment - prop.mSegments.Elements()) < + prop.mSegments.Length(), + "out of array bounds"); + + if (!aStyleRule) { + // Allocate the style rule now that we know we have animation data. + aStyleRule = new css::AnimValuesStyleRule(); + } + + double positionInSegment = + (computedTiming.mTimeFraction - segment->mFromKey) / + (segment->mToKey - segment->mFromKey); + double valuePosition = + segment->mTimingFunction.GetValue(positionInSegment); + + StyleAnimationValue *val = aStyleRule->AddEmptyValue(prop.mProperty); + +#ifdef DEBUG + bool result = +#endif + StyleAnimationValue::Interpolate(prop.mProperty, + segment->mFromValue, + segment->mToValue, + valuePosition, *val); + MOZ_ASSERT(result, "interpolate must succeed now"); + } +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/animation/KeyframeEffect.h b/dom/animation/KeyframeEffect.h new file mode 100644 index 0000000000..a5236414a8 --- /dev/null +++ b/dom/animation/KeyframeEffect.h @@ -0,0 +1,353 @@ +/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_KeyframeEffect_h +#define mozilla_dom_KeyframeEffect_h + +#include "nsAutoPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsCSSPseudoElements.h" +#include "nsIDocument.h" +#include "nsWrapperCache.h" +#include "mozilla/Attributes.h" +#include "mozilla/StickyTimeDuration.h" +#include "mozilla/StyleAnimationValue.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/dom/AnimationEffectReadonly.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/Nullable.h" +#include "nsSMILKeySpline.h" +#include "nsStyleStruct.h" // for nsTimingFunction + +struct JSContext; +class nsCSSPropertySet; + +namespace mozilla { +namespace css { +class AnimValuesStyleRule; +} // namespace css + +/** + * Input timing parameters. + * + * Eventually this will represent all the input timing parameters specified + * by content but for now it encapsulates just the subset of those + * parameters passed to GetPositionInIteration. + */ +struct AnimationTiming +{ + TimeDuration mIterationDuration; + TimeDuration mDelay; + float mIterationCount; // mozilla::PositiveInfinity() means infinite + uint8_t mDirection; + uint8_t mFillMode; + + bool FillsForwards() const { + return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH || + mFillMode == NS_STYLE_ANIMATION_FILL_MODE_FORWARDS; + } + bool FillsBackwards() const { + return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH || + mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BACKWARDS; + } + bool operator==(const AnimationTiming& aOther) const { + return mIterationDuration == aOther.mIterationDuration && + mDelay == aOther.mDelay && + mIterationCount == aOther.mIterationCount && + mDirection == aOther.mDirection && + mFillMode == aOther.mFillMode; + } + bool operator!=(const AnimationTiming& aOther) const { + return !(*this == aOther); + } +}; + +/** + * Stores the results of calculating the timing properties of an animation + * at a given sample time. + */ +struct ComputedTiming +{ + ComputedTiming() + : mTimeFraction(kNullTimeFraction) + , mCurrentIteration(0) + , mPhase(AnimationPhase_Null) + { } + + static const double kNullTimeFraction; + + // The total duration of the animation including all iterations. + // Will equal StickyTimeDuration::Forever() if the animation repeats + // indefinitely. + StickyTimeDuration mActiveDuration; + + // Will be kNullTimeFraction if the animation is neither animating nor + // filling at the sampled time. + double mTimeFraction; + + // Zero-based iteration index (meaningless if mTimeFraction is + // kNullTimeFraction). + uint64_t mCurrentIteration; + + enum { + // Not sampled (null sample time) + AnimationPhase_Null, + // Sampled prior to the start of the active interval + AnimationPhase_Before, + // Sampled within the active interval + AnimationPhase_Active, + // Sampled after (or at) the end of the active interval + AnimationPhase_After + } mPhase; +}; + +class ComputedTimingFunction +{ +public: + typedef nsTimingFunction::Type Type; + void Init(const nsTimingFunction &aFunction); + double GetValue(double aPortion) const; + const nsSMILKeySpline* GetFunction() const { + NS_ASSERTION(mType == nsTimingFunction::Function, "Type mismatch"); + return &mTimingFunction; + } + Type GetType() const { return mType; } + uint32_t GetSteps() const { return mSteps; } + bool operator==(const ComputedTimingFunction& aOther) const { + return mType == aOther.mType && + (mType == nsTimingFunction::Function ? + mTimingFunction == aOther.mTimingFunction : + mSteps == aOther.mSteps); + } + bool operator!=(const ComputedTimingFunction& aOther) const { + return !(*this == aOther); + } + +private: + Type mType; + nsSMILKeySpline mTimingFunction; + uint32_t mSteps; +}; + +struct AnimationPropertySegment +{ + float mFromKey, mToKey; + StyleAnimationValue mFromValue, mToValue; + ComputedTimingFunction mTimingFunction; + + bool operator==(const AnimationPropertySegment& aOther) const { + return mFromKey == aOther.mFromKey && + mToKey == aOther.mToKey && + mFromValue == aOther.mFromValue && + mToValue == aOther.mToValue && + mTimingFunction == aOther.mTimingFunction; + } + bool operator!=(const AnimationPropertySegment& aOther) const { + return !(*this == aOther); + } +}; + +struct AnimationProperty +{ + nsCSSProperty mProperty; + + // Does this property win in the CSS Cascade? + // + // For CSS transitions, this is true as long as a CSS animation on the + // same property and element is not running, in which case we set this + // to false so that the animation (lower in the cascade) can win. We + // then use this to decide whether to apply the style both in the CSS + // cascade and for OMTA. + // + // For CSS Animations, which are overridden by !important rules in the + // cascade, we actually determine this from the CSS cascade + // computations, and then use it for OMTA. + // **NOTE**: For CSS animations, we only bother setting mWinsInCascade + // accurately for properties that we can animate on the compositor. + // For other properties, we make it always be true. + bool mWinsInCascade; + + InfallibleTArray mSegments; + + bool operator==(const AnimationProperty& aOther) const { + return mProperty == aOther.mProperty && + mWinsInCascade == aOther.mWinsInCascade && + mSegments == aOther.mSegments; + } + bool operator!=(const AnimationProperty& aOther) const { + return !(*this == aOther); + } +}; + +struct ElementPropertyTransition; + +namespace dom { + +class KeyframeEffectReadonly : public AnimationEffectReadonly +{ +public: + KeyframeEffectReadonly(nsIDocument* aDocument, + Element* aTarget, + nsCSSPseudoElements::Type aPseudoType, + const AnimationTiming &aTiming, + const nsSubstring& aName) + : AnimationEffectReadonly(aDocument) + , mTarget(aTarget) + , mTiming(aTiming) + , mName(aName) + , mIsFinishedTransition(false) + , mPseudoType(aPseudoType) + { + MOZ_ASSERT(aTarget, "null animation target is not yet supported"); + } + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(KeyframeEffectReadonly, + AnimationEffectReadonly) + + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + + virtual ElementPropertyTransition* AsTransition() { return nullptr; } + virtual const ElementPropertyTransition* AsTransition() const { + return nullptr; + } + + // KeyframeEffectReadonly interface + Element* GetTarget() const { + // Currently we only implement Element.getAnimations() which only + // returns animations targetting Elements so this should never + // be called for an animation that targets a pseudo-element. + MOZ_ASSERT(mPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement, + "Requesting the target of a KeyframeEffect that targets a" + " pseudo-element is not yet supported."); + return mTarget; + } + void GetName(nsString& aRetVal) const + { + aRetVal = Name(); + } + + // Temporary workaround to return both the target element and pseudo-type + // until we implement PseudoElement. + void GetTarget(Element*& aTarget, + nsCSSPseudoElements::Type& aPseudoType) const { + aTarget = mTarget; + aPseudoType = mPseudoType; + } + // Alternative to GetName that returns a reference to the member for + // more efficient internal usage. + virtual const nsString& Name() const + { + return mName; + } + + void SetParentTime(Nullable aParentTime); + + const AnimationTiming& Timing() const { + return mTiming; + } + AnimationTiming& Timing() { + return mTiming; + } + + // Return the duration from the start the active interval to the point where + // the animation begins playback. This is zero unless the animation has + // a negative delay in which case it is the absolute value of the delay. + // This is used for setting the elapsedTime member of CSS AnimationEvents. + TimeDuration InitialAdvance() const { + return std::max(TimeDuration(), mTiming.mDelay * -1); + } + + Nullable GetLocalTime() const { + // Since the *animation* start time is currently always zero, the local + // time is equal to the parent time. + return mParentTime; + } + + // This function takes as input the timing parameters of an animation and + // returns the computed timing at the specified local time. + // + // The local time may be null in which case only static parameters such as the + // active duration are calculated. All other members of the returned object + // are given a null/initial value. + // + // This function returns ComputedTiming::kNullTimeFraction for the + // mTimeFraction member of the return value if the animation should not be + // run (because it is not currently active and is not filling at this time). + static ComputedTiming + GetComputedTimingAt(const Nullable& aLocalTime, + const AnimationTiming& aTiming); + + // Shortcut for that gets the computed timing using the current local time as + // calculated from the timeline time. + ComputedTiming GetComputedTiming(const AnimationTiming* aTiming + = nullptr) const { + return GetComputedTimingAt(GetLocalTime(), aTiming ? *aTiming : mTiming); + } + + // Return the duration of the active interval for the given timing parameters. + static StickyTimeDuration + ActiveDuration(const AnimationTiming& aTiming); + + // After transitions finish they need to be retained in order to + // address the issue described in + // https://lists.w3.org/Archives/Public/www-style/2015Jan/0444.html . + // However, finished transitions are ignored for many purposes. + bool IsFinishedTransition() const { + return mIsFinishedTransition; + } + + void SetIsFinishedTransition(bool aIsFinished) { + MOZ_ASSERT(AsTransition(), + "Calling SetIsFinishedTransition but it's not a transition"); + mIsFinishedTransition = aIsFinished; + } + + bool IsInPlay(const Animation& aAnimation) const; + bool IsCurrent(const Animation& aAnimation) const; + bool IsInEffect() const; + + const AnimationProperty* + GetAnimationOfProperty(nsCSSProperty aProperty) const; + bool HasAnimationOfProperty(nsCSSProperty aProperty) const { + return GetAnimationOfProperty(aProperty) != nullptr; + } + bool HasAnimationOfProperties(const nsCSSProperty* aProperties, + size_t aPropertyCount) const; + const InfallibleTArray& Properties() const { + return mProperties; + } + InfallibleTArray& Properties() { + return mProperties; + } + + // Updates |aStyleRule| with the animation values produced by this + // Animation for the current time except any properties already contained + // in |aSetProperties|. + // Any updated properties are added to |aSetProperties|. + void ComposeStyle(nsRefPtr& aStyleRule, + nsCSSPropertySet& aSetProperties); + +protected: + virtual ~KeyframeEffectReadonly() { } + + nsCOMPtr mTarget; + Nullable mParentTime; + + AnimationTiming mTiming; + nsString mName; + // A flag to mark transitions that have finished and are due to + // be removed on the next throttle-able cycle. + bool mIsFinishedTransition; + nsCSSPseudoElements::Type mPseudoType; + + InfallibleTArray mProperties; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_KeyframeEffect_h diff --git a/dom/animation/PendingPlayerTracker.cpp b/dom/animation/PendingAnimationTracker.cpp similarity index 53% rename from dom/animation/PendingPlayerTracker.cpp rename to dom/animation/PendingAnimationTracker.cpp index 740cd71238..615c482146 100644 --- a/dom/animation/PendingPlayerTracker.cpp +++ b/dom/animation/PendingAnimationTracker.cpp @@ -3,9 +3,9 @@ * 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 "PendingPlayerTracker.h" +#include "PendingAnimationTracker.h" -#include "mozilla/dom/AnimationTimeline.h" +#include "mozilla/dom/DocumentTimeline.h" #include "nsIFrame.h" #include "nsIPresShell.h" @@ -13,19 +13,19 @@ using namespace mozilla; namespace mozilla { -NS_IMPL_CYCLE_COLLECTION(PendingPlayerTracker, +NS_IMPL_CYCLE_COLLECTION(PendingAnimationTracker, mPlayPendingSet, mPausePendingSet, mDocument) -NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PendingPlayerTracker, AddRef) -NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PendingPlayerTracker, Release) +NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PendingAnimationTracker, AddRef) +NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PendingAnimationTracker, Release) void -PendingPlayerTracker::AddPending(dom::AnimationPlayer& aPlayer, - AnimationPlayerSet& aSet) +PendingAnimationTracker::AddPending(dom::Animation& aAnimation, + AnimationSet& aSet) { - aSet.PutEntry(&aPlayer); + aSet.PutEntry(&aAnimation); // Schedule a paint. Otherwise animations that don't trigger a paint by // themselves (e.g. CSS animations with an empty keyframes rule) won't @@ -34,70 +34,70 @@ PendingPlayerTracker::AddPending(dom::AnimationPlayer& aPlayer, } void -PendingPlayerTracker::RemovePending(dom::AnimationPlayer& aPlayer, - AnimationPlayerSet& aSet) +PendingAnimationTracker::RemovePending(dom::Animation& aAnimation, + AnimationSet& aSet) { - aSet.RemoveEntry(&aPlayer); + aSet.RemoveEntry(&aAnimation); } bool -PendingPlayerTracker::IsWaiting(const dom::AnimationPlayer& aPlayer, - const AnimationPlayerSet& aSet) const +PendingAnimationTracker::IsWaiting(const dom::Animation& aAnimation, + const AnimationSet& aSet) const { - return aSet.Contains(const_cast(&aPlayer)); + return aSet.Contains(const_cast(&aAnimation)); } PLDHashOperator -TriggerPlayerAtTime(nsRefPtrHashKey* aKey, +TriggerAnimationAtTime(nsRefPtrHashKey* aKey, void* aReadyTime) { - dom::AnimationPlayer* player = aKey->GetKey(); - dom::AnimationTimeline* timeline = player->Timeline(); + dom::Animation* animation = aKey->GetKey(); + dom::DocumentTimeline* timeline = animation->Timeline(); // When the timeline's refresh driver is under test control, its values // have no correspondance to wallclock times so we shouldn't try to convert // aReadyTime (which is a wallclock time) to a timeline value. Instead, the - // animation player will be started/paused when the refresh driver is next - // advanced since this will trigger a call to TriggerPendingPlayersNow. + // animation will be started/paused when the refresh driver is next + // advanced since this will trigger a call to TriggerPendingAnimationsNow. if (timeline->IsUnderTestControl()) { return PL_DHASH_NEXT; } Nullable readyTime = timeline->ToTimelineTime(*static_cast(aReadyTime)); - player->TriggerOnNextTick(readyTime); + animation->TriggerOnNextTick(readyTime); return PL_DHASH_REMOVE; } void -PendingPlayerTracker::TriggerPendingPlayersOnNextTick(const TimeStamp& +PendingAnimationTracker::TriggerPendingAnimationsOnNextTick(const TimeStamp& aReadyTime) { - mPlayPendingSet.EnumerateEntries(TriggerPlayerAtTime, + mPlayPendingSet.EnumerateEntries(TriggerAnimationAtTime, const_cast(&aReadyTime)); - mPausePendingSet.EnumerateEntries(TriggerPlayerAtTime, + mPausePendingSet.EnumerateEntries(TriggerAnimationAtTime, const_cast(&aReadyTime)); } PLDHashOperator -TriggerPlayerNow(nsRefPtrHashKey* aKey, void*) +TriggerAnimationNow(nsRefPtrHashKey* aKey, void*) { aKey->GetKey()->TriggerNow(); return PL_DHASH_NEXT; } void -PendingPlayerTracker::TriggerPendingPlayersNow() +PendingAnimationTracker::TriggerPendingAnimationsNow() { - mPlayPendingSet.EnumerateEntries(TriggerPlayerNow, nullptr); + mPlayPendingSet.EnumerateEntries(TriggerAnimationNow, nullptr); mPlayPendingSet.Clear(); - mPausePendingSet.EnumerateEntries(TriggerPlayerNow, nullptr); + mPausePendingSet.EnumerateEntries(TriggerAnimationNow, nullptr); mPausePendingSet.Clear(); } void -PendingPlayerTracker::EnsurePaintIsScheduled() +PendingAnimationTracker::EnsurePaintIsScheduled() { if (!mDocument) { return; diff --git a/dom/animation/PendingAnimationTracker.h b/dom/animation/PendingAnimationTracker.h new file mode 100644 index 0000000000..2a6280e865 --- /dev/null +++ b/dom/animation/PendingAnimationTracker.h @@ -0,0 +1,83 @@ +/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_PendingAnimationTracker_h +#define mozilla_dom_PendingAnimationTracker_h + +#include "mozilla/dom/Animation.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIDocument.h" +#include "nsTHashtable.h" + +class nsIFrame; + +namespace mozilla { + +class PendingAnimationTracker final +{ +public: + explicit PendingAnimationTracker(nsIDocument* aDocument) + : mDocument(aDocument) + { } + + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PendingAnimationTracker) + NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(PendingAnimationTracker) + + void AddPlayPending(dom::Animation& aAnimation) + { + MOZ_ASSERT(!IsWaitingToPause(aAnimation), + "Animation is already waiting to pause"); + AddPending(aAnimation, mPlayPendingSet); + } + void RemovePlayPending(dom::Animation& aAnimation) + { + RemovePending(aAnimation, mPlayPendingSet); + } + bool IsWaitingToPlay(const dom::Animation& aAnimation) const + { + return IsWaiting(aAnimation, mPlayPendingSet); + } + + void AddPausePending(dom::Animation& aAnimation) + { + MOZ_ASSERT(!IsWaitingToPlay(aAnimation), + "Animation is already waiting to play"); + AddPending(aAnimation, mPausePendingSet); + } + void RemovePausePending(dom::Animation& aAnimation) + { + RemovePending(aAnimation, mPausePendingSet); + } + bool IsWaitingToPause(const dom::Animation& aAnimation) const + { + return IsWaiting(aAnimation, mPausePendingSet); + } + + void TriggerPendingAnimationsOnNextTick(const TimeStamp& aReadyTime); + void TriggerPendingAnimationsNow(); + bool HasPendingAnimations() const { + return mPlayPendingSet.Count() > 0 || mPausePendingSet.Count() > 0; + } + +private: + ~PendingAnimationTracker() { } + + void EnsurePaintIsScheduled(); + + typedef nsTHashtable> AnimationSet; + + void AddPending(dom::Animation& aAnimation, AnimationSet& aSet); + void RemovePending(dom::Animation& aAnimation, AnimationSet& aSet); + bool IsWaiting(const dom::Animation& aAnimation, + const AnimationSet& aSet) const; + + AnimationSet mPlayPendingSet; + AnimationSet mPausePendingSet; + nsCOMPtr mDocument; +}; + +} // namespace mozilla + +#endif // mozilla_dom_PendingAnimationTracker_h diff --git a/dom/animation/PendingPlayerTracker.h b/dom/animation/PendingPlayerTracker.h deleted file mode 100644 index 0ce979a1f2..0000000000 --- a/dom/animation/PendingPlayerTracker.h +++ /dev/null @@ -1,86 +0,0 @@ -/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_PendingPlayerTracker_h -#define mozilla_dom_PendingPlayerTracker_h - -#include "mozilla/dom/AnimationPlayer.h" -#include "nsCycleCollectionParticipant.h" -#include "nsIDocument.h" -#include "nsTHashtable.h" - -class nsIFrame; - -namespace mozilla { - -class PendingPlayerTracker final -{ -public: - explicit PendingPlayerTracker(nsIDocument* aDocument) - : mDocument(aDocument) - { } - - NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PendingPlayerTracker) - NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(PendingPlayerTracker) - - void AddPlayPending(dom::AnimationPlayer& aPlayer) - { - MOZ_ASSERT(!IsWaitingToPause(aPlayer), - "Player is already waiting to pause"); - AddPending(aPlayer, mPlayPendingSet); - } - void RemovePlayPending(dom::AnimationPlayer& aPlayer) - { - RemovePending(aPlayer, mPlayPendingSet); - } - bool IsWaitingToPlay(const dom::AnimationPlayer& aPlayer) const - { - return IsWaiting(aPlayer, mPlayPendingSet); - } - - void AddPausePending(dom::AnimationPlayer& aPlayer) - { - MOZ_ASSERT(!IsWaitingToPlay(aPlayer), - "Player is already waiting to play"); - AddPending(aPlayer, mPausePendingSet); - } - void RemovePausePending(dom::AnimationPlayer& aPlayer) - { - RemovePending(aPlayer, mPausePendingSet); - } - bool IsWaitingToPause(const dom::AnimationPlayer& aPlayer) const - { - return IsWaiting(aPlayer, mPausePendingSet); - } - - void TriggerPendingPlayersOnNextTick(const TimeStamp& aReadyTime); - void TriggerPendingPlayersNow(); - bool HasPendingPlayers() const { - return mPlayPendingSet.Count() > 0 || mPausePendingSet.Count() > 0; - } - -private: - ~PendingPlayerTracker() { } - - void EnsurePaintIsScheduled(); - - typedef nsTHashtable> - AnimationPlayerSet; - - void AddPending(dom::AnimationPlayer& aPlayer, - AnimationPlayerSet& aSet); - void RemovePending(dom::AnimationPlayer& aPlayer, - AnimationPlayerSet& aSet); - bool IsWaiting(const dom::AnimationPlayer& aPlayer, - const AnimationPlayerSet& aSet) const; - - AnimationPlayerSet mPlayPendingSet; - AnimationPlayerSet mPausePendingSet; - nsCOMPtr mDocument; -}; - -} // namespace mozilla - -#endif // mozilla_dom_PendingPlayerTracker_h diff --git a/dom/animation/moz.build b/dom/animation/moz.build index 4be377afb2..03725162c3 100644 --- a/dom/animation/moz.build +++ b/dom/animation/moz.build @@ -9,21 +9,24 @@ MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini'] EXPORTS.mozilla.dom += [ 'Animation.h', - 'AnimationEffect.h', - 'AnimationPlayer.h', + 'AnimationEffectReadonly.h', 'AnimationTimeline.h', + 'DocumentTimeline.h', + 'KeyframeEffect.h', ] EXPORTS.mozilla += [ - 'PendingPlayerTracker.h', + 'AnimationUtils.h', + 'PendingAnimationTracker.h', ] UNIFIED_SOURCES += [ 'Animation.cpp', - 'AnimationEffect.cpp', - 'AnimationPlayer.cpp', + 'AnimationEffectReadonly.cpp', 'AnimationTimeline.cpp', - 'PendingPlayerTracker.cpp', + 'DocumentTimeline.cpp', + 'KeyframeEffect.cpp', + 'PendingAnimationTracker.cpp', ] FAIL_ON_WARNINGS = True diff --git a/dom/animation/test/css-animations/test_animation-player-currenttime.html b/dom/animation/test/css-animations/test_animation-currenttime.html similarity index 95% rename from dom/animation/test/css-animations/test_animation-player-currenttime.html rename to dom/animation/test/css-animations/test_animation-currenttime.html index b5debd158f..7b9dddea92 100644 --- a/dom/animation/test/css-animations/test_animation-player-currenttime.html +++ b/dom/animation/test/css-animations/test_animation-currenttime.html @@ -193,11 +193,10 @@ function EventWatcher(watchedNode, eventTypes) // terms used in the Web Animations specification for specific phases of an // animation. The terms can be found here: // -// http://w3c.github.io/web-animations/#animation-node-phases-and-states +// https://w3c.github.io/web-animations/#animation-effect-phases-and-states // -// Note the distinction between "player start time" and "animation start time". -// The former is the start of the start delay. The latter is the start of the -// active interval. (If there is no delay, they are the same.) +// Note the distinction between the "animation start time" which occurs before +// the start delay and the start of the active interval which occurs after it. // Called when currentTime is set to zero (the beginning of the start delay). function checkStateOnSettingCurrentTimeToZero(animation) @@ -208,11 +207,11 @@ function checkStateOnSettingCurrentTimeToZero(animation) 'Animation.playState should be "running" at the start of ' + 'the start delay'); - assert_equals(animation.source.target.style.animationPlayState, 'running', - 'Animation.source.target.style.animationPlayState should be ' + + assert_equals(animation.effect.target.style.animationPlayState, 'running', + 'Animation.effect.target.style.animationPlayState should be ' + '"running" at the start of the start delay'); - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_equals(marginLeft, UNANIMATED_POSITION, 'the computed value of margin-left should be unaffected ' + @@ -233,11 +232,11 @@ function checkStateOnReadyPromiseResolved(animation) 'Animation.playState should be "running" on the first paint ' + 'tick after animation creation'); - assert_equals(animation.source.target.style.animationPlayState, 'running', - 'Animation.source.target.style.animationPlayState should be ' + + assert_equals(animation.effect.target.style.animationPlayState, 'running', + 'Animation.effect.target.style.animationPlayState should be ' + '"running" on the first paint tick after animation creation'); - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_equals(marginLeft, UNANIMATED_POSITION, 'the computed value of margin-left should be unaffected ' + @@ -253,11 +252,11 @@ function checkStateAtActiveIntervalStartTime(animation) 'Animation.playState should be "running" at the start of ' + 'the active interval'); - assert_equals(animation.source.target.style.animationPlayState, 'running', - 'Animation.source.target.style.animationPlayState should be ' + + assert_equals(animation.effect.target.style.animationPlayState, 'running', + 'Animation.effect.target.style.animationPlayState should be ' + '"running" at the start of the active interval'); - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION, 'the computed value of margin-left should be close to the value at the ' + @@ -268,7 +267,7 @@ function checkStateAtFiftyPctOfActiveInterval(animation) { // We don't test animation.currentTime since our caller just set it. - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_equals(marginLeft, FIFTY_PCT_POSITION, 'the computed value of margin-left should be half way through the ' + @@ -284,11 +283,11 @@ function checkStateAtActiveIntervalEndTime(animation) 'Animation.playState should be "finished" at the end of ' + 'the active interval'); - assert_equals(animation.source.target.style.animationPlayState, "running", - 'Animation.source.target.style.animationPlayState should be ' + + assert_equals(animation.effect.target.style.animationPlayState, "running", + 'Animation.effect.target.style.animationPlayState should be ' + '"finished" at the end of the active interval'); - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_equals(marginLeft, UNANIMATED_POSITION, 'the computed value of margin-left should be unaffected ' + @@ -314,8 +313,8 @@ test(function(t) 'Animation.playState should be "pending" when an animation ' + 'is initially created'); - assert_equals(animation.source.target.style.animationPlayState, 'running', - 'Animation.source.target.style.animationPlayState should be ' + + assert_equals(animation.effect.target.style.animationPlayState, 'running', + 'Animation.effect.target.style.animationPlayState should be ' + '"running" when an animation is initially created'); // XXX Ideally we would have a test to check the ready Promise is initially diff --git a/dom/animation/test/css-animations/test_animation-player-finished.html b/dom/animation/test/css-animations/test_animation-finished.html similarity index 100% rename from dom/animation/test/css-animations/test_animation-player-finished.html rename to dom/animation/test/css-animations/test_animation-finished.html diff --git a/dom/animation/test/css-animations/test_animation-player-playstate.html b/dom/animation/test/css-animations/test_animation-playstate.html similarity index 100% rename from dom/animation/test/css-animations/test_animation-player-playstate.html rename to dom/animation/test/css-animations/test_animation-playstate.html diff --git a/dom/animation/test/css-animations/test_animation-player-ready.html b/dom/animation/test/css-animations/test_animation-ready.html similarity index 100% rename from dom/animation/test/css-animations/test_animation-player-ready.html rename to dom/animation/test/css-animations/test_animation-ready.html diff --git a/dom/animation/test/css-animations/test_animation-player-starttime.html b/dom/animation/test/css-animations/test_animation-starttime.html similarity index 96% rename from dom/animation/test/css-animations/test_animation-player-starttime.html rename to dom/animation/test/css-animations/test_animation-starttime.html index 54d9ce6b4b..db2432abd6 100644 --- a/dom/animation/test/css-animations/test_animation-player-starttime.html +++ b/dom/animation/test/css-animations/test_animation-starttime.html @@ -193,11 +193,10 @@ function EventWatcher(watchedNode, eventTypes) // terms used in the Web Animations specification for specific phases of an // animation. The terms can be found here: // -// http://w3c.github.io/web-animations/#animation-node-phases-and-states +// https://w3c.github.io/web-animations/#animation-effect-phases-and-states // -// Note the distinction between "player start time" and "animation start time". -// The former is the start of the start delay. The latter is the start of the -// active interval. (If there is no delay, they are the same.) +// Note the distinction between the "animation start time" which occurs before +// the start delay and the start of the active interval which occurs after it. // Called when the ready Promise's callbacks should happen function checkStateOnReadyPromiseResolved(animation) @@ -210,11 +209,11 @@ function checkStateOnReadyPromiseResolved(animation) 'Animation.playState should be "running" on the first paint ' + 'tick after animation creation'); - assert_equals(animation.source.target.style.animationPlayState, 'running', - 'Animation.source.target.style.animationPlayState should be ' + + assert_equals(animation.effect.target.style.animationPlayState, 'running', + 'Animation.effect.target.style.animationPlayState should be ' + '"running" on the first paint tick after animation creation'); - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_equals(marginLeft, UNANIMATED_POSITION, 'the computed value of margin-left should be unaffected ' + @@ -230,11 +229,11 @@ function checkStateAtActiveIntervalStartTime(animation) 'Animation.playState should be "running" at the start of ' + 'the active interval'); - assert_equals(animation.source.target.style.animationPlayState, 'running', - 'Animation.source.target.style.animationPlayState should be ' + + assert_equals(animation.effect.target.style.animationPlayState, 'running', + 'Animation.effect.target.style.animationPlayState should be ' + '"running" at the start of the active interval'); - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION, 'the computed value of margin-left should be close to the value at the ' + @@ -245,7 +244,7 @@ function checkStateAtFiftyPctOfActiveInterval(animation) { // We don't test animation.startTime since our caller just set it. - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_equals(marginLeft, FIFTY_PCT_POSITION, 'the computed value of margin-left should be half way through the ' + @@ -261,11 +260,11 @@ function checkStateAtActiveIntervalEndTime(animation) 'Animation.playState should be "finished" at the end of ' + 'the active interval'); - assert_equals(animation.source.target.style.animationPlayState, "running", - 'Animation.source.target.style.animationPlayState should be ' + + assert_equals(animation.effect.target.style.animationPlayState, "running", + 'Animation.effect.target.style.animationPlayState should be ' + '"finished" at the end of the active interval'); - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_equals(marginLeft, UNANIMATED_POSITION, 'the computed value of margin-left should be unaffected ' + diff --git a/dom/animation/test/css-animations/test_animation-effect-name.html b/dom/animation/test/css-animations/test_effect-name.html similarity index 75% rename from dom/animation/test/css-animations/test_animation-effect-name.html rename to dom/animation/test/css-animations/test_effect-name.html index 7d8eb4a303..634f11531a 100644 --- a/dom/animation/test/css-animations/test_animation-effect-name.html +++ b/dom/animation/test/css-animations/test_effect-name.html @@ -15,22 +15,22 @@ test(function(t) { var div = addDiv(t); div.style.animation = 'xyz 100s'; - assert_equals(div.getAnimations()[0].source.effect.name, 'xyz', + assert_equals(div.getAnimations()[0].effect.name, 'xyz', 'Animation effect name matches keyframes rule name'); }, 'Effect name makes keyframe rule'); test(function(t) { var div = addDiv(t); div.style.animation = 'x\\yz 100s'; - assert_equals(div.getAnimations()[0].source.effect.name, 'xyz', + assert_equals(div.getAnimations()[0].effect.name, 'xyz', 'Escaped animation effect name matches keyframes rule name'); }, 'Escaped animation name'); test(function(t) { var div = addDiv(t); div.style.animation = 'x\\79 z 100s'; - assert_equals(div.getAnimations()[0].source.effect.name, 'xyz', - 'Hex-escaped animation effect name matches keyframes rule' + assert_equals(div.getAnimations()[0].effect.name, 'xyz', + 'Hex-escaped animation name matches keyframes rule' + ' name'); }, 'Animation name with hex-escape'); diff --git a/dom/animation/test/css-animations/test_animation-target.html b/dom/animation/test/css-animations/test_effect-target.html similarity index 91% rename from dom/animation/test/css-animations/test_animation-target.html rename to dom/animation/test/css-animations/test_effect-target.html index 5d6f71e6ab..c812213f71 100644 --- a/dom/animation/test/css-animations/test_animation-target.html +++ b/dom/animation/test/css-animations/test_effect-target.html @@ -14,7 +14,7 @@ test(function(t) { var div = addDiv(t); div.style.animation = 'anim 100s'; var animation = div.getAnimations()[0]; - assert_equals(animation.source.target, div, + assert_equals(animation.effect.target, div, 'Animation.target is the animatable div'); }, 'Returned CSS animations have the correct Animation.target'); diff --git a/dom/animation/test/css-animations/test_element-get-animation-players.html b/dom/animation/test/css-animations/test_element-get-animations.html similarity index 99% rename from dom/animation/test/css-animations/test_element-get-animation-players.html rename to dom/animation/test/css-animations/test_element-get-animations.html index f207cc68f2..5ecf4f51b9 100644 --- a/dom/animation/test/css-animations/test_element-get-animation-players.html +++ b/dom/animation/test/css-animations/test_element-get-animations.html @@ -243,7 +243,7 @@ test(function(t) { // Update duration (an Animation change) div.style.animationDuration = '200s'; var extendedAnimation = div.getAnimations()[0]; - // FIXME: Check extendedAnimation.source.timing.duration has changed once the + // FIXME: Check extendedAnimation.effect.timing.duration has changed once the // API is available assert_equals(originalAnimation, extendedAnimation, 'getAnimations returns the same objects even when their' diff --git a/dom/animation/test/css-transitions/test_animation-player-currenttime.html b/dom/animation/test/css-transitions/test_animation-currenttime.html similarity index 97% rename from dom/animation/test/css-transitions/test_animation-player-currenttime.html rename to dom/animation/test/css-transitions/test_animation-currenttime.html index 62fb7858a3..e0a106a816 100644 --- a/dom/animation/test/css-transitions/test_animation-player-currenttime.html +++ b/dom/animation/test/css-transitions/test_animation-currenttime.html @@ -194,11 +194,11 @@ function checkStateOnSettingCurrentTimeToZero(animation) 'Animation.playState should be "running" at the start of ' + 'the start delay'); - assert_equals(animation.source.target.style.animationPlayState, 'running', - 'Animation.source.target.style.animationPlayState should be ' + + assert_equals(animation.effect.target.style.animationPlayState, 'running', + 'Animation.effect.target.style.animationPlayState should be ' + '"running" at the start of the start delay'); - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_equals(marginLeft, UNANIMATED_POSITION, 'the computed value of margin-left should be unaffected ' + @@ -219,7 +219,7 @@ function checkStateOnReadyPromiseResolved(animation) 'Animation.playState should be "running" on the first paint ' + 'tick after animation creation'); - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_equals(marginLeft, INITIAL_POSITION, 'the computed value of margin-left should be unaffected ' + @@ -235,7 +235,7 @@ function checkStateAtActiveIntervalStartTime(animation) 'Animation.playState should be "running" at the start of ' + 'the active interval'); - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION, 'the computed value of margin-left should be close to the value at the ' + @@ -246,7 +246,7 @@ function checkStateAtFiftyPctOfActiveInterval(animation) { // We don't test animation.currentTime since our caller just set it. - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_equals(marginLeft, FIFTY_PCT_POSITION, 'the computed value of margin-left should be half way through the ' + @@ -262,7 +262,7 @@ function checkStateAtActiveIntervalEndTime(animation) 'Animation.playState should be "finished" at the end of ' + 'the active interval'); - var div = animation.source.target; + var div = animation.effect.target; var marginLeft = parseFloat(getComputedStyle(div).marginLeft); assert_equals(marginLeft, END_POSITION, 'the computed value of margin-left should be the final transitioned-to ' + diff --git a/dom/animation/test/css-transitions/test_animation-player-ready.html b/dom/animation/test/css-transitions/test_animation-player-ready.html index 9707a97b30..2385531b97 100644 --- a/dom/animation/test/css-transitions/test_animation-player-ready.html +++ b/dom/animation/test/css-transitions/test_animation-player-ready.html @@ -1,96 +1,663 @@ - - - - -
- + + + + +
+ + + -}, 'ready promise is rejected when a transition is cancelled by updating' - + ' transition-property'); - -async_test(function(t) { - var div = addDiv(t); - - // Set up pending transition - div.style.marginLeft = '0px'; - window.getComputedStyle(div).marginLeft; - div.style.transition = 'margin-left 100s'; - div.style.marginLeft = '100px'; - window.getComputedStyle(div).marginLeft; - - var animation = div.getAnimations()[0]; - assert_equals(animation.playState, 'pending', 'Animation is initially pending'); - - // Set up listeners on ready promise - animation.ready.then(t.step_func(function() { - assert_unreached('ready promise was fulfilled'); - })).catch(t.step_func(function(err) { - assert_equals(err.name, 'AbortError', - 'ready promise is rejected with AbortError'); - assert_equals(animation.playState, 'idle', - 'Animation is idle after transition was cancelled'); - })).then(t.step_func(function() { - t.done(); - })); - - // Now update the transition to animate to something not-interpolable - div.style.marginLeft = 'auto'; - window.getComputedStyle(div).marginLeft; - -}, 'ready promise is rejected when a transition is cancelled by changing' - + ' the transition property to something not interpolable'); - - diff --git a/dom/animation/test/css-transitions/test_animation-ready.html b/dom/animation/test/css-transitions/test_animation-ready.html new file mode 100644 index 0000000000..9707a97b30 --- /dev/null +++ b/dom/animation/test/css-transitions/test_animation-ready.html @@ -0,0 +1,96 @@ + + + + + +
+ diff --git a/dom/animation/test/css-transitions/test_animation-starttime.html b/dom/animation/test/css-transitions/test_animation-starttime.html new file mode 100644 index 0000000000..154b30aef7 --- /dev/null +++ b/dom/animation/test/css-transitions/test_animation-starttime.html @@ -0,0 +1,403 @@ + + + + + Tests for the effect of setting a CSS transition's + Animation.startTime + + + + + + +
+ + + diff --git a/dom/animation/test/css-transitions/test_animation-effect-name.html b/dom/animation/test/css-transitions/test_effect-name.html similarity index 89% rename from dom/animation/test/css-transitions/test_animation-effect-name.html rename to dom/animation/test/css-transitions/test_effect-name.html index b764723cfc..19012b88d0 100644 --- a/dom/animation/test/css-transitions/test_animation-effect-name.html +++ b/dom/animation/test/css-transitions/test_effect-name.html @@ -16,7 +16,7 @@ test(function(t) { div.style.transition = 'all 100s'; div.style.left = '100px'; - assert_equals(div.getAnimations()[0].source.effect.name, 'left', + assert_equals(div.getAnimations()[0].effect.name, 'left', 'The name for the transitions corresponds to the property ' + 'being transitioned'); }, 'Effect name for transitions'); diff --git a/dom/animation/test/css-transitions/test_animation-target.html b/dom/animation/test/css-transitions/test_effect-target.html similarity index 92% rename from dom/animation/test/css-transitions/test_animation-target.html rename to dom/animation/test/css-transitions/test_effect-target.html index c63b9a5718..2f0c723d9d 100644 --- a/dom/animation/test/css-transitions/test_animation-target.html +++ b/dom/animation/test/css-transitions/test_effect-target.html @@ -16,7 +16,7 @@ test(function(t) { div.style.left = '100px'; var animation = div.getAnimations()[0]; - assert_equals(animation.source.target, div, + assert_equals(animation.effect.target, div, 'Animation.target is the animatable div'); }, 'Returned CSS transitions have the correct Animation.target'); diff --git a/dom/animation/test/css-transitions/test_element-get-animation-players.html b/dom/animation/test/css-transitions/test_element-get-animations.html similarity index 100% rename from dom/animation/test/css-transitions/test_element-get-animation-players.html rename to dom/animation/test/css-transitions/test_element-get-animations.html diff --git a/dom/animation/test/animation-timeline/test_animation-timeline.html b/dom/animation/test/document-timeline/test_document-timeline.html similarity index 98% rename from dom/animation/test/animation-timeline/test_animation-timeline.html rename to dom/animation/test/document-timeline/test_document-timeline.html index 4740836e72..4d656135fd 100644 --- a/dom/animation/test/animation-timeline/test_animation-timeline.html +++ b/dom/animation/test/document-timeline/test_document-timeline.html @@ -1,6 +1,6 @@ -Web Animations API: AnimationTimeline tests +Web Animations API: DocumentTimeline tests
diff --git a/dom/animation/test/animation-timeline/test_request_animation_frame.html b/dom/animation/test/document-timeline/test_request_animation_frame.html similarity index 100% rename from dom/animation/test/animation-timeline/test_request_animation_frame.html rename to dom/animation/test/document-timeline/test_request_animation_frame.html diff --git a/dom/animation/test/mochitest.ini b/dom/animation/test/mochitest.ini index 43a7a3e174..74a40b097d 100644 --- a/dom/animation/test/mochitest.ini +++ b/dom/animation/test/mochitest.ini @@ -2,26 +2,27 @@ support-files = testcommon.js -[animation-timeline/test_animation-timeline.html] -[animation-timeline/test_request_animation_frame.html] -skip-if = buildapp == 'mulet' [css-animations/test_animations-dynamic-changes.html] -[css-animations/test_animation-effect-name.html] [css-animations/test_animation-pausing.html] -[css-animations/test_animation-player-currenttime.html] -[css-animations/test_animation-player-finished.html] -[css-animations/test_animation-player-playstate.html] -[css-animations/test_animation-player-ready.html] -[css-animations/test_animation-player-starttime.html] -[css-animations/test_animation-target.html] -[css-animations/test_element-get-animation-players.html] +[css-animations/test_animation-currenttime.html] +[css-animations/test_animation-finished.html] +[css-animations/test_animation-playstate.html] +[css-animations/test_animation-ready.html] +[css-animations/test_animation-starttime.html] +[css-animations/test_effect-name.html] +[css-animations/test_effect-target.html] +[css-animations/test_element-get-animations.html] skip-if = buildapp == 'mulet' -[css-transitions/test_animation-effect-name.html] [css-transitions/test_animation-pausing.html] -[css-transitions/test_animation-player-currenttime.html] -[css-transitions/test_animation-player-ready.html] -[css-transitions/test_animation-target.html] -[css-transitions/test_element-get-animation-players.html] +[css-transitions/test_animation-currenttime.html] +[css-transitions/test_animation-ready.html] +[css-transitions/test_animation-starttime.html] +[css-transitions/test_effect-name.html] +[css-transitions/test_effect-target.html] +[css-transitions/test_element-get-animations.html] +skip-if = buildapp == 'mulet' +[document-timeline/test_document-timeline.html] +[document-timeline/test_request_animation_frame.html] skip-if = buildapp == 'mulet' [mozilla/test_deferred_start.html] skip-if = buildapp == 'mulet' || buildapp == 'b2g' # bug 1113425, 1119981 diff --git a/dom/animation/test/testcommon.js b/dom/animation/test/testcommon.js index fca90ca56e..7aed100989 100644 --- a/dom/animation/test/testcommon.js +++ b/dom/animation/test/testcommon.js @@ -36,3 +36,14 @@ function waitForAllAnimations(animations) { return animation.ready; })); } + +/** + * Flush the computed style for the given element. This is useful, for example, + * when we are testing a transition and need the initial value of a property + * to be computed so that when we synchronouslyet set it to a different value + * we actually get a transition instead of that being the initial value. + */ +function flushComputedStyle(elem) { + var cs = window.getComputedStyle(elem); + cs.marginLeft; +} diff --git a/dom/archivereader/ArchiveReader.cpp b/dom/archivereader/ArchiveReader.cpp index be02239561..ff6851ea30 100644 --- a/dom/archivereader/ArchiveReader.cpp +++ b/dom/archivereader/ArchiveReader.cpp @@ -105,7 +105,7 @@ ArchiveReader::GetSize(uint64_t* aSize) { ErrorResult rv; *aSize = mFileImpl->GetSize(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } // Here we open the archive: diff --git a/dom/archivereader/ArchiveZipFile.cpp b/dom/archivereader/ArchiveZipFile.cpp index d326a36511..ac8f1e942e 100644 --- a/dom/archivereader/ArchiveZipFile.cpp +++ b/dom/archivereader/ArchiveZipFile.cpp @@ -367,7 +367,7 @@ ArchiveZipFileImpl::GetInternalStream(nsIInputStream** aStream) ErrorResult rv; uint64_t size = mFileImpl->GetSize(rv); if (NS_WARN_IF(rv.Failed())) { - return rv.ErrorCode(); + return rv.StealNSResult(); } nsCOMPtr inputStream; diff --git a/dom/base/Attr.cpp b/dom/base/Attr.cpp index c1bc066f83..3f3e020f87 100644 --- a/dom/base/Attr.cpp +++ b/dom/base/Attr.cpp @@ -215,7 +215,7 @@ Attr::SetValue(const nsAString& aValue) { ErrorResult rv; SetValue(aValue, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } bool diff --git a/dom/base/DOMCursor.cpp b/dom/base/DOMCursor.cpp index cbe1b26824..ba9cb9f9b3 100644 --- a/dom/base/DOMCursor.cpp +++ b/dom/base/DOMCursor.cpp @@ -57,7 +57,7 @@ DOMCursor::Continue() { ErrorResult rv; Continue(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void diff --git a/dom/base/DOMException.cpp b/dom/base/DOMException.cpp index e90ad22139..b53e2705b2 100644 --- a/dom/base/DOMException.cpp +++ b/dom/base/DOMException.cpp @@ -682,31 +682,5 @@ DOMException::Create(nsresult aRv) return inst.forget(); } -bool -DOMException::Sanitize(JSContext* aCx, - JS::MutableHandle aSanitizedValue) -{ - nsRefPtr retval = this; - if (mLocation && !mLocation->CallerSubsumes(aCx)) { - nsString message; - GetMessageMoz(message); - nsString name; - GetName(name); - retval = new dom::DOMException(nsresult(Result()), - NS_ConvertUTF16toUTF8(message), - NS_ConvertUTF16toUTF8(name), - Code()); - // Now it's possible that the stack on retval still starts with - // stuff aCx is not supposed to touch; it depends on what's on the - // stack right this second. Walk past all of that. - nsCOMPtr stack; - nsresult rv = retval->mLocation->GetSanitized(aCx, getter_AddRefs(stack)); - NS_ENSURE_SUCCESS(rv, false); - retval->mLocation.swap(stack); - } - - return ToJSValue(aCx, retval, aSanitizedValue); -} - } // namespace dom } // namespace mozilla diff --git a/dom/base/DOMException.h b/dom/base/DOMException.h index e03dd03b03..15f4e70d54 100644 --- a/dom/base/DOMException.h +++ b/dom/base/DOMException.h @@ -153,15 +153,6 @@ public: static already_AddRefed Create(nsresult aRv); - // Sanitize() is a workaround for the fact that DOMExceptions can leak stack - // information for the first stackframe to callers that should not have access - // to it. To prevent this, we check whether aCx subsumes our first stackframe - // and if not hand out a JS::Value for a clone of ourselves. Otherwise we - // hand out a JS::Value for ourselves. - // - // If the return value is false, an exception was thrown on aCx. - bool Sanitize(JSContext* aCx, JS::MutableHandle aSanitizedValue); - protected: virtual ~DOMException() {} diff --git a/dom/base/DOMImplementation.cpp b/dom/base/DOMImplementation.cpp index c637fc29db..bf14981ac5 100644 --- a/dom/base/DOMImplementation.cpp +++ b/dom/base/DOMImplementation.cpp @@ -90,7 +90,7 @@ DOMImplementation::CreateDocumentType(const nsAString& aQualifiedName, ErrorResult rv; *aReturn = CreateDocumentType(aQualifiedName, aPublicId, aSystemId, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsresult diff --git a/dom/base/DocumentType.cpp b/dom/base/DocumentType.cpp index a170bf2666..893af6cb93 100644 --- a/dom/base/DocumentType.cpp +++ b/dom/base/DocumentType.cpp @@ -29,7 +29,7 @@ NS_NewDOMDocumentType(nsIDOMDocumentType** aDocType, mozilla::ErrorResult rv; *aDocType = NS_NewDOMDocumentType(aNodeInfoManager, aName, aPublicId, aSystemId, aInternalSubset, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 47cfaff1a1..f3890488b7 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -14,7 +14,7 @@ #include "AnimationCommon.h" #include "mozilla/DebugOnly.h" -#include "mozilla/dom/AnimationPlayer.h" +#include "mozilla/dom/Animation.h" #include "mozilla/dom/Attr.h" #include "nsDOMAttributeMap.h" #include "nsIAtom.h" @@ -1371,7 +1371,7 @@ Element::GetElementsByTagNameNS(const nsAString& namespaceURI, nsCOMPtr list = GetElementsByTagNameNS(namespaceURI, localName, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } list.forget(aResult); return NS_OK; @@ -3103,7 +3103,7 @@ Element::SetTokenList(nsIAtom* aAtom, nsIVariant* aValue) aValue->GetAsAString(string); ErrorResult rv; itemType->SetValue(string, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } Element* @@ -3280,7 +3280,7 @@ Element::MozRequestPointerLock() } void -Element::GetAnimations(nsTArray >& aAnimations) +Element::GetAnimations(nsTArray>& aAnimations) { nsIDocument* doc = GetComposedDoc(); if (doc) { @@ -3291,18 +3291,18 @@ Element::GetAnimations(nsTArray >& aAnimations) nsGkAtoms::animationsProperty }; for (size_t propIdx = 0; propIdx < MOZ_ARRAY_LENGTH(properties); propIdx++) { - AnimationPlayerCollection* collection = - static_cast( + AnimationCollection* collection = + static_cast( GetProperty(properties[propIdx])); if (!collection) { continue; } - for (size_t playerIdx = 0; - playerIdx < collection->mPlayers.Length(); - playerIdx++) { - AnimationPlayer* player = collection->mPlayers[playerIdx]; - if (player->IsRelevant()) { - aAnimations.AppendElement(player); + for (size_t animIdx = 0; + animIdx < collection->mAnimations.Length(); + animIdx++) { + Animation* anim = collection->mAnimations[animIdx]; + if (anim->IsRelevant()) { + aAnimations.AppendElement(anim); } } } diff --git a/dom/base/Element.h b/dom/base/Element.h index a19e79b536..7ea02643c5 100644 --- a/dom/base/Element.h +++ b/dom/base/Element.h @@ -116,7 +116,7 @@ class EventStateManager; namespace dom { -class AnimationPlayer; +class Animation; class Link; class UndoManager; class DOMRect; @@ -847,7 +847,7 @@ public: { } - void GetAnimations(nsTArray >& aAnimations); + void GetAnimations(nsTArray>& aAnimations); NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML); virtual void SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError); @@ -1566,7 +1566,7 @@ NS_IMETHOD SetAttribute(const nsAString& name, \ { \ mozilla::ErrorResult rv; \ Element::SetAttribute(name, value, rv); \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD SetAttributeNS(const nsAString& namespaceURI, \ const nsAString& qualifiedName, \ @@ -1574,21 +1574,21 @@ NS_IMETHOD SetAttributeNS(const nsAString& namespaceURI, \ { \ mozilla::ErrorResult rv; \ Element::SetAttributeNS(namespaceURI, qualifiedName, value, rv); \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } \ using Element::RemoveAttribute; \ NS_IMETHOD RemoveAttribute(const nsAString& name) final override \ { \ mozilla::ErrorResult rv; \ RemoveAttribute(name, rv); \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD RemoveAttributeNS(const nsAString& namespaceURI, \ const nsAString& localName) final override \ { \ mozilla::ErrorResult rv; \ Element::RemoveAttributeNS(namespaceURI, localName, rv); \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } \ using Element::HasAttribute; \ NS_IMETHOD HasAttribute(const nsAString& name, \ @@ -1624,7 +1624,7 @@ NS_IMETHOD SetAttributeNode(nsIDOMAttr* newAttr, \ mozilla::ErrorResult rv; \ mozilla::dom::Attr* attr = static_cast(newAttr); \ *_retval = Element::SetAttributeNode(*attr, rv).take(); \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD RemoveAttributeNode(nsIDOMAttr* oldAttr, \ nsIDOMAttr** _retval) final override \ @@ -1635,7 +1635,7 @@ NS_IMETHOD RemoveAttributeNode(nsIDOMAttr* oldAttr, \ mozilla::ErrorResult rv; \ mozilla::dom::Attr* attr = static_cast(oldAttr); \ *_retval = Element::RemoveAttributeNode(*attr, rv).take(); \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD GetAttributeNodeNS(const nsAString& namespaceURI, \ const nsAString& localName, \ @@ -1651,7 +1651,7 @@ NS_IMETHOD SetAttributeNodeNS(nsIDOMAttr* newAttr, \ mozilla::ErrorResult rv; \ mozilla::dom::Attr* attr = static_cast(newAttr); \ *_retval = Element::SetAttributeNodeNS(*attr, rv).take(); \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD GetElementsByTagName(const nsAString& name, \ nsIDOMHTMLCollection** _retval) final \ @@ -1804,7 +1804,7 @@ NS_IMETHOD MozMatchesSelector(const nsAString& selector, \ { \ mozilla::ErrorResult rv; \ *_retval = Element::MozMatchesSelector(selector, rv); \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD SetCapture(bool retargetToElement) final override \ { \ @@ -1820,7 +1820,7 @@ NS_IMETHOD MozRequestFullScreen(void) final override \ { \ mozilla::ErrorResult rv; \ Element::MozRequestFullScreen(nullptr, JS::UndefinedHandleValue, rv); \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD MozRequestPointerLock(void) final override \ { \ diff --git a/dom/base/File.cpp b/dom/base/File.cpp index 887546d2d1..53a25249ed 100644 --- a/dom/base/File.cpp +++ b/dom/base/File.cpp @@ -347,7 +347,7 @@ File::GetLastModifiedDate(JSContext* aCx, ErrorResult rv; Date value = GetLastModifiedDate(rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } if (!value.ToDateObject(aCx, aDate)) { @@ -379,7 +379,7 @@ File::GetMozFullPath(nsAString& aFileName) { ErrorResult rv; GetMozFullPath(aFileName, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -393,7 +393,7 @@ File::GetMozFullPathInternal(nsAString& aFileName) { ErrorResult rv; mImpl->GetMozFullPathInternal(aFileName, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP @@ -403,7 +403,7 @@ File::GetSize(uint64_t* aSize) ErrorResult rv; *aSize = GetSize(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } uint64_t @@ -426,7 +426,7 @@ File::GetMozLastModifiedDate(uint64_t* aDate) ErrorResult rv; *aDate = GetLastModified(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } // Makes sure that aStart and aEnd is less then or equal to aSize and greater @@ -484,7 +484,7 @@ File::Slice(int64_t aStart, int64_t aEnd, ErrorResult rv; nsRefPtr file = Slice(start, end, aContentType, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } file.forget(aBlob); @@ -903,7 +903,7 @@ FileImplBase::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength, ErrorResult error; *aContentLength = GetSize(error); if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); + return error.StealNSResult(); } nsAutoString contentType; @@ -939,7 +939,7 @@ FileImplBase::SetMutable(bool aMutable) ErrorResult error; GetSize(error); if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); + return error.StealNSResult(); } } diff --git a/dom/base/MultipartFileImpl.cpp b/dom/base/MultipartFileImpl.cpp index 0f5ed745ba..861a14fe06 100644 --- a/dom/base/MultipartFileImpl.cpp +++ b/dom/base/MultipartFileImpl.cpp @@ -46,7 +46,8 @@ MultipartFileImpl::GetInternalStream(nsIInputStream** aStream) NS_ENSURE_SUCCESS(rv, rv); } - return CallQueryInterface(stream, aStream); + stream.forget(aStream); + return NS_OK; } already_AddRefed diff --git a/dom/base/NodeIterator.h b/dom/base/NodeIterator.h index a3313df74e..e7c7659873 100644 --- a/dom/base/NodeIterator.h +++ b/dom/base/NodeIterator.h @@ -100,7 +100,7 @@ private: mozilla::ErrorResult rv; nsCOMPtr node = (this->*aGetter)(rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } *aRetval = node ? node.forget().take()->AsDOMNode() : nullptr; return NS_OK; diff --git a/dom/base/ScriptSettings.cpp b/dom/base/ScriptSettings.cpp index 146ae4edf1..4518a2b16f 100644 --- a/dom/base/ScriptSettings.cpp +++ b/dom/base/ScriptSettings.cpp @@ -566,6 +566,7 @@ AutoJSAPI::StealException(JS::MutableHandle aVal) } AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject, + const char *aReason, bool aIsMainThread, JSContext* aCx) : AutoJSAPI(aGlobalObject, aIsMainThread, @@ -586,7 +587,7 @@ AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject, } if (mDocShellForJSRunToCompletion) { - mDocShellForJSRunToCompletion->NotifyJSRunToCompletionStart(); + mDocShellForJSRunToCompletion->NotifyJSRunToCompletionStart(aReason); } } diff --git a/dom/base/ScriptSettings.h b/dom/base/ScriptSettings.h index 3ca52690e9..8b304af68b 100644 --- a/dom/base/ScriptSettings.h +++ b/dom/base/ScriptSettings.h @@ -331,11 +331,16 @@ private: /* * A class that represents a new script entry point. + * + * |aReason| should be a statically-allocated C string naming the reason we're + * invoking JavaScript code: "setTimeout", "event", and so on. The devtools use + * these strings to label JS execution in timeline and profiling displays. */ class MOZ_STACK_CLASS AutoEntryScript : public AutoJSAPI, protected ScriptSettingsStackEntry { public: - explicit AutoEntryScript(nsIGlobalObject* aGlobalObject, + AutoEntryScript(nsIGlobalObject* aGlobalObject, + const char *aReason, bool aIsMainThread = NS_IsMainThread(), // Note: aCx is mandatory off-main-thread. JSContext* aCx = nullptr); diff --git a/dom/base/TreeWalker.cpp b/dom/base/TreeWalker.cpp index f62bc80d63..f61a05ead0 100644 --- a/dom/base/TreeWalker.cpp +++ b/dom/base/TreeWalker.cpp @@ -106,7 +106,7 @@ NS_IMETHODIMP TreeWalker::SetCurrentNode(nsIDOMNode * aCurrentNode) ErrorResult rv; SetCurrentNode(*node, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void diff --git a/dom/base/TreeWalker.h b/dom/base/TreeWalker.h index bbac7fd67f..9a7477579e 100644 --- a/dom/base/TreeWalker.h +++ b/dom/base/TreeWalker.h @@ -97,7 +97,7 @@ private: mozilla::ErrorResult rv; nsCOMPtr node = (this->*aGetter)(rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } *aRetval = node ? node.forget().take()->AsDOMNode() : nullptr; return NS_OK; diff --git a/dom/base/nsContentPermissionHelper.cpp b/dom/base/nsContentPermissionHelper.cpp index 48f5148f64..83e77b5ffd 100644 --- a/dom/base/nsContentPermissionHelper.cpp +++ b/dom/base/nsContentPermissionHelper.cpp @@ -234,7 +234,7 @@ ContentPermissionType::GetOptions(nsIArray** aOptions) NS_ENSURE_SUCCESS(rv, rv); } - NS_ADDREF(*aOptions = options); + options.forget(aOptions); return NS_OK; } diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index bb26fb3390..3621f74b00 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -3787,7 +3787,7 @@ nsContentUtils::ConvertStringFromEncoding(const nsACString& aEncoding, decoder->Decode(aInput.BeginReading(), aInput.Length(), false, aOutput, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } /* static */ @@ -4124,7 +4124,7 @@ nsContentUtils::CreateContextualFragment(nsINode* aContextNode, ErrorResult rv; *aReturn = CreateContextualFragment(aContextNode, aFragment, aPreventScriptExecution, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -6482,7 +6482,7 @@ nsContentUtils::FindInternalContentViewer(const nsACString& aType, nsCOMPtr docFactory; nsXPIDLCString contractID; - nsresult rv = catMan->GetCategoryEntry("Goanna-Content-Viewers", + nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", PromiseFlatCString(aType).get(), getter_Copies(contractID)); if (NS_SUCCEEDED(rv)) { diff --git a/dom/base/nsDOMAttributeMap.cpp b/dom/base/nsDOMAttributeMap.cpp index 96e8b4195c..5fc015e85b 100644 --- a/dom/base/nsDOMAttributeMap.cpp +++ b/dom/base/nsDOMAttributeMap.cpp @@ -267,7 +267,7 @@ nsDOMAttributeMap::SetNamedItem(nsIDOMAttr* aAttr, nsIDOMAttr** aReturn) ErrorResult rv; *aReturn = SetNamedItem(*attribute, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP @@ -278,7 +278,7 @@ nsDOMAttributeMap::SetNamedItemNS(nsIDOMAttr* aAttr, nsIDOMAttr** aReturn) ErrorResult rv; *aReturn = SetNamedItemNS(*attribute, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -396,7 +396,7 @@ nsDOMAttributeMap::RemoveNamedItem(const nsAString& aName, ErrorResult rv; *aReturn = RemoveNamedItem(aName, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -534,7 +534,7 @@ nsDOMAttributeMap::RemoveNamedItemNS(const nsAString& aNamespaceURI, NS_ENSURE_ARG_POINTER(aReturn); ErrorResult rv; *aReturn = RemoveNamedItemNS(aNamespaceURI, aLocalName, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed diff --git a/dom/base/nsDOMFileReader.cpp b/dom/base/nsDOMFileReader.cpp index 6dda3a1edc..7679338813 100644 --- a/dom/base/nsDOMFileReader.cpp +++ b/dom/base/nsDOMFileReader.cpp @@ -188,7 +188,7 @@ nsDOMFileReader::ReadAsArrayBuffer(nsIDOMBlob* aFile, JSContext* aCx) ErrorResult rv; nsRefPtr file = static_cast(aFile); ReadAsArrayBuffer(aCx, *file, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP @@ -198,7 +198,7 @@ nsDOMFileReader::ReadAsBinaryString(nsIDOMBlob* aFile) ErrorResult rv; nsRefPtr file = static_cast(aFile); ReadAsBinaryString(*file, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP @@ -209,7 +209,7 @@ nsDOMFileReader::ReadAsText(nsIDOMBlob* aFile, ErrorResult rv; nsRefPtr file = static_cast(aFile); ReadAsText(*file, aCharset, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP @@ -219,7 +219,7 @@ nsDOMFileReader::ReadAsDataURL(nsIDOMBlob* aFile) ErrorResult rv; nsRefPtr file = static_cast(aFile); ReadAsDataURL(*file, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP @@ -227,7 +227,7 @@ nsDOMFileReader::Abort() { ErrorResult rv; FileIOObject::Abort(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } /* virtual */ void diff --git a/dom/base/nsDOMMutationObserver.cpp b/dom/base/nsDOMMutationObserver.cpp index e8d9666b36..19c4c953bc 100644 --- a/dom/base/nsDOMMutationObserver.cpp +++ b/dom/base/nsDOMMutationObserver.cpp @@ -14,6 +14,8 @@ #include "nsIDOMMutationEvent.h" #include "nsTextFragment.h" #include "nsServiceManagerUtils.h" +#include "mozilla/dom/Animation.h" +#include "mozilla/dom/KeyframeEffect.h" nsAutoTArray, 4>* nsDOMMutationObserver::sScheduledMutationObservers = nullptr; @@ -323,15 +325,15 @@ void nsMutationReceiver::NodeWillBeDestroyed(const nsINode *aNode) } void -nsAnimationReceiver::RecordAnimationMutation(AnimationPlayer* aPlayer, +nsAnimationReceiver::RecordAnimationMutation(Animation* aAnimation, AnimationMutation aMutationType) { - Animation* source = aPlayer->GetSource(); - if (!source) { + KeyframeEffectReadonly* effect = aAnimation->GetEffect(); + if (!effect) { return; } - Element* animationTarget = source->GetTarget(); + Element* animationTarget = effect->GetTarget(); if (!animationTarget) { return; } @@ -348,13 +350,13 @@ nsAnimationReceiver::RecordAnimationMutation(AnimationPlayer* aPlayer, switch (aMutationType) { case eAnimationMutation_Added: - nsAutoAnimationMutationBatch::AnimationAdded(aPlayer); + nsAutoAnimationMutationBatch::AnimationAdded(aAnimation); break; case eAnimationMutation_Changed: - nsAutoAnimationMutationBatch::AnimationChanged(aPlayer); + nsAutoAnimationMutationBatch::AnimationChanged(aAnimation); break; case eAnimationMutation_Removed: - nsAutoAnimationMutationBatch::AnimationRemoved(aPlayer); + nsAutoAnimationMutationBatch::AnimationRemoved(aAnimation); break; } @@ -371,33 +373,33 @@ nsAnimationReceiver::RecordAnimationMutation(AnimationPlayer* aPlayer, switch (aMutationType) { case eAnimationMutation_Added: - m->mAddedAnimations.AppendElement(aPlayer); + m->mAddedAnimations.AppendElement(aAnimation); break; case eAnimationMutation_Changed: - m->mChangedAnimations.AppendElement(aPlayer); + m->mChangedAnimations.AppendElement(aAnimation); break; case eAnimationMutation_Removed: - m->mRemovedAnimations.AppendElement(aPlayer); + m->mRemovedAnimations.AppendElement(aAnimation); break; } } void -nsAnimationReceiver::AnimationAdded(AnimationPlayer* aPlayer) +nsAnimationReceiver::AnimationAdded(Animation* aAnimation) { - RecordAnimationMutation(aPlayer, eAnimationMutation_Added); + RecordAnimationMutation(aAnimation, eAnimationMutation_Added); } void -nsAnimationReceiver::AnimationChanged(AnimationPlayer* aPlayer) +nsAnimationReceiver::AnimationChanged(Animation* aAnimation) { - RecordAnimationMutation(aPlayer, eAnimationMutation_Changed); + RecordAnimationMutation(aAnimation, eAnimationMutation_Changed); } void -nsAnimationReceiver::AnimationRemoved(AnimationPlayer* aPlayer) +nsAnimationReceiver::AnimationRemoved(Animation* aAnimation) { - RecordAnimationMutation(aPlayer, eAnimationMutation_Removed); + RecordAnimationMutation(aAnimation, eAnimationMutation_Removed); } NS_IMPL_ISUPPORTS_INHERITED(nsAnimationReceiver, nsMutationReceiver, @@ -1018,11 +1020,11 @@ nsAutoAnimationMutationBatch::Done() for (const Entry& e : mEntries) { if (e.mState == eState_Added) { - m->mAddedAnimations.AppendElement(e.mPlayer); + m->mAddedAnimations.AppendElement(e.mAnimation); } else if (e.mState == eState_Removed) { - m->mRemovedAnimations.AppendElement(e.mPlayer); + m->mRemovedAnimations.AppendElement(e.mAnimation); } else if (e.mState == eState_RemainedPresent && e.mChanged) { - m->mChangedAnimations.AppendElement(e.mPlayer); + m->mChangedAnimations.AppendElement(e.mAnimation); } } diff --git a/dom/base/nsDOMMutationObserver.h b/dom/base/nsDOMMutationObserver.h index 1f0f5fa1c8..901a156008 100644 --- a/dom/base/nsDOMMutationObserver.h +++ b/dom/base/nsDOMMutationObserver.h @@ -24,7 +24,7 @@ #include "nsWrapperCache.h" #include "mozilla/dom/MutationObserverBinding.h" #include "nsIDocument.h" -#include "mozilla/dom/AnimationPlayer.h" +#include "mozilla/dom/Animation.h" #include "nsIAnimationObserver.h" class nsDOMMutationObserver; @@ -36,7 +36,7 @@ class nsDOMMutationRecord final : public nsISupports, virtual ~nsDOMMutationRecord() {} public: - typedef nsTArray> AnimationPlayerArray; + typedef nsTArray> AnimationArray; nsDOMMutationRecord(nsIAtom* aType, nsISupports* aOwner) : mType(aType), mAttrNamespace(NullString()), mPrevValue(NullString()), mOwner(aOwner) @@ -95,17 +95,17 @@ public: aRetVal.SetOwnedString(mPrevValue); } - void GetAddedAnimations(AnimationPlayerArray& aRetVal) const + void GetAddedAnimations(AnimationArray& aRetVal) const { aRetVal = mAddedAnimations; } - void GetRemovedAnimations(AnimationPlayerArray& aRetVal) const + void GetRemovedAnimations(AnimationArray& aRetVal) const { aRetVal = mRemovedAnimations; } - void GetChangedAnimations(AnimationPlayerArray& aRetVal) const + void GetChangedAnimations(AnimationArray& aRetVal) const { aRetVal = mChangedAnimations; } @@ -119,9 +119,9 @@ public: nsRefPtr mRemovedNodes; nsCOMPtr mPreviousSibling; nsCOMPtr mNextSibling; - AnimationPlayerArray mAddedAnimations; - AnimationPlayerArray mRemovedAnimations; - AnimationPlayerArray mChangedAnimations; + AnimationArray mAddedAnimations; + AnimationArray mRemovedAnimations; + AnimationArray mChangedAnimations; nsRefPtr mNext; nsCOMPtr mOwner; @@ -434,7 +434,7 @@ private: eAnimationMutation_Removed }; - void RecordAnimationMutation(mozilla::dom::AnimationPlayer* aPlayer, + void RecordAnimationMutation(mozilla::dom::Animation* aAnimation, AnimationMutation aMutationType); }; @@ -756,13 +756,13 @@ public: return sCurrentBatch->mBatchTarget; } - static void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer) + static void AnimationAdded(mozilla::dom::Animation* aAnimation) { if (!IsBatching()) { return; } - Entry* entry = sCurrentBatch->FindEntry(aPlayer); + Entry* entry = sCurrentBatch->FindEntry(aAnimation); if (entry) { switch (entry->mState) { case eState_RemainedAbsent: @@ -777,15 +777,15 @@ public: } } else { entry = sCurrentBatch->mEntries.AppendElement(); - entry->mPlayer = aPlayer; + entry->mAnimation = aAnimation; entry->mState = eState_Added; entry->mChanged = false; } } - static void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer) + static void AnimationChanged(mozilla::dom::Animation* aAnimation) { - Entry* entry = sCurrentBatch->FindEntry(aPlayer); + Entry* entry = sCurrentBatch->FindEntry(aAnimation); if (entry) { NS_ASSERTION(entry->mState == eState_RemainedPresent || entry->mState == eState_Added, @@ -794,15 +794,15 @@ public: entry->mChanged = true; } else { entry = sCurrentBatch->mEntries.AppendElement(); - entry->mPlayer = aPlayer; + entry->mAnimation = aAnimation; entry->mState = eState_RemainedPresent; entry->mChanged = true; } } - static void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer) + static void AnimationRemoved(mozilla::dom::Animation* aAnimation) { - Entry* entry = sCurrentBatch->FindEntry(aPlayer); + Entry* entry = sCurrentBatch->FindEntry(aAnimation); if (entry) { switch (entry->mState) { case eState_RemainedPresent: @@ -817,17 +817,17 @@ public: } } else { entry = sCurrentBatch->mEntries.AppendElement(); - entry->mPlayer = aPlayer; + entry->mAnimation = aAnimation; entry->mState = eState_Removed; entry->mChanged = false; } } private: - Entry* FindEntry(mozilla::dom::AnimationPlayer* aPlayer) + Entry* FindEntry(mozilla::dom::Animation* aAnimation) { for (Entry& e : mEntries) { - if (e.mPlayer == aPlayer) { + if (e.mAnimation == aAnimation) { return &e; } } @@ -843,7 +843,7 @@ private: struct Entry { - nsRefPtr mPlayer; + nsRefPtr mAnimation; State mState; bool mChanged; }; diff --git a/dom/base/nsDOMSerializer.cpp b/dom/base/nsDOMSerializer.cpp index cb26fb2453..88e2034743 100644 --- a/dom/base/nsDOMSerializer.cpp +++ b/dom/base/nsDOMSerializer.cpp @@ -83,8 +83,7 @@ SetUpEncoder(nsIDOMNode *aRoot, const nsACString& aCharset, } if (NS_SUCCEEDED(rv)) { - *aEncoder = encoder.get(); - NS_ADDREF(*aEncoder); + encoder.forget(aEncoder); } return rv; diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 78b5d2273c..f1ac3d1c0e 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -19,7 +19,7 @@ #include "nsFrameManager.h" #include "nsRefreshDriver.h" #include "mozilla/dom/Touch.h" -#include "mozilla/PendingPlayerTracker.h" +#include "mozilla/PendingAnimationTracker.h" #include "nsIObjectLoadingContent.h" #include "nsFrame.h" #include "mozilla/layers/ShadowLayers.h" @@ -2609,16 +2609,15 @@ nsDOMWindowUtils::AdvanceTimeAndRefresh(int64_t aMilliseconds) // Before we advance the time, we should trigger any animations that are // waiting to start. This is because there are many tests that call this // which expect animations to start immediately. Ideally, we should make - // all these tests do an asynchronous wait on the corresponding animation - // player's 'ready' promise before continuing. Then we could remove the - // special handling here and the code path followed when testing would - // more closely match the code path during regular operation. Filed as - // bug 1112957. + // all these tests do an asynchronous wait on the corresponding animation's + // 'ready' promise before continuing. Then we could remove the special + // handling here and the code path followed when testing would more closely + // match the code path during regular operation. Filed as bug 1112957. nsCOMPtr doc = GetDocument(); if (doc) { - PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker(); + PendingAnimationTracker* tracker = doc->GetPendingAnimationTracker(); if (tracker) { - tracker->TriggerPendingPlayersNow(); + tracker->TriggerPendingAnimationsNow(); } } @@ -2916,19 +2915,6 @@ nsDOMWindowUtils::LeafLayersPartitionWindow(bool* aResult) return NS_OK; } -NS_IMETHODIMP -nsDOMWindowUtils::GetMayHaveTouchEventListeners(bool* aResult) -{ - MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome()); - - nsCOMPtr window = do_QueryReferent(mWindow); - NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); - - nsPIDOMWindow* innerWindow = window->GetCurrentInnerWindow(); - *aResult = innerWindow ? innerWindow->HasTouchEventListeners() : false; - return NS_OK; -} - NS_IMETHODIMP nsDOMWindowUtils::CheckAndClearPaintedState(nsIDOMElement* aElement, bool* aResult) { @@ -3802,7 +3788,7 @@ nsDOMWindowUtils::GetOMTAStyle(nsIDOMElement* aElement, ErrorResult rv; cssValue->GetCssText(text, rv); aResult.Assign(text); - return rv.ErrorCode(); + return rv.StealNSResult(); } else { aResult.Truncate(); } @@ -4021,6 +4007,32 @@ nsDOMWindowUtils::GetFramesReflowed(uint64_t* aResult) return NS_OK; } +NS_IMETHODIMP +nsDOMWindowUtils::SetServiceWorkersTestingEnabled(bool aEnabled) +{ + MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome()); + + nsCOMPtr window = do_QueryReferent(mWindow); + NS_ENSURE_STATE(window); + + window->SetServiceWorkersTestingEnabled(aEnabled); + + return NS_OK; +} + +NS_IMETHODIMP +nsDOMWindowUtils::GetServiceWorkersTestingEnabled(bool *aEnabled) +{ + MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome()); + + nsCOMPtr window = do_QueryReferent(mWindow); + NS_ENSURE_STATE(window); + + *aEnabled = window->GetServiceWorkersTestingEnabled(); + + return NS_OK; +} + NS_INTERFACE_MAP_BEGIN(nsTranslationNodeList) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList) diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index be82055c4a..025e3539f1 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -187,9 +187,9 @@ #include "nsSandboxFlags.h" #include "nsIAppsService.h" #include "mozilla/dom/AnonymousContent.h" -#include "mozilla/dom/AnimationTimeline.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/DocumentFragment.h" +#include "mozilla/dom/DocumentTimeline.h" #include "mozilla/dom/Event.h" #include "mozilla/dom/HTMLBodyElement.h" #include "mozilla/dom/HTMLInputElement.h" @@ -1218,7 +1218,7 @@ nsExternalResourceMap::PendingLoad::SetupViewer(nsIRequest* aRequest, do_GetService(NS_CATEGORYMANAGER_CONTRACTID); NS_ENSURE_TRUE(catMan, NS_ERROR_NOT_AVAILABLE); nsXPIDLCString contractId; - nsresult rv = catMan->GetCategoryEntry("Goanna-Content-Viewers", type.get(), + nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", type.get(), getter_Copies(contractId)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr docLoaderFactory = @@ -1994,8 +1994,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedEncoder) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStateObjectCached) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUndoManager) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnimationTimeline) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingPlayerTracker) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentTimeline) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingAnimationTracker) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTemplateContentsOwner) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildrenCollection) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRegistry) @@ -2078,8 +2078,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK(mOriginalDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedEncoder) NS_IMPL_CYCLE_COLLECTION_UNLINK(mUndoManager) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mAnimationTimeline) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingPlayerTracker) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentTimeline) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingAnimationTracker) NS_IMPL_CYCLE_COLLECTION_UNLINK(mTemplateContentsOwner) NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildrenCollection) NS_IMPL_CYCLE_COLLECTION_UNLINK(mRegistry) @@ -2280,7 +2280,7 @@ nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) // Note that, since mTiming does not change during a reset, the // navigationStart time remains unchanged and therefore any future new // timeline will have the same global clock time as the old one. - mAnimationTimeline = nullptr; + mDocumentTimeline = nullptr; nsCOMPtr bag = do_QueryInterface(aChannel); if (bag) { @@ -3290,14 +3290,14 @@ nsDocument::IsWebAnimationsEnabled(JSContext* /*unused*/, JSObject* /*unused*/) Preferences::GetBool("dom.animations-api.core.enabled"); } -AnimationTimeline* +DocumentTimeline* nsDocument::Timeline() { - if (!mAnimationTimeline) { - mAnimationTimeline = new AnimationTimeline(this); + if (!mDocumentTimeline) { + mDocumentTimeline = new DocumentTimeline(this); } - return mAnimationTimeline; + return mDocumentTimeline; } /* Return true if the document is in the focused top-level window, and is an @@ -3307,7 +3307,7 @@ nsDocument::HasFocus(bool* aResult) { ErrorResult rv; *aResult = nsIDocument::HasFocus(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } bool @@ -3939,6 +3939,42 @@ nsIDocument::TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks) mFrameRequestCallbacks.Clear(); } +bool +nsIDocument::ShouldThrottleFrameRequests() +{ + if (!mIsShowing) { + // We're not showing (probably in a background tab or the bf cache). + return true; + } + + if (!mPresShell) { + return false; // Can't do anything smarter. + } + + nsIFrame* frame = mPresShell->GetRootFrame(); + if (!frame) { + return false; // Can't do anything smarter. + } + + nsIFrame* displayRootFrame = nsLayoutUtils::GetDisplayRootFrame(frame); + if (!displayRootFrame) { + return false; // Can't do anything smarter. + } + + if (!displayRootFrame->DidPaintPresShell(mPresShell)) { + // We didn't get painted during the last paint, so we're not visible. + // Throttle. Note that because we have to paint this document at least + // once to unthrottle it, we will drop one requestAnimationFrame frame + // when a document that previously wasn't visible scrolls into view. This + // is acceptable since it would happen outside the viewport on APZ + // platforms and is unlikely to be human-perceivable on non-APZ platforms. + return true; + } + + // We got painted during the last paint, so run at full speed. + return false; +} + PLDHashOperator RequestDiscardEnumerator(imgIRequest* aKey, uint32_t aData, void* userArg) @@ -5421,7 +5457,7 @@ nsDocument::GetImplementation(nsIDOMDOMImplementation** aImplementation) *aImplementation = GetImplementation(rv); if (rv.Failed()) { MOZ_ASSERT(!*aImplementation); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_ADDREF(*aImplementation); return NS_OK; @@ -5473,7 +5509,7 @@ nsDocument::CreateElement(const nsAString& aTagName, *aReturn = nullptr; ErrorResult rv; nsCOMPtr element = nsIDocument::CreateElement(aTagName, rv); - NS_ENSURE_FALSE(rv.Failed(), rv.ErrorCode()); + NS_ENSURE_FALSE(rv.Failed(), rv.StealNSResult()); return CallQueryInterface(element, aReturn); } @@ -5580,7 +5616,7 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI, ErrorResult rv; nsCOMPtr element = nsIDocument::CreateElementNS(aNamespaceURI, aQualifiedName, rv); - NS_ENSURE_FALSE(rv.Failed(), rv.ErrorCode()); + NS_ENSURE_FALSE(rv.Failed(), rv.StealNSResult()); return CallQueryInterface(element, aReturn); } @@ -5693,7 +5729,7 @@ nsDocument::CreateCDATASection(const nsAString& aData, NS_ENSURE_ARG_POINTER(aReturn); ErrorResult rv; *aReturn = nsIDocument::CreateCDATASection(aData, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -5726,7 +5762,7 @@ nsDocument::CreateProcessingInstruction(const nsAString& aTarget, ErrorResult rv; *aReturn = nsIDocument::CreateProcessingInstruction(aTarget, aData, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -5757,7 +5793,7 @@ nsDocument::CreateAttribute(const nsAString& aName, { ErrorResult rv; *aReturn = nsIDocument::CreateAttribute(aName, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -5798,7 +5834,7 @@ nsDocument::CreateAttributeNS(const nsAString & aNamespaceURI, ErrorResult rv; *aResult = nsIDocument::CreateAttributeNS(aNamespaceURI, aQualifiedName, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -6469,7 +6505,7 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI, nsRefPtr list = nsIDocument::GetElementsByTagNameNS(aNamespaceURI, aLocalName, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } // transfer ref to aReturn @@ -6693,7 +6729,7 @@ nsDocument::ImportNode(nsIDOMNode* aImportedNode, ErrorResult rv; nsCOMPtr result = nsIDocument::ImportNode(*imported, aDeep, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_ADDREF(*aResult = result->AsDOMNode()); @@ -6740,7 +6776,7 @@ nsDocument::LoadBindingDocument(const nsAString& aURI) { ErrorResult rv; nsIDocument::LoadBindingDocument(aURI, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -6883,7 +6919,7 @@ nsDocument::CreateRange(nsIDOMRange** aReturn) { ErrorResult rv; *aReturn = nsIDocument::CreateRange(rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -6923,7 +6959,7 @@ nsDocument::CreateNodeIterator(nsIDOMNode *aRoot, NodeFilterHolder holder(aFilter); *_retval = nsIDocument::CreateNodeIterator(*root, aWhatToShow, holder, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -6966,7 +7002,7 @@ nsDocument::CreateTreeWalker(nsIDOMNode *aRoot, NodeFilterHolder holder(aFilter); *_retval = nsIDocument::CreateTreeWalker(*root, aWhatToShow, holder, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -7465,14 +7501,14 @@ nsDocument::GetAnimationController() return mAnimationController; } -PendingPlayerTracker* -nsDocument::GetOrCreatePendingPlayerTracker() +PendingAnimationTracker* +nsDocument::GetOrCreatePendingAnimationTracker() { - if (!mPendingPlayerTracker) { - mPendingPlayerTracker = new PendingPlayerTracker(this); + if (!mPendingAnimationTracker) { + mPendingAnimationTracker = new PendingAnimationTracker(this); } - return mPendingPlayerTracker; + return mPendingAnimationTracker; } /** @@ -7688,7 +7724,7 @@ nsDocument::AdoptNode(nsIDOMNode *aAdoptedNode, nsIDOMNode **aResult) ErrorResult rv; nsINode* result = nsIDocument::AdoptNode(*adoptedNode, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_ADDREF(*aResult = result->AsDOMNode()); @@ -8133,7 +8169,7 @@ nsDocument::CreateEvent(const nsAString& aEventType, nsIDOMEvent** aReturn) NS_ENSURE_ARG_POINTER(aReturn); ErrorResult rv; *aReturn = nsIDocument::CreateEvent(aEventType, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -11887,7 +11923,7 @@ nsDocument::GetMozFullScreenElement(nsIDOMElement **aFullScreenElement) ErrorResult rv; Element* el = GetMozFullScreenElement(rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } nsCOMPtr retval = do_QueryInterface(el); retval.forget(aFullScreenElement); diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h index f34daf7a1c..763252ba5d 100644 --- a/dom/base/nsDocument.h +++ b/dom/base/nsDocument.h @@ -59,7 +59,7 @@ #include "mozilla/EventListenerManager.h" #include "mozilla/EventStates.h" #include "mozilla/MemoryReporting.h" -#include "mozilla/PendingPlayerTracker.h" +#include "mozilla/PendingAnimationTracker.h" #include "mozilla/dom/DOMImplementation.h" #include "mozilla/dom/StyleSheetList.h" #include "nsDataHashtable.h" @@ -779,7 +779,7 @@ public: virtual already_AddRefed GetUndoManager() override; static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject); - virtual mozilla::dom::AnimationTimeline* Timeline() override; + virtual mozilla::dom::DocumentTimeline* Timeline() override; virtual nsresult SetSubDocumentFor(Element* aContent, nsIDocument* aSubDoc) override; @@ -1048,14 +1048,14 @@ public: // If HasAnimationController is true, this is guaranteed to return non-null. nsSMILAnimationController* GetAnimationController() override; - virtual mozilla::PendingPlayerTracker* - GetPendingPlayerTracker() final override + virtual mozilla::PendingAnimationTracker* + GetPendingAnimationTracker() final override { - return mPendingPlayerTracker; + return mPendingAnimationTracker; } - virtual mozilla::PendingPlayerTracker* - GetOrCreatePendingPlayerTracker() override; + virtual mozilla::PendingAnimationTracker* + GetOrCreatePendingAnimationTracker() override; void SetImagesNeedAnimating(bool aAnimating) override; @@ -1534,9 +1534,9 @@ protected: // Array of observers nsTObserverArray mObservers; - // Tracker for animation players that are waiting to start. - // nullptr until GetOrCreatePendingPlayerTracker is called. - nsRefPtr mPendingPlayerTracker; + // Tracker for animations that are waiting to start. + // nullptr until GetOrCreatePendingAnimationTracker is called. + nsRefPtr mPendingAnimationTracker; // Weak reference to the scope object (aka the script global object) // that, unlike mScriptGlobalObject, is never unset once set. This @@ -1801,7 +1801,7 @@ private: nsRefPtr mUndoManager; - nsRefPtr mAnimationTimeline; + nsRefPtr mDocumentTimeline; enum ViewportType { DisplayWidthHeight, diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index 913fba70ea..2309a130d3 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -1785,10 +1785,6 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow, // focus can be traversed from the top level down to the newly focused // window. AdjustWindowFocus(aWindow, false); - - // Update the window touch registration to reflect the state of - // the new document that got focus - aWindow->UpdateTouchState(); } // indicate that the window has taken focus. @@ -2612,8 +2608,9 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow, // as long as the found node was not the same as the starting node, // set it as the return value. - if (nextFocus != originalStartContent) - NS_ADDREF(*aNextContent = nextFocus); + if (nextFocus != originalStartContent) { + nextFocus.forget(aNextContent); + } return NS_OK; } @@ -3095,8 +3092,7 @@ nsFocusManager::GetLastDocShell(nsIDocShellTreeItem* aItem, int32_t childCount = 0; curItem->GetChildCount(&childCount); if (!childCount) { - *aResult = curItem; - NS_ADDREF(*aResult); + curItem.forget(aResult); return; } @@ -3174,7 +3170,7 @@ nsFocusManager::GetPreviousDocShell(nsIDocShellTreeItem* aItem, if (prevItem) GetLastDocShell(prevItem, aResult); else - NS_ADDREF(*aResult = parentItem); + parentItem.forget(aResult); } nsIContent* @@ -3392,7 +3388,7 @@ nsFocusManager::GetFocusInSelection(nsPIDOMWindow* aWindow, nsCOMPtr uri; if (testContent == currentFocus || testContent->IsLink(getter_AddRefs(uri))) { - NS_ADDREF(*aFocusedContent = testContent); + testContent.forget(aFocusedContent); return; } @@ -3422,7 +3418,7 @@ nsFocusManager::GetFocusInSelection(nsPIDOMWindow* aWindow, nsCOMPtr uri; if (testContent == currentFocus || testContent->IsLink(getter_AddRefs(uri))) { - NS_ADDREF(*aFocusedContent = testContent); + testContent.forget(aFocusedContent); return; } diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index 86b929c018..bd434f2174 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -2505,7 +2505,9 @@ nsFrameLoader::GetMessageManager(nsIMessageSender** aManager) { EnsureMessageManager(); if (mMessageManager) { - CallQueryInterface(mMessageManager, aManager); + nsRefPtr mm(mMessageManager); + mm.forget(aManager); + return NS_OK; } return NS_OK; } diff --git a/dom/base/nsFrameMessageManager.cpp b/dom/base/nsFrameMessageManager.cpp index 6e42af3782..1bedfae9c0 100644 --- a/dom/base/nsFrameMessageManager.cpp +++ b/dom/base/nsFrameMessageManager.cpp @@ -1053,7 +1053,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, // JSContext* cx = aes.cx(); nsIGlobalObject* nativeGlobal = xpc::NativeGlobal(js::GetGlobalForObjectCrossCompartment(wrappedJS->GetJSObject())); - AutoEntryScript aes(nativeGlobal); + AutoEntryScript aes(nativeGlobal, "message manager handler"); aes.TakeOwnershipOfErrorReporting(); JSContext* cx = aes.cx(); JS::Rooted object(cx, wrappedJS->GetJSObject()); @@ -1492,11 +1492,12 @@ NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult) { NS_ENSURE_TRUE(XRE_GetProcessType() == GeckoProcessType_Default, NS_ERROR_NOT_AVAILABLE); - nsFrameMessageManager* mm = new nsFrameMessageManager(nullptr, - nullptr, - MM_CHROME | MM_GLOBAL | MM_BROADCASTER); + nsRefPtr mm = new nsFrameMessageManager(nullptr, + nullptr, + MM_CHROME | MM_GLOBAL | MM_BROADCASTER); RegisterStrongMemoryReporter(new MessageManagerReporter()); - return CallQueryInterface(mm, aResult); + mm.forget(aResult); + return NS_OK; } nsDataHashtable* @@ -1567,7 +1568,8 @@ nsMessageManagerScriptExecutor::LoadScriptInternal(const nsAString& aURL, JS::Rooted global(rt, mGlobal->GetJSObject()); if (global) { - AutoEntryScript aes(xpc::NativeGlobal(global)); + AutoEntryScript aes(xpc::NativeGlobal(global), + "message manager script load"); aes.TakeOwnershipOfErrorReporting(); JSContext* cx = aes.cx(); if (script) { @@ -1990,7 +1992,8 @@ NS_NewParentProcessMessageManager(nsIMessageBroadcaster** aResult) MM_CHROME | MM_PROCESSMANAGER | MM_BROADCASTER); nsFrameMessageManager::sParentProcessManager = mm; nsFrameMessageManager::NewProcessMessageManager(false); // Create same process message manager. - return CallQueryInterface(mm, aResult); + mm.forget(aResult); + return NS_OK; } @@ -2037,9 +2040,10 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult) nullptr, MM_PROCESSMANAGER | MM_OWNSCALLBACK); nsFrameMessageManager::SetChildProcessManager(mm); - ProcessGlobal* global = new ProcessGlobal(mm); + nsRefPtr global = new ProcessGlobal(mm); NS_ENSURE_TRUE(global->Init(), NS_ERROR_UNEXPECTED); - return CallQueryInterface(global, aResult); + global.forget(aResult); + return NS_OK; } diff --git a/dom/base/nsGenericDOMDataNode.cpp b/dom/base/nsGenericDOMDataNode.cpp index 53951f1118..7cc765e0ab 100644 --- a/dom/base/nsGenericDOMDataNode.cpp +++ b/dom/base/nsGenericDOMDataNode.cpp @@ -202,7 +202,7 @@ nsGenericDOMDataNode::SubstringData(uint32_t aStart, uint32_t aCount, { ErrorResult rv; SubstringData(aStart, aCount, aReturn, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h index 27d4511a8d..532f6857b2 100644 --- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -33,6 +33,9 @@ GK_ATOM(_empty, "") GK_ATOM(moz, "_moz") GK_ATOM(mozframetype, "mozframetype") +GK_ATOM(_moz_abspos, "_moz_activated") +GK_ATOM(_moz_activated, "_moz_activated") +GK_ATOM(_moz_resizing, "_moz_resizing") GK_ATOM(mozallowfullscreen, "mozallowfullscreen") GK_ATOM(moztype, "_moz-type") GK_ATOM(mozdirty, "_moz_dirty") @@ -90,6 +93,7 @@ GK_ATOM(anchor, "anchor") GK_ATOM(_and, "and") GK_ATOM(animations, "animations") GK_ATOM(anonid, "anonid") +GK_ATOM(anonlocation, "anonlocation") GK_ATOM(any, "any") GK_ATOM(mozapp, "mozapp") GK_ATOM(mozwidget, "mozwidget") diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 295c847a6d..aeab6204bf 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -189,6 +189,7 @@ #include "mozilla/dom/StructuredCloneTags.h" #ifdef MOZ_GAMEPAD +#include "mozilla/dom/Gamepad.h" #include "mozilla/dom/GamepadService.h" #endif @@ -218,6 +219,7 @@ #include "mozilla/dom/MozSelfSupportBinding.h" #include "mozilla/dom/PopStateEvent.h" #include "mozilla/dom/PopupBlockedEvent.h" +#include "mozilla/dom/PrimitiveConversions.h" #include "mozilla/dom/WindowBinding.h" #include "nsITabChild.h" #include "mozilla/dom/MediaQueryList.h" @@ -501,7 +503,9 @@ public: private: ~nsGlobalWindowObserver() {} - nsGlobalWindow* mWindow; + // This reference is non-owning and safe because it's cleared by + // nsGlobalWindow::CleanUp(). + nsGlobalWindow* MOZ_NON_OWNING_REF mWindow; }; NS_IMPL_ISUPPORTS(nsGlobalWindowObserver, nsIObserver, nsIInterfaceRequestor) @@ -585,7 +589,7 @@ nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow) mOuterWindow(aOuterWindow), // Make sure no actual window ends up with mWindowID == 0 mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false), - mMarkedCCGeneration(0) + mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false) {} nsPIDOMWindow::~nsPIDOMWindow() {} @@ -2722,8 +2726,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, // up with the outer. See bug 969156. if (createdInnerWindow) { // AutoEntryScript required to invoke debugger hook, which is a - // Goanna-specific concept at present. - AutoEntryScript aes(newInnerWindow); + // Gecko-specific concept at present. + AutoEntryScript aes(newInnerWindow, "nsGlobalWindow report new global"); JS::Rooted global(aes.cx(), newInnerWindow->GetWrapper()); JS_FireOnNewGlobalObject(aes.cx(), global); } @@ -3538,7 +3542,7 @@ NS_IMETHODIMP nsGlobalWindow::GetWindow(nsIDOMWindow** aWindow) { ErrorResult rv; - FORWARD_TO_OUTER_OR_THROW(GetWindow, (aWindow), rv, rv.ErrorCode()); + FORWARD_TO_OUTER_OR_THROW(GetWindow, (aWindow), rv, rv.StealNSResult()); nsCOMPtr window = Window(); window.forget(aWindow); @@ -3556,7 +3560,7 @@ NS_IMETHODIMP nsGlobalWindow::GetSelf(nsIDOMWindow** aWindow) { ErrorResult rv; - FORWARD_TO_OUTER_OR_THROW(GetSelf, (aWindow), rv, rv.ErrorCode()); + FORWARD_TO_OUTER_OR_THROW(GetSelf, (aWindow), rv, rv.StealNSResult()); nsCOMPtr window = Self(); window.forget(aWindow); @@ -3583,7 +3587,7 @@ nsGlobalWindow::GetNavigator(nsIDOMNavigator** aNavigator) nsCOMPtr navigator = GetNavigator(rv); navigator.forget(aNavigator); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsScreen* @@ -3609,7 +3613,7 @@ nsGlobalWindow::GetScreen(nsIDOMScreen** aScreen) nsRefPtr screen = GetScreen(rv); screen.forget(aScreen); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsHistory* @@ -3631,7 +3635,7 @@ nsGlobalWindow::GetHistory(nsISupports** aHistory) nsCOMPtr history = GetHistory(rv); history.forget(aHistory); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsPerformance* @@ -4005,7 +4009,7 @@ nsGlobalWindow::GetContent(nsIDOMWindow** aContent) ErrorResult rv; *aContent = GetContentInternal(rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } MozSelfSupport* @@ -4031,7 +4035,7 @@ nsGlobalWindow::GetScriptableContent(JSContext* aCx, JS::MutableHandle prompter(do_GetInterface(mDocShell)); NS_ENSURE_TRUE(prompter, NS_ERROR_NO_INTERFACE); - NS_ADDREF(*aPrompt = prompter); + prompter.forget(aPrompt); return NS_OK; } @@ -4075,7 +4079,7 @@ nsGlobalWindow::GetMenubar(nsISupports** aMenubar) nsCOMPtr menubar = GetMenubar(rv); menubar.forget(aMenubar); - return rv.ErrorCode(); + return rv.StealNSResult(); } BarProp* @@ -4097,7 +4101,7 @@ nsGlobalWindow::GetToolbar(nsISupports** aToolbar) nsCOMPtr toolbar = GetToolbar(rv); toolbar.forget(aToolbar); - return rv.ErrorCode(); + return rv.StealNSResult(); } BarProp* @@ -4118,7 +4122,7 @@ nsGlobalWindow::GetLocationbar(nsISupports** aLocationbar) nsCOMPtr locationbar = GetLocationbar(rv); locationbar.forget(aLocationbar); - return rv.ErrorCode(); + return rv.StealNSResult(); } BarProp* @@ -4139,7 +4143,7 @@ nsGlobalWindow::GetPersonalbar(nsISupports** aPersonalbar) nsCOMPtr personalbar = GetPersonalbar(rv); personalbar.forget(aPersonalbar); - return rv.ErrorCode(); + return rv.StealNSResult(); } BarProp* @@ -4160,7 +4164,7 @@ nsGlobalWindow::GetStatusbar(nsISupports** aStatusbar) nsCOMPtr statusbar = GetStatusbar(rv); statusbar.forget(aStatusbar); - return rv.ErrorCode(); + return rv.StealNSResult(); } BarProp* @@ -4182,7 +4186,7 @@ nsGlobalWindow::GetScrollbars(nsISupports** aScrollbars) nsCOMPtr scrollbars = GetScrollbars(rv); scrollbars.forget(aScrollbars); - return rv.ErrorCode(); + return rv.StealNSResult(); } bool @@ -4200,7 +4204,7 @@ nsGlobalWindow::GetClosed(bool* aClosed) ErrorResult rv; *aClosed = GetClosed(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsDOMWindowList* @@ -4386,7 +4390,7 @@ nsGlobalWindow::GetApplicationCache(nsIDOMOfflineResourceList **aApplicationCach GetApplicationCache(rv); applicationCache.forget(aApplicationCache); - return rv.ErrorCode(); + return rv.StealNSResult(); } Crypto* @@ -4408,7 +4412,7 @@ nsGlobalWindow::GetCrypto(nsIDOMCrypto** aCrypto) nsCOMPtr crypto = GetCrypto(rv); crypto.forget(aCrypto); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsIControllers* @@ -4452,7 +4456,7 @@ nsGlobalWindow::GetControllers(nsIControllers** aResult) nsCOMPtr controllers = GetControllers(rv); controllers.forget(aResult); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsPIDOMWindow* @@ -4523,7 +4527,7 @@ nsGlobalWindow::GetScriptableOpener(JSContext* aCx, ErrorResult rv; GetOpener(aCx, aOpener, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } @@ -4549,18 +4553,7 @@ nsGlobalWindow::SetOpener(JSContext* aCx, JS::Handle aOpener, // get reset on navigation. This is just like replaceable properties, but // we're not quite readonly. if (!aOpener.isNull() && !nsContentUtils::IsCallerChrome()) { - JS::Rooted thisObj(aCx, GetWrapperPreserveColor()); - if (!thisObj) { - aError.Throw(NS_ERROR_UNEXPECTED); - return; - } - - if (!JS_WrapObject(aCx, &thisObj) || - !JS_DefineProperty(aCx, thisObj, "opener", aOpener, JSPROP_ENUMERATE, - JS_STUBGETTER, JS_STUBSETTER)) { - aError.Throw(NS_ERROR_FAILURE); - } - + RedefineProperty(aCx, "opener", aOpener, aError); return; } @@ -4605,7 +4598,7 @@ nsGlobalWindow::SetScriptableOpener(JSContext* aCx, ErrorResult rv; SetOpener(aCx, aOpener, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } @@ -4623,7 +4616,7 @@ nsGlobalWindow::GetStatus(nsAString& aStatus) ErrorResult rv; GetStatus(aStatus, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -4655,7 +4648,7 @@ nsGlobalWindow::SetStatus(const nsAString& aStatus) ErrorResult rv; SetStatus(aStatus, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -4674,7 +4667,7 @@ nsGlobalWindow::GetName(nsAString& aName) ErrorResult rv; GetName(aName, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -4693,7 +4686,7 @@ nsGlobalWindow::SetName(const nsAString& aName) ErrorResult rv; SetName(aName, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } // Helper functions used by many methods below. @@ -4806,13 +4799,22 @@ nsGlobalWindow::GetInnerWidth(ErrorResult& aError) return size.width; } +void +nsGlobalWindow::GetInnerWidth(JSContext* aCx, + JS::MutableHandle aValue, + ErrorResult& aError) +{ + GetReplaceableWindowCoord(aCx, &nsGlobalWindow::GetInnerWidth, aValue, + aError); +} + NS_IMETHODIMP nsGlobalWindow::GetInnerWidth(int32_t* aInnerWidth) { ErrorResult rv; *aInnerWidth = GetInnerWidth(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -4825,14 +4827,6 @@ nsGlobalWindow::SetInnerWidth(int32_t aInnerWidth, ErrorResult& aError) return; } - /* - * If caller is not chrome and the user has not explicitly exempted the site, - * prevent setting window.innerWidth by exiting early - */ - if (!CanMoveResizeWindows() || IsFrame()) { - return; - } - CheckSecurityWidthAndHeight(&aInnerWidth, nullptr); nsRefPtr presShell = mDocShell->GetPresShell(); @@ -4859,13 +4853,25 @@ nsGlobalWindow::SetInnerWidth(int32_t aInnerWidth, ErrorResult& aError) aError = SetDocShellWidthAndHeight(CSSToDevIntPixels(aInnerWidth), height); } +void +nsGlobalWindow::SetInnerWidth(JSContext* aCx, JS::Handle aValue, + ErrorResult& aError) +{ + SetReplaceableWindowCoord(aCx, &nsGlobalWindow::SetInnerWidth, + aValue, "innerWidth", aError); +} + NS_IMETHODIMP nsGlobalWindow::SetInnerWidth(int32_t aInnerWidth) { + if (IsFrame()) { + return NS_OK; + } + ErrorResult rv; SetInnerWidth(aInnerWidth, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } int32_t @@ -4878,13 +4884,22 @@ nsGlobalWindow::GetInnerHeight(ErrorResult& aError) return size.height; } +void +nsGlobalWindow::GetInnerHeight(JSContext* aCx, + JS::MutableHandle aValue, + ErrorResult& aError) +{ + GetReplaceableWindowCoord(aCx, &nsGlobalWindow::GetInnerHeight, aValue, + aError); +} + NS_IMETHODIMP nsGlobalWindow::GetInnerHeight(int32_t* aInnerHeight) { ErrorResult rv; *aInnerHeight = GetInnerHeight(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -4897,14 +4912,6 @@ nsGlobalWindow::SetInnerHeight(int32_t aInnerHeight, ErrorResult& aError) return; } - /* - * If caller is not chrome and the user has not explicitly exempted the site, - * prevent setting window.innerHeight by exiting early - */ - if (!CanMoveResizeWindows() || IsFrame()) { - return; - } - nsRefPtr presShell = mDocShell->GetPresShell(); if (presShell && presShell->GetIsViewportOverridden()) @@ -4930,13 +4937,25 @@ nsGlobalWindow::SetInnerHeight(int32_t aInnerHeight, ErrorResult& aError) aError = SetDocShellWidthAndHeight(width, CSSToDevIntPixels(aInnerHeight)); } +void +nsGlobalWindow::SetInnerHeight(JSContext* aCx, JS::Handle aValue, + ErrorResult& aError) +{ + SetReplaceableWindowCoord(aCx, &nsGlobalWindow::SetInnerHeight, + aValue, "innerHeight", aError); +} + NS_IMETHODIMP nsGlobalWindow::SetInnerHeight(int32_t aInnerHeight) { + if (IsFrame()) { + return NS_OK; + } + ErrorResult rv; SetInnerHeight(aInnerHeight, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsIntSize @@ -4972,13 +4991,22 @@ nsGlobalWindow::GetOuterWidth(ErrorResult& aError) return GetOuterSize(aError).width; } +void +nsGlobalWindow::GetOuterWidth(JSContext* aCx, + JS::MutableHandle aValue, + ErrorResult& aError) +{ + GetReplaceableWindowCoord(aCx, &nsGlobalWindow::GetOuterWidth, aValue, + aError); +} + NS_IMETHODIMP nsGlobalWindow::GetOuterWidth(int32_t* aOuterWidth) { ErrorResult rv; *aOuterWidth = GetOuterWidth(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } int32_t @@ -4988,13 +5016,22 @@ nsGlobalWindow::GetOuterHeight(ErrorResult& aError) return GetOuterSize(aError).height; } +void +nsGlobalWindow::GetOuterHeight(JSContext* aCx, + JS::MutableHandle aValue, + ErrorResult& aError) +{ + GetReplaceableWindowCoord(aCx, &nsGlobalWindow::GetOuterHeight, aValue, + aError); +} + NS_IMETHODIMP nsGlobalWindow::GetOuterHeight(int32_t* aOuterHeight) { ErrorResult rv; *aOuterHeight = GetOuterHeight(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -5003,15 +5040,6 @@ nsGlobalWindow::SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth, { MOZ_ASSERT(IsOuterWindow()); - /* - * If caller is not chrome and the user has not explicitly exempted the site, - * prevent setting window.outerWidth by exiting early - */ - - if (!CanMoveResizeWindows() || IsFrame()) { - return; - } - nsCOMPtr treeOwnerAsWin = GetTreeOwnerWindow(); if (!treeOwnerAsWin) { aError.Throw(NS_ERROR_FAILURE); @@ -5044,13 +5072,25 @@ nsGlobalWindow::SetOuterWidth(int32_t aOuterWidth, ErrorResult& aError) SetOuterSize(aOuterWidth, true, aError); } +void +nsGlobalWindow::SetOuterWidth(JSContext* aCx, JS::Handle aValue, + ErrorResult& aError) +{ + SetReplaceableWindowCoord(aCx, &nsGlobalWindow::SetOuterWidth, + aValue, "outerWidth", aError); +} + NS_IMETHODIMP nsGlobalWindow::SetOuterWidth(int32_t aOuterWidth) { + if (IsFrame()) { + return NS_OK; + } + ErrorResult rv; SetOuterWidth(aOuterWidth, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -5061,13 +5101,25 @@ nsGlobalWindow::SetOuterHeight(int32_t aOuterHeight, ErrorResult& aError) SetOuterSize(aOuterHeight, false, aError); } +void +nsGlobalWindow::SetOuterHeight(JSContext* aCx, JS::Handle aValue, + ErrorResult& aError) +{ + SetReplaceableWindowCoord(aCx, &nsGlobalWindow::SetOuterHeight, + aValue, "outerHeight", aError); +} + NS_IMETHODIMP nsGlobalWindow::SetOuterHeight(int32_t aOuterHeight) { + if (IsFrame()) { + return NS_OK; + } + ErrorResult rv; SetOuterHeight(aOuterHeight, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsIntPoint @@ -5094,13 +5146,22 @@ nsGlobalWindow::GetScreenX(ErrorResult& aError) return DevToCSSIntPixels(GetScreenXY(aError).x); } +void +nsGlobalWindow::GetScreenX(JSContext* aCx, + JS::MutableHandle aValue, + ErrorResult& aError) +{ + GetReplaceableWindowCoord(aCx, &nsGlobalWindow::GetScreenX, aValue, + aError); +} + NS_IMETHODIMP nsGlobalWindow::GetScreenX(int32_t* aScreenX) { ErrorResult rv; *aScreenX = GetScreenX(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsRect @@ -5149,7 +5210,7 @@ nsGlobalWindow::GetMozInnerScreenX(float* aScreenX) ErrorResult rv; *aScreenX = GetMozInnerScreenX(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } float @@ -5167,7 +5228,7 @@ nsGlobalWindow::GetMozInnerScreenY(float* aScreenY) ErrorResult rv; *aScreenY = GetMozInnerScreenY(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } float @@ -5195,7 +5256,7 @@ nsGlobalWindow::GetDevicePixelRatio(float* aRatio) ErrorResult rv; *aRatio = GetDevicePixelRatio(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } uint64_t @@ -5217,7 +5278,7 @@ nsGlobalWindow::GetMozPaintCount(uint64_t* aResult) ErrorResult rv; *aResult = GetMozPaintCount(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP @@ -5235,7 +5296,7 @@ nsGlobalWindow::MozRequestAnimationFrame(nsIFrameRequestCallback* aCallback, nsIDocument::FrameRequestCallbackHolder holder(aCallback); *aHandle = RequestAnimationFrame(holder, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } int32_t @@ -5290,7 +5351,7 @@ nsGlobalWindow::RequestAnimationFrame(JS::Handle aCallback, ErrorResult rv; *aHandle = RequestAnimationFrame(*callback, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP @@ -5323,7 +5384,7 @@ nsGlobalWindow::CancelAnimationFrame(int32_t aHandle) ErrorResult rv; CancelAnimationFrame(aHandle, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } int64_t @@ -5349,7 +5410,7 @@ nsGlobalWindow::GetMozAnimationStartTime(int64_t *aTime) ErrorResult rv; *aTime = GetMozAnimationStartTime(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -5378,7 +5439,7 @@ nsGlobalWindow::MatchMedia(const nsAString& aMediaQueryList, nsRefPtr mediaQueryList = MatchMedia(aMediaQueryList, rv); mediaQueryList.forget(aResult); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -5386,15 +5447,6 @@ nsGlobalWindow::SetScreenX(int32_t aScreenX, ErrorResult& aError) { FORWARD_TO_OUTER_OR_THROW(SetScreenX, (aScreenX, aError), aError, ); - /* - * If caller is not chrome and the user has not explicitly exempted the site, - * prevent setting window.screenX by exiting early - */ - - if (!CanMoveResizeWindows() || IsFrame()) { - return; - } - nsCOMPtr treeOwnerAsWin = GetTreeOwnerWindow(); if (!treeOwnerAsWin) { aError.Throw(NS_ERROR_FAILURE); @@ -5413,13 +5465,25 @@ nsGlobalWindow::SetScreenX(int32_t aScreenX, ErrorResult& aError) aError = treeOwnerAsWin->SetPosition(x, y); } +void +nsGlobalWindow::SetScreenX(JSContext* aCx, JS::Handle aValue, + ErrorResult& aError) +{ + SetReplaceableWindowCoord(aCx, &nsGlobalWindow::SetScreenX, + aValue, "screenX", aError); +} + NS_IMETHODIMP nsGlobalWindow::SetScreenX(int32_t aScreenX) { + if (IsFrame()) { + return NS_OK; + } + ErrorResult rv; SetScreenX(aScreenX, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } int32_t @@ -5436,7 +5500,16 @@ nsGlobalWindow::GetScreenY(int32_t* aScreenY) ErrorResult rv; *aScreenY = GetScreenY(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); +} + +void +nsGlobalWindow::GetScreenY(JSContext* aCx, + JS::MutableHandle aValue, + ErrorResult& aError) +{ + GetReplaceableWindowCoord(aCx, &nsGlobalWindow::GetScreenY, aValue, + aError); } void @@ -5444,15 +5517,6 @@ nsGlobalWindow::SetScreenY(int32_t aScreenY, ErrorResult& aError) { FORWARD_TO_OUTER_OR_THROW(SetScreenY, (aScreenY, aError), aError, ); - /* - * If caller is not chrome and the user has not explicitly exempted the site, - * prevent setting window.screenY by exiting early - */ - - if (!CanMoveResizeWindows() || IsFrame()) { - return; - } - nsCOMPtr treeOwnerAsWin = GetTreeOwnerWindow(); if (!treeOwnerAsWin) { aError.Throw(NS_ERROR_FAILURE); @@ -5471,13 +5535,25 @@ nsGlobalWindow::SetScreenY(int32_t aScreenY, ErrorResult& aError) aError = treeOwnerAsWin->SetPosition(x, y); } +void +nsGlobalWindow::SetScreenY(JSContext* aCx, JS::Handle aValue, + ErrorResult& aError) +{ + SetReplaceableWindowCoord(aCx, &nsGlobalWindow::SetScreenY, + aValue, "screenY", aError); +} + NS_IMETHODIMP nsGlobalWindow::SetScreenY(int32_t aScreenY) { + if (IsFrame()) { + return NS_OK; + } + ErrorResult rv; SetScreenY(aScreenY, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } // NOTE: Arguments to this function should have values scaled to @@ -5666,7 +5742,7 @@ nsGlobalWindow::GetScrollMinX(int32_t* aScrollMinX) ErrorResult rv; *aScrollMinX = GetScrollMinX(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } int32_t @@ -5685,7 +5761,7 @@ nsGlobalWindow::GetScrollMinY(int32_t* aScrollMinY) ErrorResult rv; *aScrollMinY = GetScrollMinY(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } int32_t @@ -5704,7 +5780,7 @@ nsGlobalWindow::GetScrollMaxX(int32_t* aScrollMaxX) ErrorResult rv; *aScrollMaxX = GetScrollMaxX(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } int32_t @@ -5723,7 +5799,7 @@ nsGlobalWindow::GetScrollMaxY(int32_t* aScrollMaxY) ErrorResult rv; *aScrollMaxY = GetScrollMaxY(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } CSSPoint @@ -5766,7 +5842,7 @@ nsGlobalWindow::GetScrollX(int32_t* aScrollX) NS_ENSURE_ARG_POINTER(aScrollX); ErrorResult rv; *aScrollX = GetScrollX(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } double @@ -5782,7 +5858,7 @@ nsGlobalWindow::GetScrollY(int32_t* aScrollY) NS_ENSURE_ARG_POINTER(aScrollY); ErrorResult rv; *aScrollY = GetScrollY(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } uint32_t @@ -6056,7 +6132,7 @@ nsGlobalWindow::SetFullScreenInternal(bool aFullScreen, bool aRequireTrust, gfx: mWakeLock = pmService->NewWakeLock(NS_LITERAL_STRING("DOM_Fullscreen"), this, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } } else if (mWakeLock && !mFullScreen) { @@ -6104,7 +6180,7 @@ nsGlobalWindow::GetFullScreen(bool* aFullScreen) ErrorResult rv; *aFullScreen = GetFullScreen(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP @@ -6131,7 +6207,7 @@ nsGlobalWindow::Dump(const nsAString& aStr) PrintToDebugger(cstr); #endif #ifdef ANDROID - __android_log_write(ANDROID_LOG_INFO, "GoannaDump", cstr); + __android_log_write(ANDROID_LOG_INFO, "GeckoDump", cstr); #endif FILE *fp = gDumpFile ? gDumpFile : stdout; fputs(cstr, fp); @@ -6404,7 +6480,7 @@ nsGlobalWindow::Alert(const nsAString& aString) ErrorResult rv; Alert(aString, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } bool @@ -6421,7 +6497,7 @@ nsGlobalWindow::Confirm(const nsAString& aString, bool* aReturn) ErrorResult rv; *aReturn = Confirm(aString, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -6522,7 +6598,7 @@ nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial, ErrorResult rv; Prompt(aMessage, aInitial, aReturn, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -6641,7 +6717,7 @@ nsGlobalWindow::Focus() ErrorResult rv; Focus(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -6682,7 +6758,7 @@ nsGlobalWindow::Blur() ErrorResult rv; Blur(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -6705,7 +6781,7 @@ nsGlobalWindow::Back() ErrorResult rv; Back(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -6728,7 +6804,7 @@ nsGlobalWindow::Forward() ErrorResult rv; Forward(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -6789,7 +6865,7 @@ nsGlobalWindow::Home() ErrorResult rv; Home(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -6809,7 +6885,7 @@ nsGlobalWindow::Stop() ErrorResult rv; Stop(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -6895,7 +6971,7 @@ nsGlobalWindow::Print() ErrorResult rv; Print(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -6933,7 +7009,7 @@ nsGlobalWindow::MoveTo(int32_t aXPos, int32_t aYPos) ErrorResult rv; MoveTo(aXPos, aYPos, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -6985,7 +7061,7 @@ nsGlobalWindow::MoveBy(int32_t aXDif, int32_t aYDif) ErrorResult rv; MoveBy(aXDif, aYDif, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -7035,7 +7111,7 @@ nsGlobalWindow::ResizeTo(int32_t aWidth, int32_t aHeight) ErrorResult rv; ResizeTo(aWidth, aHeight, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -7107,7 +7183,7 @@ nsGlobalWindow::ResizeBy(int32_t aWidthDif, int32_t aHeightDif) ErrorResult rv; ResizeBy(aWidthDif, aHeightDif, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -7166,7 +7242,7 @@ nsGlobalWindow::SizeToContent() ErrorResult rv; SizeToContent(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP @@ -7415,7 +7491,7 @@ nsGlobalWindow::ClearTimeout(int32_t aHandle) ErrorResult rv; ClearTimeout(aHandle, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -7432,7 +7508,7 @@ nsGlobalWindow::ClearInterval(int32_t aHandle) ErrorResult rv; ClearInterval(aHandle, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP @@ -7838,7 +7914,7 @@ nsGlobalWindow::GetFrames(nsIDOMWindow** aFrames) nsCOMPtr frames = GetFrames(rv); frames.forget(aFrames); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsGlobalWindow* @@ -8418,7 +8494,7 @@ nsGlobalWindow::PostMessageMoz(JS::Handle aMessage, ErrorResult rv; PostMessageMoz(aCx, aMessage, aOrigin, aTransfer, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } class nsCloseEvent : public nsRunnable { @@ -8564,7 +8640,7 @@ nsGlobalWindow::Close() ErrorResult rv; Close(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -8857,8 +8933,8 @@ nsGlobalWindow::IsInModalState() nsGlobalWindow *topWin = GetScriptableTopInternal(); if (!topWin) { - NS_ERROR("Uh, IsInModalState() called w/o a reachable top window?"); - + // IsInModalState() getting called w/o a reachable top window is a bit + // iffy, but valid enough not to make noise about it. See bug 404828 return false; } @@ -9120,7 +9196,7 @@ nsGlobalWindow::GetScriptableFrameElement(nsIDOMElement** aFrameElement) ErrorResult rv; nsCOMPtr frameElement = do_QueryInterface(GetFrameElement(rv)); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } frameElement.forget(aFrameElement); @@ -9182,7 +9258,7 @@ nsGlobalWindow::GetRealFrameElement(nsIDOMElement** aFrameElement) do_QueryInterface(GetRealFrameElement(rv)); frameElement.forget(aFrameElement); - return rv.ErrorCode(); + return rv.StealNSResult(); } // Helper for converting window.showModalDialog() options (list of ';' @@ -9431,7 +9507,7 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs_, nsCOMPtr retVal = ShowModalDialog(aURI, aArgs, aOptions, rv); retVal.forget(aRetVal); - return rv.ErrorCode(); + return rv.StealNSResult(); } class ChildCommandDispatcher : public nsRunnable @@ -9535,7 +9611,7 @@ nsGlobalWindow::GetSelection(nsISelection** aSelection) nsCOMPtr selection = GetSelection(rv); selection.forget(aSelection); - return rv.ErrorCode(); + return rv.StealNSResult(); } bool @@ -9625,7 +9701,7 @@ nsGlobalWindow::Find(const nsAString& aStr, bool aCaseSensitive, *aDidFind = Find(aStr, aCaseSensitive, aBackwards, aWrapAround, aWholeWord, aSearchInFrames, aShowDialog, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -9642,7 +9718,7 @@ nsGlobalWindow::Atob(const nsAString& aAsciiBase64String, ErrorResult rv; Atob(aAsciiBase64String, aBinaryData, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -9659,7 +9735,7 @@ nsGlobalWindow::Btoa(const nsAString& aBinaryData, ErrorResult rv; Btoa(aBinaryData, aAsciiBase64String, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } //***************************************************************************** @@ -9906,7 +9982,7 @@ nsGlobalWindow::GetLocation(nsIDOMLocation ** aLocation) nsCOMPtr location = GetLocation(rv); location.forget(aLocation); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -10000,15 +10076,6 @@ void nsGlobalWindow::MaybeUpdateTouchState() { FORWARD_TO_INNER_VOID(MaybeUpdateTouchState, ()); - nsIFocusManager* fm = nsFocusManager::GetFocusManager(); - - nsCOMPtr focusedWindow; - fm->GetFocusedWindow(getter_AddRefs(focusedWindow)); - - if(this == focusedWindow) { - UpdateTouchState(); - } - if (mMayHaveTouchEventListener) { nsCOMPtr observerService = services::GetObserverService(); @@ -10021,22 +10088,6 @@ void nsGlobalWindow::MaybeUpdateTouchState() } } -void nsGlobalWindow::UpdateTouchState() -{ - FORWARD_TO_INNER_VOID(UpdateTouchState, ()); - - nsCOMPtr mainWidget = GetMainWidget(); - if (!mainWidget) { - return; - } - - if (mMayHaveTouchEventListener) { - mainWidget->RegisterTouchWindow(); - } else { - mainWidget->UnregisterTouchWindow(); - } -} - void nsGlobalWindow::EnableGamepadUpdates() { @@ -10545,7 +10596,7 @@ nsGlobalWindow::GetComputedStyleHelper(nsIDOMElement* aElt, GetComputedStyleHelper(*element, aPseudoElt, aDefaultStylesOnly, rv); declaration.forget(aReturn); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -10682,7 +10733,7 @@ nsGlobalWindow::GetSessionStorage(nsISupports** aSessionStorage) nsCOMPtr storage = GetSessionStorage(rv); storage.forget(aSessionStorage); - return rv.ErrorCode(); + return rv.StealNSResult(); } DOMStorage* @@ -10752,7 +10803,7 @@ nsGlobalWindow::GetLocalStorage(nsISupports** aLocalStorage) nsCOMPtr storage = GetLocalStorage(rv); storage.forget(aLocalStorage); - return rv.ErrorCode(); + return rv.StealNSResult(); } IDBFactory* @@ -10773,7 +10824,7 @@ nsGlobalWindow::GetIndexedDB(nsISupports** _retval) nsCOMPtr request(GetIndexedDB(rv)); request.forget(_retval); - return rv.ErrorCode(); + return rv.StealNSResult(); } //***************************************************************************** @@ -11624,7 +11675,7 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic, NS_LITERAL_STRING("storage"), event, error); if (error.Failed()) { - return error.ErrorCode(); + return error.StealNSResult(); } newEvent->SetTrusted(true); @@ -12438,6 +12489,13 @@ nsGlobalWindow::RunTimeoutHandler(nsTimeout* aTimeout, sNestingLevel = timeout->mNestingLevel; } + const char *reason; + if (timeout->mIsInterval) { + reason = "setInterval handler"; + } else { + reason = "setTimeout handler"; + } + nsCOMPtr handler(timeout->mScriptHandler); nsRefPtr callback = handler->GetCallback(); if (!callback) { @@ -12450,8 +12508,8 @@ nsGlobalWindow::RunTimeoutHandler(nsTimeout* aTimeout, handler->GetLocation(&filename, &lineNo); // New script entry point required, due to the "Create a script" sub-step of - // http://www.whatwg.org/specs/web-apps/current-work/#timer-initialization-steps - AutoEntryScript entryScript(this, true, aScx->GetNativeContext()); + // http://www.whatwg.org/specs/web-apps/current-work/#timer-initialisation-steps + AutoEntryScript entryScript(this, reason, true, aScx->GetNativeContext()); entryScript.TakeOwnershipOfErrorReporting(); JS::CompileOptions options(entryScript.cx()); options.setFileAndLine(filename, lineNo) @@ -12464,7 +12522,7 @@ nsGlobalWindow::RunTimeoutHandler(nsTimeout* aTimeout, nsCOMPtr me(static_cast(this)); ErrorResult ignored; JS::Rooted ignoredVal(CycleCollectedJSRuntime::Get()->Runtime()); - callback->Call(me, handler->GetArgs(), &ignoredVal, ignored); + callback->Call(me, handler->GetArgs(), &ignoredVal, ignored, reason); } // We ignore any failures from calling EvaluateString() on the context or @@ -13477,6 +13535,15 @@ void nsGlobalWindow::AddGamepad(uint32_t aIndex, Gamepad* aGamepad) { MOZ_ASSERT(IsInnerWindow()); + // Create the index we will present to content based on which indices are + // already taken, as required by the spec. + // https://w3c.github.io/gamepad/gamepad.html#widl-Gamepad-index + int index = 0; + while(mGamepadIndexSet.Contains(index)) { + ++index; + } + mGamepadIndexSet.Put(index); + aGamepad->SetIndex(index); mGamepads.Put(aIndex, aGamepad); } @@ -13484,6 +13551,12 @@ void nsGlobalWindow::RemoveGamepad(uint32_t aIndex) { MOZ_ASSERT(IsInnerWindow()); + nsRefPtr gamepad; + if (!mGamepads.Get(aIndex, getter_AddRefs(gamepad))) { + return; + } + // Free up the index we were using so it can be reused + mGamepadIndexSet.Remove(gamepad->Index()); mGamepads.Remove(aIndex); } @@ -13494,8 +13567,8 @@ nsGlobalWindow::EnumGamepadsForGet(const uint32_t& aKey, Gamepad* aData, { nsTArray >* array = static_cast >*>(aUserArg); - array->EnsureLengthAtLeast(aKey + 1); - (*array)[aKey] = aData; + array->EnsureLengthAtLeast(aData->Index() + 1); + (*array)[aData->Index()] = aData; return PL_DHASH_NEXT; } @@ -13514,6 +13587,7 @@ nsGlobalWindow::GetGamepad(uint32_t aIndex) { MOZ_ASSERT(IsInnerWindow()); nsRefPtr gamepad; + if (mGamepads.Get(aIndex, getter_AddRefs(gamepad))) { return gamepad.forget(); } @@ -13651,7 +13725,7 @@ nsGlobalChromeWindow::Maximize() { ErrorResult rv; Maximize(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -13669,7 +13743,7 @@ nsGlobalChromeWindow::Minimize() { ErrorResult rv; Minimize(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -13687,7 +13761,7 @@ nsGlobalChromeWindow::Restore() { ErrorResult rv; Restore(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -13705,7 +13779,7 @@ nsGlobalChromeWindow::GetAttention() { ErrorResult rv; GetAttention(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -13719,7 +13793,7 @@ nsGlobalChromeWindow::GetAttentionWithCycleCount(int32_t aCycleCount) { ErrorResult rv; GetAttentionWithCycleCount(aCycleCount, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -13745,7 +13819,7 @@ nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent *aMouseDownEvent, nsIDOMElemen ErrorResult rv; BeginWindowMove(*mouseDownEvent, panel, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -13785,6 +13859,14 @@ nsGlobalWindow::BeginWindowMove(Event& aMouseDownEvent, Element* aPanel, aError = widget->BeginMoveDrag(mouseEvent); } +already_AddRefed +nsGlobalWindow::GetWindowRoot(mozilla::ErrorResult& aError) +{ + FORWARD_TO_OUTER_OR_THROW(GetWindowRoot, (aError), aError, nullptr); + nsCOMPtr root = GetTopWindowRoot(); + return root.forget().downcast(); +} + //Note: This call will lock the cursor, it will not change as it moves. //To unlock, the cursor must be set back to CURSOR_AUTO. NS_IMETHODIMP @@ -13792,7 +13874,7 @@ nsGlobalChromeWindow::SetCursor(const nsAString& aCursor) { ErrorResult rv; SetCursor(aCursor, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -13855,7 +13937,7 @@ nsGlobalChromeWindow::GetBrowserDOMWindow(nsIBrowserDOMWindow **aBrowserWindow) { ErrorResult rv; NS_IF_ADDREF(*aBrowserWindow = GetBrowserDOMWindow(rv)); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsIBrowserDOMWindow* @@ -13872,7 +13954,7 @@ nsGlobalChromeWindow::SetBrowserDOMWindow(nsIBrowserDOMWindow *aBrowserWindow) { ErrorResult rv; SetBrowserDOMWindow(aBrowserWindow, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -13893,7 +13975,7 @@ nsGlobalChromeWindow::NotifyDefaultButtonLoaded(nsIDOMElement* aDefaultButton) ErrorResult rv; NotifyDefaultButtonLoaded(*defaultButton, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -13950,7 +14032,7 @@ nsGlobalChromeWindow::GetMessageManager(nsIMessageBroadcaster** aManager) { ErrorResult rv; NS_IF_ADDREF(*aManager = GetMessageManager(rv)); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsIMessageBroadcaster* @@ -13976,7 +14058,7 @@ nsGlobalChromeWindow::GetGroupMessageManager(const nsAString& aGroup, { ErrorResult rv; NS_IF_ADDREF(*aManager = GetGroupMessageManager(aGroup, rv)); - return rv.ErrorCode(); + return rv.StealNSResult(); } nsIMessageBroadcaster* @@ -14152,7 +14234,7 @@ nsGlobalWindow::GetConsole(JSContext* aCx, ErrorResult rv; nsRefPtr console = GetConsole(rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } if (!GetOrCreateDOMReflector(aCx, console, aConsole)) { @@ -14165,18 +14247,9 @@ nsGlobalWindow::GetConsole(JSContext* aCx, NS_IMETHODIMP nsGlobalWindow::SetConsole(JSContext* aCx, JS::Handle aValue) { - JS::Rooted thisObj(aCx, GetWrapper()); - if (!thisObj) { - return NS_ERROR_UNEXPECTED; - } - - if (!JS_WrapObject(aCx, &thisObj) || - !JS_DefineProperty(aCx, thisObj, "console", aValue, JSPROP_ENUMERATE, - JS_STUBGETTER, JS_STUBSETTER)) { - return NS_ERROR_FAILURE; - } - - return NS_OK; + ErrorResult rv; + RedefineProperty(aCx, "console", aValue, rv); + return rv.StealNSResult(); } Console* @@ -14336,6 +14409,63 @@ nsGlobalWindow::DisableNetworkEvent(uint32_t aType) } #endif // MOZ_B2G +void +nsGlobalWindow::RedefineProperty(JSContext* aCx, const char* aPropName, + JS::Handle aValue, + ErrorResult& aError) +{ + JS::Rooted thisObj(aCx, GetWrapperPreserveColor()); + if (!thisObj) { + aError.Throw(NS_ERROR_UNEXPECTED); + return; + } + + if (!JS_WrapObject(aCx, &thisObj) || + !JS_DefineProperty(aCx, thisObj, aPropName, aValue, JSPROP_ENUMERATE, + JS_STUBGETTER, JS_STUBSETTER)) { + aError.Throw(NS_ERROR_FAILURE); + } +} + +void +nsGlobalWindow::GetReplaceableWindowCoord(JSContext* aCx, + nsGlobalWindow::WindowCoordGetter aGetter, + JS::MutableHandle aRetval, + ErrorResult& aError) +{ + int32_t coord = (this->*aGetter)(aError); + if (!aError.Failed() && + !ToJSValue(aCx, coord, aRetval)) { + aError.Throw(NS_ERROR_FAILURE); + } +} + +void +nsGlobalWindow::SetReplaceableWindowCoord(JSContext* aCx, + nsGlobalWindow::WindowCoordSetter aSetter, + JS::Handle aValue, + const char* aPropName, + ErrorResult& aError) +{ + /* + * If caller is not chrome and the user has not explicitly exempted the site, + * just treat this the way we would an IDL replaceable property. + */ + nsGlobalWindow* outer = GetOuterWindowInternal(); + if (!outer || !outer->CanMoveResizeWindows() || outer->IsFrame()) { + RedefineProperty(aCx, aPropName, aValue, aError); + return; + } + + int32_t value; + if (!ValueToPrimitive(aCx, aValue, &value)) { + aError.Throw(NS_ERROR_UNEXPECTED); + return; + } + + (this->*aSetter)(value, aError); +} + #ifdef _WINDOWS_ #error "Never include windows.h in this file!" #endif diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 60ac1d740f..3602e411ed 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -52,6 +52,7 @@ #include "Units.h" #include "nsComponentManagerUtils.h" #include "nsSize.h" +#include "nsCheapSets.h" #define DEFAULT_HOME_PAGE "www.mozilla.org" #define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage" @@ -478,7 +479,6 @@ public: virtual void ForceClose() override; virtual void MaybeUpdateTouchState() override; - virtual void UpdateTouchState() override; // Outer windows only. virtual bool DispatchCustomEvent(const nsAString& aEventName) override; @@ -966,10 +966,14 @@ public: void ScrollByPages(int32_t numPages, const mozilla::dom::ScrollOptions& aOptions); void MozScrollSnap(); - int32_t GetInnerWidth(mozilla::ErrorResult& aError); - void SetInnerWidth(int32_t aInnerWidth, mozilla::ErrorResult& aError); - int32_t GetInnerHeight(mozilla::ErrorResult& aError); - void SetInnerHeight(int32_t aInnerHeight, mozilla::ErrorResult& aError); + void GetInnerWidth(JSContext* aCx, JS::MutableHandle aValue, + mozilla::ErrorResult& aError); + void SetInnerWidth(JSContext* aCx, JS::Handle aValue, + mozilla::ErrorResult& aError); + void GetInnerHeight(JSContext* aCx, JS::MutableHandle aValue, + mozilla::ErrorResult& aError); + void SetInnerHeight(JSContext* aCx, JS::Handle aValue, + mozilla::ErrorResult& aError); double GetScrollX(mozilla::ErrorResult& aError); double GetPageXOffset(mozilla::ErrorResult& aError) { @@ -981,14 +985,22 @@ public: return GetScrollY(aError); } void MozRequestOverfill(mozilla::dom::OverfillCallback& aCallback, mozilla::ErrorResult& aError); - int32_t GetScreenX(mozilla::ErrorResult& aError); - void SetScreenX(int32_t aScreenX, mozilla::ErrorResult& aError); - int32_t GetScreenY(mozilla::ErrorResult& aError); - void SetScreenY(int32_t aScreenY, mozilla::ErrorResult& aError); - int32_t GetOuterWidth(mozilla::ErrorResult& aError); - void SetOuterWidth(int32_t aOuterWidth, mozilla::ErrorResult& aError); - int32_t GetOuterHeight(mozilla::ErrorResult& aError); - void SetOuterHeight(int32_t aOuterHeight, mozilla::ErrorResult& aError); + void GetScreenX(JSContext* aCx, JS::MutableHandle aValue, + mozilla::ErrorResult& aError); + void SetScreenX(JSContext* aCx, JS::Handle aValue, + mozilla::ErrorResult& aError); + void GetScreenY(JSContext* aCx, JS::MutableHandle aValue, + mozilla::ErrorResult& aError); + void SetScreenY(JSContext* aCx, JS::Handle aValue, + mozilla::ErrorResult& aError); + void GetOuterWidth(JSContext* aCx, JS::MutableHandle aValue, + mozilla::ErrorResult& aError); + void SetOuterWidth(JSContext* aCx, JS::Handle aValue, + mozilla::ErrorResult& aError); + void GetOuterHeight(JSContext* aCx, JS::MutableHandle aValue, + mozilla::ErrorResult& aError); + void SetOuterHeight(JSContext* aCx, JS::Handle aValue, + mozilla::ErrorResult& aError); int32_t RequestAnimationFrame(mozilla::dom::FrameRequestCallback& aCallback, mozilla::ErrorResult& aError); void CancelAnimationFrame(int32_t aHandle, mozilla::ErrorResult& aError); @@ -1092,7 +1104,44 @@ public: JS::MutableHandle aRetval, mozilla::ErrorResult& aError); + already_AddRefed GetWindowRoot(mozilla::ErrorResult& aError); + protected: + // Web IDL helpers + + // Redefine the property called aPropName on this window object to be a value + // property with the value aValue, much like we would do for a [Replaceable] + // property in IDL. + void RedefineProperty(JSContext* aCx, const char* aPropName, + JS::Handle aValue, + mozilla::ErrorResult& aError); + + // Implementation guts for our writable IDL attributes that are really + // supposed to be readonly replaceable. + typedef int32_t (nsGlobalWindow::*WindowCoordGetter)(mozilla::ErrorResult&); + typedef void (nsGlobalWindow::*WindowCoordSetter)(int32_t, + mozilla::ErrorResult&); + void GetReplaceableWindowCoord(JSContext* aCx, WindowCoordGetter aGetter, + JS::MutableHandle aRetval, + mozilla::ErrorResult& aError); + void SetReplaceableWindowCoord(JSContext* aCx, WindowCoordSetter aSetter, + JS::Handle aValue, + const char* aPropName, + mozilla::ErrorResult& aError); + // And the implementations of WindowCoordGetter/WindowCoordSetter. + int32_t GetInnerWidth(mozilla::ErrorResult& aError); + void SetInnerWidth(int32_t aInnerWidth, mozilla::ErrorResult& aError); + int32_t GetInnerHeight(mozilla::ErrorResult& aError); + void SetInnerHeight(int32_t aInnerHeight, mozilla::ErrorResult& aError); + int32_t GetScreenX(mozilla::ErrorResult& aError); + void SetScreenX(int32_t aScreenX, mozilla::ErrorResult& aError); + int32_t GetScreenY(mozilla::ErrorResult& aError); + void SetScreenY(int32_t aScreenY, mozilla::ErrorResult& aError); + int32_t GetOuterWidth(mozilla::ErrorResult& aError); + void SetOuterWidth(int32_t aOuterWidth, mozilla::ErrorResult& aError); + int32_t GetOuterHeight(mozilla::ErrorResult& aError); + void SetOuterHeight(int32_t aOuterHeight, mozilla::ErrorResult& aError); + // Array of idle observers that are notified of idle events. nsTObserverArray mIdleObservers; @@ -1267,7 +1316,7 @@ public: { mozilla::ErrorResult rv; ClearTimeoutOrInterval(aTimerID, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } // JS specific timeout functions (JS args grabbed from context). @@ -1543,6 +1592,7 @@ protected: // Indicates whether this window wants gamepad input events bool mHasGamepad : 1; #ifdef MOZ_GAMEPAD + nsCheapSet mGamepadIndexSet; nsRefPtrHashtable mGamepads; bool mHasSeenGamepadInput; #endif diff --git a/dom/base/nsGlobalWindowCommands.cpp b/dom/base/nsGlobalWindowCommands.cpp index 29b3b16568..c8c21f89a4 100644 --- a/dom/base/nsGlobalWindowCommands.cpp +++ b/dom/base/nsGlobalWindowCommands.cpp @@ -661,8 +661,7 @@ nsSelectionCommand::GetContentViewerEditFromContext(nsISupports *aContext, nsCOMPtr edit(do_QueryInterface(viewer)); NS_ENSURE_TRUE(edit, NS_ERROR_FAILURE); - *aEditInterface = edit; - NS_ADDREF(*aEditInterface); + edit.forget(aEditInterface); return NS_OK; } diff --git a/dom/base/nsHTMLContentSerializer.cpp b/dom/base/nsHTMLContentSerializer.cpp index 7ee26af4d3..9f4be312e0 100644 --- a/dom/base/nsHTMLContentSerializer.cpp +++ b/dom/base/nsHTMLContentSerializer.cpp @@ -40,14 +40,12 @@ using namespace mozilla::dom; -nsresult NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer) +nsresult +NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer) { - nsHTMLContentSerializer* it = new nsHTMLContentSerializer(); - if (!it) { - return NS_ERROR_OUT_OF_MEMORY; - } - - return CallQueryInterface(it, aSerializer); + nsRefPtr it = new nsHTMLContentSerializer(); + it.forget(aSerializer); + return NS_OK; } nsHTMLContentSerializer::nsHTMLContentSerializer() diff --git a/dom/base/nsHostObjectProtocolHandler.cpp b/dom/base/nsHostObjectProtocolHandler.cpp index 7a42c2e2c8..4542ba765a 100644 --- a/dom/base/nsHostObjectProtocolHandler.cpp +++ b/dom/base/nsHostObjectProtocolHandler.cpp @@ -538,7 +538,7 @@ nsHostObjectProtocolHandler::NewChannel2(nsIURI* uri, ErrorResult error; uint64_t size = blob->GetSize(error); if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); + return error.StealNSResult(); } channel->SetOriginalURI(uri); diff --git a/dom/base/nsIAnimationObserver.h b/dom/base/nsIAnimationObserver.h index c78f080359..fe05a4d60f 100644 --- a/dom/base/nsIAnimationObserver.h +++ b/dom/base/nsIAnimationObserver.h @@ -9,7 +9,7 @@ namespace mozilla { namespace dom { -class AnimationPlayer; +class Animation; } } @@ -22,36 +22,36 @@ class nsIAnimationObserver : public nsIMutationObserver public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_IANIMATION_OBSERVER_IID) - virtual void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer) = 0; - virtual void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer) = 0; - virtual void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer) = 0; + virtual void AnimationAdded(mozilla::dom::Animation* aAnimation) = 0; + virtual void AnimationChanged(mozilla::dom::Animation* aAnimation) = 0; + virtual void AnimationRemoved(mozilla::dom::Animation* aAnimation) = 0; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIAnimationObserver, NS_IANIMATION_OBSERVER_IID) #define NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONADDED \ - virtual void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer) \ + virtual void AnimationAdded(mozilla::dom::Animation* aAnimation) \ override; #define NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONCHANGED \ - virtual void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer) \ + virtual void AnimationChanged(mozilla::dom::Animation* aAnimation) \ override; #define NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONREMOVED \ - virtual void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer) \ + virtual void AnimationRemoved(mozilla::dom::Animation* aAnimation) \ override; #define NS_IMPL_NSIANIMATIONOBSERVER_STUB(class_) \ void \ -class_::AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer) \ +class_::AnimationAdded(mozilla::dom::Animation* aAnimation) \ { \ } \ void \ -class_::AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer) \ +class_::AnimationChanged(mozilla::dom::Animation* aAnimation) \ { \ } \ void \ -class_::AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer) \ +class_::AnimationRemoved(mozilla::dom::Animation* aAnimation) \ { \ } \ NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(class_) \ diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index 11ad3981f4..883723ba32 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -89,7 +89,7 @@ namespace mozilla { class CSSStyleSheet; class ErrorResult; class EventStates; -class PendingPlayerTracker; +class PendingAnimationTracker; class SVGAttrAnimationRuleProcessor; namespace css { @@ -102,7 +102,6 @@ class VRHMDInfo; } // namespace gfx namespace dom { -class AnimationTimeline; class AnonymousContent; class Attr; class BoxObject; @@ -110,6 +109,7 @@ class CDATASection; class Comment; struct CustomElementDefinition; class DocumentFragment; +class DocumentTimeline; class DocumentType; class DOMImplementation; class DOMStringList; @@ -1888,16 +1888,17 @@ public: // mAnimationController isn't yet initialized. virtual nsSMILAnimationController* GetAnimationController() = 0; - // Gets the tracker for animation players that are waiting to start. - // Returns nullptr if there is no pending player tracker for this document + // Gets the tracker for animations that are waiting to start. + // Returns nullptr if there is no pending animation tracker for this document // which will be the case if there have never been any CSS animations or // transitions on elements in the document. - virtual mozilla::PendingPlayerTracker* GetPendingPlayerTracker() = 0; + virtual mozilla::PendingAnimationTracker* GetPendingAnimationTracker() = 0; - // Gets the tracker for animation players that are waiting to start and + // Gets the tracker for animations that are waiting to start and // creates it if it doesn't already exist. As a result, the return value // will never be nullptr. - virtual mozilla::PendingPlayerTracker* GetOrCreatePendingPlayerTracker() = 0; + virtual mozilla::PendingAnimationTracker* + GetOrCreatePendingAnimationTracker() = 0; // Makes the images on this document capable of having their animation // active or suspended. An Image will animate as long as at least one of its @@ -2138,7 +2139,7 @@ public: virtual already_AddRefed GetUndoManager() = 0; - virtual mozilla::dom::AnimationTimeline* Timeline() = 0; + virtual mozilla::dom::DocumentTimeline* Timeline() = 0; typedef mozilla::dom::CallbackObjectHolder< mozilla::dom::FrameRequestCallback, @@ -2154,6 +2155,13 @@ public: */ void TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks); + /** + * @return true if this document's frame request callbacks should be + * throttled. We throttle requestAnimationFrame for documents which aren't + * visible (e.g. scrolled out of the viewport). + */ + bool ShouldThrottleFrameRequests(); + // This returns true when the document tree is being teared down. bool InUnlinkOrDeletion() { return mInUnlinkOrDeletion; } diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp index 1cfeb06aff..c78062ac42 100644 --- a/dom/base/nsINode.cpp +++ b/dom/base/nsINode.cpp @@ -556,7 +556,7 @@ nsINode::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn) if (!rv.Failed()) { NS_ADDREF(*aReturn = aOldChild); } - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -2463,7 +2463,7 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsIDOMNode *aNewChild, if (result) { NS_ADDREF(*aReturn = result->AsDOMNode()); } - return rv.ErrorCode(); + return rv.StealNSResult(); } nsresult @@ -2650,7 +2650,7 @@ nsINode::ParseSelectorList(const nsAString& aSelectorString, // We hit this for syntax errors, which are quite common, so don't // use NS_ENSURE_SUCCESS. (For example, jQuery has an extended set // of selectors, but it sees if we can parse them first.) - MOZ_ASSERT(aRv.ErrorCode() == NS_ERROR_DOM_SYNTAX_ERR, + MOZ_ASSERT(aRv.ErrorCodeIs(NS_ERROR_DOM_SYNTAX_ERR), "Unexpected error, so cached version won't return it"); cache.CacheList(aSelectorString, nullptr); return nullptr; @@ -2858,7 +2858,7 @@ nsINode::QuerySelector(const nsAString& aSelector, nsIDOMElement **aReturn) ErrorResult rv; Element* result = nsINode::QuerySelector(aSelector, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } nsCOMPtr elt = do_QueryInterface(result); elt.forget(aReturn); @@ -2870,7 +2870,7 @@ nsINode::QuerySelectorAll(const nsAString& aSelector, nsIDOMNodeList **aReturn) { ErrorResult rv; *aReturn = nsINode::QuerySelectorAll(aSelector, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } Element* diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h index 596d820de6..cd2eb56f0e 100644 --- a/dom/base/nsINode.h +++ b/dom/base/nsINode.h @@ -1779,7 +1779,7 @@ public: nsINode* parent = GetParentNode(); mozilla::ErrorResult rv; parent->RemoveChild(*this, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } // ChildNode methods @@ -2029,7 +2029,7 @@ ToCanonicalSupports(nsINode* aPointer) { \ mozilla::ErrorResult rv; \ nsINode::SetNodeValue(aNodeValue, rv); \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD GetNodeType(uint16_t* aNodeType) __VA_ARGS__ override \ { \ @@ -2097,7 +2097,7 @@ ToCanonicalSupports(nsINode* aPointer) mozilla::ErrorResult rv; \ nsCOMPtr clone = nsINode::CloneNode(aDeep, rv); \ if (rv.Failed()) { \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } \ *aResult = clone.forget().take()->AsDOMNode(); \ return NS_OK; \ @@ -2140,13 +2140,13 @@ ToCanonicalSupports(nsINode* aPointer) { \ mozilla::ErrorResult rv; \ nsINode::GetTextContent(aTextContent, rv); \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD SetTextContent(const nsAString& aTextContent) __VA_ARGS__ override \ { \ mozilla::ErrorResult rv; \ nsINode::SetTextContent(aTextContent, rv); \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } \ NS_IMETHOD LookupPrefix(const nsAString& aNamespaceURI, nsAString& aResult) __VA_ARGS__ override \ { \ diff --git a/dom/base/nsImageLoadingContent.cpp b/dom/base/nsImageLoadingContent.cpp index b95376a37f..3307f63f63 100644 --- a/dom/base/nsImageLoadingContent.cpp +++ b/dom/base/nsImageLoadingContent.cpp @@ -498,7 +498,7 @@ nsImageLoadingContent::GetRequest(int32_t aRequestType, ErrorResult result; *aRequest = GetRequest(aRequestType, result).take(); - return result.ErrorCode(); + return result.StealNSResult(); } NS_IMETHODIMP_(bool) @@ -610,7 +610,7 @@ nsImageLoadingContent::GetRequestType(imgIRequest* aRequest, ErrorResult result; *aRequestType = GetRequestType(aRequest, result); - return result.ErrorCode(); + return result.StealNSResult(); } already_AddRefed @@ -636,7 +636,7 @@ nsImageLoadingContent::GetCurrentURI(nsIURI** aURI) ErrorResult result; *aURI = GetCurrentURI(result).take(); - return result.ErrorCode(); + return result.StealNSResult(); } already_AddRefed @@ -693,7 +693,7 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel, ErrorResult result; *aListener = LoadImageWithChannel(aChannel, result).take(); - return result.ErrorCode(); + return result.StealNSResult(); } void @@ -733,7 +733,7 @@ nsImageLoadingContent::ForceReload(bool aNotify /* = true */, ErrorResult result; ForceReload(notify, result); - return result.ErrorCode(); + return result.StealNSResult(); } NS_IMETHODIMP diff --git a/dom/base/nsJSTimeoutHandler.cpp b/dom/base/nsJSTimeoutHandler.cpp index 751a3d37e2..3687cf2788 100644 --- a/dom/base/nsJSTimeoutHandler.cpp +++ b/dom/base/nsJSTimeoutHandler.cpp @@ -340,7 +340,7 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval, ErrorResult error; *aAllowEval = CheckCSPForEval(cx, aWindow, error); if (error.Failed() || !*aAllowEval) { - return error.ErrorCode(); + return error.StealNSResult(); } MOZ_ASSERT(mExpr.IsEmpty()); diff --git a/dom/base/nsNodeUtils.cpp b/dom/base/nsNodeUtils.cpp index 182d6819eb..c13e70b39d 100644 --- a/dom/base/nsNodeUtils.cpp +++ b/dom/base/nsNodeUtils.cpp @@ -24,8 +24,10 @@ #include "nsBindingManager.h" #include "nsGenericHTMLElement.h" #include "mozilla/Assertions.h" +#include "mozilla/dom/Animation.h" #include "mozilla/dom/HTMLImageElement.h" #include "mozilla/dom/HTMLMediaElement.h" +#include "mozilla/dom/KeyframeEffect.h" #include "nsWrapperCacheInlines.h" #include "nsObjectLoadingContent.h" #include "nsDOMMutationObserver.h" @@ -214,16 +216,16 @@ nsNodeUtils::ContentRemoved(nsINode* aContainer, } static inline Element* -GetTarget(AnimationPlayer* aPlayer) +GetTarget(Animation* aAnimation) { - Animation* source = aPlayer->GetSource(); - if (!source) { + KeyframeEffectReadonly* effect = aAnimation->GetEffect(); + if (!effect) { return nullptr; } Element* target; nsCSSPseudoElements::Type pseudoType; - source->GetTarget(target, pseudoType); + effect->GetTarget(target, pseudoType); // If the animation targets a pseudo-element, we don't dispatch // notifications for it. (In the future we will have PseudoElement @@ -232,48 +234,48 @@ GetTarget(AnimationPlayer* aPlayer) return nullptr; } - return source->GetTarget(); + return effect->GetTarget(); } void -nsNodeUtils::AnimationAdded(AnimationPlayer* aPlayer) +nsNodeUtils::AnimationAdded(Animation* aAnimation) { - Element* target = GetTarget(aPlayer); + Element* target = GetTarget(aAnimation); if (!target) { return; } nsIDocument* doc = target->OwnerDoc(); if (doc->MayHaveAnimationObservers()) { - IMPL_ANIMATION_NOTIFICATION(AnimationAdded, target, (aPlayer)); + IMPL_ANIMATION_NOTIFICATION(AnimationAdded, target, (aAnimation)); } } void -nsNodeUtils::AnimationChanged(AnimationPlayer* aPlayer) +nsNodeUtils::AnimationChanged(Animation* aAnimation) { - Element* target = GetTarget(aPlayer); + Element* target = GetTarget(aAnimation); if (!target) { return; } nsIDocument* doc = target->OwnerDoc(); if (doc->MayHaveAnimationObservers()) { - IMPL_ANIMATION_NOTIFICATION(AnimationChanged, target, (aPlayer)); + IMPL_ANIMATION_NOTIFICATION(AnimationChanged, target, (aAnimation)); } } void -nsNodeUtils::AnimationRemoved(AnimationPlayer* aPlayer) +nsNodeUtils::AnimationRemoved(Animation* aAnimation) { - Element* target = GetTarget(aPlayer); + Element* target = GetTarget(aAnimation); if (!target) { return; } nsIDocument* doc = target->OwnerDoc(); if (doc->MayHaveAnimationObservers()) { - IMPL_ANIMATION_NOTIFICATION(AnimationRemoved, target, (aPlayer)); + IMPL_ANIMATION_NOTIFICATION(AnimationRemoved, target, (aAnimation)); } } diff --git a/dom/base/nsNodeUtils.h b/dom/base/nsNodeUtils.h index 91433b37ae..d5e2679973 100644 --- a/dom/base/nsNodeUtils.h +++ b/dom/base/nsNodeUtils.h @@ -16,7 +16,7 @@ template class nsCOMArray; class nsCycleCollectionTraversalCallback; namespace mozilla { namespace dom { -class AnimationPlayer; +class Animation; } } @@ -125,9 +125,9 @@ public: } } - static void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer); - static void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer); - static void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer); + static void AnimationAdded(mozilla::dom::Animation* aAnimation); + static void AnimationChanged(mozilla::dom::Animation* aAnimation); + static void AnimationRemoved(mozilla::dom::Animation* aAnimation); /** * To be called when reference count of aNode drops to zero. diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index d5b4f56800..17bf74a330 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -63,8 +63,8 @@ enum UIStateChangeType }; #define NS_PIDOMWINDOW_IID \ -{ 0x19fb3019, 0x7b5d, 0x4235, \ - { 0xa9, 0x59, 0xa2, 0x31, 0xa2, 0xe7, 0x94, 0x79 } } +{ 0x2485d4d7, 0xf7cb, 0x481e, \ + { 0x9c, 0x89, 0xb2, 0xa8, 0x12, 0x67, 0x7f, 0x97 } } class nsPIDOMWindow : public nsIDOMWindowInternal { @@ -178,7 +178,6 @@ public: } virtual void MaybeUpdateTouchState() {} - virtual void UpdateTouchState() {} nsIDocument* GetExtantDoc() const { @@ -206,6 +205,18 @@ public: float GetAudioGlobalVolume(); + virtual void SetServiceWorkersTestingEnabled(bool aEnabled) + { + MOZ_ASSERT(IsOuterWindow()); + mServiceWorkersTestingEnabled = aEnabled; + } + + bool GetServiceWorkersTestingEnabled() + { + MOZ_ASSERT(IsOuterWindow()); + return mServiceWorkersTestingEnabled; + } + protected: // Lazily instantiate an about:blank document if necessary, and if // we have what it takes to do so. @@ -462,13 +473,10 @@ public: */ void SetHasTouchEventListeners() { - mMayHaveTouchEventListener = true; - MaybeUpdateTouchState(); - } - - bool HasTouchEventListeners() - { - return mMayHaveTouchEventListener; + if (!mMayHaveTouchEventListener) { + mMayHaveTouchEventListener = true; + MaybeUpdateTouchState(); + } } /** @@ -847,6 +855,10 @@ protected: bool mHasNotifiedGlobalCreated; uint32_t mMarkedCCGeneration; + + // Let the service workers plumbing know that some feature are enabled while + // testing. + bool mServiceWorkersTestingEnabled; }; diff --git a/dom/base/nsPlainTextSerializer.cpp b/dom/base/nsPlainTextSerializer.cpp index 2b7d56be0f..5ebb60e2fa 100644 --- a/dom/base/nsPlainTextSerializer.cpp +++ b/dom/base/nsPlainTextSerializer.cpp @@ -54,14 +54,12 @@ static int32_t GetUnicharStringWidth(const char16_t* pwcs, int32_t n); static const uint32_t TagStackSize = 500; static const uint32_t OLStackSize = 100; -nsresult NS_NewPlainTextSerializer(nsIContentSerializer** aSerializer) +nsresult +NS_NewPlainTextSerializer(nsIContentSerializer** aSerializer) { - nsPlainTextSerializer* it = new nsPlainTextSerializer(); - if (!it) { - return NS_ERROR_OUT_OF_MEMORY; - } - - return CallQueryInterface(it, aSerializer); + nsRefPtr it = new nsPlainTextSerializer(); + it.forget(aSerializer); + return NS_OK; } nsPlainTextSerializer::nsPlainTextSerializer() diff --git a/dom/base/nsRange.cpp b/dom/base/nsRange.cpp index 99379f5559..873c9af6e2 100644 --- a/dom/base/nsRange.cpp +++ b/dom/base/nsRange.cpp @@ -745,7 +745,7 @@ nsRange::IsPointInRange(nsIDOMNode* aParent, int32_t aOffset, bool* aResult) ErrorResult rv; *aResult = IsPointInRange(*parent, aOffset, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } bool @@ -753,8 +753,8 @@ nsRange::IsPointInRange(nsINode& aParent, uint32_t aOffset, ErrorResult& aRv) { uint16_t compareResult = ComparePoint(aParent, aOffset, aRv); // If the node isn't in the range's document, it clearly isn't in the range. - if (aRv.ErrorCode() == NS_ERROR_DOM_WRONG_DOCUMENT_ERR) { - aRv = NS_OK; + if (aRv.ErrorCodeIs(NS_ERROR_DOM_WRONG_DOCUMENT_ERR)) { + aRv.SuppressException(); return false; } @@ -771,7 +771,7 @@ nsRange::ComparePoint(nsIDOMNode* aParent, int32_t aOffset, int16_t* aResult) ErrorResult rv; *aResult = ComparePoint(*parent, aOffset, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } int16_t @@ -823,7 +823,7 @@ nsRange::IntersectsNode(nsIDOMNode* aNode, bool* aResult) ErrorResult rv; *aResult = IntersectsNode(*node, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } bool @@ -1107,7 +1107,7 @@ nsRange::GetCommonAncestorContainer(nsIDOMNode** aCommonParent) *aCommonParent = nullptr; } - return rv.ErrorCode(); + return rv.StealNSResult(); } nsINode* @@ -1178,7 +1178,7 @@ nsRange::SetStart(nsIDOMNode* aParent, int32_t aOffset) ErrorResult rv; SetStart(*parent, aOffset, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } /* virtual */ nsresult @@ -1228,7 +1228,7 @@ nsRange::SetStartBefore(nsIDOMNode* aSibling) ErrorResult rv; SetStartBefore(*sibling, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -1253,7 +1253,7 @@ nsRange::SetStartAfter(nsIDOMNode* aSibling) ErrorResult rv; SetStartAfter(*sibling, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -1277,7 +1277,7 @@ nsRange::SetEnd(nsIDOMNode* aParent, int32_t aOffset) ErrorResult rv; SetEnd(*parent, aOffset, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } /* virtual */ nsresult @@ -1327,7 +1327,7 @@ nsRange::SetEndBefore(nsIDOMNode* aSibling) ErrorResult rv; SetEndBefore(*sibling, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -1352,7 +1352,7 @@ nsRange::SetEndAfter(nsIDOMNode* aSibling) ErrorResult rv; SetEndAfter(*sibling, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP @@ -1378,7 +1378,7 @@ nsRange::SelectNode(nsIDOMNode* aN) ErrorResult rv; SelectNode(*node, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -1414,7 +1414,7 @@ nsRange::SelectNodeContents(nsIDOMNode* aN) ErrorResult rv; SelectNodeContents(*node, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -1709,12 +1709,12 @@ CollapseRangeAfterDelete(nsRange* aRange) ErrorResult rv; nsCOMPtr commonAncestor = aRange->GetCommonAncestorContainer(rv); - if (rv.Failed()) return rv.ErrorCode(); + if (rv.Failed()) return rv.StealNSResult(); nsCOMPtr startContainer = aRange->GetStartContainer(rv); - if (rv.Failed()) return rv.ErrorCode(); + if (rv.Failed()) return rv.StealNSResult(); nsCOMPtr endContainer = aRange->GetEndContainer(rv); - if (rv.Failed()) return rv.ErrorCode(); + if (rv.Failed()) return rv.StealNSResult(); // Collapse to one of the end points if they are already in the // commonAncestor. This should work ok since this method is called @@ -1745,7 +1745,7 @@ CollapseRangeAfterDelete(nsRange* aRange) return NS_ERROR_FAILURE; // This should never happen! aRange->SelectNode(*nodeToSelect, rv); - if (rv.Failed()) return rv.ErrorCode(); + if (rv.Failed()) return rv.StealNSResult(); return aRange->Collapse(false); } @@ -1782,7 +1782,7 @@ PrependChild(nsINode* aParent, nsINode* aChild) nsCOMPtr first = aParent->GetFirstChild(); ErrorResult rv; aParent->InsertBefore(*aChild, first, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } // Helper function for CutContents, making sure that the current node wasn't @@ -1814,7 +1814,7 @@ nsRange::CutContents(DocumentFragment** aFragment) ErrorResult res; nsCOMPtr commonAncestor = GetCommonAncestorContainer(res); - NS_ENSURE_SUCCESS(res.ErrorCode(), res.ErrorCode()); + NS_ENSURE_TRUE(!res.Failed(), res.StealNSResult()); // If aFragment isn't null, create a temporary fragment to hold our return. nsRefPtr retval; @@ -1865,7 +1865,7 @@ nsRange::CutContents(DocumentFragment** aFragment) // There's nothing for us to delete. rv = CollapseRangeAfterDelete(this); if (NS_SUCCEEDED(rv) && aFragment) { - NS_ADDREF(*aFragment = retval); + retval.forget(aFragment); } return rv; } @@ -1988,7 +1988,7 @@ nsRange::CutContents(DocumentFragment** aFragment) if (retval) { ErrorResult rv; nodeToResult = node->CloneNode(false, rv); - NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode()); + NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult()); } handled = true; } @@ -2052,7 +2052,7 @@ nsRange::CutContents(DocumentFragment** aFragment) if (parent) { mozilla::ErrorResult error; parent->RemoveChild(*node, error); - NS_ENSURE_FALSE(error.Failed(), error.ErrorCode()); + NS_ENSURE_FALSE(error.Failed(), error.StealNSResult()); } NS_ENSURE_STATE(!guard.Mutated(1) || ValidateCurrentNode(this, iter)); @@ -2072,7 +2072,7 @@ nsRange::CutContents(DocumentFragment** aFragment) rv = CollapseRangeAfterDelete(this); if (NS_SUCCEEDED(rv) && aFragment) { - NS_ADDREF(*aFragment = retval); + retval.forget(aFragment); } return rv; } @@ -2116,7 +2116,7 @@ nsRange::CompareBoundaryPoints(uint16_t aHow, nsIDOMRange* aOtherRange, ErrorResult rv; *aCmpRet = CompareBoundaryPoints(aHow, *otherRange, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } int16_t @@ -2194,7 +2194,7 @@ nsRange::CloneParentsBetween(nsINode *aAncestor, nsCOMPtr clone = parent->CloneNode(false, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } if (!clone) { return NS_ERROR_FAILURE; @@ -2204,7 +2204,7 @@ nsRange::CloneParentsBetween(nsINode *aAncestor, firstParent = lastParent = clone; } else { clone->AppendChild(*lastParent, rv); - if (rv.Failed()) return rv.ErrorCode(); + if (rv.Failed()) return rv.StealNSResult(); lastParent = clone; } @@ -2226,7 +2226,7 @@ nsRange::CloneContents(nsIDOMDocumentFragment** aReturn) { ErrorResult rv; *aReturn = CloneContents(rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -2462,7 +2462,7 @@ nsRange::InsertNode(nsIDOMNode* aNode) ErrorResult rv; InsertNode(*node, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -2559,7 +2559,7 @@ nsRange::SurroundContents(nsIDOMNode* aNewParent) } ErrorResult rv; SurroundContents(*node, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void diff --git a/dom/base/nsScreen.cpp b/dom/base/nsScreen.cpp index a63e9796eb..bff3456aa3 100644 --- a/dom/base/nsScreen.cpp +++ b/dom/base/nsScreen.cpp @@ -85,7 +85,7 @@ nsScreen::GetPixelDepth(ErrorResult& aRv) { \ ErrorResult rv; \ *aOut = Get ## _name(rv); \ - return rv.ErrorCode(); \ + return rv.StealNSResult(); \ } FORWARD_LONG_GETTER(AvailWidth) diff --git a/dom/base/nsScriptLoader.cpp b/dom/base/nsScriptLoader.cpp index 0fdb6d4c47..1d4641c605 100644 --- a/dom/base/nsScriptLoader.cpp +++ b/dom/base/nsScriptLoader.cpp @@ -1153,7 +1153,8 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest, // New script entry point required, due to the "Create a script" sub-step of // http://www.whatwg.org/specs/web-apps/current-work/#execute-the-script-block - AutoEntryScript entryScript(globalObject, true, context->GetNativeContext()); + AutoEntryScript entryScript(globalObject, " + + + + + + + + diff --git a/dom/base/test/test_bug345339.html b/dom/base/test/test_bug345339.html index 4439331199..e2a83895e5 100644 --- a/dom/base/test/test_bug345339.html +++ b/dom/base/test/test_bug345339.html @@ -17,11 +17,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=345339 src="http://mochi.test:8888/tests/dom/base/test/345339_iframe.html">
-
 
diff --git a/dom/base/test/test_innersize_scrollport.html b/dom/base/test/test_innersize_scrollport.html index 407f71f266..a000e93554 100644 --- a/dom/base/test/test_innersize_scrollport.html +++ b/dom/base/test/test_innersize_scrollport.html @@ -27,10 +27,15 @@ function run() is(window.innerWidth, newWidth, "innerWidth not updated to scroll port width"); is(window.innerHeight, newHeight, "innerHeight not updated to scroll port height"); + var innerWidthGetter = Object.getOwnPropertyDescriptor(window, "innerWidth").get; + var innerHeightGetter = Object.getOwnPropertyDescriptor(window, "innerHeight").get; + window.innerWidth = oldWidth; window.innerHeight = oldHeight; - is(window.innerWidth, newWidth, "innerWidth clobbered by direct set"); - is(window.innerHeight, newHeight, "innerHeight clobbered by direct set"); + is(window.innerWidth, oldWidth, "Should have redefined innerWidth"); + is(window.innerHeight, oldHeight, "Should have redefined innerWidth"); + is(innerWidthGetter.call(window), newWidth, "innerWidth clobbered by direct set"); + is(innerHeightGetter.call(window), newHeight, "innerHeight clobbered by direct set"); SimpleTest.finish(); } diff --git a/dom/base/test/test_writable-replaceable.html b/dom/base/test/test_writable-replaceable.html index e7e19571fe..20aad7aef8 100644 --- a/dom/base/test/test_writable-replaceable.html +++ b/dom/base/test/test_writable-replaceable.html @@ -14,29 +14,30 @@ diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index 29d74f29fb..6ad58cdfbd 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -20,6 +20,7 @@ #include "nsDataHandler.h" #include "nsHostObjectProtocolHandler.h" #include "nsNetUtil.h" +#include "nsPrintfCString.h" #include "nsStreamUtils.h" #include "nsStringStream.h" @@ -216,7 +217,7 @@ FetchDriver::BasicFetch() uint64_t size = blob->GetSize(result); if (NS_WARN_IF(result.Failed())) { FailWithNetworkError(); - return result.ErrorCode(); + return result.StealNSResult(); } nsAutoString sizeStr; @@ -224,7 +225,7 @@ FetchDriver::BasicFetch() response->Headers()->Append(NS_LITERAL_CSTRING("Content-Length"), NS_ConvertUTF16toUTF8(sizeStr), result); if (NS_WARN_IF(result.Failed())) { FailWithNetworkError(); - return result.ErrorCode(); + return result.StealNSResult(); } nsAutoString type; @@ -232,7 +233,7 @@ FetchDriver::BasicFetch() response->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), NS_ConvertUTF16toUTF8(type), result); if (NS_WARN_IF(result.Failed())) { FailWithNetworkError(); - return result.ErrorCode(); + return result.StealNSResult(); } } @@ -626,7 +627,13 @@ public: { ErrorResult result; mResponse->Headers()->Append(aHeader, aValue, result); - return result.ErrorCode(); + if (result.Failed()) { + NS_WARNING(nsPrintfCString("Fetch ignoring illegal header - '%s': '%s'", + PromiseFlatCString(aHeader).get(), + PromiseFlatCString(aValue).get()).get()); + result.SuppressException(); + } + return NS_OK; } }; diff --git a/dom/filehandle/FileHandle.cpp b/dom/filehandle/FileHandle.cpp index c64022a55c..fb94a97b2f 100644 --- a/dom/filehandle/FileHandle.cpp +++ b/dom/filehandle/FileHandle.cpp @@ -474,7 +474,7 @@ FileHandleBase::OpenInputStream(bool aWholeFile, uint64_t aStart, // Common state checking ErrorResult error; if (!CheckState(error)) { - return error.ErrorCode(); + return error.StealNSResult(); } // Do nothing if the window is closed diff --git a/dom/gamepad/GamepadFunctions.cpp b/dom/gamepad/GamepadFunctions.cpp new file mode 100644 index 0000000000..26693b5b99 --- /dev/null +++ b/dom/gamepad/GamepadFunctions.cpp @@ -0,0 +1,105 @@ +/* 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 "mozilla/dom/GamepadFunctions.h" +#include "mozilla/dom/GamepadService.h" +#include "nsHashKeys.h" +#include "mozilla/dom/ContentParent.h" +#include "mozilla/unused.h" + +namespace mozilla { +namespace dom { +namespace GamepadFunctions { + +namespace { +// Increments as gamepads are added +uint32_t gGamepadIndex = 0; +} + +template +void +NotifyGamepadChange(const T& aInfo) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); + GamepadChangeEvent e(aInfo); + nsTArray t; + ContentParent::GetAll(t); + for(uint32_t i = 0; i < t.Length(); ++i) { + unused << t[i]->SendGamepadUpdate(e); + } + // If we have a GamepadService in the main process, send directly to it. + if (GamepadService::IsServiceRunning()) { + nsRefPtr svc = GamepadService::GetService(); + svc->Update(e); + } +} + +uint32_t +AddGamepad(const char* aID, + GamepadMappingType aMapping, + uint32_t aNumButtons, uint32_t aNumAxes) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); + + int index = gGamepadIndex; + gGamepadIndex++; + GamepadAdded a(NS_ConvertUTF8toUTF16(nsDependentCString(aID)), index, + (uint32_t)aMapping, aNumButtons, aNumAxes); + gGamepadIndex++; + NotifyGamepadChange(a); + return index; +} + +void +RemoveGamepad(uint32_t aIndex) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); + GamepadRemoved a(aIndex); + NotifyGamepadChange(a); +} + +void +NewButtonEvent(uint32_t aIndex, uint32_t aButton, + bool aPressed, double aValue) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); + GamepadButtonInformation a(aIndex, aButton, aPressed, aValue); + NotifyGamepadChange(a); +} + +void +NewButtonEvent(uint32_t aIndex, uint32_t aButton, + bool aPressed) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); + // When only a digital button is available the value will be synthesized. + NewButtonEvent(aIndex, aButton, aPressed, aPressed ? 1.0L : 0.0L); +} + +void +NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis, + double aValue) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); + GamepadAxisInformation a(aIndex, aAxis, aValue); + NotifyGamepadChange(a); +} + +void +ResetGamepadIndexes() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); + gGamepadIndex = 0; +} + +} // namespace GamepadFunctions +} // namespace dom +} // namespace mozilla diff --git a/dom/gamepad/GamepadFunctions.h b/dom/gamepad/GamepadFunctions.h new file mode 100644 index 0000000000..6ac631ce84 --- /dev/null +++ b/dom/gamepad/GamepadFunctions.h @@ -0,0 +1,45 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_GamepadFunctions_h_ +#define mozilla_dom_GamepadFunctions_h_ + +#include "mozilla/dom/GamepadBinding.h" + +namespace mozilla { +namespace dom { +namespace GamepadFunctions { + +// Functions for building and transmitting IPDL messages through the HAL +// sandbox. Used by platform specific Gamepad implementations + +// Add a gamepad to the list of known gamepads, and return its index. +uint32_t AddGamepad(const char* aID, GamepadMappingType aMapping, + uint32_t aNumButtons, uint32_t aNumAxes); +// Remove the gamepad at |aIndex| from the list of known gamepads. +void RemoveGamepad(uint32_t aIndex); + +// Update the state of |aButton| for the gamepad at |aIndex| for all +// windows that are listening and visible, and fire one of +// a gamepadbutton{up,down} event at them as well. +// aPressed is used for digital buttons, aValue is for analog buttons. +void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, + double aValue); +// When only a digital button is available the value will be synthesized. +void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed); + +// Update the state of |aAxis| for the gamepad at |aIndex| for all +// windows that are listening and visible, and fire a gamepadaxismove +// event at them as well. +void NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis, double aValue); + +// When shutting down the platform communications for gamepad, also reset the +// indexes. +void ResetGamepadIndexes(); + +} // namespace GamepadFunctions +} // namespace dom +} // namespace mozilla + +#endif diff --git a/dom/gamepad/GamepadMonitoring.cpp b/dom/gamepad/GamepadMonitoring.cpp new file mode 100644 index 0000000000..be94e5e5fe --- /dev/null +++ b/dom/gamepad/GamepadMonitoring.cpp @@ -0,0 +1,31 @@ +/* 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 "mozilla/dom/GamepadMonitoring.h" +#include "mozilla/dom/GamepadFunctions.h" +#include "mozilla/dom/PContentParent.h" + +namespace mozilla { +namespace dom { + +using namespace GamepadFunctions; + +void +MaybeStopGamepadMonitoring() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); + nsTArray t; + ContentParent::GetAll(t); + for(uint32_t i = 0; i < t.Length(); ++i) { + if (t[i]->HasGamepadListener()) { + return; + } + } + StopGamepadMonitoring(); + ResetGamepadIndexes(); +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/gamepad/GamepadMonitoring.h b/dom/gamepad/GamepadMonitoring.h new file mode 100644 index 0000000000..f088aba261 --- /dev/null +++ b/dom/gamepad/GamepadMonitoring.h @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_GamepadMonitoring_h_ +#define mozilla_dom_GamepadMonitoring_h_ + +namespace mozilla { +namespace dom { +// Functions for platform specific gamepad monitoring. + +void MaybeStopGamepadMonitoring(); + +// These two functions are implemented in the platform specific service files +// (linux/LinuxGamepad.cpp, cocoa/CocoaGamepad.cpp, etc) +void StartGamepadMonitoring(); +void StopGamepadMonitoring(); + +} // namespace dom +} // namespace mozilla + +#endif diff --git a/dom/gamepad/GamepadService.cpp b/dom/gamepad/GamepadService.cpp index 236c9b641b..17f5bd25e0 100644 --- a/dom/gamepad/GamepadService.cpp +++ b/dom/gamepad/GamepadService.cpp @@ -2,13 +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/. */ -#include "mozilla/Hal.h" +#include "mozilla/dom/GamepadService.h" +#include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/Gamepad.h" +#include "mozilla/dom/GamepadAxisMoveEvent.h" +#include "mozilla/dom/GamepadButtonEvent.h" +#include "mozilla/dom/GamepadEvent.h" +#include "mozilla/dom/GamepadMonitoring.h" + #include "mozilla/ClearOnShutdown.h" #include "mozilla/Preferences.h" #include "mozilla/StaticPtr.h" -#include "GamepadService.h" -#include "Gamepad.h" #include "nsAutoPtr.h" #include "nsIDOMEvent.h" #include "nsIDOMDocument.h" @@ -20,10 +25,6 @@ #include "nsThreadUtils.h" #include "mozilla/Services.h" -#include "mozilla/dom/GamepadAxisMoveEvent.h" -#include "mozilla/dom/GamepadButtonEvent.h" -#include "mozilla/dom/GamepadEvent.h" - #include namespace mozilla { @@ -82,7 +83,11 @@ GamepadService::BeginShutdown() mTimer->Cancel(); } if (mStarted) { - mozilla::hal::StopMonitoringGamepadStatus(); + if (XRE_GetProcessType() == GeckoProcessType_Default) { + MaybeStopGamepadMonitoring(); + } else { + ContentChild::GetSingleton()->SendGamepadListenerRemoved(); + } mStarted = false; } // Don't let windows call back to unregister during shutdown @@ -99,7 +104,6 @@ GamepadService::AddListener(nsGlobalWindow* aWindow) { MOZ_ASSERT(aWindow); MOZ_ASSERT(aWindow->IsInnerWindow()); - if (mShuttingDown) { return; } @@ -109,10 +113,13 @@ GamepadService::AddListener(nsGlobalWindow* aWindow) } if (!mStarted && mEnabled) { - mozilla::hal::StartMonitoringGamepadStatus(); + if (XRE_GetProcessType() == GeckoProcessType_Default) { + StartGamepadMonitoring(); + } else { + ContentChild::GetSingleton()->SendGamepadListenerAdded(); + } mStarted = true; } - mListeners.AppendElement(aWindow); } @@ -139,8 +146,20 @@ GamepadService::RemoveListener(nsGlobalWindow* aWindow) } } -uint32_t -GamepadService::AddGamepad(const char* aId, +already_AddRefed +GamepadService::GetGamepad(uint32_t aIndex) +{ + nsRefPtr gamepad; + if (mGamepads.Get(aIndex, getter_AddRefs(gamepad))) { + return gamepad.forget(); + } + + return nullptr; +} + +void +GamepadService::AddGamepad(uint32_t aIndex, + const nsAString& aId, GamepadMappingType aMapping, uint32_t aNumButtons, uint32_t aNumAxes) @@ -148,63 +167,40 @@ GamepadService::AddGamepad(const char* aId, //TODO: bug 852258: get initial button/axis state nsRefPtr gamepad = new Gamepad(nullptr, - NS_ConvertUTF8toUTF16(nsDependentCString(aId)), - 0, + aId, + 0, // index is set by global window aMapping, aNumButtons, aNumAxes); - int index = -1; - for (uint32_t i = 0; i < mGamepads.Length(); i++) { - if (!mGamepads[i]) { - mGamepads[i] = gamepad; - index = i; - break; - } - } - if (index == -1) { - mGamepads.AppendElement(gamepad); - index = mGamepads.Length() - 1; - } - gamepad->SetIndex(index); - NewConnectionEvent(index, true); - - return index; + // We store the gamepad related to its index given by the parent process. + mGamepads.Put(aIndex, gamepad); + NewConnectionEvent(aIndex, true); } void GamepadService::RemoveGamepad(uint32_t aIndex) { - if (aIndex < mGamepads.Length()) { - mGamepads[aIndex]->SetConnected(false); - NewConnectionEvent(aIndex, false); - // If this is the last entry in the list, just remove it. - if (aIndex == mGamepads.Length() - 1) { - mGamepads.RemoveElementAt(aIndex); - } else { - // Otherwise just null it out and leave it, so the - // indices of the following entries remain valid. - mGamepads[aIndex] = nullptr; - } + nsRefPtr gamepad = GetGamepad(aIndex); + if (!gamepad) { + NS_WARNING("Trying to delete gamepad with invalid index"); + return; } -} - -void -GamepadService::NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed) -{ - // Synthesize a value: 1.0 for pressed, 0.0 for unpressed. - NewButtonEvent(aIndex, aButton, aPressed, aPressed ? 1.0L : 0.0L); + gamepad->SetConnected(false); + NewConnectionEvent(aIndex, false); + mGamepads.Remove(aIndex); } void GamepadService::NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, double aValue) { - if (mShuttingDown || aIndex >= mGamepads.Length()) { + nsRefPtr gamepad = GetGamepad(aIndex); + if (mShuttingDown || !gamepad) { return; } - mGamepads[aIndex]->SetButton(aButton, aPressed, aValue); + gamepad->SetButton(aButton, aPressed, aValue); // Hold on to listeners in a separate array because firing events // can mutate the mListeners array. @@ -227,15 +223,15 @@ GamepadService::NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, first_time = true; } - nsRefPtr gamepad = listeners[i]->GetGamepad(aIndex); - if (gamepad) { - gamepad->SetButton(aButton, aPressed, aValue); + nsRefPtr listenerGamepad = listeners[i]->GetGamepad(aIndex); + if (listenerGamepad) { + listenerGamepad->SetButton(aButton, aPressed, aValue); if (first_time) { - FireConnectionEvent(listeners[i], gamepad, true); + FireConnectionEvent(listeners[i], listenerGamepad, true); } if (mNonstandardEventsEnabled) { // Fire event - FireButtonEvent(listeners[i], gamepad, aButton, aValue); + FireButtonEvent(listeners[i], listenerGamepad, aButton, aValue); } } } @@ -266,10 +262,11 @@ GamepadService::FireButtonEvent(EventTarget* aTarget, void GamepadService::NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis, double aValue) { - if (mShuttingDown || aIndex >= mGamepads.Length()) { + nsRefPtr gamepad = GetGamepad(aIndex); + if (mShuttingDown || !gamepad) { return; } - mGamepads[aIndex]->SetAxis(aAxis, aValue); + gamepad->SetAxis(aAxis, aValue); // Hold on to listeners in a separate array because firing events // can mutate the mListeners array. @@ -292,15 +289,15 @@ GamepadService::NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis, double aValue) first_time = true; } - nsRefPtr gamepad = listeners[i]->GetGamepad(aIndex); - if (gamepad) { - gamepad->SetAxis(aAxis, aValue); + nsRefPtr listenerGamepad = listeners[i]->GetGamepad(aIndex); + if (listenerGamepad) { + listenerGamepad->SetAxis(aAxis, aValue); if (first_time) { - FireConnectionEvent(listeners[i], gamepad, true); + FireConnectionEvent(listeners[i], listenerGamepad, true); } if (mNonstandardEventsEnabled) { // Fire event - FireAxisMoveEvent(listeners[i], gamepad, aAxis, aValue); + FireAxisMoveEvent(listeners[i], listenerGamepad, aAxis, aValue); } } } @@ -332,7 +329,9 @@ GamepadService::FireAxisMoveEvent(EventTarget* aTarget, void GamepadService::NewConnectionEvent(uint32_t aIndex, bool aConnected) { - if (mShuttingDown || aIndex >= mGamepads.Length()) { + nsRefPtr gamepad = GetGamepad(aIndex); + + if (mShuttingDown || !gamepad) { return; } @@ -358,10 +357,10 @@ GamepadService::NewConnectionEvent(uint32_t aIndex, bool aConnected) SetWindowHasSeenGamepad(listeners[i], aIndex); - nsRefPtr gamepad = listeners[i]->GetGamepad(aIndex); - if (gamepad) { + nsRefPtr listenerGamepad = listeners[i]->GetGamepad(aIndex); + if (listenerGamepad) { // Fire event - FireConnectionEvent(listeners[i], gamepad, aConnected); + FireConnectionEvent(listeners[i], listenerGamepad, aConnected); } } } else { @@ -374,11 +373,11 @@ GamepadService::NewConnectionEvent(uint32_t aIndex, bool aConnected) // deal with the hassle of syncing the state of removed gamepads. if (WindowHasSeenGamepad(listeners[i], aIndex)) { - nsRefPtr gamepad = listeners[i]->GetGamepad(aIndex); - if (gamepad) { - gamepad->SetConnected(false); + nsRefPtr listenerGamepad = listeners[i]->GetGamepad(aIndex); + if (listenerGamepad) { + listenerGamepad->SetConnected(false); // Fire event - FireConnectionEvent(listeners[i], gamepad, false); + FireConnectionEvent(listeners[i], listenerGamepad, false); listeners[i]->RemoveGamepad(aIndex); } } @@ -409,11 +408,19 @@ GamepadService::FireConnectionEvent(EventTarget* aTarget, void GamepadService::SyncGamepadState(uint32_t aIndex, Gamepad* aGamepad) { - if (mShuttingDown || !mEnabled || aIndex > mGamepads.Length()) { + nsRefPtr gamepad = GetGamepad(aIndex); + if (mShuttingDown || !mEnabled || !gamepad) { return; } - aGamepad->SyncState(mGamepads[aIndex]); + aGamepad->SyncState(gamepad); +} + +// static +bool +GamepadService::IsServiceRunning() +{ + return !!gGamepadServiceSingleton; } // static @@ -461,8 +468,13 @@ GamepadService::SetWindowHasSeenGamepad(nsGlobalWindow* aWindow, if (aHasSeen) { aWindow->SetHasSeenGamepadInput(true); nsCOMPtr window = ToSupports(aWindow); - nsRefPtr gamepad = mGamepads[aIndex]->Clone(window); - aWindow->AddGamepad(aIndex, gamepad); + nsRefPtr gamepad = GetGamepad(aIndex); + MOZ_ASSERT(gamepad); + if (!gamepad) { + return; + } + nsRefPtr clonedGamepad = gamepad->Clone(window); + aWindow->AddGamepad(aIndex, clonedGamepad); } else { aWindow->RemoveGamepad(aIndex); } @@ -486,13 +498,16 @@ GamepadService::TimeoutHandler(nsITimer* aTimer, void* aClosure) } if (self->mListeners.Length() == 0) { - mozilla::hal::StopMonitoringGamepadStatus(); + if (XRE_GetProcessType() == GeckoProcessType_Default) { + MaybeStopGamepadMonitoring(); + } else { + ContentChild::GetSingleton()->SendGamepadListenerRemoved(); + } + self->mStarted = false; - if (!self->mGamepads.IsEmpty()) { self->mGamepads.Clear(); } } -} void GamepadService::StartCleanupTimer() @@ -510,71 +525,26 @@ GamepadService::StartCleanupTimer() } } -/* - * Implementation of the test service. This is just to provide a simple binding - * of the GamepadService to JavaScript via XPCOM so that we can write Mochitests - * that add and remove fake gamepads, avoiding the platform-specific backends. - */ -NS_IMPL_ISUPPORTS(GamepadServiceTest, nsIGamepadServiceTest) - -GamepadServiceTest* GamepadServiceTest::sSingleton = nullptr; - -// static -already_AddRefed -GamepadServiceTest::CreateService() +void +GamepadService::Update(const GamepadChangeEvent& aEvent) { - if (sSingleton == nullptr) { - sSingleton = new GamepadServiceTest(); + if (aEvent.type() == GamepadChangeEvent::TGamepadAdded) { + const GamepadAdded& a = aEvent.get_GamepadAdded(); + AddGamepad(a.index(), a.id(), + static_cast(a.mapping()), + a.num_buttons(), a.num_axes()); + } else if (aEvent.type() == GamepadChangeEvent::TGamepadRemoved) { + const GamepadRemoved& a = aEvent.get_GamepadRemoved(); + RemoveGamepad(a.index()); + } else if (aEvent.type() == GamepadChangeEvent::TGamepadButtonInformation) { + const GamepadButtonInformation& a = aEvent.get_GamepadButtonInformation(); + NewButtonEvent(a.index(), a.button(), a.pressed(), a.value()); + } else if (aEvent.type() == GamepadChangeEvent::TGamepadAxisInformation) { + const GamepadAxisInformation& a = aEvent.get_GamepadAxisInformation(); + NewAxisMoveEvent(a.index(), a.axis(), a.value()); + } else { + MOZ_CRASH("We shouldn't be here!"); } - nsRefPtr service = sSingleton; - return service.forget(); -} - -GamepadServiceTest::GamepadServiceTest() -{ - /* member initializers and constructor code */ - nsRefPtr service = GamepadService::GetService(); -} - -/* uint32_t addGamepad (in string id, in unsigned long mapping, in unsigned long numButtons, in unsigned long numAxes); */ -NS_IMETHODIMP GamepadServiceTest::AddGamepad(const char* aID, - uint32_t aMapping, - uint32_t aNumButtons, - uint32_t aNumAxes, - uint32_t* aRetval) -{ - *aRetval = gGamepadServiceSingleton->AddGamepad(aID, - static_cast(aMapping), - aNumButtons, - aNumAxes); - return NS_OK; -} - -/* void removeGamepad (in uint32_t index); */ -NS_IMETHODIMP GamepadServiceTest::RemoveGamepad(uint32_t aIndex) -{ - gGamepadServiceSingleton->RemoveGamepad(aIndex); - return NS_OK; -} - -/* void newButtonEvent (in uint32_t index, in uint32_t button, - in boolean pressed); */ -NS_IMETHODIMP GamepadServiceTest::NewButtonEvent(uint32_t aIndex, - uint32_t aButton, - bool aPressed) -{ - gGamepadServiceSingleton->NewButtonEvent(aIndex, aButton, aPressed); - return NS_OK; -} - -/* void newAxisMoveEvent (in uint32_t index, in uint32_t axis, - in double value); */ -NS_IMETHODIMP GamepadServiceTest::NewAxisMoveEvent(uint32_t aIndex, - uint32_t aAxis, - double aValue) -{ - gGamepadServiceSingleton->NewAxisMoveEvent(aIndex, aAxis, aValue); - return NS_OK; } } // namespace dom diff --git a/dom/gamepad/GamepadService.h b/dom/gamepad/GamepadService.h index 29e44c0325..77060c93c8 100644 --- a/dom/gamepad/GamepadService.h +++ b/dom/gamepad/GamepadService.h @@ -6,7 +6,6 @@ #define mozilla_dom_GamepadService_h_ #include -#include "Gamepad.h" #include "nsAutoPtr.h" #include "nsCOMArray.h" #include "nsIGamepadServiceTest.h" @@ -15,11 +14,14 @@ #include "nsIObserver.h" #include "nsITimer.h" #include "nsTArray.h" - +// Needed for GamepadMappingType +#include "mozilla/dom/GamepadBinding.h" namespace mozilla { namespace dom { class EventTarget; +class GamepadChangeEvent; +class Gamepad; class GamepadService : public nsIObserver { @@ -27,6 +29,8 @@ class GamepadService : public nsIObserver NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER + // Returns true if we actually have a service up and running + static bool IsServiceRunning(); // Get the singleton service static already_AddRefed GetService(); // Return true if the API is preffed on. @@ -39,9 +43,10 @@ class GamepadService : public nsIObserver // Indicate that |aWindow| should no longer receive gamepad events. void RemoveListener(nsGlobalWindow* aWindow); - // Add a gamepad to the list of known gamepads, and return its index. - uint32_t AddGamepad(const char* aID, GamepadMappingType aMapping, + // Add a gamepad to the list of known gamepads. + void AddGamepad(uint32_t aIndex, const nsAString& aID, GamepadMappingType aMapping, uint32_t aNumButtons, uint32_t aNumAxes); + // Remove the gamepad at |aIndex| from the list of known gamepads. void RemoveGamepad(uint32_t aIndex); @@ -51,8 +56,6 @@ class GamepadService : public nsIObserver // aPressed is used for digital buttons, aValue is for analog buttons. void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, double aValue); - // When only a digital button is available the value will be synthesized. - void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed); // Update the state of |aAxis| for the gamepad at |aIndex| for all // windows that are listening and visible, and fire a gamepadaxismove @@ -62,6 +65,11 @@ class GamepadService : public nsIObserver // Synchronize the state of |aGamepad| to match the gamepad stored at |aIndex| void SyncGamepadState(uint32_t aIndex, Gamepad* aGamepad); + // Returns gamepad object if index exists, null otherwise + already_AddRefed GetGamepad(uint32_t aIndex); + + // Receive GamepadChangeEvent messages from parent process to fire DOM events + void Update(const GamepadChangeEvent& aGamepadEvent); protected: GamepadService(); virtual ~GamepadService() {}; @@ -115,37 +123,13 @@ class GamepadService : public nsIObserver // Gamepads connected to the system. Copies of these are handed out // to each window. - nsTArray > mGamepads; + nsRefPtrHashtable mGamepads; // Inner windows that are listening for gamepad events. // has been sent to that window. nsTArray > mListeners; nsCOMPtr mTimer; - nsCOMPtr mFocusManager; - nsCOMPtr mObserver; -}; - -// Service for testing purposes -class GamepadServiceTest : public nsIGamepadServiceTest -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIGAMEPADSERVICETEST - - GamepadServiceTest(); - - static already_AddRefed CreateService(); - -private: - static GamepadServiceTest* sSingleton; - virtual ~GamepadServiceTest() {}; }; } // namespace dom } // namespace mozilla - -#define NS_GAMEPAD_TEST_CID \ -{ 0xfb1fcb57, 0xebab, 0x4cf4, \ -{ 0x96, 0x3b, 0x1e, 0x4d, 0xb8, 0x52, 0x16, 0x96 } } -#define NS_GAMEPAD_TEST_CONTRACTID "@mozilla.org/gamepad-test;1" - #endif // mozilla_dom_GamepadService_h_ diff --git a/dom/gamepad/GamepadServiceTest.cpp b/dom/gamepad/GamepadServiceTest.cpp new file mode 100644 index 0000000000..086408aa18 --- /dev/null +++ b/dom/gamepad/GamepadServiceTest.cpp @@ -0,0 +1,92 @@ +/* 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 "GamepadServiceTest.h" +#include "mozilla/dom/GamepadService.h" +#include "mozilla/dom/GamepadFunctions.h" + +using namespace mozilla::dom; + +/* + * Implementation of the test service. This is just to provide a simple binding + * of the GamepadService to JavaScript via XPCOM so that we can write Mochitests + * that add and remove fake gamepads, avoiding the platform-specific backends. + */ +NS_IMPL_ISUPPORTS(GamepadServiceTest, nsIGamepadServiceTest) + +GamepadServiceTest* GamepadServiceTest::sSingleton = nullptr; + +// static +already_AddRefed +GamepadServiceTest::CreateService() +{ + if (sSingleton == nullptr) { + sSingleton = new GamepadServiceTest(); + } + nsRefPtr service = sSingleton; + return service.forget(); +} + +GamepadServiceTest::GamepadServiceTest() : + mService(GamepadService::GetService()) +{ +} + +GamepadServiceTest::~GamepadServiceTest() +{ +} + +/* uint32_t addGamepad(in unsigned long index, in string id, in unsigned long mapping, in unsigned long numButtons, in unsigned long numAxes); */ +NS_IMETHODIMP +GamepadServiceTest::AddGamepad(const char* aID, + uint32_t aMapping, + uint32_t aNumButtons, + uint32_t aNumAxes, + uint32_t* aGamepadIndex) +{ + *aGamepadIndex = GamepadFunctions::AddGamepad(aID, + static_cast(aMapping), + aNumButtons, + aNumAxes); + return NS_OK; +} + +/* void removeGamepad (in uint32_t index); */ +NS_IMETHODIMP GamepadServiceTest::RemoveGamepad(uint32_t aIndex) +{ + GamepadFunctions::RemoveGamepad(aIndex); + return NS_OK; +} + +/* void newButtonEvent (in uint32_t index, in uint32_t button, + in boolean pressed); */ +NS_IMETHODIMP GamepadServiceTest::NewButtonEvent(uint32_t aIndex, + uint32_t aButton, + bool aPressed) +{ + GamepadFunctions::NewButtonEvent(aIndex, aButton, aPressed); + return NS_OK; +} + +/* void newButtonEvent (in uint32_t index, in uint32_t button, + in boolean pressed, double value); */ +NS_IMETHODIMP GamepadServiceTest::NewButtonValueEvent(uint32_t aIndex, + uint32_t aButton, + bool aPressed, + double aValue) +{ + GamepadFunctions::NewButtonEvent(aIndex, aButton, aPressed, aValue); + return NS_OK; +} + +/* void newAxisMoveEvent (in uint32_t index, in uint32_t axis, + in double value); */ +NS_IMETHODIMP GamepadServiceTest::NewAxisMoveEvent(uint32_t aIndex, + uint32_t aAxis, + double aValue) +{ + GamepadFunctions::NewAxisMoveEvent(aIndex, aAxis, aValue); + return NS_OK; +} + diff --git a/dom/gamepad/GamepadServiceTest.h b/dom/gamepad/GamepadServiceTest.h new file mode 100644 index 0000000000..1df45932c1 --- /dev/null +++ b/dom/gamepad/GamepadServiceTest.h @@ -0,0 +1,42 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_GamepadServiceTest_h_ +#define mozilla_dom_GamepadServiceTest_h_ + +#include "nsIGamepadServiceTest.h" + +namespace mozilla { +namespace dom { + +class GamepadService; + +// Service for testing purposes +class GamepadServiceTest : public nsIGamepadServiceTest +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIGAMEPADSERVICETEST + + GamepadServiceTest(); + + static already_AddRefed CreateService(); + +private: + static GamepadServiceTest* sSingleton; + // Hold a reference to the gamepad service so we don't have to worry about + // execution order in tests. + nsRefPtr mService; + virtual ~GamepadServiceTest(); +}; + +} // namespace dom +} // namespace mozilla + +#define NS_GAMEPAD_TEST_CID \ +{ 0xfb1fcb57, 0xebab, 0x4cf4, \ +{ 0x96, 0x3b, 0x1e, 0x4d, 0xb8, 0x52, 0x16, 0x96 } } +#define NS_GAMEPAD_TEST_CONTRACTID "@mozilla.org/gamepad-test;1" + +#endif diff --git a/hal/android/AndroidGamepad.cpp b/dom/gamepad/android/AndroidGamepad.cpp similarity index 56% rename from hal/android/AndroidGamepad.cpp rename to dom/gamepad/android/AndroidGamepad.cpp index 71a8fd7efe..75e60bc9b9 100644 --- a/hal/android/AndroidGamepad.cpp +++ b/dom/gamepad/android/AndroidGamepad.cpp @@ -3,25 +3,20 @@ * 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 "Hal.h" #include "AndroidBridge.h" -using namespace mozilla::hal; - namespace mozilla { -namespace hal_impl { +namespace dom { -void -StartMonitoringGamepadStatus() +void StartGamepadMonitoring() { - widget::GoannaAppShell::StartMonitoringGamepad(); + widget::GeckoAppShell::StartMonitoringGamepad(); } -void -StopMonitoringGamepadStatus() +void StopGamepadMonitoring() { - widget::GoannaAppShell::StopMonitoringGamepad(); + widget::GeckoAppShell::StopMonitoringGamepad(); } -} // hal_impl -} // mozilla +} // namespace dom +} // namespace mozilla diff --git a/hal/cocoa/CocoaGamepad.cpp b/dom/gamepad/cocoa/CocoaGamepad.cpp similarity index 57% rename from hal/cocoa/CocoaGamepad.cpp rename to dom/gamepad/cocoa/CocoaGamepad.cpp index c1e126c1e5..454d5fc185 100644 --- a/hal/cocoa/CocoaGamepad.cpp +++ b/dom/gamepad/cocoa/CocoaGamepad.cpp @@ -6,7 +6,8 @@ // mostly derived from the Allegro source code at: // http://alleg.svn.sourceforge.net/viewvc/alleg/allegro/branches/4.9/src/macosx/hidjoy.m?revision=13760&view=markup -#include "mozilla/dom/GamepadService.h" +#include "mozilla/dom/GamepadFunctions.h" +#include "mozilla/ArrayUtils.h" #include #include #include @@ -17,64 +18,109 @@ namespace { -using mozilla::dom::GamepadService; - +using namespace mozilla; +using namespace mozilla::dom::GamepadFunctions; using std::vector; struct Button { int id; + bool analog; IOHIDElementRef element; + CFIndex min; + CFIndex max; + + Button(int aId, IOHIDElementRef aElement, CFIndex aMin, CFIndex aMax) : + id(aId), + analog((aMax - aMin) > 1), + element(aElement), + min(aMin), + max(aMax) {} }; struct Axis { int id; IOHIDElementRef element; + uint32_t usagePage; + uint32_t usage; CFIndex min; CFIndex max; }; +typedef bool dpad_buttons[4]; + // These values can be found in the USB HID Usage Tables: // http://www.usb.org/developers/hidpage -#define GENERIC_DESKTOP_USAGE_PAGE 0x01 -#define JOYSTICK_USAGE_NUMBER 0x04 -#define GAMEPAD_USAGE_NUMBER 0x05 -#define AXIS_MIN_USAGE_NUMBER 0x30 -#define AXIS_MAX_USAGE_NUMBER 0x35 -#define BUTTON_USAGE_PAGE 0x09 +const unsigned kDesktopUsagePage = 0x01; +const unsigned kSimUsagePage = 0x02; +const unsigned kAcceleratorUsage = 0xC4; +const unsigned kBrakeUsage = 0xC5; +const unsigned kJoystickUsage = 0x04; +const unsigned kGamepadUsage = 0x05; +const unsigned kAxisUsageMin = 0x30; +const unsigned kAxisUsageMax = 0x35; +const unsigned kDpadUsage = 0x39; +const unsigned kButtonUsagePage = 0x09; +const unsigned kConsumerPage = 0x0C; +const unsigned kHomeUsage = 0x223; +const unsigned kBackUsage = 0x224; + class Gamepad { private: IOHIDDeviceRef mDevice; - vector -
details
- embed - - - - - - object - - - + a + + +
details
+ embed + + + + + + object + + + - a - - - - object - - tabindex + + + + object + + + tabindex + + + + object + diff --git a/dom/html/test/test_formSubmission.html b/dom/html/test/test_formSubmission.html index c7897051b1..db7da4ed84 100644 --- a/dom/html/test/test_formSubmission.html +++ b/dom/html/test/test_formSubmission.html @@ -399,41 +399,59 @@ t_6_v SimpleTest.waitForExplicitFinish(); -var myFile1, myFile2, emptyFile; +const placeholder_myFile1 = {}; +const placeholder_myFile2 = {}; +const placeholder_emptyFile = {}; -(function setFileNames() { +var myFile1, myFile2, emptyFile; +let openerURL = SimpleTest.getTestFileURL("formSubmission_chrome.js"); +let opener = SpecialPowers.loadChromeScript(openerURL); + +{ let xhr = new XMLHttpRequest; xhr.open("GET", "/dynamic/getMyDirectory.sjs", false); xhr.send(); - var basePath = xhr.responseText; + let basePath = xhr.responseText; - singleFile = basePath + "file_formSubmission_text.txt"; - multiFile = [basePath + "file_formSubmission_text.txt", - basePath + "file_formSubmission_img.jpg"]; + opener.addMessageListener("files.opened", onFilesOpened); + opener.sendAsyncMessage("files.open", [ + basePath + "file_formSubmission_text.txt", + basePath + "file_formSubmission_img.jpg", + ]); +} + +function onFilesOpened(files) { + let [textFile, imageFile] = files; + opener.destroy(); + + let singleFile = textFile; + let multiFile = [textFile, imageFile]; var addList = document.getElementsByClassName("setfile"); let i = 0; var input; while (input = addList[i++]) { if (input.classList.contains("multi")) { - SpecialPowers.wrap(input).mozSetFileNameArray(multiFile, multiFile.length); + SpecialPowers.wrap(input).mozSetFileArray(multiFile); } else { - SpecialPowers.wrap(input).value = singleFile; + SpecialPowers.wrap(input).mozSetFileArray([singleFile]); } } input = document.createElement("input"); input.type = "file"; input.multiple = true; - SpecialPowers.wrap(input).mozSetFileNameArray(multiFile, multiFile.length); + SpecialPowers.wrap(input).mozSetFileArray(multiFile); myFile1 = input.files[0]; myFile2 = input.files[1]; is(myFile1.size, 20, "File1 size"); is(myFile2.size, 2711, "File2 size"); emptyFile = { name: "", type: "application/octet-stream" }; -})(); + // Now, actually run the tests; see below. + onFilesSet(); +}; var expectedSub = [ // Default input @@ -495,13 +513,13 @@ var expectedSub = [ // Reset button // Unknown button // File - { name: "file_1", value: myFile1 }, - { name: "file_2", value: emptyFile }, + { name: "file_1", value: placeholder_myFile1 }, + { name: "file_2", value: placeholder_emptyFile }, // Multiple file - { name: "file_3", value: myFile1 }, - { name: "file_4", value: myFile1 }, - { name: "file_4", value: myFile2 }, - { name: "file_5", value: emptyFile }, + { name: "file_3", value: placeholder_myFile1 }, + { name: "file_4", value: placeholder_myFile1 }, + { name: "file_4", value: placeholder_myFile2 }, + { name: "file_5", value: placeholder_emptyFile }, // Textarea { name: "t1", value: "t_1_v" }, { name: "t2", value: "" }, @@ -562,12 +580,12 @@ var expectedSub = [ { name: "msel_31", value: "msel_31_v1" }, ]; -expectedAugment = [ +var expectedAugment = [ { name: "aName", value: "aValue" }, //{ name: "aNameBool", value: "false" }, { name: "aNameNum", value: "9.2" }, - { name: "aNameFile1", value: myFile1 }, - { name: "aNameFile2", value: myFile2 }, + { name: "aNameFile1", value: placeholder_myFile1 }, + { name: "aNameFile2", value: placeholder_myFile2 }, //{ name: "aNameObj", value: "[object XMLHttpRequest]" }, //{ name: "aNameNull", value: "null" }, //{ name: "aNameUndef", value: "undefined" }, @@ -661,10 +679,13 @@ function setDisabled(list, state) { }); } -var gen = runTest(); -addLoadEvent(function() { - gen.next(); -}); +var gen; +function onFilesSet() { + gen = runTest(); + addLoadEvent(function() { + gen.next(); + }); +} function runTest() { // Set up the expectedSub array @@ -676,17 +697,17 @@ function runTest() { yield undefined; // Wait for both FileReaders. We don't care which order they finish. yield undefined; function fileFixup(o) { - if (o.value == myFile1) { + if (o.value === placeholder_myFile1) { o.value = fileReader1.result; o.fileName = myFile1.name; o.contentType = myFile1.type; } - else if (o.value == myFile2) { + else if (o.value === placeholder_myFile2) { o.value = fileReader2.result; o.fileName = myFile2.name; o.contentType = myFile2.type; } - else if (o.value == emptyFile) { + else if (o.value === placeholder_emptyFile) { o.value = ""; o.fileName = emptyFile.name; o.contentType = emptyFile.type; diff --git a/dom/imptests/failures/editing/conformancetest/test_runtest.html.json b/dom/imptests/failures/editing/conformancetest/test_runtest.html.json index 059a34a032..64236c6aca 100644 --- a/dom/imptests/failures/editing/conformancetest/test_runtest.html.json +++ b/dom/imptests/failures/editing/conformancetest/test_runtest.html.json @@ -1216,86 +1216,30 @@ "[[\"delete\",\"\"]] \"

f[]\" compare innerHTML":true, "[[\"delete\",\"\"]] \"[foo]\" compare innerHTML":true, "[[\"delete\",\"\"]] \"

[foo]
\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"

[foo

bar]

\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"

[foo

bar]

\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"[foo bar]\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"[foo bar]\" queryCommandIndeterm(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"[foo bar]\" queryCommandIndeterm(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"

[foo

bar

baz]

\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"

[foo

bar

baz]

\" queryCommandIndeterm(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"

[foo

bar

baz]

\" queryCommandIndeterm(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"

[foo


bar]\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"

[foo


bar]\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"]] \"foo{}bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"]] \"foo[]bar\" queryCommandValue(\"fontname\") after":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[barbaz]qozquz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[barbaz]qozquz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[barbaz]qozquz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[barbaz]qozquz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"{

foo

}\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"{

foo

}\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"
foob[a]rbaz
\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"
foob[a]rbaz
\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"
foobarbaz
\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"
foobarbaz
\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"
foobarbaz
\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"
foobarbaz
\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"
foobarbaz
\" queryCommandIndeterm(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"
foobarbaz
\" queryCommandIndeterm(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"
foobarbaz
\" queryCommandIndeterm(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"
foobarbaz
\" queryCommandIndeterm(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"{
foobarbaz
}\" queryCommandIndeterm(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"{
foobarbaz
}\" queryCommandIndeterm(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") after":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" compare innerHTML":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") after":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") after":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" compare innerHTML":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") after":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo
[bar]
baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo
[bar]
baz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") after":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" compare innerHTML":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") after":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" compare innerHTML":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") after":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" compare innerHTML":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") after":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo
b[a]r
baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo
b[a]r
baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" compare innerHTML":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"[foobarbaz]\" compare innerHTML":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"[foobarbaz]\" queryCommandIndeterm(\"fontname\") after":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"[foobarbaz]\" compare innerHTML":true, @@ -1324,16 +1268,7 @@ "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foob[arbaz]\" queryCommandValue(\"fontname\") after":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foob[arbaz]\" compare innerHTML":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foob[arbaz]\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foob[a]rbaz\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"]] \"fooba[rb]az\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"]] \"fooba[rb]az\" queryCommandValue(\"fontname\") after":true, - "[[\"fontname\",\"sans-serif\"]] \"fo[ob]arbaz\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"]] \"fo[ob]arbaz\" queryCommandValue(\"fontname\") after":true, - "[[\"fontname\",\"sans-serif\"]] \"foo{}
bar\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo{
}bar\" compare innerHTML":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo{
}bar\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo{
}bar\" queryCommandValue(\"fontname\") after":true, @@ -1351,17 +1286,7 @@ "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"fo[ob]arbaz\" compare innerHTML":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"fooba[rb]az\" compare innerHTML":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[b]arbaz\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[b]arbaz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[b]arbaz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"fooba[r]baz\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"fooba[r]baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"fooba[r]baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo[bar]baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo{bar}baz\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo{bar}baz\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"fo[ob]ar\" compare innerHTML":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"fo[ob]ar\" queryCommandIndeterm(\"fontname\") after":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"fo[ob]ar\" compare innerHTML":true, @@ -1369,14 +1294,8 @@ "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"fo[ob]ar\" compare innerHTML":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"fo[ob]ar\" compare innerHTML":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"fo[ob]ar\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"fo[ob]ar\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"fo[ob]ar\" compare innerHTML":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"fo[ob]ar\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"
fo[o
b]ar\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"
fo[o
b]ar\" queryCommandValue(\"fontname\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"fo[ob]ar\" compare innerHTML":true, - "[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"fo[ob]ar\" queryCommandValue(\"fontname\") before":true, - "[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"fo[ob]ar\" queryCommandValue(\"fontname\") before":true, "[[\"fontsize\",\"4\"]] \"foo[]bar\" queryCommandValue(\"fontsize\") before":true, "[[\"stylewithcss\",\"true\"],[\"fontsize\",\"4\"]] \"

[foo

bar]

\" compare innerHTML":true, "[[\"stylewithcss\",\"true\"],[\"fontsize\",\"4\"]] \"

[foo

bar]

\" queryCommandValue(\"fontsize\") before":true, @@ -11568,60 +11487,27 @@ "[[\"createlink\",\"http://www.google.com/\"],[\"justifyright\",\"\"]] \"foo[]bar\" compare innerHTML":true, "[[\"createlink\",\"http://www.google.com/\"],[\"justifyright\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" compare innerHTML":true, "[[\"createlink\",\"http://www.google.com/\"],[\"outdent\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"delete\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"delete\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"formatblock\",\"
\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"formatblock\",\"
\"]] \"foo[]bar\" queryCommandValue(\"formatblock\") after":true, - "[[\"fontname\",\"sans-serif\"],[\"formatblock\",\"
\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"formatblock\",\"
\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"formatblock\") after":true, - "[[\"fontname\",\"sans-serif\"],[\"forwarddelete\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"forwarddelete\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"indent\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"indent\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"inserthorizontalrule\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"inserthorizontalrule\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"inserthtml\",\"abcd\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"inserthtml\",\"abcd\"]] \"foo[]bar\" queryCommandValue(\"fontname\") after":true, "[[\"fontname\",\"sans-serif\"],[\"inserthtml\",\"abcd\"],[\"inserttext\",\"a\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"inserthtml\",\"abcd\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"inserthtml\",\"abcd\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") after":true, - "[[\"fontname\",\"sans-serif\"],[\"insertimage\",\"/img/lion.svg\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"insertimage\",\"/img/lion.svg\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"insertlinebreak\",\"\"]] \"foo[]bar\": execCommand(\"insertlinebreak\", false, \"\") return value":true, "[[\"fontname\",\"sans-serif\"],[\"insertlinebreak\",\"\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"insertlinebreak\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"insertlinebreak\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\": execCommand(\"insertlinebreak\", false, \"\") return value":true, "[[\"fontname\",\"sans-serif\"],[\"insertlinebreak\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"insertlinebreak\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"insertorderedlist\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"insertorderedlist\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"insertparagraph\",\"\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"insertparagraph\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"insertparagraph\",\"\"]] \"foo[]bar\" queryCommandValue(\"insertparagraph\") after":true, "[[\"fontname\",\"sans-serif\"],[\"insertparagraph\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"insertparagraph\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"insertparagraph\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"insertparagraph\") after":true, - "[[\"fontname\",\"sans-serif\"],[\"insertunorderedlist\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"insertunorderedlist\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"justifycenter\",\"\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"justifycenter\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"justifycenter\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"justifycenter\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"justifyfull\",\"\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"justifyfull\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"justifyfull\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"justifyfull\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"justifyleft\",\"\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"justifyleft\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"justifyleft\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"justifyleft\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"justifyright\",\"\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"justifyright\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontname\",\"sans-serif\"],[\"justifyright\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" compare innerHTML":true, - "[[\"fontname\",\"sans-serif\"],[\"justifyright\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"outdent\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, - "[[\"fontname\",\"sans-serif\"],[\"outdent\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontname\") before":true, "[[\"fontsize\",\"4\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontsize\") before":true, "[[\"fontsize\",\"4\"],[\"delete\",\"\"]] \"foo[]bar\" queryCommandValue(\"fontsize\") before":true, "[[\"fontsize\",\"4\"],[\"delete\",\"\"],[\"inserttext\",\"a\"]] \"foo[]bar\" queryCommandValue(\"fontsize\") before":true, diff --git a/dom/inputport/InputPortManager.cpp b/dom/inputport/InputPortManager.cpp index d29740cf98..7111fdff4b 100644 --- a/dom/inputport/InputPortManager.cpp +++ b/dom/inputport/InputPortManager.cpp @@ -186,12 +186,12 @@ InputPortManager::NotifySuccess(nsIArray* aDataList) } if (NS_WARN_IF(erv.Failed())) { - return erv.ErrorCode(); + return erv.StealNSResult(); } erv = SetInputPorts(ports); - return erv.ErrorCode(); + return erv.StealNSResult(); } NS_IMETHODIMP diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index 1bd103ec6c..232d7b9538 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -51,7 +51,7 @@ interface nsIJSRAIIHelper; interface nsIContentPermissionRequest; interface nsIObserver; -[scriptable, uuid(dde97573-f4cf-45ce-bbb0-5af4e5f77440)] +[scriptable, uuid(7f2f44ab-2857-4cc2-8c9d-3d9816f5a4d6)] interface nsIDOMWindowUtils : nsISupports { /** @@ -1462,11 +1462,6 @@ interface nsIDOMWindowUtils : nsISupports { * the bounds of the window. Always returns true in non-DEBUG builds. */ boolean leafLayersPartitionWindow(); - - /** - * true if the (current inner) window may have event listeners for touch events. - */ - readonly attribute boolean mayHaveTouchEventListeners; /** * Check if any PaintedLayer painting has been done for this element, @@ -1790,6 +1785,11 @@ interface nsIDOMWindowUtils : nsISupports { in int32_t aRight, in int32_t aBottom, in int32_t aLeft); + + /** + * Enable some service workers testing features. + */ + attribute boolean serviceWorkersTestingEnabled; }; [scriptable, uuid(c694e359-7227-4392-a138-33c0cc1f15a6)] diff --git a/dom/interfaces/gamepad/nsIGamepadServiceTest.idl b/dom/interfaces/gamepad/nsIGamepadServiceTest.idl index 48f1dfd655..170d2366b1 100644 --- a/dom/interfaces/gamepad/nsIGamepadServiceTest.idl +++ b/dom/interfaces/gamepad/nsIGamepadServiceTest.idl @@ -9,18 +9,21 @@ interface nsIVariant; /* * This interface is intended only for use in tests. */ -[scriptable, uuid(b6ed093c-6ea0-4141-a8eb-f99645162651)] +[scriptable, uuid(c03ec4ed-8a7e-40e7-99da-c609f1760d0c)] interface nsIGamepadServiceTest : nsISupports { const unsigned long NO_MAPPING = 0; const unsigned long STANDARD_MAPPING = 1; - unsigned long addGamepad(in string id, in unsigned long mapping, + unsigned long addGamepad(in string id, + in unsigned long mapping, in unsigned long numButtons, in unsigned long numAxes); void removeGamepad(in unsigned long index); void newButtonEvent(in unsigned long index, in unsigned long button, in boolean pressed); + void newButtonValueEvent(in unsigned long index, in unsigned long button, + in boolean pressed, in double value); void newAxisMoveEvent(in unsigned long index, in unsigned long axis, in double value); }; diff --git a/dom/ipc/Blob.cpp b/dom/ipc/Blob.cpp index d60a017cbb..07860f184b 100644 --- a/dom/ipc/Blob.cpp +++ b/dom/ipc/Blob.cpp @@ -1339,7 +1339,7 @@ RemoteInputStream::Available(uint64_t* aAvailable) ErrorResult error; *aAvailable = mBlobImpl->GetSize(error); if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); + return error.StealNSResult(); } return NS_OK; diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index e1dc87808d..2436a7a5db 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -152,6 +152,10 @@ #include "ipc/Nuwa.h" #endif +#ifdef MOZ_GAMEPAD +#include "mozilla/dom/GamepadService.h" +#endif + #include "mozilla/dom/File.h" #include "mozilla/dom/cellbroadcast/CellBroadcastIPCService.h" #include "mozilla/dom/icc/IccChild.h" @@ -2794,6 +2798,18 @@ ContentChild::DeallocPContentPermissionRequestChild(PContentPermissionRequestChi return true; } +bool +ContentChild::RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) +{ +#ifdef MOZ_GAMEPAD + nsRefPtr svc(GamepadService::GetService()); + if (svc) { + svc->Update(aGamepadEvent); + } +#endif + return true; +} + // This code goes here rather than nsGlobalWindow.cpp because nsGlobalWindow.cpp // can't include ContentChild.h since it includes windows.h. diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index acc29092ea..1ed2869d1a 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -463,6 +463,8 @@ public: virtual bool DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor) override; + virtual bool RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) override; + private: virtual void ActorDestroy(ActorDestroyReason why) override; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 45386464ea..5793330493 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -215,6 +215,10 @@ using namespace mozilla::system; #include "nsIBrowserSearchService.h" #endif +#ifdef MOZ_GAMEPAD +#include "mozilla/dom/GamepadMonitoring.h" +#endif + static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID); static const char* sClipboardTextFlavors[] = { kUnicodeMime }; @@ -2095,6 +2099,7 @@ ContentParent::ContentParent(mozIApplication* aApp, , mOpener(aOpener) , mIsForBrowser(aIsForBrowser) , mIsNuwaProcess(aIsNuwaProcess) + , mHasGamepadListener(false) { InitializeMembers(); // Perform common initialization. @@ -2618,7 +2623,7 @@ ContentParent::RecvGetShowPasswordSetting(bool* showPassword) #ifdef MOZ_WIDGET_ANDROID NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available"); - *showPassword = mozilla::widget::GoannaAppShell::GetShowPasswordSetting(); + *showPassword = mozilla::widget::GeckoAppShell::GetShowPasswordSetting(); #endif return true; } @@ -4795,6 +4800,34 @@ ContentParent::DeallocPContentPermissionRequestParent(PContentPermissionRequestP return true; } +bool +ContentParent::RecvGamepadListenerAdded() +{ +#ifdef MOZ_GAMEPAD + if (mHasGamepadListener) { + NS_WARNING("Gamepad listener already started, cannot start again!"); + return false; + } + mHasGamepadListener = true; + StartGamepadMonitoring(); +#endif + return true; +} + +bool +ContentParent::RecvGamepadListenerRemoved() +{ +#ifdef MOZ_GAMEPAD + if (!mHasGamepadListener) { + NS_WARNING("Gamepad listener already stopped, cannot stop again!"); + return false; + } + mHasGamepadListener = false; + MaybeStopGamepadMonitoring(); +#endif + return true; +} + } // namespace dom } // namespace mozilla diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index d96ae14e9b..4a6a96ff89 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -369,6 +369,8 @@ public: virtual bool DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor) override; + bool HasGamepadListener() const { return mHasGamepadListener; } + protected: void OnChannelConnected(int32_t pid) override; virtual void ActorDestroy(ActorDestroyReason why) override; @@ -825,6 +827,10 @@ private: virtual bool RecvUpdateDropEffect(const uint32_t& aDragAction, const uint32_t& aDropEffect) override; + + virtual bool RecvGamepadListenerAdded() override; + virtual bool RecvGamepadListenerRemoved() override; + // If you add strong pointers to cycle collected objects here, be sure to // release these objects in ShutDownProcess. See the comment there for more // details. @@ -869,6 +875,7 @@ private: bool mSendDataStoreInfos; bool mIsForBrowser; bool mIsNuwaProcess; + bool mHasGamepadListener; // These variables track whether we've called Close(), CloseWithError() // and KillHard() on our channel. diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index baae561821..8c2778a875 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -366,6 +366,38 @@ struct DomainPolicyClone URIParams[] superWhitelist; }; +struct GamepadAdded { + nsString id; + uint32_t index; + uint32_t mapping; + uint32_t num_buttons; + uint32_t num_axes; +}; + +struct GamepadRemoved { + uint32_t index; +}; + +struct GamepadAxisInformation { + uint32_t index; + uint32_t axis; + double value; +}; + +struct GamepadButtonInformation { + uint32_t index; + uint32_t button; + bool pressed; + double value; +}; + +union GamepadChangeEvent { + GamepadAdded; + GamepadRemoved; + GamepadAxisInformation; + GamepadButtonInformation; +}; + prio(normal upto urgent) sync protocol PContent { parent spawns PPluginModule; @@ -602,6 +634,10 @@ child: */ async UpdateWindow(uintptr_t aChildId); + /** + * Send gamepad status update to child. + */ + GamepadUpdate(GamepadChangeEvent aGamepadEvent); parent: /** * Tell the parent process a new accessible document has been created. @@ -975,6 +1011,16 @@ parent: PContentPermissionRequest(PermissionRequest[] aRequests, Principal aPrincipal, TabId tabId); + /* + * Tells the parent to start the gamepad listening service if it hasn't already. + */ + GamepadListenerAdded(); + + /** + * Tells the parent to stop the gamepad listening service if it hasn't already. + */ + GamepadListenerRemoved(); + both: AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows, Principal aPrincipal); diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build index 6d82ac66b4..144d944ed7 100644 --- a/dom/ipc/moz.build +++ b/dom/ipc/moz.build @@ -148,10 +148,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gonk', 'qt'): if CONFIG['MOZ_TOOLKIT_SEARCH']: DEFINES['MOZ_TOOLKIT_SEARCH'] = True -for var in ('MOZ_PERMISSIONS', 'MOZ_CHILD_PERMISSIONS'): - if CONFIG[var]: - DEFINES[var] = True - JAR_MANIFESTS += ['jar.mn'] BROWSER_CHROME_MANIFESTS += ['tests/browser.ini'] diff --git a/dom/jsurl/nsJSProtocolHandler.cpp b/dom/jsurl/nsJSProtocolHandler.cpp index 0ff89428e5..7708cb2a9f 100644 --- a/dom/jsurl/nsJSProtocolHandler.cpp +++ b/dom/jsurl/nsJSProtocolHandler.cpp @@ -249,7 +249,7 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel, // New script entry point required, due to the "Create a script" step of // http://www.whatwg.org/specs/web-apps/current-work/#javascript-protocol - AutoEntryScript entryScript(innerGlobal, true, + AutoEntryScript entryScript(innerGlobal, "javascript: URI", true, scriptContext->GetNativeContext()); // We want to make sure we report any exceptions that happen before we // return, since whatever happens inside our execution shouldn't affect any diff --git a/dom/media/AudioSegment.cpp b/dom/media/AudioSegment.cpp index 93af3aa031..ddd16bbe16 100644 --- a/dom/media/AudioSegment.cpp +++ b/dom/media/AudioSegment.cpp @@ -199,12 +199,14 @@ AudioSegment::WriteTo(uint64_t aID, AudioMixer& aMixer, uint32_t aOutputChannels offset += frames * aOutputChannels; +#if !defined(MOZILLA_XPCOMRT_API) if (!c.mTimeStamp.IsNull()) { TimeStamp now = TimeStamp::Now(); // would be more efficient to c.mTimeStamp to ms on create time then pass here LogTime(AsyncLatencyLogger::AudioMediaStreamTrack, aID, (now - c.mTimeStamp).ToMilliseconds(), c.mTimeStamp); } +#endif // !defined(MOZILLA_XPCOMRT_API) } if (offset) { diff --git a/dom/media/AudioSegment.h b/dom/media/AudioSegment.h index 54c2889ee6..e0c77708fb 100644 --- a/dom/media/AudioSegment.h +++ b/dom/media/AudioSegment.h @@ -197,7 +197,10 @@ public: MOZ_ASSERT(channels == segmentChannelCount); output.SetLength(channels); bufferPtrs.SetLength(channels); +#if !defined(MOZILLA_XPCOMRT_API) +// FIXME Bug 1126414 - XPCOMRT does not support dom::WebAudioUtils::SpeexResamplerProcess uint32_t inFrames = c.mDuration; +#endif // !defined(MOZILLA_XPCOMRT_API) // Round up to allocate; the last frame may not be used. NS_ASSERTION((UINT32_MAX - aInRate + 1) / c.mDuration >= aOutRate, "Dropping samples"); @@ -207,10 +210,13 @@ public: T* out = output[i].AppendElements(outSize); uint32_t outFrames = outSize; +#if !defined(MOZILLA_XPCOMRT_API) +// FIXME Bug 1126414 - XPCOMRT does not support dom::WebAudioUtils::SpeexResamplerProcess dom::WebAudioUtils::SpeexResamplerProcess(aResampler, i, in, &inFrames, out, &outFrames); MOZ_ASSERT(inFrames == c.mDuration); +#endif // !defined(MOZILLA_XPCOMRT_API) bufferPtrs[i] = out; output[i].SetLength(outFrames); } diff --git a/dom/media/SimpleImageBuffer.cpp b/dom/media/SimpleImageBuffer.cpp new file mode 100644 index 0000000000..e9b1ce22f5 --- /dev/null +++ b/dom/media/SimpleImageBuffer.cpp @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set ts=4 sw=4 sts=4 ci et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "SimpleImageBuffer.h" +#include "mozilla/NullPtr.h" + +namespace mozilla { + +void +SimpleImageBuffer::SetImage(const unsigned char* frame, unsigned int size, int width, int height) +{ + mWidth = width; + mHeight = height; + if (!mBuffer || (size > mBufferSize)) { + if (mBuffer) { + delete[] mBuffer; + mBuffer = nullptr; + } + mBufferSize = size; + if (size > 0) { + mBuffer = new unsigned char[size]; + } + } + + if (mBuffer) { + if (frame && (size > 0)) { + memcpy((void *)mBuffer, (const void*)frame, size); + } + mSize = size; + } +} + +void +SimpleImageBuffer::Copy(const SimpleImageBuffer* aImage) +{ + if (aImage) { + SetImage(aImage->mBuffer, aImage->mSize, aImage->mWidth, aImage->mHeight); + } +} + +const unsigned char* +SimpleImageBuffer::GetImage(unsigned int* size) const +{ + if (size) { + *size = mSize; + } + return mBuffer; +} + +} // namespace mozilla diff --git a/dom/media/SimpleImageBuffer.h b/dom/media/SimpleImageBuffer.h new file mode 100644 index 0000000000..ef0e2753cf --- /dev/null +++ b/dom/media/SimpleImageBuffer.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set ts=4 sw=4 sts=4 ci et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef simple_image_buffer_h +#define simple_image_buffer_h + +#include "mozilla/NullPtr.h" +#include "nsISupportsImpl.h" + +namespace mozilla { + +class SimpleImageBuffer { +NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SimpleImageBuffer) +public: + SimpleImageBuffer() : mBuffer(nullptr), mBufferSize(0), mSize(0), mWidth(0), mHeight(0) {} + void SetImage(const unsigned char* frame, unsigned int size, int width, int height); + void Copy(const SimpleImageBuffer* aImage); + const unsigned char* GetImage(unsigned int* size) const; + void GetWidthAndHeight(int* width, int* height) const + { + if (width) { + *width = mWidth; + } + if (height) { + *height = mHeight; + } + } + +protected: + ~SimpleImageBuffer() + { + delete[] mBuffer; + } + const unsigned char* mBuffer; + unsigned int mBufferSize; + unsigned int mSize; + int mWidth; + int mHeight; + +private: + SimpleImageBuffer(const SimpleImageBuffer& aImage); + SimpleImageBuffer& operator=(const SimpleImageBuffer& aImage); +}; + +} // namespace mozilla + +#endif // simple_image_buffer_h diff --git a/dom/media/VideoSegment.cpp b/dom/media/VideoSegment.cpp index 4671963164..41cf8ca9f0 100644 --- a/dom/media/VideoSegment.cpp +++ b/dom/media/VideoSegment.cpp @@ -39,6 +39,7 @@ VideoFrame::TakeFrom(VideoFrame* aFrame) mForceBlack = aFrame->GetForceBlack(); } +#if !defined(MOZILLA_XPCOMRT_API) /* static */ already_AddRefed VideoFrame::CreateBlackImage(const gfxIntSize& aSize) { @@ -83,6 +84,7 @@ VideoFrame::CreateBlackImage(const gfxIntSize& aSize) return image.forget(); } +#endif // !defined(MOZILLA_XPCOMRT_API) VideoChunk::VideoChunk() {} diff --git a/dom/media/VideoSegment.h b/dom/media/VideoSegment.h index a22634b466..fed071c1de 100644 --- a/dom/media/VideoSegment.h +++ b/dom/media/VideoSegment.h @@ -10,7 +10,11 @@ #include "nsCOMPtr.h" #include "gfxPoint.h" #include "nsAutoPtr.h" +#if defined(MOZILLA_XPCOMRT_API) +#include "SimpleImageBuffer.h" +#else #include "ImageContainer.h" +#endif namespace mozilla { @@ -20,7 +24,11 @@ class Image; class VideoFrame { public: +#if defined(MOZILLA_XPCOMRT_API) + typedef mozilla::SimpleImageBuffer Image; +#else typedef mozilla::layers::Image Image; +#endif VideoFrame(already_AddRefed& aImage, const gfxIntSize& aIntrinsicSize); VideoFrame(); @@ -44,8 +52,10 @@ public: void SetNull(); void TakeFrom(VideoFrame* aFrame); +#if !defined(MOZILLA_XPCOMRT_API) // Create a planar YCbCr black image. static already_AddRefed CreateBlackImage(const gfxIntSize& aSize); +#endif // !defined(MOZILLA_XPCOMRT_API) protected: // mImage can be null to indicate "no video" (aka "empty frame"). It can @@ -93,7 +103,11 @@ struct VideoChunk { class VideoSegment : public MediaSegmentBase { public: +#if defined(MOZILLA_XPCOMRT_API) + typedef mozilla::SimpleImageBuffer Image; +#else typedef mozilla::layers::Image Image; +#endif typedef mozilla::gfx::IntSize IntSize; VideoSegment(); diff --git a/dom/media/moz.build b/dom/media/moz.build index 03e4c1581d..47da607997 100644 --- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -18,6 +18,7 @@ DIRS += [ 'webrtc', 'webspeech', 'webvtt', + 'standalone', ] if CONFIG['MOZ_RAW']: diff --git a/dom/media/standalone/moz.build b/dom/media/standalone/moz.build new file mode 100644 index 0000000000..2d33738c7f --- /dev/null +++ b/dom/media/standalone/moz.build @@ -0,0 +1,47 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +if CONFIG['OS_TARGET'] != 'WINNT' and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk': + Library('media_standalone') + +UNIFIED_SOURCES += [ + '../AudioChannelFormat.cpp', + '../AudioSegment.cpp', + '../SimpleImageBuffer.cpp', + '../VideoSegment.cpp', +] + +if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': + UNIFIED_SOURCES += ['../systemservices/OSXRunLoopSingleton.cpp'] + +MSVC_ENABLE_PGO = True + +LOCAL_INCLUDES += [ + '/caps', + '/dom/base', + '/dom/camera', + '/layout/generic', + '/layout/xul', + '/netwerk/base', +] + +if CONFIG['MOZ_WEBRTC']: + LOCAL_INCLUDES += [ + '/media/webrtc/signaling/src/common', + '/media/webrtc/trunk', + ] + +DEFINES['MOZILLA_INTERNAL_API'] = True +DEFINES['MOZILLA_XPCOMRT_API'] = True +DEFINES['MOZILLA_EXTERNAL_LINKAGE'] = True + +include('/ipc/chromium/chromium-config.mozbuild') + +# Suppress some GCC warnings being treated as errors: +# - about attributes on forward declarations for types that are already +# defined, which complains about an important MOZ_EXPORT for android::AString +if CONFIG['GNU_CC']: + CXXFLAGS += ['-Wno-error=attributes'] diff --git a/dom/media/webaudio/AudioProcessingEvent.cpp b/dom/media/webaudio/AudioProcessingEvent.cpp index a17be051f2..5af19fd317 100644 --- a/dom/media/webaudio/AudioProcessingEvent.cpp +++ b/dom/media/webaudio/AudioProcessingEvent.cpp @@ -55,7 +55,7 @@ AudioProcessingEvent::LazilyCreateBuffer(uint32_t aNumberOfChannels, AudioBuffer::Create(mNode->Context(), aNumberOfChannels, mNode->BufferSize(), mNode->Context()->SampleRate(), cx, aRv); - MOZ_ASSERT(buffer || aRv.ErrorCode() == NS_ERROR_OUT_OF_MEMORY); + MOZ_ASSERT(buffer || aRv.ErrorCodeIs(NS_ERROR_OUT_OF_MEMORY)); return buffer.forget(); } diff --git a/dom/network/UDPSocket.cpp b/dom/network/UDPSocket.cpp index 310d66e061..6aa3b66cb2 100644 --- a/dom/network/UDPSocket.cpp +++ b/dom/network/UDPSocket.cpp @@ -292,7 +292,7 @@ UDPSocket::DoPendingMcastCommand() } if (NS_WARN_IF(rv.Failed())) { - return rv.ErrorCode(); + return rv.StealNSResult(); } } @@ -527,12 +527,12 @@ UDPSocket::Init(const nsString& aLocalAddress, mOpened = Promise::Create(global, rv); if (NS_WARN_IF(rv.Failed())) { - return rv.ErrorCode(); + return rv.StealNSResult(); } mClosed = Promise::Create(global, rv); if (NS_WARN_IF(rv.Failed())) { - return rv.ErrorCode(); + return rv.StealNSResult(); } class OpenSocketRunnable final : public nsRunnable diff --git a/dom/notification/Notification.cpp b/dom/notification/Notification.cpp index 483bac98b8..c074c58e33 100644 --- a/dom/notification/Notification.cpp +++ b/dom/notification/Notification.cpp @@ -83,7 +83,7 @@ public: ErrorResult rv; notification->InitFromBase64(aCx, aData, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } notification->SetStoredState(true); @@ -338,7 +338,7 @@ NotificationPermissionRequest::CallCallback() { ErrorResult rv; mCallback->Call(mPermission, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP diff --git a/dom/offline/nsDOMOfflineResourceList.cpp b/dom/offline/nsDOMOfflineResourceList.cpp index 27f5b50abb..27edea4769 100644 --- a/dom/offline/nsDOMOfflineResourceList.cpp +++ b/dom/offline/nsDOMOfflineResourceList.cpp @@ -224,7 +224,7 @@ nsDOMOfflineResourceList::GetMozItems(nsISupports** aItems) ErrorResult rv; nsRefPtr items = GetMozItems(rv); items.forget(aItems); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP diff --git a/dom/plugins/base/android/ANPSystem.cpp b/dom/plugins/base/android/ANPSystem.cpp index 44743339a1..86cc46428a 100644 --- a/dom/plugins/base/android/ANPSystem.cpp +++ b/dom/plugins/base/android/ANPSystem.cpp @@ -60,7 +60,7 @@ jclass anp_system_loadJavaClass(NPP instance, const char* className) nsCString libName; lib->GetLibraryPath(libName); - return mozilla::widget::GoannaAppShell::LoadPluginClass(className, libName).Forget(); + return mozilla::widget::GeckoAppShell::LoadPluginClass(className, libName).Forget(); } void anp_system_setPowerState(NPP instance, ANPPowerState powerState) diff --git a/dom/plugins/base/nsJSNPRuntime.cpp b/dom/plugins/base/nsJSNPRuntime.cpp index f3afce6491..f58058f930 100644 --- a/dom/plugins/base/nsJSNPRuntime.cpp +++ b/dom/plugins/base/nsJSNPRuntime.cpp @@ -773,8 +773,8 @@ doInvoke(NPObject *npobj, NPIdentifier method, const NPVariant *args, } // We're about to run script via JS_CallFunctionValue, so we need an - // AutoEntryScript. NPAPI plugins are Goanna-specific and not in any spec. - dom::AutoEntryScript aes(globalObject); + // AutoEntryScript. NPAPI plugins are Gecko-specific and not in any spec. + dom::AutoEntryScript aes(globalObject, "NPAPI doInvoke"); JSContext *cx = aes.cx(); if (!npobj || !result) { @@ -901,8 +901,8 @@ nsJSObjWrapper::NP_GetProperty(NPObject *npobj, NPIdentifier id, } // We're about to run script via JS_CallFunctionValue, so we need an - // AutoEntryScript. NPAPI plugins are Goanna-specific and not in any spec. - dom::AutoEntryScript aes(globalObject); + // AutoEntryScript. NPAPI plugins are Gecko-specific and not in any spec. + dom::AutoEntryScript aes(globalObject, "NPAPI get"); JSContext *cx = aes.cx(); if (!npobj) { @@ -935,8 +935,8 @@ nsJSObjWrapper::NP_SetProperty(NPObject *npobj, NPIdentifier npid, } // We're about to run script via JS_CallFunctionValue, so we need an - // AutoEntryScript. NPAPI plugins are Goanna-specific and not in any spec. - dom::AutoEntryScript aes(globalObject); + // AutoEntryScript. NPAPI plugins are Gecko-specific and not in any spec. + dom::AutoEntryScript aes(globalObject, "NPAPI set"); JSContext *cx = aes.cx(); if (!npobj) { diff --git a/dom/plugins/base/nsNPAPIPlugin.cpp b/dom/plugins/base/nsNPAPIPlugin.cpp index fdbaec9f34..d9594f945a 100644 --- a/dom/plugins/base/nsNPAPIPlugin.cpp +++ b/dom/plugins/base/nsNPAPIPlugin.cpp @@ -1507,7 +1507,7 @@ _evaluate(NPP npp, NPObject* npobj, NPString *script, NPVariant *result) return false; } - dom::AutoEntryScript aes(win); + dom::AutoEntryScript aes(win, "NPAPI NPN_evaluate"); aes.TakeOwnershipOfErrorReporting(); JSContext* cx = aes.cx(); @@ -2280,7 +2280,7 @@ _getvalue(NPP npp, NPNVariable variable, void *result) } case kJavaContext_ANPGetValue: { - auto ret = widget::GoannaAppShell::GetContext(); + auto ret = widget::GeckoAppShell::GetContext(); if (!ret) return NPERR_GENERIC_ERROR; diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp index ff2ecd3cc1..4b0c779cd6 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -847,7 +847,7 @@ void nsNPAPIPluginInstance::NotifyFullScreen(bool aFullScreen) SendLifecycleEvent(this, mFullScreen ? kEnterFullScreen_ANPLifecycleAction : kExitFullScreen_ANPLifecycleAction); if (mFullScreen && mFullScreenOrientation != dom::eScreenOrientation_None) { - widget::GoannaAppShell::LockScreenOrientation(mFullScreenOrientation); + widget::GeckoAppShell::LockScreenOrientation(mFullScreenOrientation); } } @@ -904,11 +904,11 @@ void nsNPAPIPluginInstance::SetFullScreenOrientation(uint32_t orientation) // We're already fullscreen so immediately apply the orientation change if (mFullScreenOrientation != dom::eScreenOrientation_None) { - widget::GoannaAppShell::LockScreenOrientation(mFullScreenOrientation); + widget::GeckoAppShell::LockScreenOrientation(mFullScreenOrientation); } else if (oldOrientation != dom::eScreenOrientation_None) { // We applied an orientation when we entered fullscreen, but // we don't want it anymore - widget::GoannaAppShell::UnlockScreenOrientation(); + widget::GeckoAppShell::UnlockScreenOrientation(); } } } diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp index 51c370ec05..44c6d60c46 100644 --- a/dom/plugins/base/nsPluginHost.cpp +++ b/dom/plugins/base/nsPluginHost.cpp @@ -102,7 +102,7 @@ #ifdef ANDROID #include -#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GoannaPlugins" , ## args) +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) #endif using namespace mozilla; @@ -2486,7 +2486,7 @@ nsPluginHost::RegisterWithCategoryManager(nsCString &aMimeType, "@mozilla.org/content/plugin/document-loader-factory;1"; if (aType == ePluginRegister) { - catMan->AddCategoryEntry("Goanna-Content-Viewers", + catMan->AddCategoryEntry("Gecko-Content-Viewers", aMimeType.get(), contractId, false, /* persist: broken by bug 193031 */ @@ -2495,11 +2495,11 @@ nsPluginHost::RegisterWithCategoryManager(nsCString &aMimeType, } else { // Only delete the entry if a plugin registered for it nsXPIDLCString value; - nsresult rv = catMan->GetCategoryEntry("Goanna-Content-Viewers", + nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", aMimeType.get(), getter_Copies(value)); if (NS_SUCCEEDED(rv) && strcmp(value, contractId) == 0) { - catMan->DeleteCategoryEntry("Goanna-Content-Viewers", + catMan->DeleteCategoryEntry("Gecko-Content-Viewers", aMimeType.get(), true); } diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index d30efffcbe..5878f6c199 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -1362,7 +1362,7 @@ void nsPluginInstanceOwner::RemovePluginView() if (!mInstance || !mJavaView) return; - widget::GoannaAppShell::RemovePluginView( + widget::GeckoAppShell::RemovePluginView( jni::Object::Ref::From(jobject(mJavaView)), mFullScreen); AndroidBridge::GetJNIEnv()->DeleteGlobalRef((jobject)mJavaView); mJavaView = nullptr; diff --git a/dom/power/PowerManagerService.cpp b/dom/power/PowerManagerService.cpp index 9fdd0c5d48..383d8ac600 100644 --- a/dom/power/PowerManagerService.cpp +++ b/dom/power/PowerManagerService.cpp @@ -227,7 +227,7 @@ PowerManagerService::NewWakeLock(const nsAString &aTopic, mozilla::ErrorResult rv; nsRefPtr wakelock = NewWakeLock(aTopic, aWindow, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } nsCOMPtr eventListener = wakelock.get(); diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp index b29cd370cb..b05a1d23b1 100644 --- a/dom/promise/Promise.cpp +++ b/dom/promise/Promise.cpp @@ -205,18 +205,13 @@ protected: JS::Rooted rootedThenable(cx, mThenable); mThen->Call(rootedThenable, resolveFunc, rejectFunc, rv, - CallbackObject::eRethrowExceptions, + "promise thenable", CallbackObject::eRethrowExceptions, mPromise->Compartment()); rv.WouldReportJSException(); if (rv.Failed()) { JS::Rooted exn(cx); if (rv.IsJSException()) { - // Enter the compartment of mPromise before stealing the JS exception, - // since the StealJSException call will use the current compartment for - // a security check that determines how much of the stack we're allowed - // to see and we'll be exposing that stack to consumers of mPromise. - JSAutoCompartment ac(cx, mPromise->GlobalJSObject()); rv.StealJSException(cx, &exn); } else { // Convert the ErrorResult to a JS exception object that we can reject @@ -603,20 +598,13 @@ Promise::CallInitFunction(const GlobalObject& aGlobal, return; } - aInit.Call(resolveFunc, rejectFunc, aRv, CallbackObject::eRethrowExceptions, - Compartment()); + aInit.Call(resolveFunc, rejectFunc, aRv, "promise initializer", + CallbackObject::eRethrowExceptions, Compartment()); aRv.WouldReportJSException(); if (aRv.IsJSException()) { JS::Rooted value(cx); - { // scope for ac - // Enter the compartment of our global before stealing the JS exception, - // since the StealJSException call will use the current compartment for - // a security check that determines how much of the stack we're allowed - // to see, and we'll be exposing that stack to consumers of this promise. - JSAutoCompartment ac(cx, GlobalJSObject()); - aRv.StealJSException(cx, &value); - } + aRv.StealJSException(cx, &value); // we want the same behavior as this JS implementation: // function Promise(arg) { try { arg(a, b); } catch (e) { this.reject(e); }} @@ -1440,35 +1428,13 @@ PromiseWorkerProxy::StoreISupports(nsISupports* aSupports) mSupportsArray.AppendElement(supports); } -namespace { - -class PromiseWorkerProxyControlRunnable final - : public WorkerControlRunnable +bool +PromiseWorkerProxyControlRunnable::WorkerRun(JSContext* aCx, + WorkerPrivate* aWorkerPrivate) { - nsRefPtr mProxy; - -public: - PromiseWorkerProxyControlRunnable(WorkerPrivate* aWorkerPrivate, - PromiseWorkerProxy* aProxy) - : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount) - , mProxy(aProxy) - { - MOZ_ASSERT(aProxy); - } - - virtual bool - WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override - { - mProxy->CleanUp(aCx); - return true; - } - -private: - ~PromiseWorkerProxyControlRunnable() - {} -}; - -} // anonymous namespace + mProxy->CleanUp(aCx); + return true; +} void PromiseWorkerProxy::RunCallback(JSContext* aCx, diff --git a/dom/promise/PromiseCallback.cpp b/dom/promise/PromiseCallback.cpp index d578f8de44..7d63f66a9a 100644 --- a/dom/promise/PromiseCallback.cpp +++ b/dom/promise/PromiseCallback.cpp @@ -205,7 +205,8 @@ WrapperPromiseCallback::Call(JSContext* aCx, // PromiseReactionTask step 6 JS::Rooted retValue(aCx); - mCallback->Call(value, &retValue, rv, CallbackObject::eRethrowExceptions, + mCallback->Call(value, &retValue, rv, "promise callback", + CallbackObject::eRethrowExceptions, mNextPromise->Compartment()); rv.WouldReportJSException(); @@ -214,15 +215,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, if (rv.Failed()) { JS::Rooted value(aCx); if (rv.IsJSException()) { - { // scope for ac - // Enter the compartment of mNextPromise before stealing the JS - // exception, since the StealJSException call will use the current - // compartment for a security check that determines how much of the - // stack we're allowed to see and we'll be exposing that stack to - // consumers of mPromise. - JSAutoCompartment ac(aCx, mNextPromise->GlobalJSObject()); - rv.StealJSException(aCx, &value); - } + rv.StealJSException(aCx, &value); if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); diff --git a/dom/promise/PromiseWorkerProxy.h b/dom/promise/PromiseWorkerProxy.h index d033e52f38..c8b68683e1 100644 --- a/dom/promise/PromiseWorkerProxy.h +++ b/dom/promise/PromiseWorkerProxy.h @@ -11,6 +11,8 @@ #include "mozilla/dom/workers/bindings/WorkerFeature.h" #include "nsProxyRelease.h" +#include "WorkerRunnable.h" + namespace mozilla { namespace dom { @@ -53,8 +55,12 @@ class WorkerPrivate; // dispatch a runnable to the worker. Use GetWorkerPrivate() to acquire the // worker. This might be null! In the WorkerRunnable's WorkerRun() use // GetWorkerPromise() to access the Promise and resolve/reject it. Then call -// CleanUp() on the worker -// thread. +// CleanUp() on the worker thread. +// +// IMPORTANT: Dispatching the runnable to the worker thread may fail causing +// the promise to leak. To successfully release the promise on the +// worker thread in this case, use |PromiseWorkerProxyControlRunnable| to +// dispatch a control runnable that will deref the object on the correct thread. class PromiseWorkerProxy : public PromiseNativeHandler, public workers::WorkerFeature @@ -78,6 +84,17 @@ public: void CleanUp(JSContext* aCx); + Mutex& GetCleanUpLock() + { + return mCleanUpLock; + } + + bool IsClean() const + { + mCleanUpLock.AssertCurrentThreadOwns(); + return mCleanedUp; + } + protected: virtual void ResolvedCallback(JSContext* aCx, JS::Handle aValue) override; @@ -119,6 +136,30 @@ private: Mutex mCleanUpLock; }; +// Helper runnable used for releasing the proxied promise when the worker +// is not accepting runnables and the promise object would leak. +// See the instructions above. +class PromiseWorkerProxyControlRunnable final : public workers::WorkerControlRunnable +{ + nsRefPtr mProxy; + +public: + PromiseWorkerProxyControlRunnable(workers::WorkerPrivate* aWorkerPrivate, + PromiseWorkerProxy* aProxy) + : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount) + , mProxy(aProxy) + { + MOZ_ASSERT(aProxy); + } + + virtual bool + WorkerRun(JSContext* aCx, workers::WorkerPrivate* aWorkerPrivate) override; + +private: + ~PromiseWorkerProxyControlRunnable() + {} +}; + } // namespace dom } // namespace mozilla diff --git a/dom/quota/QuotaManager.cpp b/dom/quota/QuotaManager.cpp index 25435b5c92..dd8a5fac1b 100644 --- a/dom/quota/QuotaManager.cpp +++ b/dom/quota/QuotaManager.cpp @@ -2247,7 +2247,7 @@ QuotaManager::EnsureOriginIsInitialized(PersistenceType aPersistenceType, if (IsTreatedAsPersistent(aPersistenceType, aIsApp)) { if (mInitializedOrigins.Contains(OriginKey(aPersistenceType, aOrigin))) { - NS_ADDREF(*aDirectory = directory); + directory.forget(aDirectory); return NS_OK; } } else if (!mTemporaryStorageInitialized) { diff --git a/dom/storage/DOMStorage.cpp b/dom/storage/DOMStorage.cpp index 5c4bbc853f..c7d236fae6 100644 --- a/dom/storage/DOMStorage.cpp +++ b/dom/storage/DOMStorage.cpp @@ -131,7 +131,7 @@ DOMStorage::SetItem(const nsAString& aKey, const nsAString& aData, return; } - if (aRv.ErrorCode() != NS_SUCCESS_DOM_NO_OPERATION) { + if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) { BroadcastChangeNotification(aKey, old, aData); } } @@ -150,7 +150,7 @@ DOMStorage::RemoveItem(const nsAString& aKey, ErrorResult& aRv) return; } - if (aRv.ErrorCode() != NS_SUCCESS_DOM_NO_OPERATION) { + if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) { BroadcastChangeNotification(aKey, old, NullString()); } } @@ -168,7 +168,7 @@ DOMStorage::Clear(ErrorResult& aRv) return; } - if (aRv.ErrorCode() != NS_SUCCESS_DOM_NO_OPERATION) { + if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) { BroadcastChangeNotification(NullString(), NullString(), NullString()); } } diff --git a/dom/svg/DOMSVGLength.cpp b/dom/svg/DOMSVGLength.cpp index 25c5a8569f..c9e3f4ccaf 100644 --- a/dom/svg/DOMSVGLength.cpp +++ b/dom/svg/DOMSVGLength.cpp @@ -254,7 +254,7 @@ DOMSVGLength::GetValue(float* aValue) { ErrorResult rv; *aValue = GetValue(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -308,7 +308,7 @@ DOMSVGLength::SetValue(float aUserUnitValue) ErrorResult rv; SetValue(aUserUnitValue, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } float @@ -368,7 +368,7 @@ DOMSVGLength::SetValueInSpecifiedUnits(float aValue) ErrorResult rv; SetValueInSpecifiedUnits(aValue, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -406,7 +406,7 @@ DOMSVGLength::SetValueAsString(const nsAString& aValue) { ErrorResult rv; SetValueAsString(aValue, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } NS_IMETHODIMP @@ -473,7 +473,7 @@ DOMSVGLength::NewValueSpecifiedUnits(uint16_t aUnit, float aValue) ErrorResult rv; NewValueSpecifiedUnits(aUnit, aValue, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -523,7 +523,7 @@ DOMSVGLength::ConvertToSpecifiedUnits(uint16_t aUnit) { ErrorResult rv; ConvertToSpecifiedUnits(aUnit, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } JSObject* diff --git a/dom/system/android/AndroidLocationProvider.cpp b/dom/system/android/AndroidLocationProvider.cpp index 9f691b56d9..f6919f7ba9 100644 --- a/dom/system/android/AndroidLocationProvider.cpp +++ b/dom/system/android/AndroidLocationProvider.cpp @@ -26,7 +26,7 @@ AndroidLocationProvider::~AndroidLocationProvider() NS_IMETHODIMP AndroidLocationProvider::Startup() { - widget::GoannaAppShell::EnableLocation(true); + widget::GeckoAppShell::EnableLocation(true); return NS_OK; } @@ -42,13 +42,13 @@ AndroidLocationProvider::Watch(nsIGeolocationUpdate* aCallback) NS_IMETHODIMP AndroidLocationProvider::Shutdown() { - widget::GoannaAppShell::EnableLocation(false); + widget::GeckoAppShell::EnableLocation(false); return NS_OK; } NS_IMETHODIMP AndroidLocationProvider::SetHighAccuracy(bool enable) { - widget::GoannaAppShell::EnableLocationHighAccuracy(enable); + widget::GeckoAppShell::EnableLocationHighAccuracy(enable); return NS_OK; } diff --git a/dom/system/android/nsHapticFeedback.cpp b/dom/system/android/nsHapticFeedback.cpp index cbd36ec599..93d17afbb0 100644 --- a/dom/system/android/nsHapticFeedback.cpp +++ b/dom/system/android/nsHapticFeedback.cpp @@ -14,6 +14,6 @@ NS_IMPL_ISUPPORTS(nsHapticFeedback, nsIHapticFeedback) NS_IMETHODIMP nsHapticFeedback::PerformSimpleAction(int32_t aType) { - widget::GoannaAppShell::PerformHapticFeedback(aType == LongPress); + widget::GeckoAppShell::PerformHapticFeedback(aType == LongPress); return NS_OK; } diff --git a/dom/system/gonk/nsVolumeMountLock.cpp b/dom/system/gonk/nsVolumeMountLock.cpp index a7b6bb0559..0bb4fbd111 100644 --- a/dom/system/gonk/nsVolumeMountLock.cpp +++ b/dom/system/gonk/nsVolumeMountLock.cpp @@ -160,7 +160,7 @@ nsVolumeMountLock::Lock(nsIVolume* aVolume) ErrorResult err; mWakeLock = pmService->NewWakeLock(mountLockName, nullptr, err); if (err.Failed()) { - return err.ErrorCode(); + return err.StealNSResult(); } LOG("nsVolumeMountLock acquired for '%s' gen %d", diff --git a/dom/system/gonk/nsVolumeService.cpp b/dom/system/gonk/nsVolumeService.cpp index a4858d6743..eaa41f2c90 100644 --- a/dom/system/gonk/nsVolumeService.cpp +++ b/dom/system/gonk/nsVolumeService.cpp @@ -239,7 +239,7 @@ nsVolumeService::GetVolumeNames(nsIArray** aVolNames) NS_ENSURE_SUCCESS(rv, rv); } - NS_ADDREF(*aVolNames = volNames); + volNames.forget(aVolNames); return NS_OK; } diff --git a/dom/tests/mochitest/bugs/test_bug400204.html b/dom/tests/mochitest/bugs/test_bug400204.html index bb479eb52c..44703f9490 100644 --- a/dom/tests/mochitest/bugs/test_bug400204.html +++ b/dom/tests/mochitest/bugs/test_bug400204.html @@ -25,6 +25,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=400204 try { success = (c.contentWindow.innerHeight == 0); } catch(ex) { success = false; } ok(success, "can't access hidden iframe innerHeight, or it's not 0"); + // Snag the canonical getter and setter + var innerWidthGetter = Object.getOwnPropertyDescriptor(c.contentWindow, "innerWidth").get; + var innerHeightGetter = Object.getOwnPropertyDescriptor(c.contentWindow, "innerHeight").get; + // try to set innerWidth success = false; try { c.contentWindow.innerWidth = 100; success = true; } catch(ex) { success = false; } @@ -36,15 +40,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=400204 ok(success, "can't set hidden iframe innerHeight"); // now try these again for good measure, and to ensure the values - // haven't changed + // haven't changed except via getting replaced // try to access innerWidth success = false; - try { success = (c.contentWindow.innerWidth == 0); } catch(ex) { success = false; } + try { success = (c.contentWindow.innerWidth == 100); } catch(ex) { success = false; } + ok(success, "can't access hidden iframe innerWidth, or it's not 100"); + + success = false; + try { success = (innerWidthGetter.call(c.contentWindow) == 0); } catch(ex) { success = false; } ok(success, "can't access hidden iframe innerWidth, or it's not 0"); // try to access innerHeight success = false; - try { success = (c.contentWindow.innerHeight == 0); } catch(ex) { success = false; } + try { success = (c.contentWindow.innerHeight == 100); } catch(ex) { success = false; } + ok(success, "can't access hidden iframe innerHeight, or it's not 100"); + + success = false; + try { success = (innerHeightGetter.call(c.contentWindow) == 0); } catch(ex) { success = false; } ok(success, "can't access hidden iframe innerHeight, or it's not 0"); diff --git a/dom/tests/mochitest/bugs/test_bug61098.html b/dom/tests/mochitest/bugs/test_bug61098.html index 23de36d084..ae22446f26 100644 --- a/dom/tests/mochitest/bugs/test_bug61098.html +++ b/dom/tests/mochitest/bugs/test_bug61098.html @@ -21,7 +21,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=61098 diff --git a/dom/tests/mochitest/gamepad/test_navigator_gamepads.html b/dom/tests/mochitest/gamepad/test_navigator_gamepads.html index df8940f97d..8a64999e7c 100644 --- a/dom/tests/mochitest/gamepad/test_navigator_gamepads.html +++ b/dom/tests/mochitest/gamepad/test_navigator_gamepads.html @@ -37,49 +37,61 @@ function disconnecthandler(e) { window.addEventListener("gamepadconnected", connecthandler); window.addEventListener("gamepaddisconnected", disconnecthandler); // Add a gamepad -var index1 = GamepadService.addGamepad("test gamepad 1", // id +var internal_index1 = GamepadService.addGamepad("test gamepad 1", // id SpecialPowers.Ci.nsIGamepadServiceTest.NO_MAPPING, 4, // buttons 2);// axes -var index2; +var content_index1 = 0; +var internal_index2; +var content_index2 = 1; // Press a button to make the gamepad visible to the page. -GamepadService.newButtonEvent(index1, 0, true); +GamepadService.newButtonEvent(internal_index1, 0, true); function check_first_gamepad(e) { + ok(true, "Checking first gamepad"); // First gamepad gets added. is(e.gamepad.id, "test gamepad 1", "correct gamepad name"); var gamepads = navigator.getGamepads(); is(gamepads.length, 1, "should have one gamepad exposed"); is(gamepads[e.gamepad.index], e.gamepad, "right gamepad exposed at index"); + is(gamepads[content_index1], e.gamepad, "gamepad counter working correctly"); // Add a second gamepad, should automatically show up. - index2 = GamepadService.addGamepad("test gamepad 2", // id + internal_index2 = GamepadService.addGamepad("test gamepad 2", // id SpecialPowers.Ci.nsIGamepadServiceTest.NO_MAPPING, 4, // buttons 2);// axes + ok(true, "Done checking first gamepad"); } function check_second_gamepad(e) { + ok(true, "Checking seceond gamepad"); // Second gamepad gets added. + is(e.gamepad.index, 1, "gamepad index should be 1") is(e.gamepad.id, "test gamepad 2", "correct gamepad name"); var gamepads = navigator.getGamepads(); is(gamepads.length, 2, "should have two gamepads exposed"); is(gamepads[e.gamepad.index], e.gamepad, "right gamepad exposed at index"); + is(gamepads[content_index2], e.gamepad, "gamepad counter working correctly"); // Now remove the first one. - GamepadService.removeGamepad(index1); + GamepadService.removeGamepad(internal_index1); + ok(true, "Done checking second gamepad"); } function check_gamepad_hole(e) { + ok(true, "Checking gamepad hole"); // First gamepad gets removed. var gamepads = navigator.getGamepads(); is(gamepads.length, 2, "gamepads should have two entries"); - is(gamepads[index1], null, "should be a hole in the gamepad list"); - isnot(gamepads[index2], null, "second gamepad should exist"); + is(gamepads[content_index1], null, "should be a hole in the gamepad list"); + isnot(gamepads[content_index2], null, "second gamepad should exist"); // Now remove the second one. - GamepadService.removeGamepad(index2); + GamepadService.removeGamepad(internal_index2); + ok(true, "Done checking gamepad hole"); } function check_no_gamepads(e) { + ok(true, "Checking no gamepads"); // Second gamepad gets removed. var gamepads = navigator.getGamepads(); is(gamepads.length, 0, "gamepads should be empty"); diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html index 99b8a7b1b1..f130fe0294 100644 --- a/dom/tests/mochitest/general/test_interfaces.html +++ b/dom/tests/mochitest/general/test_interfaces.html @@ -129,14 +129,12 @@ var interfaceNamesInGlobalScope = {name: "AlarmsManager", pref: "dom.mozAlarms.enabled"}, // IMPORTANT: Do not change this list without review from a DOM peer! "AnalyserNode", -// IMPORTANT: Do not change this list without review from a DOM peer! - "AnimationEvent", // IMPORTANT: Do not change this list without review from a DOM peer! {name: "Animation", pref: "dom.animations-api.core.enabled"}, // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "AnimationEffect", pref: "dom.animations-api.core.enabled"}, + {name: "AnimationEffectReadonly", pref: "dom.animations-api.core.enabled"}, // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "AnimationPlayer", pref: "dom.animations-api.core.enabled"}, + "AnimationEvent", // IMPORTANT: Do not change this list without review from a DOM peer! {name: "AnimationTimeline", pref: "dom.animations-api.core.enabled"}, // IMPORTANT: Do not change this list without review from a DOM peer! @@ -352,6 +350,8 @@ var interfaceNamesInGlobalScope = "Document", // IMPORTANT: Do not change this list without review from a DOM peer! "DocumentFragment", +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "DocumentTimeline", pref: "dom.animations-api.core.enabled"}, // IMPORTANT: Do not change this list without review from a DOM peer! "DocumentType", // IMPORTANT: Do not change this list without review from a DOM peer! @@ -652,6 +652,8 @@ var interfaceNamesInGlobalScope = "KeyEvent", // IMPORTANT: Do not change this list without review from a DOM peer! "KeyboardEvent", +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "KeyframeEffectReadonly", pref: "dom.animations-api.core.enabled"}, // IMPORTANT: Do not change this list without review from a DOM peer! "LocalMediaStream", // IMPORTANT: Do not change this list without review from a DOM peer! diff --git a/dom/webidl/Animatable.webidl b/dom/webidl/Animatable.webidl index 38cafcfc40..03985f797b 100644 --- a/dom/webidl/Animatable.webidl +++ b/dom/webidl/Animatable.webidl @@ -13,5 +13,5 @@ [NoInterfaceObject] interface Animatable { [Func="nsDocument::IsWebAnimationsEnabled"] - sequence getAnimations(); + sequence getAnimations(); }; diff --git a/dom/webidl/Animation.webidl b/dom/webidl/Animation.webidl index db852cf8ed..6eb57ef720 100644 --- a/dom/webidl/Animation.webidl +++ b/dom/webidl/Animation.webidl @@ -4,18 +4,46 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. * * The origin of this IDL file is - * http://dev.w3.org/fxtf/web-animations/#the-animation-interface + * http://w3c.github.io/web-animations/#the-animation-interface * - * Copyright © 2014 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C + * Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C * liability, trademark and document use rules apply. */ +enum AnimationPlayState { "idle", "pending", "running", "paused", "finished" }; + [Func="nsDocument::IsWebAnimationsEnabled"] interface Animation { - // FIXME: |effect| should have type (AnimationEffect or EffectCallback)? - // but we haven't implemented EffectCallback yet. - [Cached,Pure] - readonly attribute AnimationEffect? effect; - // FIXME: This should be writeable (bug 1067769) - readonly attribute Element? target; + // Bug 1049975: Make 'effect' writeable + [Pure] + readonly attribute AnimationEffectReadonly? effect; + readonly attribute AnimationTimeline timeline; + [BinaryName="startTimeAsDouble"] + attribute double? startTime; + [SetterThrows, BinaryName="currentTimeAsDouble"] + attribute double? currentTime; + + attribute double playbackRate; + [BinaryName="playStateFromJS"] + readonly attribute AnimationPlayState playState; + [Throws] + readonly attribute Promise ready; + [Throws] + readonly attribute Promise finished; + /* + void cancel (); + void finish (); + */ + [BinaryName="playFromJS"] + void play (); + [BinaryName="pauseFromJS"] + void pause (); + /* + void reverse (); + */ +}; + +// Non-standard extensions +partial interface Animation { + [ChromeOnly] readonly attribute boolean isRunningOnCompositor; }; diff --git a/dom/webidl/AnimationEffectReadonly.webidl b/dom/webidl/AnimationEffectReadonly.webidl new file mode 100644 index 0000000000..b430b82f51 --- /dev/null +++ b/dom/webidl/AnimationEffectReadonly.webidl @@ -0,0 +1,18 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * http://w3c.github.io/web-animations/#animationeffectreadonly + * + * Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C + * liability, trademark and document use rules apply. + */ + +[Func="nsDocument::IsWebAnimationsEnabled"] +interface AnimationEffectReadonly { + // Not yet implemented: + // readonly attribute AnimationEffectTimingReadonly timing; + // readonly attribute ComputedTimingProperties computedTiming; +}; diff --git a/dom/webidl/AnimationPlayer.webidl b/dom/webidl/AnimationPlayer.webidl deleted file mode 100644 index 6186eb4e6f..0000000000 --- a/dom/webidl/AnimationPlayer.webidl +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - * - * The origin of this IDL file is - * http://dev.w3.org/fxtf/web-animations/#idl-def-AnimationPlayer - * - * Copyright © 2014 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C - * liability, trademark and document use rules apply. - */ - -enum AnimationPlayState { "idle", "pending", "running", "paused", "finished" }; - -[Func="nsDocument::IsWebAnimationsEnabled"] -interface AnimationPlayer { - // Bug 1049975 - // attribute AnimationNode? source; - [Pure] - readonly attribute Animation? source; - readonly attribute AnimationTimeline timeline; - [BinaryName="startTimeAsDouble"] - attribute double? startTime; - [SetterThrows, BinaryName="currentTimeAsDouble"] - attribute double? currentTime; - - attribute double playbackRate; - [BinaryName="playStateFromJS"] - readonly attribute AnimationPlayState playState; - [Throws] - readonly attribute Promise ready; - [Throws] - readonly attribute Promise finished; - /* - void cancel (); - void finish (); - */ - [BinaryName="playFromJS"] - void play (); - [BinaryName="pauseFromJS"] - void pause (); - /* - void reverse (); - */ -}; - -// Non-standard extensions -partial interface AnimationPlayer { - [ChromeOnly] readonly attribute boolean isRunningOnCompositor; -}; diff --git a/dom/webidl/AnimationTimeline.webidl b/dom/webidl/AnimationTimeline.webidl index 14d67254ba..e920e13ec0 100644 --- a/dom/webidl/AnimationTimeline.webidl +++ b/dom/webidl/AnimationTimeline.webidl @@ -4,9 +4,9 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. * * The origin of this IDL file is - * http://dev.w3.org/fxtf/web-animations/#the-animationtimeline-interface + * https://w3c.github.io/web-animations/#animationtimeline * - * Copyright © 2014 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C + * Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C * liability, trademark and document use rules apply. */ @@ -15,6 +15,6 @@ interface AnimationTimeline { [BinaryName="currentTimeAsDouble"] readonly attribute double? currentTime; // Not yet implemented: - // AnimationPlayer play (optional TimedItem? source = null); - // sequence getAnimations (); + // Animation play (optional TimedItem? source = null); + // sequence getAnimations (); }; diff --git a/dom/webidl/Client.webidl b/dom/webidl/Client.webidl index b09d0b9b43..a2111a8d61 100644 --- a/dom/webidl/Client.webidl +++ b/dom/webidl/Client.webidl @@ -22,6 +22,8 @@ interface WindowClient : Client { readonly attribute VisibilityState visibilityState; readonly attribute boolean focused; readonly attribute FrameType frameType; + + [Throws] Promise focus(); }; diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl index 8ee7081c61..c499f948ca 100644 --- a/dom/webidl/Document.webidl +++ b/dom/webidl/Document.webidl @@ -303,10 +303,10 @@ partial interface Document { //(Not implemented)NodeList findAll(DOMString selectors, optional (Element or sequence)? refNodes); }; -// http://dev.w3.org/fxtf/web-animations/#extensions-to-the-document-interface +// http://w3c.github.io/web-animations/#extensions-to-the-document-interface partial interface Document { [Func="nsDocument::IsWebAnimationsEnabled"] - readonly attribute AnimationTimeline timeline; + readonly attribute DocumentTimeline timeline; }; // Mozilla extensions of various sorts diff --git a/dom/webidl/AnimationEffect.webidl b/dom/webidl/DocumentTimeline.webidl similarity index 64% rename from dom/webidl/AnimationEffect.webidl rename to dom/webidl/DocumentTimeline.webidl index 3c0c5eec18..bd7c793b49 100644 --- a/dom/webidl/AnimationEffect.webidl +++ b/dom/webidl/DocumentTimeline.webidl @@ -4,13 +4,14 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. * * The origin of this IDL file is - * http://dev.w3.org/fxtf/web-animations/#the-animationeffect-interface + * https://w3c.github.io/web-animations/#documenttimeline * - * Copyright © 2014 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C + * Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C * liability, trademark and document use rules apply. */ +// Not yet implemented: +// [Constructor (DOMHighResTimeStamp originTime)] [Func="nsDocument::IsWebAnimationsEnabled"] -interface AnimationEffect { - readonly attribute DOMString name; +interface DocumentTimeline : AnimationTimeline { }; diff --git a/dom/webidl/HTMLInputElement.webidl b/dom/webidl/HTMLInputElement.webidl index dbddb23e78..31c24fd61c 100644 --- a/dom/webidl/HTMLInputElement.webidl +++ b/dom/webidl/HTMLInputElement.webidl @@ -151,7 +151,7 @@ partial interface HTMLInputElement { [ChromeOnly] sequence mozGetFileNameArray(); - [ChromeOnly] + [ChromeOnly, Throws] void mozSetFileNameArray(sequence fileNames); [ChromeOnly] diff --git a/dom/webidl/KeyframeEffect.webidl b/dom/webidl/KeyframeEffect.webidl new file mode 100644 index 0000000000..3ee355417e --- /dev/null +++ b/dom/webidl/KeyframeEffect.webidl @@ -0,0 +1,24 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * http://w3c.github.io/web-animations/#the-keyframeeffect-interfaces + * + * Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C + * liability, trademark and document use rules apply. + */ + +[HeaderFile="mozilla/dom/KeyframeEffect.h", + Func="nsDocument::IsWebAnimationsEnabled"] +interface KeyframeEffectReadonly : AnimationEffectReadonly { + readonly attribute Element? target; + readonly attribute DOMString name; + // Not yet implemented: + // readonly attribute IterationCompositeOperation iterationComposite; + // readonly attribute CompositeOperation composite; + // readonly attribute DOMString spacing; + // KeyframeEffect clone(); + // sequence getFrames (); +}; diff --git a/dom/webidl/MutationObserver.webidl b/dom/webidl/MutationObserver.webidl index 42bff95d2b..b8c0fb528b 100644 --- a/dom/webidl/MutationObserver.webidl +++ b/dom/webidl/MutationObserver.webidl @@ -29,11 +29,11 @@ interface MutationRecord { [Constant] readonly attribute DOMString? oldValue; [Constant,Cached,ChromeOnly] - readonly attribute sequence addedAnimations; + readonly attribute sequence addedAnimations; [Constant,Cached,ChromeOnly] - readonly attribute sequence changedAnimations; + readonly attribute sequence changedAnimations; [Constant,Cached,ChromeOnly] - readonly attribute sequence removedAnimations; + readonly attribute sequence removedAnimations; }; [Constructor(MutationCallback mutationCallback)] diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index fdab89df7e..7e3f13fbf1 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -160,8 +160,10 @@ dictionary ScrollToOptions : ScrollOptions { partial interface Window { //[Throws,NewObject] MediaQueryList matchMedia(DOMString query); [Throws,NewObject] MediaQueryList? matchMedia(DOMString query); - //[SameObject] - [Throws] readonly attribute Screen screen; + // Per spec, screen is SameObject, but we don't actually guarantee that given + // nsGlobalWindow::Cleanup. :( + //[SameObject, Replaceable, Throws] readonly attribute Screen screen; + [Replaceable, Throws] readonly attribute Screen screen; // browsing context //[Throws] void moveTo(double x, double y); @@ -174,41 +176,49 @@ partial interface Window { [Throws, UnsafeInPrerendering] void resizeBy(long x, long y); // viewport - //[Throws] readonly attribute double innerWidth; - //[Throws] readonly attribute double innerHeight; - [Throws] attribute long innerWidth; - [Throws] attribute long innerHeight; + // These are writable because we allow chrome to write them. And they need + // to use 'any' as the type, because non-chrome writing them needs to act + // like a [Replaceable] attribute would, which needs the original JS value. + //[Replaceable, Throws] readonly attribute double innerWidth; + //[Replaceable, Throws] readonly attribute double innerHeight; + [Throws] attribute any innerWidth; + [Throws] attribute any innerHeight; // viewport scrolling - //[Throws] readonly attribute double scrollX; - //[Throws] readonly attribute double pageXOffset; - //[Throws] readonly attribute double scrollY; - //[Throws] readonly attribute double pageYOffset; void scroll(unrestricted double x, unrestricted double y); void scroll(optional ScrollToOptions options); void scrollTo(unrestricted double x, unrestricted double y); void scrollTo(optional ScrollToOptions options); void scrollBy(unrestricted double x, unrestricted double y); void scrollBy(optional ScrollToOptions options); - [Replaceable, Throws] readonly attribute double scrollX; // mozScrollSnap is used by chrome to perform scroll snapping after the // user performs actions that may affect scroll position // mozScrollSnap is deprecated, to be replaced by a web accessible API, such // as an extension to the ScrollOptions dictionary. See bug 1137937. [ChromeOnly] void mozScrollSnap(); - [Throws] readonly attribute double pageXOffset; - [Replaceable, Throws] readonly attribute double scrollY; - [Throws] readonly attribute double pageYOffset; + // The four properties below are double per spec at the moment, but whether + // that will continue is unclear. + //[Replaceable, Throws] readonly attribute double scrollX; + //[Replaceable, Throws] readonly attribute double pageXOffset; + //[Replaceable, Throws] readonly attribute double scrollY; + //[Replaceable, Throws] readonly attribute double pageYOffset; + [Replaceable, Throws] readonly attribute long scrollX; + [Replaceable, Throws] readonly attribute long pageXOffset; + [Replaceable, Throws] readonly attribute long scrollY; + [Replaceable, Throws] readonly attribute long pageYOffset; // client - //[Throws] readonly attribute double screenX; - //[Throws] readonly attribute double screenY; - //[Throws] readonly attribute double outerWidth; - //[Throws] readonly attribute double outerHeight; - [Throws] attribute long screenX; - [Throws] attribute long screenY; - [Throws] attribute long outerWidth; - [Throws] attribute long outerHeight; + // These are writable because we allow chrome to write them. And they need + // to use 'any' as the type, because non-chrome writing them needs to act + // like a [Replaceable] attribute would, which needs the original JS value. + //[Replaceable, Throws] readonly attribute double screenX; + //[Replaceable, Throws] readonly attribute double screenY; + //[Replaceable, Throws] readonly attribute double outerWidth; + //[Replaceable, Throws] readonly attribute double outerHeight; + [Throws] attribute any screenX; + [Throws] attribute any screenY; + [Throws] attribute any outerWidth; + [Throws] attribute any outerHeight; }; /** @@ -303,7 +313,7 @@ partial interface Window { [Throws] readonly attribute float mozInnerScreenX; [Throws] readonly attribute float mozInnerScreenY; - [Throws] readonly attribute float devicePixelRatio; + [Replaceable, Throws] readonly attribute float devicePixelRatio; /* The maximum offset that the window can be scrolled to (i.e., the document width/height minus the scrollport width/height) */ @@ -393,6 +403,12 @@ partial interface Window { [ChromeOnly, Throws] readonly attribute object? __content; [Throws, ChromeOnly] any getInterface(IID iid); + + /** + * Same as nsIDOMWindow.windowRoot, useful for event listener targeting. + */ + [ChromeOnly, Throws] + readonly attribute WindowRoot? windowRoot; }; Window implements TouchEventHandlers; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index dfe51df224..f37e845c55 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -23,9 +23,8 @@ WEBIDL_FILES = [ 'AnalyserNode.webidl', 'Animatable.webidl', 'Animation.webidl', - 'AnimationEffect.webidl', + 'AnimationEffectReadonly.webidl', 'AnimationEvent.webidl', - 'AnimationPlayer.webidl', 'AnimationTimeline.webidl', 'AnonymousContent.webidl', 'AppInfo.webidl', @@ -108,6 +107,7 @@ WEBIDL_FILES = [ 'DisplayPortInputPort.webidl', 'Document.webidl', 'DocumentFragment.webidl', + 'DocumentTimeline.webidl', 'DocumentType.webidl', 'DOMCursor.webidl', 'DOMError.webidl', @@ -265,6 +265,7 @@ WEBIDL_FILES = [ 'KeyAlgorithm.webidl', 'KeyboardEvent.webidl', 'KeyEvent.webidl', + 'KeyframeEffect.webidl', 'LegacyQueryInterface.webidl', 'LinkStyle.webidl', 'ListBoxObject.webidl', diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index dc0033e8ab..642dbfec08 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -2378,7 +2378,7 @@ RuntimeService::CreateSharedWorkerFromLoadInfo(JSContext* aCx, workerPrivate = WorkerPrivate::Constructor(aCx, aScriptURL, false, aType, aName, aLoadInfo, rv); - NS_ENSURE_TRUE(workerPrivate, rv.ErrorCode()); + NS_ENSURE_TRUE(workerPrivate, rv.StealNSResult()); created = true; } else { diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp index efe7a24cf3..fbbd150181 100644 --- a/dom/workers/ScriptLoader.cpp +++ b/dom/workers/ScriptLoader.cpp @@ -816,7 +816,7 @@ private: mCacheCreator->Cache_()->Put(request, *response, error); if (NS_WARN_IF(error.Failed())) { channel->Cancel(error.ErrorCode()); - return error.ErrorCode(); + return error.StealNSResult(); } nsRefPtr promiseHandler = @@ -1161,7 +1161,7 @@ CacheCreator::CreateCacheStorage(nsIPrincipal* aPrincipal) mSandboxGlobalObject, aPrincipal, error); if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); + return error.StealNSResult(); } return NS_OK; @@ -1182,7 +1182,7 @@ CacheCreator::Load(nsIPrincipal* aPrincipal) MOZ_ASSERT(!mCacheName.IsEmpty()); nsRefPtr promise = mCacheStorage->Open(mCacheName, error); if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); + return error.StealNSResult(); } promise->AppendNativeHandler(this); diff --git a/dom/workers/ServiceWorkerClient.cpp b/dom/workers/ServiceWorkerClient.cpp index 1cfaa7db02..1f56c6565c 100644 --- a/dom/workers/ServiceWorkerClient.cpp +++ b/dom/workers/ServiceWorkerClient.cpp @@ -92,7 +92,7 @@ public: ErrorResult result; dom::Navigator* navigator = window->GetNavigator(result); if (NS_WARN_IF(result.Failed())) { - return result.ErrorCode(); + return result.StealNSResult(); } nsRefPtr container = navigator->ServiceWorker(); diff --git a/dom/workers/ServiceWorkerClient.h b/dom/workers/ServiceWorkerClient.h index 2c23612d79..c2ffbae8f8 100644 --- a/dom/workers/ServiceWorkerClient.h +++ b/dom/workers/ServiceWorkerClient.h @@ -50,10 +50,10 @@ public: ServiceWorkerClient(nsISupports* aOwner, const ServiceWorkerClientInfo& aClientInfo) - : mOwner(aOwner), - mId(aClientInfo.mClientId), - mWindowId(aClientInfo.mWindowId), - mUrl(aClientInfo.mUrl) + : mOwner(aOwner) + , mId(aClientInfo.mClientId) + , mUrl(aClientInfo.mUrl) + , mWindowId(aClientInfo.mWindowId) { MOZ_ASSERT(aOwner); } @@ -90,8 +90,10 @@ protected: private: nsCOMPtr mOwner; nsString mId; - uint64_t mWindowId; nsString mUrl; + +protected: + uint64_t mWindowId; }; } // namespace workers diff --git a/dom/workers/ServiceWorkerClients.cpp b/dom/workers/ServiceWorkerClients.cpp index 5608c47a7c..6a9fb5d37c 100644 --- a/dom/workers/ServiceWorkerClients.cpp +++ b/dom/workers/ServiceWorkerClients.cpp @@ -4,6 +4,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/dom/Promise.h" +#include "mozilla/dom/PromiseWorkerProxy.h" #include "ServiceWorkerClient.h" #include "ServiceWorkerClients.h" @@ -41,96 +42,17 @@ ServiceWorkerClients::WrapObject(JSContext* aCx, JS::Handle aGivenPro namespace { -// Helper class used for passing the promise between threads while -// keeping the worker alive. -class PromiseHolder final : public WorkerFeature -{ - friend class MatchAllRunnable; - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PromiseHolder) - -public: - PromiseHolder(WorkerPrivate* aWorkerPrivate, - Promise* aPromise) - : mWorkerPrivate(aWorkerPrivate), - mPromise(aPromise), - mCleanUpLock("promiseHolderCleanUpLock"), - mClean(false) - { - MOZ_ASSERT(mWorkerPrivate); - mWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(mPromise); - - if (NS_WARN_IF(!mWorkerPrivate->AddFeature(mWorkerPrivate->GetJSContext(), this))) { - // Worker has been canceled and will go away. - // The ResolvePromiseWorkerRunnable won't run, so we can set mPromise to - // nullptr. - mPromise = nullptr; - mClean = true; - } - } - - Promise* - GetPromise() const - { - return mPromise; - } - - void - Clean() - { - mWorkerPrivate->AssertIsOnWorkerThread(); - - MutexAutoLock lock(mCleanUpLock); - if (mClean) { - return; - } - - mPromise = nullptr; - mWorkerPrivate->RemoveFeature(mWorkerPrivate->GetJSContext(), this); - mClean = true; - } - - bool - Notify(JSContext* aCx, Status aStatus) - { - mWorkerPrivate->AssertIsOnWorkerThread(); - - if (aStatus > Running) { - Clean(); - } - - return true; - } - -private: - ~PromiseHolder() - { - MOZ_ASSERT(mClean); - } - - WorkerPrivate* mWorkerPrivate; - nsRefPtr mPromise; - - // Used to prevent race conditions on |mClean| and to ensure that either a - // Notify() call or a dispatch back to the worker thread occurs before - // this object is released. - Mutex mCleanUpLock; - - bool mClean; -}; - class ResolvePromiseWorkerRunnable final : public WorkerRunnable { - nsRefPtr mPromiseHolder; + nsRefPtr mPromiseProxy; nsTArray mValue; public: ResolvePromiseWorkerRunnable(WorkerPrivate* aWorkerPrivate, - PromiseHolder* aPromiseHolder, + PromiseWorkerProxy* aPromiseProxy, nsTArray& aValue) : WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount), - mPromiseHolder(aPromiseHolder) + mPromiseProxy(aPromiseProxy) { AssertIsOnMainThread(); mValue.SwapElements(aValue); @@ -142,7 +64,7 @@ public: MOZ_ASSERT(aWorkerPrivate); aWorkerPrivate->AssertIsOnWorkerThread(); - Promise* promise = mPromiseHolder->GetPromise(); + Promise* promise = mPromiseProxy->GetWorkerPromise(); MOZ_ASSERT(promise); nsTArray> ret; @@ -154,51 +76,23 @@ public: promise->MaybeResolve(ret); // release the reference on the worker thread. - mPromiseHolder->Clean(); + mPromiseProxy->CleanUp(aCx); return true; } }; -class ReleasePromiseRunnable final : public MainThreadWorkerControlRunnable -{ - nsRefPtr mPromiseHolder; - -public: - ReleasePromiseRunnable(WorkerPrivate* aWorkerPrivate, - PromiseHolder* aPromiseHolder) - : MainThreadWorkerControlRunnable(aWorkerPrivate), - mPromiseHolder(aPromiseHolder) - { } - -private: - ~ReleasePromiseRunnable() - { } - - bool - WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) - { - MOZ_ASSERT(aWorkerPrivate); - aWorkerPrivate->AssertIsOnWorkerThread(); - - mPromiseHolder->Clean(); - - return true; - } - -}; - class MatchAllRunnable final : public nsRunnable { WorkerPrivate* mWorkerPrivate; - nsRefPtr mPromiseHolder; + nsRefPtr mPromiseProxy; nsCString mScope; public: MatchAllRunnable(WorkerPrivate* aWorkerPrivate, - PromiseHolder* aPromiseHolder, + PromiseWorkerProxy* aPromiseProxy, const nsCString& aScope) : mWorkerPrivate(aWorkerPrivate), - mPromiseHolder(aPromiseHolder), + mPromiseProxy(aPromiseProxy), mScope(aScope) { MOZ_ASSERT(aWorkerPrivate); @@ -210,8 +104,8 @@ public: { AssertIsOnMainThread(); - MutexAutoLock lock(mPromiseHolder->mCleanUpLock); - if (mPromiseHolder->mClean) { + MutexAutoLock lock(mPromiseProxy->GetCleanUpLock()); + if (mPromiseProxy->IsClean()) { // Don't resolve the promise if it was already released. return NS_OK; } @@ -221,7 +115,7 @@ public: swm->GetAllClients(mScope, result); nsRefPtr r = - new ResolvePromiseWorkerRunnable(mWorkerPrivate, mPromiseHolder, result); + new ResolvePromiseWorkerRunnable(mWorkerPrivate, mPromiseProxy, result); AutoSafeJSContext cx; if (r->Dispatch(cx)) { @@ -230,11 +124,11 @@ public: // Dispatch to worker thread failed because the worker is shutting down. // Use a control runnable to release the runnable on the worker thread. - nsRefPtr releaseRunnable = - new ReleasePromiseRunnable(mWorkerPrivate, mPromiseHolder); + nsRefPtr releaseRunnable = + new PromiseWorkerProxyControlRunnable(mWorkerPrivate, mPromiseProxy); if (!releaseRunnable->Dispatch(cx)) { - NS_RUNTIMEABORT("Failed to dispatch PromiseHolder control runnable."); + NS_RUNTIMEABORT("Failed to dispatch MatchAll promise control runnable."); } return NS_OK; @@ -264,16 +158,16 @@ ServiceWorkerClients::MatchAll(const ClientQueryOptions& aOptions, return nullptr; } - nsRefPtr promiseHolder = new PromiseHolder(workerPrivate, - promise); - if (!promiseHolder->GetPromise()) { + nsRefPtr promiseProxy = + PromiseWorkerProxy::Create(workerPrivate, promise); + if (!promiseProxy->GetWorkerPromise()) { // Don't dispatch if adding the worker feature failed. return promise.forget(); } nsRefPtr r = new MatchAllRunnable(workerPrivate, - promiseHolder, + promiseProxy, NS_ConvertUTF16toUTF8(scope)); nsresult rv = NS_DispatchToMainThread(r); diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index 20af67d236..76a9a9d854 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -899,6 +899,10 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow, nsCOMPtr window = do_QueryInterface(aWindow); + nsCOMPtr outerWindow = window->GetOuterWindow(); + bool serviceWorkersTestingEnabled = + outerWindow->GetServiceWorkersTestingEnabled(); + nsCOMPtr doc = window->GetExtantDoc(); if (!doc) { return NS_ERROR_FAILURE; @@ -907,8 +911,8 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow, nsCOMPtr documentURI = doc->GetBaseURI(); bool authenticatedOrigin = false; - // FIXME(nsm): Bug 1003991. Disable check when devtools are open. - if (Preferences::GetBool("dom.serviceWorkers.testing.enabled")) { + if (Preferences::GetBool("dom.serviceWorkers.testing.enabled") || + serviceWorkersTestingEnabled) { authenticatedOrigin = true; } @@ -989,7 +993,7 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow, ErrorResult result; nsRefPtr promise = Promise::Create(sgo, result); if (result.Failed()) { - return result.ErrorCode(); + return result.StealNSResult(); } ServiceWorkerJobQueue* queue = GetOrCreateJobQueue(cleanedScope); @@ -1324,7 +1328,7 @@ ServiceWorkerManager::GetRegistrations(nsIDOMWindow* aWindow, ErrorResult result; nsRefPtr promise = Promise::Create(sgo, result); if (result.Failed()) { - return result.ErrorCode(); + return result.StealNSResult(); } nsCOMPtr runnable = @@ -1425,7 +1429,7 @@ ServiceWorkerManager::GetRegistration(nsIDOMWindow* aWindow, ErrorResult result; nsRefPtr promise = Promise::Create(sgo, result); if (result.Failed()) { - return result.ErrorCode(); + return result.StealNSResult(); } nsCOMPtr runnable = @@ -1624,7 +1628,7 @@ ServiceWorkerManager::GetReadyPromise(nsIDOMWindow* aWindow, ErrorResult result; nsRefPtr promise = Promise::Create(sgo, result); if (result.Failed()) { - return result.ErrorCode(); + return result.StealNSResult(); } nsCOMPtr runnable = diff --git a/dom/workers/ServiceWorkerScriptCache.cpp b/dom/workers/ServiceWorkerScriptCache.cpp index f37ab09329..69819a6f3a 100644 --- a/dom/workers/ServiceWorkerScriptCache.cpp +++ b/dom/workers/ServiceWorkerScriptCache.cpp @@ -183,12 +183,12 @@ public: ErrorResult rv; nsRefPtr cacheStorage = CreateCacheStorage(aPrincipal, rv); if (NS_WARN_IF(rv.Failed())) { - return rv.ErrorCode(); + return rv.StealNSResult(); } nsRefPtr promise = cacheStorage->Open(aCacheName, rv); if (NS_WARN_IF(rv.Failed())) { - return rv.ErrorCode(); + return rv.StealNSResult(); } promise->AppendNativeHandler(this); @@ -617,14 +617,14 @@ PurgeCache(nsIPrincipal* aPrincipal, const nsAString& aCacheName) ErrorResult rv; nsRefPtr cacheStorage = CreateCacheStorage(aPrincipal, rv); if (NS_WARN_IF(rv.Failed())) { - return rv.ErrorCode(); + return rv.StealNSResult(); } // We use the ServiceWorker scope as key for the cacheStorage. nsRefPtr promise = cacheStorage->Delete(aCacheName, rv); if (NS_WARN_IF(rv.Failed())) { - return rv.ErrorCode(); + return rv.StealNSResult(); } // We don't actually care about the result of the delete operation. diff --git a/dom/workers/ServiceWorkerWindowClient.cpp b/dom/workers/ServiceWorkerWindowClient.cpp index e55a972f8d..8c2708a43b 100644 --- a/dom/workers/ServiceWorkerWindowClient.cpp +++ b/dom/workers/ServiceWorkerWindowClient.cpp @@ -7,6 +7,7 @@ #include "ServiceWorkerWindowClient.h" #include "mozilla/dom/ClientBinding.h" +#include "mozilla/dom/PromiseWorkerProxy.h" using namespace mozilla::dom; using namespace mozilla::dom::workers; @@ -17,18 +18,135 @@ ServiceWorkerWindowClient::WrapObject(JSContext* aCx, JS::Handle aGiv return WindowClientBinding::Wrap(aCx, this, aGivenProto); } -already_AddRefed -ServiceWorkerWindowClient::Focus() const +namespace { + +// Passing a null clientInfo will reject the promise with InvalidAccessError. +class ResolveOrRejectPromiseRunnable final : public WorkerRunnable { - ErrorResult result; + nsRefPtr mPromiseProxy; + UniquePtr mClientInfo; + +public: + ResolveOrRejectPromiseRunnable(WorkerPrivate* aWorkerPrivate, + PromiseWorkerProxy* aPromiseProxy, + UniquePtr&& aClientInfo) + : WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount) + , mPromiseProxy(aPromiseProxy) + , mClientInfo(Move(aClientInfo)) + { + AssertIsOnMainThread(); + } + + bool + WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override + { + MOZ_ASSERT(aWorkerPrivate); + aWorkerPrivate->AssertIsOnWorkerThread(); + + Promise* promise = mPromiseProxy->GetWorkerPromise(); + MOZ_ASSERT(promise); + + if (mClientInfo) { + nsRefPtr client = + new ServiceWorkerWindowClient(promise->GetParentObject(), *mClientInfo); + promise->MaybeResolve(client); + } else { + promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); + } + + // Release the reference on the worker thread. + mPromiseProxy->CleanUp(aCx); + + return true; + } +}; + +class ClientFocusRunnable final : public nsRunnable +{ + uint64_t mWindowId; + nsRefPtr mPromiseProxy; + +public: + ClientFocusRunnable(uint64_t aWindowId, PromiseWorkerProxy* aPromiseProxy) + : mWindowId(aWindowId) + , mPromiseProxy(aPromiseProxy) + { + MOZ_ASSERT(mPromiseProxy); + MOZ_ASSERT(mPromiseProxy->GetWorkerPromise()); + } + + NS_IMETHOD + Run() override + { + AssertIsOnMainThread(); + nsGlobalWindow* window = nsGlobalWindow::GetOuterWindowWithId(mWindowId); + UniquePtr clientInfo; + + if (window) { + ErrorResult result; + //FIXME(catalinb): Bug 1144660 - check if we are allowed to focus here. + window->Focus(result); + clientInfo.reset(new ServiceWorkerClientInfo(window->GetDocument())); + } + + DispatchResult(Move(clientInfo)); + return NS_OK; + } + +private: + void + DispatchResult(UniquePtr&& aClientInfo) + { + WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate(); + MOZ_ASSERT(workerPrivate); + + nsRefPtr resolveRunnable = + new ResolveOrRejectPromiseRunnable(workerPrivate, mPromiseProxy, + Move(aClientInfo)); + + AutoJSAPI jsapi; + jsapi.Init(); + JSContext* cx = jsapi.cx(); + if (!resolveRunnable->Dispatch(cx)) { + nsRefPtr controlRunnable = + new PromiseWorkerProxyControlRunnable(workerPrivate, mPromiseProxy); + if (!controlRunnable->Dispatch(cx)) { + NS_RUNTIMEABORT("Failed to dispatch Focus promise control runnable."); + } + } + } +}; + +} // anonymous namespace + +already_AddRefed +ServiceWorkerWindowClient::Focus(ErrorResult& aRv) const +{ + WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(workerPrivate); + workerPrivate->AssertIsOnWorkerThread(); + nsCOMPtr global = do_QueryInterface(GetParentObject()); MOZ_ASSERT(global); - nsRefPtr promise = Promise::Create(global, result); - if (NS_WARN_IF(result.Failed())) { + nsRefPtr promise = Promise::Create(global, aRv); + if (NS_WARN_IF(aRv.Failed())) { return nullptr; } - promise->MaybeReject(NS_ERROR_NOT_AVAILABLE); + nsRefPtr promiseProxy = + PromiseWorkerProxy::Create(workerPrivate, promise); + if (!promiseProxy->GetWorkerPromise()) { + // Don't dispatch if adding the worker feature failed. + return promise.forget(); + } + + nsRefPtr r = new ClientFocusRunnable(mWindowId, + promiseProxy); + aRv = NS_DispatchToMainThread(r); + if (NS_WARN_IF(aRv.Failed())) { + promise->MaybeReject(aRv.ErrorCode()); + } + return promise.forget(); } diff --git a/dom/workers/ServiceWorkerWindowClient.h b/dom/workers/ServiceWorkerWindowClient.h index 06dd112583..b60bcfaf7c 100644 --- a/dom/workers/ServiceWorkerWindowClient.h +++ b/dom/workers/ServiceWorkerWindowClient.h @@ -47,7 +47,7 @@ public: } already_AddRefed - Focus() const; + Focus(ErrorResult& aRv) const; private: ~ServiceWorkerWindowClient() diff --git a/dom/workers/WorkerRunnable.cpp b/dom/workers/WorkerRunnable.cpp index 22198cb32d..77c2c5a485 100644 --- a/dom/workers/WorkerRunnable.cpp +++ b/dom/workers/WorkerRunnable.cpp @@ -297,7 +297,7 @@ WorkerRunnable::Run() MOZ_ASSERT(IsCanceled(), "Subclass Cancel() didn't set IsCanceled()!"); return NS_OK; - } + } // Track down the appropriate global to use for the AutoJSAPI/AutoEntryScript. nsCOMPtr globalObject; @@ -332,8 +332,9 @@ WorkerRunnable::Run() Maybe aes; JSContext* cx; if (globalObject) { - aes.emplace(globalObject, isMainThread, isMainThread ? nullptr : - GetCurrentThreadJSContext()); + aes.emplace(globalObject, "Worker runnable", + isMainThread, + isMainThread ? nullptr : GetCurrentThreadJSContext()); cx = aes->cx(); } else { jsapi.Init(); @@ -352,7 +353,8 @@ WorkerRunnable::Run() // In the case of CompileScriptRunnnable, WorkerRun above can cause us to // lazily create a global, so we construct aes here before calling PostRun. if (targetIsWorkerThread && !aes && DefaultGlobalObject()) { - aes.emplace(DefaultGlobalObject(), false, GetCurrentThreadJSContext()); + aes.emplace(DefaultGlobalObject(), "worker runnable", + false, GetCurrentThreadJSContext()); cx = aes->cx(); } diff --git a/dom/workers/XMLHttpRequest.cpp b/dom/workers/XMLHttpRequest.cpp index 6663ebc8b7..e93aafdd17 100644 --- a/dom/workers/XMLHttpRequest.cpp +++ b/dom/workers/XMLHttpRequest.cpp @@ -1498,7 +1498,7 @@ OpenRunnable::MainThreadRunInternal() mProxy->mInOpen = false; if (rv2.Failed()) { - return rv2.ErrorCode(); + return rv2.StealNSResult(); } return mProxy->mXHR->SetResponseType(NS_LITERAL_STRING("text")); diff --git a/dom/xbl/nsXBLContentSink.cpp b/dom/xbl/nsXBLContentSink.cpp index aa6c9f4d13..4e54435f5e 100644 --- a/dom/xbl/nsXBLContentSink.cpp +++ b/dom/xbl/nsXBLContentSink.cpp @@ -38,13 +38,12 @@ NS_NewXBLContentSink(nsIXMLContentSink** aResult, { NS_ENSURE_ARG_POINTER(aResult); - nsXBLContentSink* it = new nsXBLContentSink(); - - nsCOMPtr kungFuDeathGrip = it; + nsRefPtr it = new nsXBLContentSink(); nsresult rv = it->Init(aDoc, aURI, aContainer); NS_ENSURE_SUCCESS(rv, rv); - return CallQueryInterface(it, aResult); + it.forget(aResult); + return NS_OK; } nsXBLContentSink::nsXBLContentSink() diff --git a/dom/xbl/nsXBLProtoImplField.cpp b/dom/xbl/nsXBLProtoImplField.cpp index 82734c896b..cd892dc7fc 100644 --- a/dom/xbl/nsXBLProtoImplField.cpp +++ b/dom/xbl/nsXBLProtoImplField.cpp @@ -404,7 +404,7 @@ nsXBLProtoImplField::InstallField(JS::Handle aBoundNode, // We are going to run script via EvaluateString, so we need a script entry // point, but as this is XBL related it does not appear in the HTML spec. - AutoEntryScript entryScript(globalObject, true); + AutoEntryScript entryScript(globalObject, "XBL initialization", true); entryScript.TakeOwnershipOfErrorReporting(); JSContext* cx = entryScript.cx(); diff --git a/dom/xbl/nsXBLProtoImplMethod.cpp b/dom/xbl/nsXBLProtoImplMethod.cpp index c8a4ed6f84..f5a55153c5 100644 --- a/dom/xbl/nsXBLProtoImplMethod.cpp +++ b/dom/xbl/nsXBLProtoImplMethod.cpp @@ -296,7 +296,7 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement, JSAddonId* aAd // We are going to run script via JS::Call, so we need a script entry point, // but as this is XBL related it does not appear in the HTML spec. - dom::AutoEntryScript aes(global); + dom::AutoEntryScript aes(global, "XBL / invocation"); aes.TakeOwnershipOfErrorReporting(); JSContext* cx = aes.cx(); diff --git a/dom/xml/XMLDocument.cpp b/dom/xml/XMLDocument.cpp index 3387a5183c..0ece4d8dc3 100644 --- a/dom/xml/XMLDocument.cpp +++ b/dom/xml/XMLDocument.cpp @@ -285,7 +285,7 @@ XMLDocument::Load(const nsAString& aUrl, bool *aReturn) { ErrorResult rv; *aReturn = Load(aUrl, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } bool diff --git a/dom/xml/nsXMLContentSink.cpp b/dom/xml/nsXMLContentSink.cpp index e80d12da77..4c382ddd3b 100644 --- a/dom/xml/nsXMLContentSink.cpp +++ b/dom/xml/nsXMLContentSink.cpp @@ -86,13 +86,13 @@ NS_NewXMLContentSink(nsIXMLContentSink** aResult, if (nullptr == aResult) { return NS_ERROR_NULL_POINTER; } - nsXMLContentSink* it = new nsXMLContentSink(); + nsRefPtr it = new nsXMLContentSink(); - nsCOMPtr kungFuDeathGrip = it; nsresult rv = it->Init(aDoc, aURI, aContainer, aChannel); NS_ENSURE_SUCCESS(rv, rv); - - return CallQueryInterface(it, aResult); + + it.forget(aResult); + return NS_OK; } nsXMLContentSink::nsXMLContentSink() diff --git a/dom/xslt/xpath/XPathEvaluator.cpp b/dom/xslt/xpath/XPathEvaluator.cpp index 61270eb604..99016ccac3 100644 --- a/dom/xslt/xpath/XPathEvaluator.cpp +++ b/dom/xslt/xpath/XPathEvaluator.cpp @@ -95,7 +95,7 @@ XPathEvaluator::Evaluate(const nsAString & aExpression, nsAutoPtr expression(CreateExpression(aExpression, resolver, rv)); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } nsCOMPtr node = do_QueryInterface(aContextNode); @@ -108,7 +108,7 @@ XPathEvaluator::Evaluate(const nsAString & aExpression, expression->Evaluate(*node, aType, static_cast(inResult.get()), rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } *aResult = ToSupports(result.forget().take()); @@ -150,7 +150,8 @@ XPathEvaluator::CreateExpression(const nsAString & aExpression, aRv = txExprParser::createExpr(PromiseFlatString(aExpression), aContext, getter_Transfers(expression)); if (aRv.Failed()) { - if (aRv.ErrorCode() != NS_ERROR_DOM_NAMESPACE_ERR) { + if (!aRv.ErrorCodeIs(NS_ERROR_DOM_NAMESPACE_ERR)) { + aRv.SuppressException(); aRv.Throw(NS_ERROR_DOM_INVALID_EXPRESSION_ERR); } @@ -216,7 +217,7 @@ nsresult XPathEvaluatorParseContext::resolveNamespacePrefix ErrorResult rv; mResolver->LookupNamespaceURI(prefix, ns, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } } else { if (aPrefix == nsGkAtoms::xml) { diff --git a/dom/xul/XULDocument.cpp b/dom/xul/XULDocument.cpp index a9e389a6ff..c3fc2dc6b9 100644 --- a/dom/xul/XULDocument.cpp +++ b/dom/xul/XULDocument.cpp @@ -733,7 +733,7 @@ XULDocument::AddBroadcastListenerFor(nsIDOMElement* aBroadcaster, nsCOMPtr listener = do_QueryInterface(aListener); NS_ENSURE_ARG(broadcaster && listener); AddBroadcastListenerFor(*broadcaster, *listener, aAttr, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } void @@ -1211,7 +1211,7 @@ XULDocument::GetElementsByAttributeNS(const nsAString& aNamespaceURI, ErrorResult rv; *aReturn = GetElementsByAttributeNS(aNamespaceURI, aAttribute, aValue, rv).take(); - return rv.ErrorCode(); + return rv.StealNSResult(); } already_AddRefed @@ -1517,7 +1517,7 @@ XULDocument::GetPopupRangeOffset(int32_t* aRangeOffset) { ErrorResult rv; *aRangeOffset = GetPopupRangeOffset(rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } int32_t @@ -2030,8 +2030,7 @@ XULDocument::PrepareToLoadPrototype(nsIURI* aURI, const char* aCommand, kCharsetFromDocTypeDefault); parser->SetContentSink(sink); // grabs a reference to the parser - *aResult = parser; - NS_ADDREF(*aResult); + parser.forget(aResult); return NS_OK; } @@ -3550,8 +3549,8 @@ XULDocument::ExecuteScript(nsXULPrototypeScript *aScript) nsAutoMicroTask mt; // We're about to run script via JS::CloneAndExecuteScript, so we need an - // AutoEntryScript. This is Goanna specific and not in any spec. - AutoEntryScript aes(mScriptGlobalObject); + // AutoEntryScript. This is Gecko specific and not in any spec. + AutoEntryScript aes(mScriptGlobalObject, "precompiled XUL + + + + diff --git a/layout/base/tests/bug956530-1.html b/layout/base/tests/bug956530-1.html new file mode 100644 index 0000000000..e45252ea9d --- /dev/null +++ b/layout/base/tests/bug956530-1.html @@ -0,0 +1,32 @@ + + + + + + + + + diff --git a/layout/base/tests/mochitest.ini b/layout/base/tests/mochitest.ini index c3bb88ed49..a5491d736d 100644 --- a/layout/base/tests/mochitest.ini +++ b/layout/base/tests/mochitest.ini @@ -13,6 +13,8 @@ support-files = enableTestPlugin.js bug558663.html bug644768.html + bug956530-1.html + bug956530-1-ref.html bug989012-1.html bug989012-1-ref.html bug989012-2.html diff --git a/layout/base/tests/test_reftests_with_caret.html b/layout/base/tests/test_reftests_with_caret.html index 77a9502d14..9e20604ee3 100644 --- a/layout/base/tests/test_reftests_with_caret.html +++ b/layout/base/tests/test_reftests_with_caret.html @@ -144,6 +144,7 @@ var tests = [ [ 'bug682712-1.html' , 'bug682712-1-ref.html' ] , function() {SpecialPowers.pushPrefEnv({'clear': [['bidi.browser.ui']]}, nextTest);} , [ 'bug746993-1.html' , 'bug746993-1-ref.html' ] , + [ 'bug956530-1.html' , 'bug956530-1-ref.html' ] , [ 'bug989012-1.html' , 'bug989012-1-ref.html' ] , [ 'bug989012-2.html' , 'bug989012-2-ref.html' ] , [ 'bug989012-3.html' , 'bug989012-3-ref.html' ] , diff --git a/layout/base/tests/test_scroll_event_ordering.html b/layout/base/tests/test_scroll_event_ordering.html index c998b8d1fd..8dd67d6426 100644 --- a/layout/base/tests/test_scroll_event_ordering.html +++ b/layout/base/tests/test_scroll_event_ordering.html @@ -47,9 +47,16 @@ function doTest() { sendKey("DOWN"); } -SimpleTest.waitForFocus(function() { - SpecialPowers.pushPrefEnv({"set":[[smoothScrollPref, false]]}, doTest); -}); +function prepareTest() { + // Start the test after we've gotten at least one rAF callback, to make sure + // that rAF is no longer throttled. (See bug 1145439.) + window.mozRequestAnimationFrame(function() { + SpecialPowers.pushPrefEnv({"set":[[smoothScrollPref, false]]}, doTest); + }); +} + +SimpleTest.waitForFocus(prepareTest); + diff --git a/layout/build/nsContentDLF.h b/layout/build/nsContentDLF.h index 957400bc42..b7f65be11a 100644 --- a/layout/build/nsContentDLF.h +++ b/layout/build/nsContentDLF.h @@ -56,35 +56,35 @@ NS_NewContentDocumentLoaderFactory(nsIDocumentLoaderFactory** aResult); #ifdef MOZ_WEBM #define CONTENTDLF_WEBM_CATEGORIES \ - { "Goanna-Content-Viewers", VIDEO_WEBM, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", AUDIO_WEBM, "@mozilla.org/content/document-loader-factory;1" }, + { "Gecko-Content-Viewers", VIDEO_WEBM, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", AUDIO_WEBM, "@mozilla.org/content/document-loader-factory;1" }, #else #define CONTENTDLF_WEBM_CATEGORIES #endif #define CONTENTDLF_CATEGORIES \ - { "Goanna-Content-Viewers", TEXT_HTML, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", TEXT_PLAIN, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", TEXT_CACHE_MANIFEST, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", TEXT_CSS, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", TEXT_JAVASCRIPT, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", TEXT_ECMASCRIPT, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", APPLICATION_JAVASCRIPT, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", APPLICATION_ECMASCRIPT, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", APPLICATION_XJAVASCRIPT, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", APPLICATION_JSON, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", TEXT_JSON, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", APPLICATION_XHTML_XML, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", TEXT_XML, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", APPLICATION_XML, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", APPLICATION_RDF_XML, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", TEXT_RDF, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", TEXT_XUL, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", APPLICATION_CACHED_XUL, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", VIEWSOURCE_CONTENT_TYPE, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", IMAGE_SVG_XML, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", APPLICATION_MATHML_XML, "@mozilla.org/content/document-loader-factory;1" }, \ - { "Goanna-Content-Viewers", TEXT_VTT, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", TEXT_HTML, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", TEXT_PLAIN, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", TEXT_CACHE_MANIFEST, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", TEXT_CSS, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", TEXT_JAVASCRIPT, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", TEXT_ECMASCRIPT, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", APPLICATION_JAVASCRIPT, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", APPLICATION_ECMASCRIPT, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", APPLICATION_XJAVASCRIPT, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", APPLICATION_JSON, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", TEXT_JSON, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", APPLICATION_XHTML_XML, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", TEXT_XML, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", APPLICATION_XML, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", APPLICATION_RDF_XML, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", TEXT_RDF, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", TEXT_XUL, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", APPLICATION_CACHED_XUL, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", VIEWSOURCE_CONTENT_TYPE, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", IMAGE_SVG_XML, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", APPLICATION_MATHML_XML, "@mozilla.org/content/document-loader-factory;1" }, \ + { "Gecko-Content-Viewers", TEXT_VTT, "@mozilla.org/content/document-loader-factory;1" }, \ CONTENTDLF_WEBM_CATEGORIES diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 62ade92964..4328ec19fc 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -209,7 +209,7 @@ static void Shutdown(); #include "nsGeolocation.h" #include "nsDeviceSensors.h" #ifdef MOZ_GAMEPAD -#include "mozilla/dom/GamepadService.h" +#include "mozilla/dom/GamepadServiceTest.h" #endif #include "mozilla/dom/nsCSPService.h" #include "mozilla/dom/nsCSPContext.h" diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 183ab10870..d158b2fb04 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -2686,8 +2686,7 @@ nsFrame::GetDataForTableSelection(const nsFrameSelection* aFrameSelection, if (offset < 0) return NS_ERROR_FAILURE; // Everything is OK -- set the return values - *aParentContent = parentContent; - NS_ADDREF(*aParentContent); + parentContent.forget(aParentContent); *aContentOffset = offset; @@ -3363,10 +3362,7 @@ NS_IMETHODIMP nsFrame::HandleRelease(nsPresContext* aPresContext, // If not, the user must have clicked in a part of the selection. // Place the caret before continuing! - bool mouseDown = frameselection->GetDragState(); - - if (!mouseDown && frameselection->HasDelayedCaretData() && - frameselection->GetClickCountInDelayedCaretData() < 2) { + if (frameselection->MouseDownRecorded()) { nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this); offsets = GetContentOffsetsFromPoint(pt, SKIP_HIDDEN); handleTableSelection = false; diff --git a/layout/generic/nsFrameSelection.h b/layout/generic/nsFrameSelection.h index 60690d0330..e19a016425 100644 --- a/layout/generic/nsFrameSelection.h +++ b/layout/generic/nsFrameSelection.h @@ -517,6 +517,13 @@ public: return mDelayedMouseEventClickCount; } + bool MouseDownRecorded() + { + return !GetDragState() && + HasDelayedCaretData() && + GetClickCountInDelayedCaretData() < 2; + } + /** Get the content node that limits the selection * When searching up a nodes for parents, as in a text edit field * in an browser page, we must stop at this node else we reach into the diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 81defbb2a6..acad386240 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -2832,16 +2832,28 @@ NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::ParagraphDepthProperty())) * the last repaint. */ void UpdatePaintCountForPaintedPresShells() { - nsTArray * list = PaintedPresShellList(); - for (int i = 0, l = list->Length(); i < l; i++) { - nsCOMPtr shell = do_QueryReferent(list->ElementAt(i)); - + for (nsWeakPtr& item : *PaintedPresShellList()) { + nsCOMPtr shell = do_QueryReferent(item); if (shell) { shell->IncrementPaintCount(); } } } + /** + * @return true if we painted @aShell during the last repaint. + */ + bool DidPaintPresShell(nsIPresShell* aShell) + { + for (nsWeakPtr& item : *PaintedPresShellList()) { + nsCOMPtr shell = do_QueryReferent(item); + if (shell == aShell) { + return true; + } + } + return false; + } + /** * Accessors for the absolute containing block. */ diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index 71301a47ae..8464ed89fb 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -1116,7 +1116,7 @@ Selection::ToStringWithFormat(const char* aFormatType, uint32_t aFlags, NS_ConvertUTF8toUTF16 format(aFormatType); ToStringWithFormat(format, aFlags, aWrapCol, aReturn, result); if (result.Failed()) { - return result.ErrorCode(); + return result.StealNSResult(); } return NS_OK; } @@ -1173,7 +1173,7 @@ Selection::SetInterlinePosition(bool aHintRight) ErrorResult result; SetInterlinePosition(aHintRight, result); if (result.Failed()) { - return result.ErrorCode(); + return result.StealNSResult(); } return NS_OK; } @@ -1194,7 +1194,7 @@ Selection::GetInterlinePosition(bool* aHintRight) ErrorResult result; *aHintRight = GetInterlinePosition(result); if (result.Failed()) { - return result.ErrorCode(); + return result.StealNSResult(); } return NS_OK; } @@ -3991,7 +3991,7 @@ Selection::GetRangesForInterval(nsIDOMNode* aBeginNode, int32_t aBeginOffset, GetRangesForInterval(*beginNode, aBeginOffset, *endNode, aEndOffset, aAllowAdjacent, results, result); if (result.Failed()) { - return result.ErrorCode(); + return result.StealNSResult(); } *aResultCount = results.Length(); if (*aResultCount == 0) { @@ -4694,7 +4694,7 @@ Selection::RemoveAllRanges() { ErrorResult result; RemoveAllRanges(result); - return result.ErrorCode(); + return result.StealNSResult(); } void @@ -4732,7 +4732,7 @@ Selection::AddRange(nsIDOMRange* aDOMRange) nsRange* range = static_cast(aDOMRange); ErrorResult result; AddRange(*range, result); - return result.ErrorCode(); + return result.StealNSResult(); } void @@ -4815,7 +4815,7 @@ Selection::RemoveRange(nsIDOMRange* aDOMRange) nsRange* range = static_cast(aDOMRange); ErrorResult result; RemoveRange(*range, result); - return result.ErrorCode(); + return result.StealNSResult(); } void @@ -4913,7 +4913,7 @@ Selection::Collapse(nsINode* aParentNode, int32_t aOffset) ErrorResult result; Collapse(*aParentNode, static_cast(aOffset), result); - return result.ErrorCode(); + return result.StealNSResult(); } void @@ -4989,7 +4989,7 @@ Selection::CollapseToStart() { ErrorResult result; CollapseToStart(result); - return result.ErrorCode(); + return result.StealNSResult(); } void @@ -5030,7 +5030,7 @@ Selection::CollapseToEnd() { ErrorResult result; CollapseToEnd(result); - return result.ErrorCode(); + return result.StealNSResult(); } void @@ -5110,7 +5110,7 @@ Selection::GetRangeAt(int32_t aIndex, nsIDOMRange** aReturn) ErrorResult result; *aReturn = GetRangeAt(aIndex, result); NS_IF_ADDREF(*aReturn); - return result.ErrorCode(); + return result.StealNSResult(); } nsRange* @@ -5217,7 +5217,7 @@ Selection::Extend(nsINode* aParentNode, int32_t aOffset) ErrorResult result; Extend(*aParentNode, static_cast(aOffset), result); - return result.ErrorCode(); + return result.StealNSResult(); } void @@ -5517,7 +5517,7 @@ Selection::SelectAllChildren(nsIDOMNode* aParentNode) nsCOMPtr node = do_QueryInterface(aParentNode); NS_ENSURE_TRUE(node, NS_ERROR_INVALID_ARG); SelectAllChildren(*node, result); - return result.ErrorCode(); + return result.StealNSResult(); } void @@ -5550,7 +5550,7 @@ Selection::ContainsNode(nsIDOMNode* aNode, bool aAllowPartial, bool* aYes) } ErrorResult result; *aYes = ContainsNode(*node, aAllowPartial, result); - return result.ErrorCode(); + return result.StealNSResult(); } bool @@ -5794,7 +5794,7 @@ Selection::ScrollIntoView(SelectionRegion aRegion, bool aIsSynchronous, ErrorResult result; ScrollIntoView(aRegion, aIsSynchronous, aVPercent, aHPercent, result); if (result.Failed()) { - return result.ErrorCode(); + return result.StealNSResult(); } return NS_OK; } @@ -5890,7 +5890,7 @@ Selection::AddSelectionListener(nsISelectionListener* aNewListener) ErrorResult result; AddSelectionListener(aNewListener, result); if (result.Failed()) { - return result.ErrorCode(); + return result.StealNSResult(); } return NS_OK; } @@ -5913,7 +5913,7 @@ Selection::RemoveSelectionListener(nsISelectionListener* aListenerToRemove) ErrorResult result; RemoveSelectionListener(aListenerToRemove, result); if (result.Failed()) { - return result.ErrorCode(); + return result.StealNSResult(); } return NS_OK; } @@ -6003,7 +6003,7 @@ Selection::DeleteFromDocument() { ErrorResult result; DeleteFromDocument(result); - return result.ErrorCode(); + return result.StealNSResult(); } void @@ -6023,7 +6023,7 @@ Selection::Modify(const nsAString& aAlter, const nsAString& aDirection, { ErrorResult result; Modify(aAlter, aDirection, aGranularity, result); - return result.ErrorCode(); + return result.StealNSResult(); } void diff --git a/layout/inspector/inDOMUtils.cpp b/layout/inspector/inDOMUtils.cpp index a5136a0554..b129293793 100644 --- a/layout/inspector/inDOMUtils.cpp +++ b/layout/inspector/inDOMUtils.cpp @@ -235,8 +235,7 @@ inDOMUtils::GetCSSStyleRules(nsIDOMElement *aElement, } } - *_retval = rules; - NS_ADDREF(*_retval); + rules.forget(_retval); return NS_OK; } @@ -296,7 +295,7 @@ inDOMUtils::GetSelectorCount(nsIDOMCSSStyleRule* aRule, uint32_t *aCount) ErrorResult rv; nsRefPtr rule = GetRuleFromDOMRule(aRule, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } uint32_t count = 0; @@ -335,7 +334,7 @@ inDOMUtils::GetSelectorText(nsIDOMCSSStyleRule* aRule, ErrorResult rv; nsCSSSelectorList* sel = GetSelectorAtIndex(aRule, aSelectorIndex, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } nsRefPtr rule = GetRuleFromDOMRule(aRule, rv); @@ -353,7 +352,7 @@ inDOMUtils::GetSpecificity(nsIDOMCSSStyleRule* aRule, ErrorResult rv; nsCSSSelectorList* sel = GetSelectorAtIndex(aRule, aSelectorIndex, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } *aSpecificity = sel->mWeight; @@ -373,7 +372,7 @@ inDOMUtils::SelectorMatchesElement(nsIDOMElement* aElement, ErrorResult rv; nsCSSSelectorList* tail = GetSelectorAtIndex(aRule, aSelectorIndex, rv); if (rv.Failed()) { - return rv.ErrorCode(); + return rv.StealNSResult(); } // We want just the one list item, not the whole list tail @@ -903,7 +902,7 @@ inDOMUtils::GetBindingURLs(nsIDOMElement *aElement, nsIArray **_retval) binding = binding->GetBaseBinding(); } - NS_ADDREF(*_retval = urls); + urls.forget(_retval); return NS_OK; } diff --git a/layout/style/AnimationCommon.cpp b/layout/style/AnimationCommon.cpp index 889893fe92..4df5f6f6fc 100644 --- a/layout/style/AnimationCommon.cpp +++ b/layout/style/AnimationCommon.cpp @@ -21,6 +21,7 @@ #include "FrameLayerBuilder.h" #include "nsDisplayList.h" #include "mozilla/MemoryReporting.h" +#include "mozilla/dom/KeyframeEffect.h" #include "RestyleManager.h" #include "nsRuleProcessorData.h" #include "nsStyleSet.h" @@ -28,8 +29,8 @@ using mozilla::layers::Layer; -using mozilla::dom::AnimationPlayer; using mozilla::dom::Animation; +using mozilla::dom::KeyframeEffectReadonly; namespace mozilla { @@ -73,8 +74,7 @@ CommonAnimationManager::Disconnect() } void -CommonAnimationManager::AddElementCollection(AnimationPlayerCollection* - aCollection) +CommonAnimationManager::AddElementCollection(AnimationCollection* aCollection) { if (!mIsObservingRefreshDriver) { NS_ASSERTION(aCollection->mNeedsRefreshes, @@ -91,34 +91,49 @@ void CommonAnimationManager::RemoveAllElementCollections() { while (!PR_CLIST_IS_EMPTY(&mElementCollections)) { - AnimationPlayerCollection* head = - static_cast( - PR_LIST_HEAD(&mElementCollections)); + AnimationCollection* head = + static_cast(PR_LIST_HEAD(&mElementCollections)); head->Destroy(); } } void -CommonAnimationManager::CheckNeedsRefresh() +CommonAnimationManager::MaybeStartObservingRefreshDriver() +{ + if (mIsObservingRefreshDriver || !NeedsRefresh()) { + return; + } + + mPresContext->RefreshDriver()->AddRefreshObserver(this, Flush_Style); + mIsObservingRefreshDriver = true; +} + +void +CommonAnimationManager::MaybeStartOrStopObservingRefreshDriver() +{ + bool needsRefresh = NeedsRefresh(); + if (needsRefresh && !mIsObservingRefreshDriver) { + mPresContext->RefreshDriver()->AddRefreshObserver(this, Flush_Style); + } else if (!needsRefresh && mIsObservingRefreshDriver) { + mPresContext->RefreshDriver()->RemoveRefreshObserver(this, Flush_Style); + } + mIsObservingRefreshDriver = needsRefresh; +} + +bool +CommonAnimationManager::NeedsRefresh() const { for (PRCList *l = PR_LIST_HEAD(&mElementCollections); l != &mElementCollections; l = PR_NEXT_LINK(l)) { - if (static_cast(l)->mNeedsRefreshes) { - if (!mIsObservingRefreshDriver) { - mPresContext->RefreshDriver()->AddRefreshObserver(this, Flush_Style); - mIsObservingRefreshDriver = true; - } - return; + if (static_cast(l)->mNeedsRefreshes) { + return true; } } - if (mIsObservingRefreshDriver) { - mIsObservingRefreshDriver = false; - mPresContext->RefreshDriver()->RemoveRefreshObserver(this, Flush_Style); - } + return false; } -AnimationPlayerCollection* +AnimationCollection* CommonAnimationManager::GetAnimationsForCompositor(nsIContent* aContent, nsIAtom* aElementProperty, nsCSSProperty aProperty) @@ -126,13 +141,12 @@ CommonAnimationManager::GetAnimationsForCompositor(nsIContent* aContent, if (!aContent->MayHaveAnimations()) return nullptr; - AnimationPlayerCollection* collection = - static_cast( - aContent->GetProperty(aElementProperty)); + AnimationCollection* collection = + static_cast(aContent->GetProperty(aElementProperty)); if (!collection || !collection->HasAnimationOfProperty(aProperty) || !collection->CanPerformOnCompositorThread( - AnimationPlayerCollection::CanAnimate_AllowPartial)) { + AnimationCollection::CanAnimate_AllowPartial)) { return nullptr; } @@ -246,8 +260,7 @@ CommonAnimationManager::AddStyleUpdatesTo(RestyleTracker& aTracker) PRCList* next = PR_LIST_HEAD(&mElementCollections); while (next != &mElementCollections) { - AnimationPlayerCollection* collection = - static_cast(next); + AnimationCollection* collection = static_cast(next); next = PR_NEXT_LINK(next); if (!collection->mNeedsRefreshes) { @@ -266,10 +279,10 @@ CommonAnimationManager::AddStyleUpdatesTo(RestyleTracker& aTracker) } void -CommonAnimationManager::NotifyCollectionUpdated(AnimationPlayerCollection& +CommonAnimationManager::NotifyCollectionUpdated(AnimationCollection& aCollection) { - CheckNeedsRefresh(); + MaybeStartObservingRefreshDriver(); mPresContext->ClearLastStyleUpdateForAllAnimations(); mPresContext->RestyleManager()->IncrementAnimationGeneration(); aCollection.UpdateAnimationGeneration(mPresContext); @@ -295,7 +308,7 @@ CommonAnimationManager::ExtractComputedValueForTransition( return result; } -AnimationPlayerCollection* +AnimationCollection* CommonAnimationManager::GetAnimations(dom::Element *aElement, nsCSSPseudoElements::Type aPseudoType, bool aCreateIfNeeded) @@ -318,15 +331,14 @@ CommonAnimationManager::GetAnimations(dom::Element *aElement, "other than :before or :after"); return nullptr; } - AnimationPlayerCollection* collection = - static_cast(aElement->GetProperty(propName)); + AnimationCollection* collection = + static_cast(aElement->GetProperty(propName)); if (!collection && aCreateIfNeeded) { // FIXME: Consider arena-allocating? - collection = - new AnimationPlayerCollection(aElement, propName, this); + collection = new AnimationCollection(aElement, propName, this); nsresult rv = aElement->SetProperty(propName, collection, - &AnimationPlayerCollection::PropertyDtor, false); + &AnimationCollection::PropertyDtor, false); if (NS_FAILED(rv)) { NS_WARNING("SetProperty failed"); delete collection; @@ -358,7 +370,7 @@ CommonAnimationManager::GetAnimationRule(mozilla::dom::Element* aElement, return nullptr; } - AnimationPlayerCollection* collection = + AnimationCollection* collection = GetAnimations(aElement, aPseudoType, false); if (!collection) { return nullptr; @@ -369,23 +381,13 @@ CommonAnimationManager::GetAnimationRule(mozilla::dom::Element* aElement, return nullptr; } - // Animations should already be refreshed, but transitions may not be. - // Note that this is temporary, we would like both animations and transitions - // to both be refreshed by this point. - if (IsAnimationManager()) { - NS_WARN_IF_FALSE(!collection->mNeedsRefreshes || - collection->mStyleRuleRefreshTime == - mPresContext->RefreshDriver()->MostRecentRefresh(), - "should already have refreshed style rule"); - } else { - // FIXME: Remove this assignment. See bug 1061364. - TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh(); - if (collection->mStyleRuleRefreshTime.IsNull() || - collection->mStyleRuleRefreshTime != now) { - collection->mNeedsRefreshes = true; - } - collection->EnsureStyleRuleFor(now, EnsureStyleRule_IsNotThrottled); + // FIXME: Remove this assignment. See bug 1061364. + if (!IsAnimationManager()) { + collection->mNeedsRefreshes = true; } + collection->EnsureStyleRuleFor( + mPresContext->RefreshDriver()->MostRecentRefresh(), + EnsureStyleRule_IsNotThrottled); return collection->mStyleRule; } @@ -506,7 +508,7 @@ AnimValuesStyleRule::List(FILE* out, int32_t aIndent) const } // namespace css bool -AnimationPlayerCollection::CanAnimatePropertyOnCompositor( +AnimationCollection::CanAnimatePropertyOnCompositor( const dom::Element *aElement, nsCSSProperty aProperty, CanAnimateFlags aFlags) @@ -572,7 +574,7 @@ AnimationPlayerCollection::CanAnimatePropertyOnCompositor( } /* static */ bool -AnimationPlayerCollection::IsCompositorAnimationDisabledForFrame( +AnimationCollection::IsCompositorAnimationDisabledForFrame( nsIFrame* aFrame) { void* prop = aFrame->Properties().Get(nsIFrame::RefusedAsyncAnimation()); @@ -580,7 +582,7 @@ AnimationPlayerCollection::IsCompositorAnimationDisabledForFrame( } bool -AnimationPlayerCollection::CanPerformOnCompositorThread( +AnimationCollection::CanPerformOnCompositorThread( CanAnimateFlags aFlags) const { nsIFrame* frame = nsLayoutUtils::GetStyleFrame(mElement); @@ -601,18 +603,18 @@ AnimationPlayerCollection::CanPerformOnCompositorThread( return false; } - for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) { - const AnimationPlayer* player = mPlayers[playerIdx]; - if (!player->IsPlaying()) { + for (size_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { + const Animation* anim = mAnimations[animIdx]; + if (!anim->IsPlaying()) { continue; } - const Animation* anim = player->GetSource(); - MOZ_ASSERT(anim, "A playing player should have a source animation"); + const KeyframeEffectReadonly* effect = anim->GetEffect(); + MOZ_ASSERT(effect, "A playing animation should have an effect"); - for (size_t propIdx = 0, propEnd = anim->Properties().Length(); + for (size_t propIdx = 0, propEnd = effect->Properties().Length(); propIdx != propEnd; ++propIdx) { - if (IsGeometricProperty(anim->Properties()[propIdx].mProperty)) { + if (IsGeometricProperty(effect->Properties()[propIdx].mProperty)) { aFlags = CanAnimateFlags(aFlags | CanAnimate_HasGeometricProperty); break; } @@ -620,20 +622,20 @@ AnimationPlayerCollection::CanPerformOnCompositorThread( } bool existsProperty = false; - for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) { - const AnimationPlayer* player = mPlayers[playerIdx]; - if (!player->IsPlaying()) { + for (size_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { + const Animation* anim = mAnimations[animIdx]; + if (!anim->IsPlaying()) { continue; } - const Animation* anim = player->GetSource(); - MOZ_ASSERT(anim, "A playing player should have a source animation"); + const KeyframeEffectReadonly* effect = anim->GetEffect(); + MOZ_ASSERT(effect, "A playing animation should have an effect"); - existsProperty = existsProperty || anim->Properties().Length() > 0; + existsProperty = existsProperty || effect->Properties().Length() > 0; - for (size_t propIdx = 0, propEnd = anim->Properties().Length(); + for (size_t propIdx = 0, propEnd = effect->Properties().Length(); propIdx != propEnd; ++propIdx) { - const AnimationProperty& prop = anim->Properties()[propIdx]; + const AnimationProperty& prop = effect->Properties()[propIdx]; if (!CanAnimatePropertyOnCompositor(mElement, prop.mProperty, aFlags) || @@ -652,11 +654,11 @@ AnimationPlayerCollection::CanPerformOnCompositorThread( } void -AnimationPlayerCollection::PostUpdateLayerAnimations() +AnimationCollection::PostUpdateLayerAnimations() { nsCSSPropertySet propsHandled; - for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) { - const auto& properties = mPlayers[playerIdx]->GetSource()->Properties(); + for (size_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { + const auto& properties = mAnimations[animIdx]->GetEffect()->Properties(); for (size_t propIdx = properties.Length(); propIdx-- != 0; ) { nsCSSProperty prop = properties[propIdx].mProperty; if (nsCSSProps::PropHasFlags(prop, @@ -676,13 +678,12 @@ AnimationPlayerCollection::PostUpdateLayerAnimations() } bool -AnimationPlayerCollection::HasAnimationOfProperty( - nsCSSProperty aProperty) const +AnimationCollection::HasAnimationOfProperty(nsCSSProperty aProperty) const { - for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) { - const Animation* anim = mPlayers[playerIdx]->GetSource(); - if (anim && anim->HasAnimationOfProperty(aProperty) && - !anim->IsFinishedTransition()) { + for (size_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { + const KeyframeEffectReadonly* effect = mAnimations[animIdx]->GetEffect(); + if (effect && effect->HasAnimationOfProperty(aProperty) && + !effect->IsFinishedTransition()) { return true; } } @@ -690,7 +691,7 @@ AnimationPlayerCollection::HasAnimationOfProperty( } mozilla::dom::Element* -AnimationPlayerCollection::GetElementToRestyle() const +AnimationCollection::GetElementToRestyle() const { if (IsForElement()) { return mElement; @@ -716,7 +717,7 @@ AnimationPlayerCollection::GetElementToRestyle() const } void -AnimationPlayerCollection::NotifyPlayerUpdated() +AnimationCollection::NotifyAnimationUpdated() { // On the next flush, force us to update the style rule mNeedsRefreshes = true; @@ -726,7 +727,7 @@ AnimationPlayerCollection::NotifyPlayerUpdated() } /* static */ void -AnimationPlayerCollection::LogAsyncAnimationFailure(nsCString& aMessage, +AnimationCollection::LogAsyncAnimationFailure(nsCString& aMessage, const nsIContent* aContent) { if (aContent) { @@ -746,11 +747,11 @@ AnimationPlayerCollection::LogAsyncAnimationFailure(nsCString& aMessage, } /*static*/ void -AnimationPlayerCollection::PropertyDtor(void *aObject, nsIAtom *aPropertyName, - void *aPropertyValue, void *aData) +AnimationCollection::PropertyDtor(void *aObject, nsIAtom *aPropertyName, + void *aPropertyValue, void *aData) { - AnimationPlayerCollection* collection = - static_cast(aPropertyValue); + AnimationCollection* collection = + static_cast(aPropertyValue); #ifdef DEBUG MOZ_ASSERT(!collection->mCalledPropertyDtor, "can't call dtor twice"); collection->mCalledPropertyDtor = true; @@ -759,17 +760,17 @@ AnimationPlayerCollection::PropertyDtor(void *aObject, nsIAtom *aPropertyName, } void -AnimationPlayerCollection::Tick() +AnimationCollection::Tick() { - for (size_t playerIdx = 0, playerEnd = mPlayers.Length(); - playerIdx != playerEnd; playerIdx++) { - mPlayers[playerIdx]->Tick(); + for (size_t animIdx = 0, animEnd = mAnimations.Length(); + animIdx != animEnd; animIdx++) { + mAnimations[animIdx]->Tick(); } } void -AnimationPlayerCollection::EnsureStyleRuleFor(TimeStamp aRefreshTime, - EnsureStyleRuleFlags aFlags) +AnimationCollection::EnsureStyleRuleFor(TimeStamp aRefreshTime, + EnsureStyleRuleFlags aFlags) { if (!mNeedsRefreshes) { mStyleRuleRefreshTime = aRefreshTime; @@ -789,8 +790,8 @@ AnimationPlayerCollection::EnsureStyleRuleFor(TimeStamp aRefreshTime, // mode behavior). CanThrottle returns false for any finishing animations // so we can force style recalculation in that case. if (aFlags == EnsureStyleRule_IsThrottled) { - for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) { - if (!mPlayers[playerIdx]->CanThrottle()) { + for (size_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { + if (!mAnimations[animIdx]->CanThrottle()) { aFlags = EnsureStyleRule_IsNotThrottled; break; } @@ -818,15 +819,15 @@ AnimationPlayerCollection::EnsureStyleRuleFor(TimeStamp aRefreshTime, // property has already been set, we don't leave it. nsCSSPropertySet properties; - for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) { - mPlayers[playerIdx]->ComposeStyle(mStyleRule, properties, mNeedsRefreshes); + for (size_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { + mAnimations[animIdx]->ComposeStyle(mStyleRule, properties, mNeedsRefreshes); } - mManager->CheckNeedsRefresh(); + mManager->MaybeStartObservingRefreshDriver(); } bool -AnimationPlayerCollection::CanThrottleTransformChanges(TimeStamp aTime) +AnimationCollection::CanThrottleTransformChanges(TimeStamp aTime) { if (!nsLayoutUtils::AreAsyncAnimationsEnabled()) { return false; @@ -865,7 +866,7 @@ AnimationPlayerCollection::CanThrottleTransformChanges(TimeStamp aTime) } bool -AnimationPlayerCollection::CanThrottleAnimation(TimeStamp aTime) +AnimationCollection::CanThrottleAnimation(TimeStamp aTime) { nsIFrame* frame = nsLayoutUtils::GetStyleFrame(mElement); if (!frame) { @@ -896,15 +897,14 @@ AnimationPlayerCollection::CanThrottleAnimation(TimeStamp aTime) } void -AnimationPlayerCollection::UpdateAnimationGeneration( - nsPresContext* aPresContext) +AnimationCollection::UpdateAnimationGeneration(nsPresContext* aPresContext) { mAnimationGeneration = aPresContext->RestyleManager()->GetAnimationGeneration(); } void -AnimationPlayerCollection::UpdateCheckGeneration( +AnimationCollection::UpdateCheckGeneration( nsPresContext* aPresContext) { mCheckGeneration = @@ -912,10 +912,10 @@ AnimationPlayerCollection::UpdateCheckGeneration( } bool -AnimationPlayerCollection::HasCurrentAnimations() const +AnimationCollection::HasCurrentAnimations() const { - for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) { - if (mPlayers[playerIdx]->HasCurrentSource()) { + for (size_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { + if (mAnimations[animIdx]->HasCurrentEffect()) { return true; } } @@ -924,16 +924,16 @@ AnimationPlayerCollection::HasCurrentAnimations() const } bool -AnimationPlayerCollection::HasCurrentAnimationsForProperties( +AnimationCollection::HasCurrentAnimationsForProperties( const nsCSSProperty* aProperties, size_t aPropertyCount) const { - for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) { - const AnimationPlayer& player = *mPlayers[playerIdx]; - const Animation* anim = player.GetSource(); - if (anim && - anim->IsCurrent(player) && - anim->HasAnimationOfProperties(aProperties, aPropertyCount)) { + for (size_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { + const Animation& anim = *mAnimations[animIdx]; + const KeyframeEffectReadonly* effect = anim.GetEffect(); + if (effect && + effect->IsCurrent(anim) && + effect->HasAnimationOfProperties(aProperties, aPropertyCount)) { return true; } } diff --git a/layout/style/AnimationCommon.h b/layout/style/AnimationCommon.h index fec40c5c8c..8880e11e8b 100644 --- a/layout/style/AnimationCommon.h +++ b/layout/style/AnimationCommon.h @@ -15,7 +15,7 @@ #include "nsDisplayList.h" // For nsDisplayItem::Type #include "mozilla/MemoryReporting.h" #include "mozilla/StyleAnimationValue.h" -#include "mozilla/dom/AnimationPlayer.h" +#include "mozilla/dom/Animation.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/Nullable.h" #include "nsStyleStruct.h" @@ -32,7 +32,7 @@ class nsPresContext; namespace mozilla { class RestyleTracker; -struct AnimationPlayerCollection; +struct AnimationCollection; namespace css { @@ -81,7 +81,7 @@ public: // elements. void AddStyleUpdatesTo(mozilla::RestyleTracker& aTracker); - AnimationPlayerCollection* + AnimationCollection* GetAnimations(dom::Element *aElement, nsCSSPseudoElements::Type aPseudoType, bool aCreateIfNeeded); @@ -99,9 +99,9 @@ public: return false; } - // Notify this manager that one of its collections of animation players, + // Notify this manager that one of its collections of animations, // has been updated. - void NotifyCollectionUpdated(AnimationPlayerCollection& aCollection); + void NotifyCollectionUpdated(AnimationCollection& aCollection); enum FlushFlags { Can_Throttle, @@ -140,14 +140,18 @@ protected: virtual ~CommonAnimationManager(); // For ElementCollectionRemoved - friend struct mozilla::AnimationPlayerCollection; + friend struct mozilla::AnimationCollection; - void AddElementCollection(AnimationPlayerCollection* aCollection); - void ElementCollectionRemoved() { CheckNeedsRefresh(); } + void AddElementCollection(AnimationCollection* aCollection); + void ElementCollectionRemoved() { MaybeStartOrStopObservingRefreshDriver(); } void RemoveAllElementCollections(); - // Check to see if we should stop or start observing the refresh driver - void CheckNeedsRefresh(); + // We should normally only call MaybeStartOrStopObservingRefreshDriver in + // situations where we will also queue events since otherwise we may stop + // getting refresh driver ticks before we queue the necessary events. + void MaybeStartObservingRefreshDriver(); + void MaybeStartOrStopObservingRefreshDriver(); + bool NeedsRefresh() const; virtual nsIAtom* GetAnimationsAtom() = 0; virtual nsIAtom* GetAnimationsBeforeAtom() = 0; @@ -157,7 +161,7 @@ protected: return false; } - static AnimationPlayerCollection* + static AnimationCollection* GetAnimationsForCompositor(nsIContent* aContent, nsIAtom* aElementProperty, nsCSSProperty aProperty); @@ -218,18 +222,17 @@ private: } // namespace css -typedef InfallibleTArray > - AnimationPlayerPtrArray; +typedef InfallibleTArray> AnimationPtrArray; enum EnsureStyleRuleFlags { EnsureStyleRule_IsThrottled, EnsureStyleRule_IsNotThrottled }; -struct AnimationPlayerCollection : public PRCList +struct AnimationCollection : public PRCList { - AnimationPlayerCollection(dom::Element *aElement, nsIAtom *aElementProperty, - mozilla::css::CommonAnimationManager *aManager) + AnimationCollection(dom::Element *aElement, nsIAtom *aElementProperty, + mozilla::css::CommonAnimationManager *aManager) : mElement(aElement) , mElementProperty(aElementProperty) , mManager(aManager) @@ -240,22 +243,22 @@ struct AnimationPlayerCollection : public PRCList , mCalledPropertyDtor(false) #endif { - MOZ_COUNT_CTOR(AnimationPlayerCollection); + MOZ_COUNT_CTOR(AnimationCollection); PR_INIT_CLIST(this); } - ~AnimationPlayerCollection() + ~AnimationCollection() { MOZ_ASSERT(mCalledPropertyDtor, "must call destructor through element property dtor"); - MOZ_COUNT_DTOR(AnimationPlayerCollection); + MOZ_COUNT_DTOR(AnimationCollection); PR_REMOVE_LINK(this); mManager->ElementCollectionRemoved(); } void Destroy() { - for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) { - mPlayers[playerIdx]->Cancel(); + for (size_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { + mAnimations[animIdx]->Cancel(); } // This will call our destructor. mElement->DeleteProperty(mElementProperty); @@ -370,7 +373,7 @@ struct AnimationPlayerCollection : public PRCList } } - void NotifyPlayerUpdated(); + void NotifyAnimationUpdated(); static void LogAsyncAnimationFailure(nsCString& aMessage, const nsIContent* aContent = nullptr); @@ -383,7 +386,7 @@ struct AnimationPlayerCollection : public PRCList mozilla::css::CommonAnimationManager *mManager; - mozilla::AnimationPlayerPtrArray mPlayers; + mozilla::AnimationPtrArray mAnimations; // This style rule contains the style data for currently animating // values. It only matches when styling with animation. When we diff --git a/layout/style/CSSStyleSheet.cpp b/layout/style/CSSStyleSheet.cpp index d173174c8e..c2f273635e 100644 --- a/layout/style/CSSStyleSheet.cpp +++ b/layout/style/CSSStyleSheet.cpp @@ -1769,7 +1769,7 @@ CSSStyleSheet::GetCssRules(nsIDOMCSSRuleList** aCssRules) ErrorResult rv; nsCOMPtr rules = GetCssRules(rv); rules.forget(aCssRules); - return rv.ErrorCode(); + return rv.StealNSResult(); } CSSRuleList* diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp index f2bce7b5b8..8f955ea6b2 100644 --- a/layout/style/nsAnimationManager.cpp +++ b/layout/style/nsAnimationManager.cpp @@ -9,6 +9,7 @@ #include "mozilla/EventDispatcher.h" #include "mozilla/MemoryReporting.h" #include "mozilla/StyleAnimationValue.h" +#include "mozilla/dom/KeyframeEffect.h" #include "nsPresContext.h" #include "nsStyleSet.h" @@ -24,59 +25,59 @@ using namespace mozilla; using namespace mozilla::css; using mozilla::dom::Animation; -using mozilla::dom::AnimationPlayer; -using mozilla::CSSAnimationPlayer; +using mozilla::dom::KeyframeEffectReadonly; +using mozilla::CSSAnimation; mozilla::dom::Promise* -CSSAnimationPlayer::GetReady(ErrorResult& aRv) +CSSAnimation::GetReady(ErrorResult& aRv) { FlushStyle(); - return AnimationPlayer::GetReady(aRv); + return Animation::GetReady(aRv); } void -CSSAnimationPlayer::Play(LimitBehavior aLimitBehavior) +CSSAnimation::Play(LimitBehavior aLimitBehavior) { mPauseShouldStick = false; - AnimationPlayer::Play(aLimitBehavior); + Animation::Play(aLimitBehavior); } void -CSSAnimationPlayer::Pause() +CSSAnimation::Pause() { mPauseShouldStick = true; - AnimationPlayer::Pause(); + Animation::Pause(); } mozilla::dom::AnimationPlayState -CSSAnimationPlayer::PlayStateFromJS() const +CSSAnimation::PlayStateFromJS() const { // Flush style to ensure that any properties controlling animation state // (e.g. animation-play-state) are fully updated. FlushStyle(); - return AnimationPlayer::PlayStateFromJS(); + return Animation::PlayStateFromJS(); } void -CSSAnimationPlayer::PlayFromJS() +CSSAnimation::PlayFromJS() { // Note that flushing style below might trigger calls to // PlayFromStyle()/PauseFromStyle() on this object. FlushStyle(); - AnimationPlayer::PlayFromJS(); + Animation::PlayFromJS(); } void -CSSAnimationPlayer::PlayFromStyle() +CSSAnimation::PlayFromStyle() { mIsStylePaused = false; if (!mPauseShouldStick) { - DoPlay(AnimationPlayer::LimitBehavior::Continue); + DoPlay(Animation::LimitBehavior::Continue); } } void -CSSAnimationPlayer::PauseFromStyle() +CSSAnimation::PauseFromStyle() { // Check if the pause state is being overridden if (mIsStylePaused) { @@ -88,13 +89,13 @@ CSSAnimationPlayer::PauseFromStyle() } void -CSSAnimationPlayer::QueueEvents(EventArray& aEventsToDispatch) +CSSAnimation::QueueEvents(EventArray& aEventsToDispatch) { - if (!mSource) { + if (!mEffect) { return; } - ComputedTiming computedTiming = mSource->GetComputedTiming(); + ComputedTiming computedTiming = mEffect->GetComputedTiming(); if (computedTiming.mPhase == ComputedTiming::AnimationPhase_Null) { return; // do nothing @@ -132,7 +133,7 @@ CSSAnimationPlayer::QueueEvents(EventArray& aEventsToDispatch) dom::Element* target; nsCSSPseudoElements::Type targetPseudoType; - mSource->GetTarget(target, targetPseudoType); + mEffect->GetTarget(target, targetPseudoType); uint32_t message; @@ -146,7 +147,7 @@ CSSAnimationPlayer::QueueEvents(EventArray& aEventsToDispatch) // First notifying for start of 0th iteration by appending an // 'animationstart': StickyTimeDuration elapsedTime = - std::min(StickyTimeDuration(mSource->InitialAdvance()), + std::min(StickyTimeDuration(mEffect->InitialAdvance()), computedTiming.mActiveDuration); AnimationEventInfo ei(target, Name(), NS_ANIMATION_START, elapsedTime, @@ -162,10 +163,10 @@ CSSAnimationPlayer::QueueEvents(EventArray& aEventsToDispatch) if (message == NS_ANIMATION_START || message == NS_ANIMATION_ITERATION) { - TimeDuration iterationStart = mSource->Timing().mIterationDuration * + TimeDuration iterationStart = mEffect->Timing().mIterationDuration * computedTiming.mCurrentIteration; elapsedTime = StickyTimeDuration(std::max(iterationStart, - mSource->InitialAdvance())); + mEffect->InitialAdvance())); } else { MOZ_ASSERT(message == NS_ANIMATION_END); elapsedTime = computedTiming.mActiveDuration; @@ -177,7 +178,7 @@ CSSAnimationPlayer::QueueEvents(EventArray& aEventsToDispatch) } CommonAnimationManager* -CSSAnimationPlayer::GetAnimationManager() const +CSSAnimation::GetAnimationManager() const { nsPresContext* context = GetPresContext(); if (!context) { @@ -188,7 +189,7 @@ CSSAnimationPlayer::GetAnimationManager() const } /* static */ nsString -CSSAnimationPlayer::PseudoTypeAsString(nsCSSPseudoElements::Type aPseudoType) +CSSAnimation::PseudoTypeAsString(nsCSSPseudoElements::Type aPseudoType) { switch (aPseudoType) { case nsCSSPseudoElements::ePseudo_before: @@ -201,8 +202,7 @@ CSSAnimationPlayer::PseudoTypeAsString(nsCSSPseudoElements::Type aPseudoType) } void -nsAnimationManager::UpdateStyleAndEvents(AnimationPlayerCollection* - aCollection, +nsAnimationManager::UpdateStyleAndEvents(AnimationCollection* aCollection, TimeStamp aRefreshTime, EnsureStyleRuleFlags aFlags) { @@ -211,25 +211,22 @@ nsAnimationManager::UpdateStyleAndEvents(AnimationPlayerCollection* } void -nsAnimationManager::QueueEvents(AnimationPlayerCollection* aCollection, +nsAnimationManager::QueueEvents(AnimationCollection* aCollection, EventArray& aEventsToDispatch) { - for (size_t playerIdx = aCollection->mPlayers.Length(); playerIdx-- != 0; ) { - CSSAnimationPlayer* player = - aCollection->mPlayers[playerIdx]->AsCSSAnimationPlayer(); - MOZ_ASSERT(player, "Expected a collection of CSS Animation players"); - player->QueueEvents(aEventsToDispatch); + for (size_t animIdx = aCollection->mAnimations.Length(); animIdx-- != 0; ) { + CSSAnimation* anim = aCollection->mAnimations[animIdx]->AsCSSAnimation(); + MOZ_ASSERT(anim, "Expected a collection of CSS Animations"); + anim->QueueEvents(aEventsToDispatch); } } void -nsAnimationManager::MaybeUpdateCascadeResults(AnimationPlayerCollection* aCollection) +nsAnimationManager::MaybeUpdateCascadeResults(AnimationCollection* aCollection) { - for (size_t playerIdx = aCollection->mPlayers.Length(); playerIdx-- != 0; ) { - CSSAnimationPlayer* player = - aCollection->mPlayers[playerIdx]->AsCSSAnimationPlayer(); - - if (player->HasInEffectSource() != player->mInEffectForCascadeResults) { + for (size_t animIdx = aCollection->mAnimations.Length(); animIdx-- != 0; ) { + CSSAnimation* anim = aCollection->mAnimations[animIdx]->AsCSSAnimation(); + if (anim->IsInEffect() != anim->mInEffectForCascadeResults) { // Update our own cascade results. mozilla::dom::Element* element = aCollection->GetElementToRestyle(); if (element) { @@ -279,7 +276,7 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, // style change, but also not in an animation restyle. const nsStyleDisplay* disp = aStyleContext->StyleDisplay(); - AnimationPlayerCollection* collection = + AnimationCollection* collection = GetAnimations(aElement, aStyleContext->GetPseudoType(), false); if (!collection && disp->mAnimationNameCount == 1 && @@ -290,13 +287,13 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, nsAutoAnimationMutationBatch mb(aElement); // build the animations list - dom::AnimationTimeline* timeline = aElement->OwnerDoc()->Timeline(); - AnimationPlayerPtrArray newPlayers; + dom::DocumentTimeline* timeline = aElement->OwnerDoc()->Timeline(); + AnimationPtrArray newAnimations; if (!aStyleContext->IsInDisplayNoneSubtree()) { - BuildAnimations(aStyleContext, aElement, timeline, newPlayers); + BuildAnimations(aStyleContext, aElement, timeline, newAnimations); } - if (newPlayers.IsEmpty()) { + if (newAnimations.IsEmpty()) { if (collection) { // There might be transitions that run now that animations don't // override them. @@ -323,10 +320,10 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, // In order to honor what the spec said, we'd copy more data over // (or potentially optimize BuildAnimations to avoid rebuilding it // in the first place). - if (!collection->mPlayers.IsEmpty()) { + if (!collection->mAnimations.IsEmpty()) { - for (size_t newIdx = newPlayers.Length(); newIdx-- != 0;) { - AnimationPlayer* newPlayer = newPlayers[newIdx]; + for (size_t newIdx = newAnimations.Length(); newIdx-- != 0;) { + Animation* newAnim = newAnimations[newIdx]; // Find the matching animation with this name in the old list // of animations. We iterate through both lists in a backwards @@ -334,19 +331,18 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, // the new list of animations with a given name than in the old // list, it will be the animations towards the of the beginning of // the list that do not match and are treated as new animations. - nsRefPtr oldPlayer; - size_t oldIdx = collection->mPlayers.Length(); + nsRefPtr oldAnim; + size_t oldIdx = collection->mAnimations.Length(); while (oldIdx-- != 0) { - CSSAnimationPlayer* a = - collection->mPlayers[oldIdx]->AsCSSAnimationPlayer(); - MOZ_ASSERT(a, "All players in the CSS Animation collection should" - " be CSSAnimationPlayer objects"); - if (a->Name() == newPlayer->Name()) { - oldPlayer = a; + CSSAnimation* a = collection->mAnimations[oldIdx]->AsCSSAnimation(); + MOZ_ASSERT(a, "All animations in the CSS Animation collection should" + " be CSSAnimation objects"); + if (a->Name() == newAnim->Name()) { + oldAnim = a; break; } } - if (!oldPlayer) { + if (!oldAnim) { continue; } @@ -354,67 +350,67 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, // Update the old from the new so we can keep the original object // identity (and any expando properties attached to it). - if (oldPlayer->GetSource() && newPlayer->GetSource()) { - Animation* oldAnim = oldPlayer->GetSource(); - Animation* newAnim = newPlayer->GetSource(); + if (oldAnim->GetEffect() && newAnim->GetEffect()) { + KeyframeEffectReadonly* oldEffect = oldAnim->GetEffect(); + KeyframeEffectReadonly* newEffect = newAnim->GetEffect(); animationChanged = - oldAnim->Timing() != newAnim->Timing() || - oldAnim->Properties() != newAnim->Properties(); - oldAnim->Timing() = newAnim->Timing(); - oldAnim->Properties() = newAnim->Properties(); + oldEffect->Timing() != newEffect->Timing() || + oldEffect->Properties() != newEffect->Properties(); + oldEffect->Timing() = newEffect->Timing(); + oldEffect->Properties() = newEffect->Properties(); } // Reset compositor state so animation will be re-synchronized. - oldPlayer->ClearIsRunningOnCompositor(); + oldAnim->ClearIsRunningOnCompositor(); // Handle changes in play state. - // CSSAnimationPlayer takes care of override behavior so that, + // CSSAnimation takes care of override behavior so that, // for example, if the author has called pause(), that will // override the animation-play-state. - // (We should check newPlayer->IsStylePaused() but that requires - // downcasting to CSSAnimationPlayer and we happen to know that - // newPlayer will only ever be paused by calling PauseFromStyle + // (We should check newAnim->IsStylePaused() but that requires + // downcasting to CSSAnimation and we happen to know that + // newAnim will only ever be paused by calling PauseFromStyle // making IsPausedOrPausing synonymous in this case.) - if (!oldPlayer->IsStylePaused() && newPlayer->IsPausedOrPausing()) { - oldPlayer->PauseFromStyle(); + if (!oldAnim->IsStylePaused() && newAnim->IsPausedOrPausing()) { + oldAnim->PauseFromStyle(); animationChanged = true; - } else if (oldPlayer->IsStylePaused() && - !newPlayer->IsPausedOrPausing()) { - oldPlayer->PlayFromStyle(); + } else if (oldAnim->IsStylePaused() && + !newAnim->IsPausedOrPausing()) { + oldAnim->PlayFromStyle(); animationChanged = true; } if (animationChanged) { - nsNodeUtils::AnimationChanged(oldPlayer); + nsNodeUtils::AnimationChanged(oldAnim); } // Replace new animation with the (updated) old one and remove the // old one from the array so we don't try to match it any more. // // Although we're doing this while iterating this is safe because - // we're not changing the length of newPlayers and we've finished + // we're not changing the length of newAnimations and we've finished // iterating over the list of old iterations. - newPlayer->Cancel(); - newPlayer = nullptr; - newPlayers.ReplaceElementAt(newIdx, oldPlayer); - collection->mPlayers.RemoveElementAt(oldIdx); + newAnim->Cancel(); + newAnim = nullptr; + newAnimations.ReplaceElementAt(newIdx, oldAnim); + collection->mAnimations.RemoveElementAt(oldIdx); // We've touched the old animation's timing properties, so this - // could update the old player's relevance. - oldPlayer->UpdateRelevance(); + // could update the old animation's relevance. + oldAnim->UpdateRelevance(); } } } else { collection = GetAnimations(aElement, aStyleContext->GetPseudoType(), true); } - collection->mPlayers.SwapElements(newPlayers); + collection->mAnimations.SwapElements(newAnimations); collection->mNeedsRefreshes = true; collection->Tick(); // Cancel removed animations - for (size_t newPlayerIdx = newPlayers.Length(); newPlayerIdx-- != 0; ) { - newPlayers[newPlayerIdx]->Cancel(); + for (size_t newAnimIdx = newAnimations.Length(); newAnimIdx-- != 0; ) { + newAnimations[newAnimIdx]->Cancel(); } UpdateCascadeResults(aStyleContext, collection); @@ -487,10 +483,10 @@ ResolvedStyleCache::Get(nsPresContext *aPresContext, void nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, dom::Element* aTarget, - dom::AnimationTimeline* aTimeline, - AnimationPlayerPtrArray& aPlayers) + dom::DocumentTimeline* aTimeline, + AnimationPtrArray& aAnimations) { - MOZ_ASSERT(aPlayers.IsEmpty(), "expect empty array"); + MOZ_ASSERT(aAnimations.IsEmpty(), "expect empty array"); ResolvedStyleCache resolvedStyles; @@ -506,7 +502,7 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, // not generate animation events. This includes when the animation-name is // "none" which is represented by an empty name in the StyleAnimation. // Since such animations neither affect style nor dispatch events, we do - // not generate a corresponding AnimationPlayer for them. + // not generate a corresponding Animation for them. nsCSSKeyframesRule* rule = src.GetName().IsEmpty() ? nullptr @@ -516,8 +512,8 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, continue; } - nsRefPtr dest = new CSSAnimationPlayer(aTimeline); - aPlayers.AppendElement(dest); + nsRefPtr dest = new CSSAnimation(aTimeline); + aAnimations.AppendElement(dest); AnimationTiming timing; timing.mIterationDuration = @@ -527,14 +523,16 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, timing.mDirection = src.GetDirection(); timing.mFillMode = src.GetFillMode(); - nsRefPtr destAnim = - new Animation(mPresContext->Document(), aTarget, - aStyleContext->GetPseudoType(), timing, src.GetName()); - dest->SetSource(destAnim); + nsRefPtr destEffect = + new KeyframeEffectReadonly(mPresContext->Document(), aTarget, + aStyleContext->GetPseudoType(), timing, + src.GetName()); + dest->SetEffect(destEffect); // Even in the case where we call PauseFromStyle below, we still need to - // call PlayFromStyle first. This is because a newly-created player is idle - // and has no effect until it is played (or otherwise given a start time). + // call PlayFromStyle first. This is because a newly-created animation is + // idle and has no effect until it is played (or otherwise given a start + // time). dest->PlayFromStyle(); if (src.GetPlayState() == NS_STYLE_ANIMATION_PLAY_STATE_PAUSED) { @@ -626,7 +624,7 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, lastKey = kf.mKey; } - AnimationProperty &propData = *destAnim->Properties().AppendElement(); + AnimationProperty &propData = *destEffect->Properties().AppendElement(); propData.mProperty = prop; propData.mWinsInCascade = true; @@ -689,8 +687,8 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, // values (which?) or skip segments, so best to skip the whole // thing for now.) if (!interpolated) { - destAnim->Properties().RemoveElementAt( - destAnim->Properties().Length() - 1); + destEffect->Properties().RemoveElementAt( + destEffect->Properties().Length() - 1); } } } @@ -737,7 +735,7 @@ nsAnimationManager::BuildSegment(InfallibleTArray& /* static */ void nsAnimationManager::UpdateCascadeResults( nsStyleContext* aStyleContext, - AnimationPlayerCollection* aElementAnimations) + AnimationCollection* aElementAnimations) { /* * Figure out which properties we need to examine. @@ -750,17 +748,17 @@ nsAnimationManager::UpdateCascadeResults( { nsCSSPropertySet propertiesToTrackAsSet; - for (size_t playerIdx = aElementAnimations->mPlayers.Length(); - playerIdx-- != 0; ) { - const AnimationPlayer* player = aElementAnimations->mPlayers[playerIdx]; - const Animation* anim = player->GetSource(); - if (!anim) { + for (size_t animIdx = aElementAnimations->mAnimations.Length(); + animIdx-- != 0; ) { + const Animation* anim = aElementAnimations->mAnimations[animIdx]; + const KeyframeEffectReadonly* effect = anim->GetEffect(); + if (!effect) { continue; } - for (size_t propIdx = 0, propEnd = anim->Properties().Length(); + for (size_t propIdx = 0, propEnd = effect->Properties().Length(); propIdx != propEnd; ++propIdx) { - const AnimationProperty& prop = anim->Properties()[propIdx]; + const AnimationProperty& prop = effect->Properties()[propIdx]; // We only bother setting mWinsInCascade for properties that we // can animate on the compositor. if (nsCSSProps::PropHasFlags(prop.mProperty, @@ -790,29 +788,28 @@ nsAnimationManager::UpdateCascadeResults( * another. * * We iterate from the last animation to the first, just like we do - * when calling ComposeStyle from - * AnimationPlayerCollection::EnsureStyleRuleFor. Later animations - * override earlier ones, so we add properties to the set of - * overridden properties as we encounter them, if the animation is + * when calling ComposeStyle from AnimationCollection::EnsureStyleRuleFor. + * Later animations override earlier ones, so we add properties to the set + * of overridden properties as we encounter them, if the animation is * currently in effect. */ bool changed = false; - for (size_t playerIdx = aElementAnimations->mPlayers.Length(); - playerIdx-- != 0; ) { - CSSAnimationPlayer* player = - aElementAnimations->mPlayers[playerIdx]->AsCSSAnimationPlayer(); - Animation* anim = player->GetSource(); + for (size_t animIdx = aElementAnimations->mAnimations.Length(); + animIdx-- != 0; ) { + CSSAnimation* anim = + aElementAnimations->mAnimations[animIdx]->AsCSSAnimation(); + KeyframeEffectReadonly* effect = anim->GetEffect(); - player->mInEffectForCascadeResults = player->HasInEffectSource(); + anim->mInEffectForCascadeResults = anim->IsInEffect(); - if (!anim) { + if (!effect) { continue; } - for (size_t propIdx = 0, propEnd = anim->Properties().Length(); + for (size_t propIdx = 0, propEnd = effect->Properties().Length(); propIdx != propEnd; ++propIdx) { - AnimationProperty& prop = anim->Properties()[propIdx]; + AnimationProperty& prop = effect->Properties()[propIdx]; // We only bother setting mWinsInCascade for properties that we // can animate on the compositor. if (nsCSSProps::PropHasFlags(prop.mProperty, @@ -824,7 +821,7 @@ nsAnimationManager::UpdateCascadeResults( } prop.mWinsInCascade = newWinsInCascade; - if (prop.mWinsInCascade && player->mInEffectForCascadeResults) { + if (prop.mWinsInCascade && anim->mInEffectForCascadeResults) { // This animation is in effect right now, so it overrides // earlier animations. (For animations that aren't in effect, // we set mWinsInCascade as though they were, but they don't @@ -868,23 +865,19 @@ nsAnimationManager::WillRefresh(mozilla::TimeStamp aTime) void nsAnimationManager::FlushAnimations(FlushFlags aFlags) { - // FIXME: check that there's at least one style rule that's not - // in its "done" state, and if there isn't, remove ourselves from - // the refresh driver (but leave the animations!). TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh(); bool didThrottle = false; for (PRCList *l = PR_LIST_HEAD(&mElementCollections); l != &mElementCollections; l = PR_NEXT_LINK(l)) { - AnimationPlayerCollection* collection = - static_cast(l); + AnimationCollection* collection = static_cast(l); nsAutoAnimationMutationBatch mb(collection->mElement); collection->Tick(); bool canThrottleTick = aFlags == Can_Throttle && collection->CanPerformOnCompositorThread( - AnimationPlayerCollection::CanAnimateFlags(0)) && + AnimationCollection::CanAnimateFlags(0)) && collection->CanThrottleAnimation(now); nsRefPtr oldStyleRule = collection->mStyleRule; @@ -902,6 +895,8 @@ nsAnimationManager::FlushAnimations(FlushFlags aFlags) mPresContext->Document()->SetNeedStyleFlush(); } + MaybeStartOrStopObservingRefreshDriver(); + DispatchEvents(); // may destroy us } diff --git a/layout/style/nsAnimationManager.h b/layout/style/nsAnimationManager.h index d49cb7b130..35d6f51211 100644 --- a/layout/style/nsAnimationManager.h +++ b/layout/style/nsAnimationManager.h @@ -9,7 +9,7 @@ #include "mozilla/ContentEvents.h" #include "AnimationCommon.h" #include "nsCSSPseudoElements.h" -#include "mozilla/dom/AnimationPlayer.h" +#include "mozilla/dom/Animation.h" #include "mozilla/MemoryReporting.h" #include "mozilla/TimeStamp.h" @@ -51,19 +51,18 @@ struct AnimationEventInfo { typedef InfallibleTArray EventArray; -class CSSAnimationPlayer final : public dom::AnimationPlayer +class CSSAnimation final : public dom::Animation { public: - explicit CSSAnimationPlayer(dom::AnimationTimeline* aTimeline) - : dom::AnimationPlayer(aTimeline) + explicit CSSAnimation(dom::DocumentTimeline* aTimeline) + : dom::Animation(aTimeline) , mIsStylePaused(false) , mPauseShouldStick(false) , mPreviousPhaseOrIteration(PREVIOUS_PHASE_BEFORE) { } - virtual CSSAnimationPlayer* - AsCSSAnimationPlayer() override { return this; } + virtual CSSAnimation* AsCSSAnimation() override { return this; } virtual dom::Promise* GetReady(ErrorResult& aRv) override; virtual void Play(LimitBehavior aLimitBehavior) override; @@ -87,7 +86,7 @@ public: bool mInEffectForCascadeResults; protected: - virtual ~CSSAnimationPlayer() { } + virtual ~CSSAnimation() { } virtual css::CommonAnimationManager* GetAnimationManager() const override; static nsString PseudoTypeAsString(nsCSSPseudoElements::Type aPseudoType); @@ -124,7 +123,7 @@ protected: // 'running' A | A | C | C | A // 'paused' E | B | D | D | E // - // The base class, AnimationPlayer already provides a boolean value, + // The base class, Animation already provides a boolean value, // mIsPaused which gives us two states. To this we add a further two booleans // to represent the states as follows. // @@ -164,21 +163,20 @@ public: { } - static mozilla::AnimationPlayerCollection* + static mozilla::AnimationCollection* GetAnimationsForCompositor(nsIContent* aContent, nsCSSProperty aProperty) { return mozilla::css::CommonAnimationManager::GetAnimationsForCompositor( aContent, nsGkAtoms::animationsProperty, aProperty); } - void UpdateStyleAndEvents(mozilla::AnimationPlayerCollection* aEA, + void UpdateStyleAndEvents(mozilla::AnimationCollection* aEA, mozilla::TimeStamp aRefreshTime, mozilla::EnsureStyleRuleFlags aFlags); - void QueueEvents(mozilla::AnimationPlayerCollection* aEA, + void QueueEvents(mozilla::AnimationCollection* aEA, mozilla::EventArray &aEventsToDispatch); - void MaybeUpdateCascadeResults(mozilla::AnimationPlayerCollection* - aCollection); + void MaybeUpdateCascadeResults(mozilla::AnimationCollection* aCollection); // nsIStyleRuleProcessor (parts) virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) @@ -236,8 +234,8 @@ protected: private: void BuildAnimations(nsStyleContext* aStyleContext, mozilla::dom::Element* aTarget, - mozilla::dom::AnimationTimeline* aTimeline, - mozilla::AnimationPlayerPtrArray& aAnimations); + mozilla::dom::DocumentTimeline* aTimeline, + mozilla::AnimationPtrArray& aAnimations); bool BuildSegment(InfallibleTArray& aSegments, nsCSSProperty aProperty, @@ -247,7 +245,7 @@ private: float aToKey, nsStyleContext* aToContext); static void UpdateCascadeResults(nsStyleContext* aStyleContext, - mozilla::AnimationPlayerCollection* + mozilla::AnimationCollection* aElementAnimations); // The guts of DispatchEvents diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index b91578b8ef..341d670827 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -365,14 +365,14 @@ nsComputedDOMStyle::GetPropertyValue(const nsAString& aPropertyName, ErrorResult error; nsRefPtr val = GetPropertyCSSValue(aPropertyName, error); if (error.Failed()) { - return error.ErrorCode(); + return error.StealNSResult(); } if (val) { nsString text; val->GetCssText(text, error); aReturn.Assign(text); - return error.ErrorCode(); + return error.StealNSResult(); } return NS_OK; diff --git a/layout/style/nsICSSDeclaration.h b/layout/style/nsICSSDeclaration.h index 6b36d9db0a..e69dbf832b 100644 --- a/layout/style/nsICSSDeclaration.h +++ b/layout/style/nsICSSDeclaration.h @@ -78,7 +78,7 @@ public: mozilla::ErrorResult error; nsRefPtr val = GetPropertyCSSValue(aProp, error); if (error.Failed()) { - return error.ErrorCode(); + return error.StealNSResult(); } nsCOMPtr xpVal = do_QueryInterface(val); diff --git a/layout/style/nsROCSSPrimitiveValue.cpp b/layout/style/nsROCSSPrimitiveValue.cpp index e267ed038a..83a01651b1 100644 --- a/layout/style/nsROCSSPrimitiveValue.cpp +++ b/layout/style/nsROCSSPrimitiveValue.cpp @@ -428,7 +428,7 @@ nsROCSSPrimitiveValue::GetFloatValue(uint16_t aType, float *aVal) { ErrorResult rv; *aVal = GetFloatValue(aType, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } @@ -508,7 +508,7 @@ nsROCSSPrimitiveValue::GetRectValue(nsIDOMRect** aRect) { ErrorResult error; NS_IF_ADDREF(*aRect = GetRectValue(error)); - return error.ErrorCode(); + return error.StealNSResult(); } nsDOMCSSRGBColor* diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index af54a2d5e8..8b27f0a4f3 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -33,11 +33,10 @@ using mozilla::TimeStamp; using mozilla::TimeDuration; -using mozilla::dom::AnimationPlayer; using mozilla::dom::Animation; +using mozilla::dom::KeyframeEffectReadonly; using namespace mozilla; -using namespace mozilla::layers; using namespace mozilla::css; const nsString& @@ -47,7 +46,7 @@ ElementPropertyTransition::Name() const const_cast(this)->mName = NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(TransitionProperty())); } - return dom::Animation::Name(); + return dom::KeyframeEffectReadonly::Name(); } double @@ -83,25 +82,25 @@ ElementPropertyTransition::CurrentValuePortion() const } /***************************************************************************** - * CSSTransitionPlayer * + * CSSTransition * *****************************************************************************/ mozilla::dom::AnimationPlayState -CSSTransitionPlayer::PlayStateFromJS() const +CSSTransition::PlayStateFromJS() const { FlushStyle(); - return AnimationPlayer::PlayStateFromJS(); + return Animation::PlayStateFromJS(); } void -CSSTransitionPlayer::PlayFromJS() +CSSTransition::PlayFromJS() { FlushStyle(); - AnimationPlayer::PlayFromJS(); + Animation::PlayFromJS(); } CommonAnimationManager* -CSSTransitionPlayer::GetAnimationManager() const +CSSTransition::GetAnimationManager() const { nsPresContext* context = GetPresContext(); if (!context) { @@ -184,8 +183,7 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement, aElement = aElement->GetParent()->AsElement(); } - AnimationPlayerCollection* collection = - GetAnimations(aElement, pseudoType, false); + AnimationCollection* collection = GetAnimations(aElement, pseudoType, false); if (!collection && disp->mTransitionPropertyCount == 1 && disp->mTransitions[0].GetCombinedDuration() <= 0.0f) { @@ -314,19 +312,19 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement, } } - AnimationPlayerPtrArray& players = collection->mPlayers; - size_t i = players.Length(); + AnimationPtrArray& animations = collection->mAnimations; + size_t i = animations.Length(); MOZ_ASSERT(i != 0, "empty transitions list?"); StyleAnimationValue currentValue; do { --i; - AnimationPlayer* player = players[i]; - dom::Animation* anim = player->GetSource(); - MOZ_ASSERT(anim && anim->Properties().Length() == 1, + Animation* anim = animations[i]; + dom::KeyframeEffectReadonly* effect = anim->GetEffect(); + MOZ_ASSERT(effect && effect->Properties().Length() == 1, "Should have one animation property for a transition"); - MOZ_ASSERT(anim && anim->Properties()[0].mSegments.Length() == 1, + MOZ_ASSERT(effect && effect->Properties()[0].mSegments.Length() == 1, "Animation property should have one segment for a transition"); - const AnimationProperty& prop = anim->Properties()[0]; + const AnimationProperty& prop = effect->Properties()[0]; const AnimationPropertySegment& segment = prop.mSegments[0]; // properties no longer in 'transition-property' if ((checkProperties && @@ -340,15 +338,15 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement, currentValue) || currentValue != segment.mToValue) { // stop the transition - if (!player->GetSource()->IsFinishedTransition()) { - player->Cancel(); + if (!anim->GetEffect()->IsFinishedTransition()) { + anim->Cancel(); collection->UpdateAnimationGeneration(mPresContext); } - players.RemoveElementAt(i); + animations.RemoveElementAt(i); } } while (i != 0); - if (players.IsEmpty()) { + if (animations.IsEmpty()) { collection->Destroy(); collection = nullptr; } @@ -385,7 +383,7 @@ nsTransitionManager::ConsiderStartingTransition( nsCSSProperty aProperty, const StyleTransition& aTransition, dom::Element* aElement, - AnimationPlayerCollection*& aElementTransitions, + AnimationCollection*& aElementTransitions, nsStyleContext* aOldStyleContext, nsStyleContext* aNewStyleContext, bool* aStartedAny, @@ -409,7 +407,7 @@ nsTransitionManager::ConsiderStartingTransition( return; } - dom::AnimationTimeline* timeline = aElement->OwnerDoc()->Timeline(); + dom::DocumentTimeline* timeline = aElement->OwnerDoc()->Timeline(); StyleAnimationValue startValue, endValue, dummyValue; bool haveValues = @@ -433,10 +431,10 @@ nsTransitionManager::ConsiderStartingTransition( size_t currentIndex = nsTArray::NoIndex; const ElementPropertyTransition *oldPT = nullptr; if (aElementTransitions) { - AnimationPlayerPtrArray& players = aElementTransitions->mPlayers; - for (size_t i = 0, i_end = players.Length(); i < i_end; ++i) { + AnimationPtrArray& animations = aElementTransitions->mAnimations; + for (size_t i = 0, i_end = animations.Length(); i < i_end; ++i) { const ElementPropertyTransition *iPt = - players[i]->GetSource()->AsTransition(); + animations[i]->GetEffect()->AsTransition(); if (iPt->TransitionProperty() == aProperty) { haveCurrentTransition = true; currentIndex = i; @@ -476,13 +474,13 @@ nsTransitionManager::ConsiderStartingTransition( // in-progress value (which is particularly easy to cause when we're // currently in the 'transition-delay'). It also might happen because we // just got a style change to a value that can't be interpolated. - AnimationPlayerPtrArray& players = aElementTransitions->mPlayers; - players[currentIndex]->Cancel(); + AnimationPtrArray& animations = aElementTransitions->mAnimations; + animations[currentIndex]->Cancel(); oldPT = nullptr; // Clear pointer so it doesn't dangle - players.RemoveElementAt(currentIndex); + animations.RemoveElementAt(currentIndex); aElementTransitions->UpdateAnimationGeneration(mPresContext); - if (players.IsEmpty()) { + if (animations.IsEmpty()) { aElementTransitions->Destroy(); // |aElementTransitions| is now a dangling pointer! aElementTransitions = nullptr; @@ -566,13 +564,13 @@ nsTransitionManager::ConsiderStartingTransition( segment.mToKey = 1; segment.mTimingFunction.Init(tf); - nsRefPtr player = new CSSTransitionPlayer(timeline); + nsRefPtr animation = new CSSTransition(timeline); // The order of the following two calls is important since PlayFromStyle - // will add the player to the PendingPlayerTracker of its source content's - // document. When we come to make source writeable (bug 1049975) we should + // will add the animation to the PendingAnimationTracker of its effect's + // document. When we come to make effect writeable (bug 1049975) we should // remove this dependency. - player->SetSource(pt); - player->PlayFromStyle(); + animation->SetEffect(pt); + animation->PlayFromStyle(); if (!aElementTransitions) { aElementTransitions = @@ -583,23 +581,23 @@ nsTransitionManager::ConsiderStartingTransition( } } - AnimationPlayerPtrArray& players = aElementTransitions->mPlayers; + AnimationPtrArray& animations = aElementTransitions->mAnimations; #ifdef DEBUG - for (size_t i = 0, i_end = players.Length(); i < i_end; ++i) { + for (size_t i = 0, i_end = animations.Length(); i < i_end; ++i) { MOZ_ASSERT( i == currentIndex || - (players[i]->GetSource() && - players[i]->GetSource()->AsTransition()->TransitionProperty() + (animations[i]->GetEffect() && + animations[i]->GetEffect()->AsTransition()->TransitionProperty() != aProperty), "duplicate transitions for property"); } #endif if (haveCurrentTransition) { - players[currentIndex]->Cancel(); + animations[currentIndex]->Cancel(); oldPT = nullptr; // Clear pointer so it doesn't dangle - players[currentIndex] = player; + animations[currentIndex] = animation; } else { - if (!players.AppendElement(player)) { + if (!animations.AppendElement(animation)) { NS_WARNING("out of memory"); return; } @@ -612,10 +610,9 @@ nsTransitionManager::ConsiderStartingTransition( void nsTransitionManager::UpdateCascadeResultsWithTransitions( - AnimationPlayerCollection* aTransitions) + AnimationCollection* aTransitions) { - AnimationPlayerCollection* animations = - mPresContext->AnimationManager()-> + AnimationCollection* animations = mPresContext->AnimationManager()-> GetAnimations(aTransitions->mElement, aTransitions->PseudoElementType(), false); UpdateCascadeResults(aTransitions, animations); @@ -623,10 +620,9 @@ nsTransitionManager::UpdateCascadeResultsWithTransitions( void nsTransitionManager::UpdateCascadeResultsWithAnimations( - AnimationPlayerCollection* aAnimations) + AnimationCollection* aAnimations) { - AnimationPlayerCollection* transitions = - mPresContext->TransitionManager()-> + AnimationCollection* transitions = mPresContext->TransitionManager()-> GetAnimations(aAnimations->mElement, aAnimations->PseudoElementType(), false); UpdateCascadeResults(transitions, aAnimations); @@ -634,12 +630,12 @@ nsTransitionManager::UpdateCascadeResultsWithAnimations( void nsTransitionManager::UpdateCascadeResultsWithAnimationsToBeDestroyed( - const AnimationPlayerCollection* aAnimations) + const AnimationCollection* aAnimations) { // aAnimations is about to be destroyed. So get transitions from it, // but then don't pass it to UpdateCascadeResults, since it has // information that may now be incorrect. - AnimationPlayerCollection* transitions = + AnimationCollection* transitions = mPresContext->TransitionManager()-> GetAnimations(aAnimations->mElement, aAnimations->PseudoElementType(), false); @@ -647,9 +643,8 @@ nsTransitionManager::UpdateCascadeResultsWithAnimationsToBeDestroyed( } void -nsTransitionManager::UpdateCascadeResults( - AnimationPlayerCollection* aTransitions, - AnimationPlayerCollection* aAnimations) +nsTransitionManager::UpdateCascadeResults(AnimationCollection* aTransitions, + AnimationCollection* aAnimations) { if (!aTransitions) { // Nothing to do. @@ -679,12 +674,12 @@ nsTransitionManager::UpdateCascadeResults( // property, it doesn't matter what order we iterate the transitions. // But let's go the same way as animations. bool changed = false; - AnimationPlayerPtrArray& players = aTransitions->mPlayers; - for (size_t playerIdx = players.Length(); playerIdx-- != 0; ) { - MOZ_ASSERT(players[playerIdx]->GetSource() && - players[playerIdx]->GetSource()->Properties().Length() == 1, + AnimationPtrArray& animations = aTransitions->mAnimations; + for (size_t animIdx = animations.Length(); animIdx-- != 0; ) { + MOZ_ASSERT(animations[animIdx]->GetEffect() && + animations[animIdx]->GetEffect()->Properties().Length() == 1, "Should have one animation property for a transition"); - AnimationProperty& prop = players[playerIdx]->GetSource()->Properties()[0]; + AnimationProperty& prop = animations[animIdx]->GetEffect()->Properties()[0]; bool newWinsInCascade = !propertiesUsed.HasProperty(prop.mProperty); if (prop.mWinsInCascade != newWinsInCascade) { changed = true; @@ -786,8 +781,7 @@ nsTransitionManager::FlushTransitions(FlushFlags aFlags) { PRCList *next = PR_LIST_HEAD(&mElementCollections); while (next != &mElementCollections) { - AnimationPlayerCollection* collection = - static_cast(next); + AnimationCollection* collection = static_cast(next); next = PR_NEXT_LINK(next); nsAutoAnimationMutationBatch mb(collection->mElement); @@ -795,7 +789,7 @@ nsTransitionManager::FlushTransitions(FlushFlags aFlags) collection->Tick(); bool canThrottleTick = aFlags == Can_Throttle && collection->CanPerformOnCompositorThread( - AnimationPlayerCollection::CanAnimateFlags(0)) && + AnimationCollection::CanAnimateFlags(0)) && collection->CanThrottleAnimation(now); MOZ_ASSERT(collection->mElement->GetCrossShadowCurrentDoc() == @@ -803,22 +797,21 @@ nsTransitionManager::FlushTransitions(FlushFlags aFlags) "Element::UnbindFromTree should have " "destroyed the element transitions object"); - size_t i = collection->mPlayers.Length(); + size_t i = collection->mAnimations.Length(); MOZ_ASSERT(i != 0, "empty transitions list?"); bool transitionStartedOrEnded = false; do { --i; - AnimationPlayer* player = collection->mPlayers[i]; - if (!player->GetSource()->IsFinishedTransition()) { - MOZ_ASSERT(player->GetSource(), - "Transitions should have source content"); + Animation* anim = collection->mAnimations[i]; + if (!anim->GetEffect()->IsFinishedTransition()) { + MOZ_ASSERT(anim->GetEffect(), "Transitions should have an effect"); ComputedTiming computedTiming = - player->GetSource()->GetComputedTiming(); + anim->GetEffect()->GetComputedTiming(); if (computedTiming.mPhase == ComputedTiming::AnimationPhase_After) { nsCSSProperty prop = - player->GetSource()->AsTransition()->TransitionProperty(); + anim->GetEffect()->AsTransition()->TransitionProperty(); TimeDuration duration = - player->GetSource()->Timing().mIterationDuration; + anim->GetEffect()->Timing().mIterationDuration; events.AppendElement( TransitionEventInfo(collection->mElement, prop, duration, @@ -831,13 +824,13 @@ nsTransitionManager::FlushTransitions(FlushFlags aFlags) // a non-animation style change that would affect it, we need // to know not to start a new transition for the transition // from the almost-completed value to the final value. - player->GetSource()->SetIsFinishedTransition(); + anim->GetEffect()->SetIsFinishedTransition(true); collection->UpdateAnimationGeneration(mPresContext); transitionStartedOrEnded = true; } else if ((computedTiming.mPhase == ComputedTiming::AnimationPhase_Active) && canThrottleTick && - !player->IsRunningOnCompositor()) { + !anim->IsRunningOnCompositor()) { // Start a transition with a delay where we should start the // transition proper. collection->UpdateAnimationGeneration(mPresContext); @@ -861,7 +854,7 @@ nsTransitionManager::FlushTransitions(FlushFlags aFlags) didThrottle = true; } - if (collection->mPlayers.IsEmpty()) { + if (collection->mAnimations.IsEmpty()) { collection->Destroy(); // |collection| is now a dangling pointer! collection = nullptr; @@ -873,7 +866,8 @@ nsTransitionManager::FlushTransitions(FlushFlags aFlags) mPresContext->Document()->SetNeedStyleFlush(); } - nsRefPtr kungFuDeathGrip(this); + MaybeStartOrStopObservingRefreshDriver(); + for (uint32_t i = 0, i_end = events.Length(); i < i_end; ++i) { TransitionEventInfo &info = events[i]; EventDispatcher::Dispatch(info.mElement, mPresContext, &info.mEvent); diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index a0c6630056..63ea75b224 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -11,7 +11,7 @@ #include "mozilla/Attributes.h" #include "mozilla/MemoryReporting.h" #include "mozilla/dom/Animation.h" -#include "mozilla/dom/AnimationPlayer.h" +#include "mozilla/dom/KeyframeEffect.h" #include "AnimationCommon.h" #include "nsCSSPseudoElements.h" @@ -29,19 +29,20 @@ struct StyleTransition; namespace mozilla { -struct ElementPropertyTransition : public dom::Animation +struct ElementPropertyTransition : public dom::KeyframeEffectReadonly { ElementPropertyTransition(nsIDocument* aDocument, dom::Element* aTarget, nsCSSPseudoElements::Type aPseudoType, const AnimationTiming &aTiming) - : dom::Animation(aDocument, aTarget, aPseudoType, aTiming, EmptyString()) + : dom::KeyframeEffectReadonly(aDocument, aTarget, aPseudoType, + aTiming, EmptyString()) { } virtual ElementPropertyTransition* AsTransition() { return this; } virtual const ElementPropertyTransition* AsTransition() const { return this; } - virtual const nsString& Name() const; + virtual const nsString& Name() const override; nsCSSProperty TransitionProperty() const { MOZ_ASSERT(Properties().Length() == 1, @@ -73,26 +74,25 @@ struct ElementPropertyTransition : public dom::Animation double CurrentValuePortion() const; }; -class CSSTransitionPlayer final : public dom::AnimationPlayer +class CSSTransition final : public dom::Animation { public: - explicit CSSTransitionPlayer(dom::AnimationTimeline* aTimeline) - : dom::AnimationPlayer(aTimeline) + explicit CSSTransition(dom::DocumentTimeline* aTimeline) + : dom::Animation(aTimeline) { } - virtual CSSTransitionPlayer* - AsCSSTransitionPlayer() override { return this; } + virtual CSSTransition* AsCSSTransition() override { return this; } virtual dom::AnimationPlayState PlayStateFromJS() const override; virtual void PlayFromJS() override; // A variant of Play() that avoids posting style updates since this method // is expected to be called whilst already updating style. - void PlayFromStyle() { DoPlay(AnimationPlayer::LimitBehavior::Continue); } + void PlayFromStyle() { DoPlay(Animation::LimitBehavior::Continue); } protected: - virtual ~CSSTransitionPlayer() { } + virtual ~CSSTransition() { } virtual css::CommonAnimationManager* GetAnimationManager() const override; }; @@ -109,9 +109,9 @@ public: { } - typedef mozilla::AnimationPlayerCollection AnimationPlayerCollection; + typedef mozilla::AnimationCollection AnimationCollection; - static AnimationPlayerCollection* + static AnimationCollection* GetAnimationsForCompositor(nsIContent* aContent, nsCSSProperty aProperty) { return mozilla::css::CommonAnimationManager::GetAnimationsForCompositor( @@ -136,14 +136,12 @@ public: nsStyleContext *aOldStyleContext, nsRefPtr* aNewStyleContext /* inout */); - void UpdateCascadeResultsWithTransitions( - AnimationPlayerCollection* aTransitions); - void UpdateCascadeResultsWithAnimations( - AnimationPlayerCollection* aAnimations); + void UpdateCascadeResultsWithTransitions(AnimationCollection* aTransitions); + void UpdateCascadeResultsWithAnimations(AnimationCollection* aAnimations); void UpdateCascadeResultsWithAnimationsToBeDestroyed( - const AnimationPlayerCollection* aAnimations); - void UpdateCascadeResults(AnimationPlayerCollection* aTransitions, - AnimationPlayerCollection* aAnimations); + const AnimationCollection* aAnimations); + void UpdateCascadeResults(AnimationCollection* aTransitions, + AnimationCollection* aAnimations); void SetInAnimationOnlyStyleUpdate(bool aInAnimationOnlyUpdate) { mInAnimationOnlyStyleUpdate = aInAnimationOnlyUpdate; @@ -179,7 +177,7 @@ private: ConsiderStartingTransition(nsCSSProperty aProperty, const mozilla::StyleTransition& aTransition, mozilla::dom::Element* aElement, - AnimationPlayerCollection*& aElementTransitions, + AnimationCollection*& aElementTransitions, nsStyleContext* aOldStyleContext, nsStyleContext* aNewStyleContext, bool* aStartedAny, diff --git a/layout/xul/tree/nsTreeBodyFrame.cpp b/layout/xul/tree/nsTreeBodyFrame.cpp index 5fe8e38b3f..5ce43ed02e 100644 --- a/layout/xul/tree/nsTreeBodyFrame.cpp +++ b/layout/xul/tree/nsTreeBodyFrame.cpp @@ -621,7 +621,7 @@ nsTreeBodyFrame::GetSelectionRegion(nsIScriptableRegion **aRegion) // clip to the tree boundary in case one row extends past it region->IntersectRect(x, top, rect.width, rect.height); - NS_ADDREF(*aRegion = region); + region.forget(aRegion); return NS_OK; } diff --git a/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java b/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java index 61bae6e171..841843f50d 100644 --- a/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java +++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java @@ -32,8 +32,8 @@ import android.view.SurfaceHolder.Callback; import android.view.SurfaceHolder; import android.view.WindowManager; -import org.mozilla.goanna.GoannaAppShell; -import org.mozilla.goanna.GoannaAppShell.AppStateListener; +import org.mozilla.goanna.GeckoAppShell; +import org.mozilla.goanna.GeckoAppShell.AppStateListener; import org.mozilla.goanna.mozglue.WebRTCJNITarget; // Wrapper for android Camera, with support for direct local preview rendering. @@ -122,7 +122,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback, AppStateL } public int GetRotateAmount() { - int rotation = GoannaAppShell.getGoannaInterface().getActivity().getWindowManager().getDefaultDisplay().getRotation(); + int rotation = GeckoAppShell.getGoannaInterface().getActivity().getWindowManager().getDefaultDisplay().getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; @@ -328,7 +328,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback, AppStateL mCaptureMaxFPS = max_mfps; // If we are resuming a paused capture, the listener is already active. if (!mResumeCapture) { - GoannaAppShell.getGoannaInterface().addAppStateListener(this); + GeckoAppShell.getGoannaInterface().addAppStateListener(this); } exchange(result, true); return; @@ -405,7 +405,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback, AppStateL camera = null; // If we want to resume after onResume, keep the listener in place. if (!mResumeCapture) { - GoannaAppShell.getGoannaInterface().removeAppStateListener(this); + GeckoAppShell.getGoannaInterface().removeAppStateListener(this); ViERenderer.DestroyLocalRenderer(); } exchange(result, true); diff --git a/modules/libjar/nsJARURI.cpp b/modules/libjar/nsJARURI.cpp index 3b23d8e57d..0047d750ea 100644 --- a/modules/libjar/nsJARURI.cpp +++ b/modules/libjar/nsJARURI.cpp @@ -512,7 +512,8 @@ nsJARURI::Clone(nsIURI **result) rv = CloneWithJARFileInternal(mJARFile, eHonorRef, getter_AddRefs(uri)); if (NS_FAILED(rv)) return rv; - return CallQueryInterface(uri, result); + uri.forget(result); + return NS_OK; } NS_IMETHODIMP @@ -524,7 +525,8 @@ nsJARURI::CloneIgnoringRef(nsIURI **result) rv = CloneWithJARFileInternal(mJARFile, eIgnoreRef, getter_AddRefs(uri)); if (NS_FAILED(rv)) return rv; - return CallQueryInterface(uri, result); + uri.forget(result); + return NS_OK; } NS_IMETHODIMP diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index d270b7505a..675e92b857 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -749,11 +749,9 @@ Preferences::GetBranch(const char *aPrefRoot, nsIPrefBranch **_retval) if ((nullptr != aPrefRoot) && (*aPrefRoot != '\0')) { // TODO: - cache this stuff and allow consumers to share branches (hold weak references I think) - nsPrefBranch* prefBranch = new nsPrefBranch(aPrefRoot, false); - if (!prefBranch) - return NS_ERROR_OUT_OF_MEMORY; - - rv = CallQueryInterface(prefBranch, _retval); + nsRefPtr prefBranch = new nsPrefBranch(aPrefRoot, false); + prefBranch.forget(_retval); + rv = NS_OK; } else { // special case caching the default root nsCOMPtr root(sRootBranch); diff --git a/netwerk/base/Tickler.cpp b/netwerk/base/Tickler.cpp index 95c7fd3f57..4b8e05dd10 100644 --- a/netwerk/base/Tickler.cpp +++ b/netwerk/base/Tickler.cpp @@ -81,7 +81,7 @@ Tickler::Init() MOZ_ASSERT(!mFD); if (AndroidBridge::HasEnv()) { - widget::GoannaAppShell::EnableNetworkNotifications(); + widget::GeckoAppShell::EnableNetworkNotifications(); } mFD = PR_OpenUDPSocket(PR_AF_INET); diff --git a/netwerk/base/nsDirectoryIndexStream.cpp b/netwerk/base/nsDirectoryIndexStream.cpp index 9a81138055..8333a21002 100644 --- a/netwerk/base/nsDirectoryIndexStream.cpp +++ b/netwerk/base/nsDirectoryIndexStream.cpp @@ -164,19 +164,16 @@ nsDirectoryIndexStream::~nsDirectoryIndexStream() nsresult nsDirectoryIndexStream::Create(nsIFile* aDir, nsIInputStream** aResult) { - nsDirectoryIndexStream* result = new nsDirectoryIndexStream(); + nsRefPtr result = new nsDirectoryIndexStream(); if (! result) return NS_ERROR_OUT_OF_MEMORY; - nsresult rv; - rv = result->Init(aDir); + nsresult rv = result->Init(aDir); if (NS_FAILED(rv)) { - delete result; return rv; } - *aResult = result; - NS_ADDREF(*aResult); + result.forget(aResult); return NS_OK; } diff --git a/netwerk/base/nsNetUtil.h b/netwerk/base/nsNetUtil.h index 9b9aea433b..cffaebf2dd 100644 --- a/netwerk/base/nsNetUtil.h +++ b/netwerk/base/nsNetUtil.h @@ -851,8 +851,9 @@ NS_NewDownloader(nsIStreamListener **result, do_CreateInstance(NS_DOWNLOADER_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { rv = downloader->Init(observer, downloadLocation); - if (NS_SUCCEEDED(rv)) - NS_ADDREF(*result = downloader); + if (NS_SUCCEEDED(rv)) { + downloader.forget(result); + } } return rv; } @@ -992,8 +993,9 @@ NS_NewSyncStreamListener(nsIStreamListener **result, do_CreateInstance(NS_SYNCSTREAMLISTENER_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { rv = listener->GetInputStream(stream); - if (NS_SUCCEEDED(rv)) - NS_ADDREF(*result = listener); // cannot use nsCOMPtr::swap + if (NS_SUCCEEDED(rv)) { + listener.forget(result); + } } return rv; } @@ -1038,8 +1040,9 @@ NS_NewRequestObserverProxy(nsIRequestObserver **result, do_CreateInstance(NS_REQUESTOBSERVERPROXY_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { rv = proxy->Init(observer, context); - if (NS_SUCCEEDED(rv)) - NS_ADDREF(*result = proxy); // cannot use nsCOMPtr::swap + if (NS_SUCCEEDED(rv)) { + proxy.forget(result); + } } return rv; } @@ -1054,8 +1057,9 @@ NS_NewSimpleStreamListener(nsIStreamListener **result, do_CreateInstance(NS_SIMPLESTREAMLISTENER_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { rv = listener->Init(sink, observer); - if (NS_SUCCEEDED(rv)) - NS_ADDREF(*result = listener); // cannot use nsCOMPtr::swap + if (NS_SUCCEEDED(rv)) { + listener.forget(result); + } } return rv; } @@ -1455,8 +1459,9 @@ NS_NewBufferedInputStream(nsIInputStream **result, do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { rv = in->Init(str, bufferSize); - if (NS_SUCCEEDED(rv)) - NS_ADDREF(*result = in); // cannot use nsCOMPtr::swap + if (NS_SUCCEEDED(rv)) { + in.forget(result); + } } return rv; } @@ -1473,8 +1478,9 @@ NS_NewBufferedOutputStream(nsIOutputStream **result, do_CreateInstance(NS_BUFFEREDOUTPUTSTREAM_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { rv = out->Init(str, bufferSize); - if (NS_SUCCEEDED(rv)) - NS_ADDREF(*result = out); // cannot use nsCOMPtr::swap + if (NS_SUCCEEDED(rv)) { + out.forget(result); + } } return rv; } @@ -1539,7 +1545,7 @@ NS_NewPostDataStream(nsIInputStream **result, if (NS_FAILED(rv)) return rv; - NS_ADDREF(*result = stream); + stream.forget(result); return NS_OK; } diff --git a/netwerk/base/nsURLHelperOSX.cpp b/netwerk/base/nsURLHelperOSX.cpp index dadba1c33e..bcc0b257fb 100644 --- a/netwerk/base/nsURLHelperOSX.cpp +++ b/netwerk/base/nsURLHelperOSX.cpp @@ -211,6 +211,6 @@ net_GetFileFromURLSpec(const nsACString &aURL, nsIFile **result) if (NS_FAILED(rv)) return rv; - NS_ADDREF(*result = localFile); + localFile.forget(result); return NS_OK; } diff --git a/netwerk/base/nsURLHelperUnix.cpp b/netwerk/base/nsURLHelperUnix.cpp index e9256474de..431d2845ec 100644 --- a/netwerk/base/nsURLHelperUnix.cpp +++ b/netwerk/base/nsURLHelperUnix.cpp @@ -96,6 +96,6 @@ net_GetFileFromURLSpec(const nsACString &aURL, nsIFile **result) if (NS_FAILED(rv)) return rv; - NS_ADDREF(*result = localFile); + localFile.forget(result); return NS_OK; } diff --git a/netwerk/base/nsURLHelperWin.cpp b/netwerk/base/nsURLHelperWin.cpp index e0ae91d98b..4ec46db4ec 100644 --- a/netwerk/base/nsURLHelperWin.cpp +++ b/netwerk/base/nsURLHelperWin.cpp @@ -112,6 +112,6 @@ net_GetFileFromURLSpec(const nsACString &aURL, nsIFile **result) if (NS_FAILED(rv)) return rv; - NS_ADDREF(*result = localFile); + localFile.forget(result); return NS_OK; } diff --git a/netwerk/protocol/data/nsDataChannel.cpp b/netwerk/protocol/data/nsDataChannel.cpp index cd3dfe8526..afd5fe2ec0 100644 --- a/netwerk/protocol/data/nsDataChannel.cpp +++ b/netwerk/protocol/data/nsDataChannel.cpp @@ -83,7 +83,7 @@ nsDataChannel::OpenContentStream(bool async, nsIInputStream **result, SetContentCharset(contentCharset); mContentLength = contentLen; - NS_ADDREF(*result = bufInStream); + bufInStream.forget(result); return NS_OK; } diff --git a/netwerk/protocol/device/AndroidCaptureProvider.cpp b/netwerk/protocol/device/AndroidCaptureProvider.cpp index dd18f6c672..cb7ab76b65 100644 --- a/netwerk/protocol/device/AndroidCaptureProvider.cpp +++ b/netwerk/protocol/device/AndroidCaptureProvider.cpp @@ -289,7 +289,8 @@ nsresult AndroidCaptureProvider::Init(nsACString& aContentType, } else { NS_NOTREACHED("Should not have asked Android for this type!"); } - return CallQueryInterface(stream, aStream); + stream.forget(aStream); + return NS_OK; } already_AddRefed GetAndroidCaptureProvider() { diff --git a/netwerk/protocol/device/CameraStreamImpl.cpp b/netwerk/protocol/device/CameraStreamImpl.cpp index f0d3765869..e1698d55a0 100644 --- a/netwerk/protocol/device/CameraStreamImpl.cpp +++ b/netwerk/protocol/device/CameraStreamImpl.cpp @@ -13,11 +13,11 @@ */ extern "C" { - NS_EXPORT void JNICALL Java_org_mozilla_goanna_GoannaAppShell_cameraCallbackBridge(JNIEnv *, jclass, jbyteArray data); + NS_EXPORT void JNICALL Java_org_mozilla_goanna_GeckoAppShell_cameraCallbackBridge(JNIEnv *, jclass, jbyteArray data); } NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_cameraCallbackBridge(JNIEnv *env, jclass, jbyteArray data) { +Java_org_mozilla_goanna_GeckoAppShell_cameraCallbackBridge(JNIEnv *env, jclass, jbyteArray data) { mozilla::net::CameraStreamImpl* impl = mozilla::net::CameraStreamImpl::GetInstance(0); impl->transmitFrame(env, &data); @@ -90,7 +90,7 @@ bool CameraStreamImpl::Init(const nsCString& contentType, const uint32_t& camera } void CameraStreamImpl::Close() { - mozilla::widget::GoannaAppShell::CloseCamera(); + mozilla::widget::GeckoAppShell::CloseCamera(); mCallback = nullptr; } diff --git a/netwerk/protocol/device/nsDeviceProtocolHandler.cpp b/netwerk/protocol/device/nsDeviceProtocolHandler.cpp index 51cfe9033d..1c7b62c34c 100644 --- a/netwerk/protocol/device/nsDeviceProtocolHandler.cpp +++ b/netwerk/protocol/device/nsDeviceProtocolHandler.cpp @@ -50,7 +50,8 @@ nsDeviceProtocolHandler::NewURI(const nsACString &spec, nsresult rv = uri->SetSpec(spec); NS_ENSURE_SUCCESS(rv, rv); - return CallQueryInterface(uri, result); + uri.forget(result); + return NS_OK; } NS_IMETHODIMP @@ -66,7 +67,8 @@ nsDeviceProtocolHandler::NewChannel2(nsIURI* aURI, rv = channel->SetLoadInfo(aLoadInfo); NS_ENSURE_SUCCESS(rv, rv); - return CallQueryInterface(channel, aResult); + channel.forget(aResult); + return NS_OK; } NS_IMETHODIMP diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index 05e062536b..1567775855 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -2039,7 +2039,7 @@ nsHttpConnectionMgr::BuildPipeline(nsConnectionEntry *ent, nsRefPtr pipeline = new nsHttpPipeline(); pipeline->AddTransaction(firstTrans); - NS_ADDREF(*result = pipeline); + pipeline.forget(result); return NS_OK; } diff --git a/netwerk/protocol/http/nsHttpDigestAuth.cpp b/netwerk/protocol/http/nsHttpDigestAuth.cpp index c112f0bbe1..f16b2418c8 100644 --- a/netwerk/protocol/http/nsHttpDigestAuth.cpp +++ b/netwerk/protocol/http/nsHttpDigestAuth.cpp @@ -271,7 +271,7 @@ nsHttpDigestAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel, do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID)); if (v) { v->SetData(1); - NS_ADDREF(*sessionState = v); + v.forget(sessionState); } } LOG((" nonce_count=%s\n", nonce_count)); diff --git a/netwerk/protocol/res/nsResProtocolHandler.cpp b/netwerk/protocol/res/nsResProtocolHandler.cpp index 2d67808929..231366eb13 100644 --- a/netwerk/protocol/res/nsResProtocolHandler.cpp +++ b/netwerk/protocol/res/nsResProtocolHandler.cpp @@ -233,10 +233,9 @@ nsResProtocolHandler::NewURI(const nsACString &aSpec, { nsresult rv; - nsResURL *resURL = new nsResURL(); + nsRefPtr resURL = new nsResURL(); if (!resURL) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(resURL); // unescape any %2f and %2e to make sure nsStandardURL coalesces them. // Later net_GetFileFromURLSpec() will do a full unescape and we want to @@ -268,9 +267,9 @@ nsResProtocolHandler::NewURI(const nsACString &aSpec, spec.Append(last, src-last); rv = resURL->Init(nsIStandardURL::URLTYPE_STANDARD, -1, spec, aCharset, aBaseURI); - if (NS_SUCCEEDED(rv)) - rv = CallQueryInterface(resURL, result); - NS_RELEASE(resURL); + if (NS_SUCCEEDED(rv)) { + resURL.forget(result); + } return rv; } diff --git a/netwerk/protocol/websocket/BaseWebSocketChannel.cpp b/netwerk/protocol/websocket/BaseWebSocketChannel.cpp index d8ff4009ad..010f45eae5 100644 --- a/netwerk/protocol/websocket/BaseWebSocketChannel.cpp +++ b/netwerk/protocol/websocket/BaseWebSocketChannel.cpp @@ -246,7 +246,7 @@ BaseWebSocketChannel::NewURI(const nsACString & aSpec, const char *aOriginCharse aOriginCharset, aBaseURI); if (NS_FAILED(rv)) return rv; - NS_ADDREF(*_retval = url); + url.forget(_retval); return NS_OK; } diff --git a/netwerk/protocol/wyciwyg/nsWyciwygProtocolHandler.cpp b/netwerk/protocol/wyciwyg/nsWyciwygProtocolHandler.cpp index 345b350992..7aaa89575c 100644 --- a/netwerk/protocol/wyciwyg/nsWyciwygProtocolHandler.cpp +++ b/netwerk/protocol/wyciwyg/nsWyciwygProtocolHandler.cpp @@ -76,8 +76,7 @@ nsWyciwygProtocolHandler::NewURI(const nsACString &aSpec, rv = url->SetSpec(aSpec); NS_ENSURE_SUCCESS(rv, rv); - *result = url; - NS_ADDREF(*result); + url.forget(result); return rv; } diff --git a/netwerk/streamconv/nsStreamConverterService.cpp b/netwerk/streamconv/nsStreamConverterService.cpp index c4997818c6..205d0a419c 100644 --- a/netwerk/streamconv/nsStreamConverterService.cpp +++ b/netwerk/streamconv/nsStreamConverterService.cpp @@ -454,9 +454,7 @@ nsStreamConverterService::Convert(nsIInputStream *aFromStream, } delete converterChain; - *_retval = convertedData; - NS_ADDREF(*_retval); - + convertedData.forget(_retval); } else { // we're going direct. rv = converter->Convert(aFromStream, aFromType, aToType, aContext, _retval); @@ -546,15 +544,11 @@ nsStreamConverterService::AsyncConvertData(const char *aFromType, } delete converterChain; // return the first listener in the chain. - *_retval = finalListener; - NS_ADDREF(*_retval); - + finalListener.forget(_retval); } else { // we're going direct. - *_retval = listener; - NS_ADDREF(*_retval); - rv = listener->AsyncConvertData(aFromType, aToType, aListener, aContext); + listener.forget(_retval); } return rv; diff --git a/netwerk/system/android/nsAndroidNetworkLinkService.cpp b/netwerk/system/android/nsAndroidNetworkLinkService.cpp index b7dbc85b2e..cbf71e336a 100644 --- a/netwerk/system/android/nsAndroidNetworkLinkService.cpp +++ b/netwerk/system/android/nsAndroidNetworkLinkService.cpp @@ -31,7 +31,7 @@ nsAndroidNetworkLinkService::GetIsLinkUp(bool *aIsUp) return NS_OK; } - *aIsUp = mozilla::widget::GoannaAppShell::IsNetworkLinkUp(); + *aIsUp = mozilla::widget::GeckoAppShell::IsNetworkLinkUp(); return NS_OK; } @@ -40,7 +40,7 @@ nsAndroidNetworkLinkService::GetLinkStatusKnown(bool *aIsKnown) { NS_ENSURE_TRUE(mozilla::AndroidBridge::Bridge(), NS_ERROR_NOT_IMPLEMENTED); - *aIsKnown = mozilla::widget::GoannaAppShell::IsNetworkLinkKnown(); + *aIsKnown = mozilla::widget::GeckoAppShell::IsNetworkLinkKnown(); return NS_OK; } @@ -56,6 +56,6 @@ nsAndroidNetworkLinkService::GetLinkType(uint32_t *aLinkType) return NS_OK; } - *aLinkType = mozilla::widget::GoannaAppShell::NetworkLinkType(); + *aLinkType = mozilla::widget::GeckoAppShell::NetworkLinkType(); return NS_OK; } diff --git a/security/manager/ssl/src/nsProtectedAuthThread.cpp b/security/manager/ssl/src/nsProtectedAuthThread.cpp index 609920c595..68f2e59b9c 100644 --- a/security/manager/ssl/src/nsProtectedAuthThread.cpp +++ b/security/manager/ssl/src/nsProtectedAuthThread.cpp @@ -4,7 +4,7 @@ #include "pk11func.h" #include "mozilla/DebugOnly.h" -#include "mozilla/RefPtr.h" +#include "mozilla/nsRefPtr.h" #include "nsCOMPtr.h" #include "PSMRunnable.h" #include "nsString.h" @@ -84,13 +84,14 @@ NS_IMETHODIMP nsProtectedAuthThread::GetTokenName(nsAString &_retval) NS_IMETHODIMP nsProtectedAuthThread::GetSlot(nsIPKCS11Slot **_retval) { - RefPtr slot; + nsRefPtr slot; { MutexAutoLock lock(mMutex); slot = new nsPKCS11Slot(mSlot); } - return CallQueryInterface (slot.get(), _retval); + slot.forget(_retval); + return NS_OK; } void nsProtectedAuthThread::SetParams(PK11SlotInfo* aSlot) diff --git a/testing/mozbase/mozcrash/mozcrash/mozcrash.py b/testing/mozbase/mozcrash/mozcrash/mozcrash.py index ecc35fc736..f029b0a229 100644 --- a/testing/mozbase/mozcrash/mozcrash/mozcrash.py +++ b/testing/mozbase/mozcrash/mozcrash/mozcrash.py @@ -316,10 +316,10 @@ def check_for_java_exception(logcat, quiet=False): for i, line in enumerate(logcat): # Logs will be of form: # - # 01-30 20:15:41.937 E/GoannaAppShell( 1703): >>> REPORTING UNCAUGHT EXCEPTION FROM THREAD 9 ("GoannaBackgroundThread") - # 01-30 20:15:41.937 E/GoannaAppShell( 1703): java.lang.NullPointerException - # 01-30 20:15:41.937 E/GoannaAppShell( 1703): at org.mozilla.goanna.GoannaApp$21.run(GoannaApp.java:1833) - # 01-30 20:15:41.937 E/GoannaAppShell( 1703): at android.os.Handler.handleCallback(Handler.java:587) + # 01-30 20:15:41.937 E/GeckoAppShell( 1703): >>> REPORTING UNCAUGHT EXCEPTION FROM THREAD 9 ("GoannaBackgroundThread") + # 01-30 20:15:41.937 E/GeckoAppShell( 1703): java.lang.NullPointerException + # 01-30 20:15:41.937 E/GeckoAppShell( 1703): at org.mozilla.goanna.GoannaApp$21.run(GoannaApp.java:1833) + # 01-30 20:15:41.937 E/GeckoAppShell( 1703): at android.os.Handler.handleCallback(Handler.java:587) if "REPORTING UNCAUGHT EXCEPTION" in line or "FATAL EXCEPTION" in line: # Strip away the date, time, logcat tag and pid from the next two lines and # concatenate the remainder to form a concise summary of the exception. diff --git a/testing/mozbase/mozcrash/tests/test.py b/testing/mozbase/mozcrash/tests/test.py index 7dd0f0a88a..c943a1c600 100644 --- a/testing/mozbase/mozcrash/tests/test.py +++ b/testing/mozbase/mozcrash/tests/test.py @@ -178,10 +178,10 @@ class TestCrash(unittest.TestCase): class TestJavaException(unittest.TestCase): def setUp(self): - self.test_log = ["01-30 20:15:41.937 E/GoannaAppShell( 1703): >>> REPORTING UNCAUGHT EXCEPTION FROM THREAD 9 (\"GoannaBackgroundThread\")", - "01-30 20:15:41.937 E/GoannaAppShell( 1703): java.lang.NullPointerException", - "01-30 20:15:41.937 E/GoannaAppShell( 1703): at org.mozilla.goanna.GoannaApp$21.run(GoannaApp.java:1833)", - "01-30 20:15:41.937 E/GoannaAppShell( 1703): at android.os.Handler.handleCallback(Handler.java:587)"] + self.test_log = ["01-30 20:15:41.937 E/GeckoAppShell( 1703): >>> REPORTING UNCAUGHT EXCEPTION FROM THREAD 9 (\"GoannaBackgroundThread\")", + "01-30 20:15:41.937 E/GeckoAppShell( 1703): java.lang.NullPointerException", + "01-30 20:15:41.937 E/GeckoAppShell( 1703): at org.mozilla.goanna.GoannaApp$21.run(GoannaApp.java:1833)", + "01-30 20:15:41.937 E/GeckoAppShell( 1703): at android.os.Handler.handleCallback(Handler.java:587)"] def test_uncaught_exception(self): """ @@ -194,7 +194,7 @@ class TestJavaException(unittest.TestCase): Test for an exception which should be caught """ fatal_log = list(self.test_log) - fatal_log[0] = "01-30 20:15:41.937 E/GoannaAppShell( 1703): >>> FATAL EXCEPTION FROM THREAD 9 (\"GoannaBackgroundThread\")" + fatal_log[0] = "01-30 20:15:41.937 E/GeckoAppShell( 1703): >>> FATAL EXCEPTION FROM THREAD 9 (\"GoannaBackgroundThread\")" self.assert_(mozcrash.check_for_java_exception(fatal_log, quiet=True)) def test_truncated_exception(self): @@ -211,7 +211,7 @@ class TestJavaException(unittest.TestCase): Test for an exception which should not be caught """ passable_log = list(self.test_log) - passable_log[0] = "01-30 20:15:41.937 E/GoannaAppShell( 1703): >>> NOT-SO-BAD EXCEPTION FROM THREAD 9 (\"GoannaBackgroundThread\")" + passable_log[0] = "01-30 20:15:41.937 E/GeckoAppShell( 1703): >>> NOT-SO-BAD EXCEPTION FROM THREAD 9 (\"GoannaBackgroundThread\")" self.assert_(not mozcrash.check_for_java_exception(passable_log, quiet=True)) if __name__ == '__main__': diff --git a/testing/web-platform/meta/html/browsers/the-window-object/window-properties.html.ini b/testing/web-platform/meta/html/browsers/the-window-object/window-properties.html.ini index 0d54dafc20..5f86b8fedb 100644 --- a/testing/web-platform/meta/html/browsers/the-window-object/window-properties.html.ini +++ b/testing/web-platform/meta/html/browsers/the-window-object/window-properties.html.ini @@ -1,44 +1,5 @@ [window-properties.html] type: testharness - [EventTarget method: addEventListener] - expected: FAIL - - [EventTarget method: removeEventListener] - expected: FAIL - - [EventTarget method: dispatchEvent] - expected: FAIL - - [Window readonly attribute: parent] - expected: FAIL - - [Window readonly attribute: external] - expected: FAIL - - [Window readonly attribute: innerWidth] - expected: FAIL - - [Window readonly attribute: innerHeight] - expected: FAIL - - [Window readonly attribute: scrollX] - expected: FAIL - - [Window readonly attribute: scrollY] - expected: FAIL - - [Window readonly attribute: screenX] - expected: FAIL - - [Window readonly attribute: screenY] - expected: FAIL - - [Window readonly attribute: outerWidth] - expected: FAIL - - [Window readonly attribute: outerHeight] - expected: FAIL - [Window attribute: oncancel] expected: FAIL diff --git a/testing/web-platform/meta/web-animations/animation-timeline/idlharness.html.ini b/testing/web-platform/meta/web-animations/animation-timeline/idlharness.html.ini new file mode 100644 index 0000000000..3091878efa --- /dev/null +++ b/testing/web-platform/meta/web-animations/animation-timeline/idlharness.html.ini @@ -0,0 +1,7 @@ +[idlharness.html] + type: testharness + [AnimationTimeline must be primary interface of document.timeline] + expected: FAIL + + [Stringification of document.timeline] + expected: FAIL diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-properties.html b/testing/web-platform/tests/html/browsers/the-window-object/window-properties.html index 843b671534..73ef77b4fe 100644 --- a/testing/web-platform/tests/html/browsers/the-window-object/window-properties.html +++ b/testing/web-platform/tests/html/browsers/the-window-object/window-properties.html @@ -42,7 +42,7 @@ var unforgeableAttributes = [ "top" ]; -var replacableAttributes = [ +var replaceableAttributes = [ "self", "locationbar", "menubar", @@ -51,7 +51,22 @@ var replacableAttributes = [ "statusbar", "toolbar", "frames", - "length" + "parent", + "external", + "length", + + // CSSOM-View + "screen", + "scrollX", + "scrollY", + "pageXOffset", + "pageYOffset", + "innerWidth", + "innerHeight", + "screenX", + "screenY", + "outerWidth", + "outerHeight", ]; var methods = [ @@ -98,10 +113,8 @@ if ("showModalDialog" in window) { var readonlyAttributes = [ "history", - "parent", "frameElement", "navigator", - "external", "applicationCache", // WindowSessionStorage @@ -109,19 +122,6 @@ var readonlyAttributes = [ // WindowLocalStorage "localStorage", - - // CSSOM-View - "screen", - "innerWidth", - "innerHeight", - "scrollX", - "pageXOffset", - "scrollY", - "pageYOffset", - "screenX", - "screenY", - "outerWidth", - "outerHeight" ]; var writableAttributes = [ @@ -259,8 +259,7 @@ test(function() { assert_equals(window[id], EventTargetProto[id]); assert_data_propdesc(Object.getOwnPropertyDescriptor(EventTargetProto, id), true, true, true); - assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id), - true, true, true); + assert_equals(Object.getOwnPropertyDescriptor(window, id), undefined); }, "EventTarget method: " + id); }); }, "EventTarget interface"); @@ -303,7 +302,7 @@ test(function() { id === "location", true, false); }, "Window unforgeable attribute: " + id); }); - replacableAttributes.forEach(function(id) { + replaceableAttributes.forEach(function(id) { test(function() { var WindowProto = Window.prototype; assert_true(id in window, id + " in window"); diff --git a/toolkit/components/alerts/nsAlertsService.cpp b/toolkit/components/alerts/nsAlertsService.cpp index 75b3a4ec16..f494b0cf16 100644 --- a/toolkit/components/alerts/nsAlertsService.cpp +++ b/toolkit/components/alerts/nsAlertsService.cpp @@ -135,7 +135,7 @@ NS_IMETHODIMP nsAlertsService::CloseAlert(const nsAString& aAlertName, } #ifdef MOZ_WIDGET_ANDROID - widget::GoannaAppShell::CloseNotification(aAlertName); + widget::GeckoAppShell::CloseNotification(aAlertName); return NS_OK; #else @@ -156,7 +156,7 @@ NS_IMETHODIMP nsAlertsService::OnProgress(const nsAString & aAlertName, const nsAString & aAlertText) { #ifdef MOZ_WIDGET_ANDROID - widget::GoannaAppShell::AlertsProgressListener_OnProgress(aAlertName, + widget::GeckoAppShell::AlertsProgressListener_OnProgress(aAlertName, aProgress, aProgressMax, aAlertText); return NS_OK; @@ -168,7 +168,7 @@ NS_IMETHODIMP nsAlertsService::OnProgress(const nsAString & aAlertName, NS_IMETHODIMP nsAlertsService::OnCancel(const nsAString & aAlertName) { #ifdef MOZ_WIDGET_ANDROID - widget::GoannaAppShell::CloseNotification(aAlertName); + widget::GeckoAppShell::CloseNotification(aAlertName); return NS_OK; #else return NS_ERROR_NOT_IMPLEMENTED; diff --git a/toolkit/components/commandlines/nsCommandLine.cpp b/toolkit/components/commandlines/nsCommandLine.cpp index d2b3a3273d..6ddf0d35f1 100644 --- a/toolkit/components/commandlines/nsCommandLine.cpp +++ b/toolkit/components/commandlines/nsCommandLine.cpp @@ -275,7 +275,7 @@ nsCommandLine::ResolveFile(const nsAString& aArgument, nsIFile* *aResult) CFRelease(newurl); if (NS_FAILED(rv)) return rv; - NS_ADDREF(*aResult = newfile); + newfile.forget(aResult); return NS_OK; #elif defined(XP_UNIX) @@ -306,7 +306,7 @@ nsCommandLine::ResolveFile(const nsAString& aArgument, nsIFile* *aResult) rv = lf->Normalize(); if (NS_FAILED(rv)) return rv; - NS_ADDREF(*aResult = lf); + lf.forget(aResult); return NS_OK; #elif defined(XP_WIN32) @@ -333,7 +333,7 @@ nsCommandLine::ResolveFile(const nsAString& aArgument, nsIFile* *aResult) rv = lf->InitWithPath(nsDependentString(pathBuf)); if (NS_FAILED(rv)) return rv; } - NS_ADDREF(*aResult = lf); + lf.forget(aResult); return NS_OK; #else diff --git a/toolkit/components/downloads/nsDownloadManager.cpp b/toolkit/components/downloads/nsDownloadManager.cpp index 0ddfb884ef..569f734549 100644 --- a/toolkit/components/downloads/nsDownloadManager.cpp +++ b/toolkit/components/downloads/nsDownloadManager.cpp @@ -1275,7 +1275,7 @@ nsDownloadManager::GetDownloadFromDB(mozIStorageConnection* aDBConn, } // Addrefing and returning - NS_ADDREF(*retVal = dl); + dl.forget(retVal); return NS_OK; } @@ -1670,7 +1670,7 @@ nsDownloadManager::AddDownload(DownloadType aDownloadType, } } - NS_ADDREF(*aDownload = dl); + dl.forget(aDownload); return NS_OK; } diff --git a/toolkit/components/filepicker/nsFileView.cpp b/toolkit/components/filepicker/nsFileView.cpp index 1864d690d1..f0e7a52fda 100644 --- a/toolkit/components/filepicker/nsFileView.cpp +++ b/toolkit/components/filepicker/nsFileView.cpp @@ -562,7 +562,7 @@ nsFileView::GetSelectedFiles(nsIArray** aFiles) } } - NS_ADDREF(*aFiles = fileArray); + fileArray.forget(aFiles); return NS_OK; } diff --git a/toolkit/components/places/SQLFunctions.cpp b/toolkit/components/places/SQLFunctions.cpp index 35b2affb8b..2b075f4570 100644 --- a/toolkit/components/places/SQLFunctions.cpp +++ b/toolkit/components/places/SQLFunctions.cpp @@ -716,7 +716,7 @@ namespace places { else { result->SetAsAString(EmptyString()); } - NS_ADDREF(*_result = result); + result.forget(_result); return NS_OK; } @@ -771,7 +771,7 @@ namespace places { } result->SetAsAString(src); - NS_ADDREF(*_result = result); + result.forget(_result); return NS_OK; } @@ -833,7 +833,7 @@ namespace places { NS_ENSURE_STATE(result); rv = result->SetAsInt32(newFrecency); NS_ENSURE_SUCCESS(rv, rv); - NS_ADDREF(*_result = result); + result.forget(_result); return NS_OK; } diff --git a/toolkit/components/places/nsAnnotationService.cpp b/toolkit/components/places/nsAnnotationService.cpp index 0563c4924b..b74bcac73e 100644 --- a/toolkit/components/places/nsAnnotationService.cpp +++ b/toolkit/components/places/nsAnnotationService.cpp @@ -667,8 +667,9 @@ nsAnnotationService::GetPageAnnotation(nsIURI* aURI, } } - if (NS_SUCCEEDED(rv)) - NS_ADDREF(*_retval = value); + if (NS_SUCCEEDED(rv)) { + value.forget(_retval); + } return rv; } @@ -711,8 +712,9 @@ nsAnnotationService::GetItemAnnotation(int64_t aItemId, } } - if (NS_SUCCEEDED(rv)) - NS_ADDREF(*_retval = value); + if (NS_SUCCEEDED(rv)) { + value.forget(_retval); + } return rv; } diff --git a/toolkit/components/places/nsNavHistoryQuery.cpp b/toolkit/components/places/nsNavHistoryQuery.cpp index 09536e3fb0..790302274d 100644 --- a/toolkit/components/places/nsNavHistoryQuery.cpp +++ b/toolkit/components/places/nsNavHistoryQuery.cpp @@ -282,7 +282,7 @@ nsNavHistory::QueryStringToQueries(const nsACString& aQueryString, NS_ADDREF((*aQueries)[i]); } } - NS_ADDREF(*aOptions = options); + options.forget(aOptions); return NS_OK; } @@ -316,7 +316,7 @@ nsNavHistory::QueryStringToQueryArray(const nsACString& aQueryString, return rv; } - NS_ADDREF(*aOptions = options); + options.forget(aOptions); return NS_OK; } @@ -1163,7 +1163,7 @@ NS_IMETHODIMP nsNavHistoryQuery::GetTags(nsIVariant **aTags) } NS_ENSURE_SUCCESS(rv, rv); - NS_ADDREF(*aTags = out); + out.forget(aTags); return NS_OK; } diff --git a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp index 03abd19adc..dd581c4e47 100644 --- a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp +++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp @@ -819,11 +819,8 @@ nsTypeAheadFind::GetSearchContainers(nsISupports *aContainer, mStartPointRange->Collapse(true); // collapse to start - *aPresShell = presShell; - NS_ADDREF(*aPresShell); - - *aPresContext = presContext; - NS_ADDREF(*aPresContext); + presShell.forget(aPresShell); + presContext.forget(aPresContext); return NS_OK; } diff --git a/toolkit/devtools/framework/test/browser.ini b/toolkit/devtools/framework/test/browser.ini index 5d0234b86d..3f9327c656 100644 --- a/toolkit/devtools/framework/test/browser.ini +++ b/toolkit/devtools/framework/test/browser.ini @@ -8,6 +8,8 @@ support-files = head.js helper_disable_cache.js doc_theme.css + browser_toolbox_options_enable_serviceworkers_testing.html + serviceworker.js [browser_devtools_api.js] [browser_devtools_api_destroy.js] @@ -51,5 +53,7 @@ skip-if = os == "mac" && os_version == "10.8" || os == "win" && os_version == "5 [browser_toolbox_zoom.js] [browser_toolbox_custom_host.js] [browser_toolbox_theme_registration.js] +[browser_toolbox_options_enable_serviceworkers_testing.js] +skip-if = e10s # Bug 1030318 diff --git a/toolkit/devtools/framework/test/browser_toolbox_options_enable_serviceworkers_testing.html b/toolkit/devtools/framework/test/browser_toolbox_options_enable_serviceworkers_testing.html new file mode 100644 index 0000000000..4c9801b48c --- /dev/null +++ b/toolkit/devtools/framework/test/browser_toolbox_options_enable_serviceworkers_testing.html @@ -0,0 +1,58 @@ + + + + browser_toolbox_options_enable_serviceworkers_testing.html + + + + + +

Test in page

+ +
+
No output
+ + diff --git a/toolkit/devtools/framework/test/browser_toolbox_options_enable_serviceworkers_testing.js b/toolkit/devtools/framework/test/browser_toolbox_options_enable_serviceworkers_testing.js new file mode 100644 index 0000000000..2530a4d167 --- /dev/null +++ b/toolkit/devtools/framework/test/browser_toolbox_options_enable_serviceworkers_testing.js @@ -0,0 +1,124 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that enabling Service Workers testing option enables the +// mServiceWorkersTestingEnabled attribute added to nsPIDOMWindow. + +const TEST_URI = URL_ROOT + + "browser_toolbox_options_enable_serviceworkers_testing.html"; + +const ELEMENT_ID = "devtools-enable-serviceWorkersTesting"; + +let toolbox; +let doc; + +function test() { + // Note: Pref dom.serviceWorkers.testing.enabled is false since we are testing + // the same capabilities are enabled with the devtool pref. + SpecialPowers.pushPrefEnv({"set": [ + ["dom.serviceWorkers.exemptFromPerDomainMax", true], + ["dom.serviceWorkers.enabled", true], + ["dom.serviceWorkers.testing.enabled", false] + ]}, start); +} + +function start() { + gBrowser.selectedTab = gBrowser.addTab(); + let target = TargetFactory.forTab(gBrowser.selectedTab); + + gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) { + gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true); + doc = content.document; + gDevTools.showToolbox(target).then(testSelectTool); + }, true); + + content.location = TEST_URI; +} + +function testSelectTool(aToolbox) { + toolbox = aToolbox; + toolbox.once("options-selected", testRegisterFails); + toolbox.selectTool("options"); +} + +function testRegisterFails() { + let output = doc.getElementById("output"); + let button = doc.getElementById("button"); + + function doTheCheck() { + info("Testing it doesn't registers correctly until enable testing"); + is(output.textContent, + "SecurityError", + "SecurityError expected"); + testRegisterInstallingWorker(); + } + + if (output.textContent !== "No output") { + doTheCheck(); + } + + button.addEventListener('click', function onClick() { + button.removeEventListener('click', onClick); + doTheCheck(); + }); +} + +function testRegisterInstallingWorker() { + toggleServiceWorkersTestingCheckbox().then(() => { + let output = doc.getElementById("output"); + let button = doc.getElementById("button"); + + function doTheCheck() { + info("Testing it registers correctly and there is an installing worker"); + is(output.textContent, + "Installing worker/", + "Installing worker expected"); + toggleServiceWorkersTestingCheckbox().then(finishUp); + } + + if (output.textContent !== "No output") { + doTheCheck(); + } + + button.addEventListener('click', function onClick() { + button.removeEventListener('click', onClick); + doTheCheck(); + }); + }); +} + +function toggleServiceWorkersTestingCheckbox() { + let deferred = promise.defer(); + + let panel = toolbox.getCurrentPanel(); + let cbx = panel.panelDoc.getElementById(ELEMENT_ID); + + cbx.scrollIntoView(); + + if (cbx.checked) { + info("Clearing checkbox to disable service workers testing"); + } else { + info("Checking checkbox to enable service workers testing"); + } + + gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) { + gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true); + doc = content.document; + deferred.resolve(); + }, true); + + cbx.click(); + + let mm = getFrameScript(); + mm.sendAsyncMessage("devtools:test:reload"); + + return deferred.promise; +} + +function finishUp() { + toolbox.destroy().then(function() { + gBrowser.removeCurrentTab(); + toolbox = doc = null; + finish(); + }); +} diff --git a/toolkit/devtools/framework/test/serviceworker.js b/toolkit/devtools/framework/test/serviceworker.js new file mode 100644 index 0000000000..5f23cd547e --- /dev/null +++ b/toolkit/devtools/framework/test/serviceworker.js @@ -0,0 +1 @@ +// empty service worker, always succeed! diff --git a/toolkit/devtools/framework/toolbox-options.js b/toolkit/devtools/framework/toolbox-options.js index 543f37fb36..9cfb109dc9 100644 --- a/toolkit/devtools/framework/toolbox-options.js +++ b/toolkit/devtools/framework/toolbox-options.js @@ -370,7 +370,7 @@ OptionsPanel.prototype = { if (this.target.activeTab) { this.target.client.attachTab(this.target.activeTab._actor, (response) => { this._origJavascriptEnabled = response.javascriptEnabled; - this.disableJSNode.checked = !this._origJavascriptEnabled + this.disableJSNode.checked = !this._origJavascriptEnabled; this.disableJSNode.addEventListener("click", this._disableJSClicked, false); }); } else { diff --git a/toolkit/devtools/framework/toolbox-options.xul b/toolkit/devtools/framework/toolbox-options.xul index b80e961ffc..7ed5c0d273 100644 --- a/toolkit/devtools/framework/toolbox-options.xul +++ b/toolkit/devtools/framework/toolbox-options.xul @@ -148,6 +148,10 @@ + { + toolboxFirstTab = aToolbox; + }); + is(gProfilerConnections, 1, "A shared profiler connection should have been created."); @@ -25,14 +29,21 @@ let test = Task.async(function*() { let secondTarget = TargetFactory.forTab(secondTab); yield secondTarget.makeRemote(); - yield gDevTools.showToolbox(secondTarget, "jsprofiler"); + let toolboxSecondTab; + yield gDevTools.showToolbox(secondTarget, "jsprofiler").then((aToolbox) => { + toolboxSecondTab = aToolbox; + }); + is(gProfilerConnections, 2, "Only one new profiler connection should have been created."); - yield removeTab(firstTab); - yield removeTab(secondTab); - - finish(); + yield toolboxFirstTab.destroy().then(() => { + removeTab(firstTab); + }); + yield toolboxSecondTab.destroy().then(() => { + removeTab(secondTab); + finish(); + }); }); function profilerConnectionObserver(subject, topic, data) { diff --git a/toolkit/devtools/server/actors/animation.js b/toolkit/devtools/server/actors/animation.js index 26ceadc3df..009adb0ac6 100644 --- a/toolkit/devtools/server/actors/animation.js +++ b/toolkit/devtools/server/actors/animation.js @@ -59,7 +59,7 @@ let AnimationPlayerActor = ActorClass({ Actor.prototype.initialize.call(this, animationsActor.conn); this.player = player; - this.node = player.source.target; + this.node = player.effect.target; this.playerIndex = playerIndex; this.styles = this.node.ownerDocument.defaultView.getComputedStyle(this.node); }, @@ -115,7 +115,7 @@ let AnimationPlayerActor = ActorClass({ // the list. names = names.split(",").map(n => n.trim()); for (let i = 0; i < names.length; i ++) { - if (names[i] === this.player.source.effect.name) { + if (names[i] === this.player.effect.name) { return i; } } @@ -207,7 +207,7 @@ let AnimationPlayerActor = ActorClass({ currentTime: this.player.currentTime, playState: this.player.playState, playbackRate: this.player.playbackRate, - name: this.player.source.effect.name, + name: this.player.effect.name, duration: this.getDuration(), delay: this.getDelay(), iterationCount: this.getIterationCount(), @@ -557,7 +557,7 @@ let AnimationsActor = exports.AnimationsActor = ActorClass({ continue; } let actor = AnimationPlayerActor( - this, player, player.source.target.getAnimations().indexOf(player)); + this, player, player.effect.target.getAnimations().indexOf(player)); this.actors.push(actor); eventData.push({ type: "added", diff --git a/toolkit/devtools/server/actors/webbrowser.js b/toolkit/devtools/server/actors/webbrowser.js index a1c6462adb..78f2886f57 100644 --- a/toolkit/devtools/server/actors/webbrowser.js +++ b/toolkit/devtools/server/actors/webbrowser.js @@ -1169,14 +1169,14 @@ TabActor.prototype = { onReconfigure: function (aRequest) { let options = aRequest.options || {}; - this._toggleJsOrCache(options); + this._toggleDevtoolsSettings(options); return {}; }, /** - * Handle logic to enable/disable JS/cache. + * Handle logic to enable/disable JS/cache/Service Worker testing. */ - _toggleJsOrCache: function(options) { + _toggleDevtoolsSettings: function(options) { // Wait a tick so that the response packet can be dispatched before the // subsequent navigation event packet. let reload = false; @@ -1190,6 +1190,13 @@ TabActor.prototype = { options.cacheDisabled !== this._getCacheDisabled()) { this._setCacheDisabled(options.cacheDisabled); } + if ((typeof options.serviceWorkersTestingEnabled !== "undefined") && + (options.serviceWorkersTestingEnabled !== + this._getServiceWorkersTestingEnabled())) { + this._setServiceWorkersTestingEnabled( + options.serviceWorkersTestingEnabled + ); + } // Reload if: // - there's an explicit `performReload` flag and it's true @@ -1223,6 +1230,20 @@ TabActor.prototype = { } }, + /** + * Disable or enable the service workers testing features. + */ + _setServiceWorkersTestingEnabled: function(enabled) { + if (!this.docShell) { + // The tab is already closed. + return null; + } + + let windowUtils = this.window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + windowUtils.serviceWorkersTestingEnabled = enabled; + }, + /** * Return cache allowed status. */ @@ -1249,6 +1270,20 @@ TabActor.prototype = { return this.docShell.allowJavascript; }, + /** + * Return service workers testing allowed status. + */ + _getServiceWorkersTestingEnabled: function() { + if (!this.docShell) { + // The tab is already closed. + return null; + } + + let windowUtils = this.window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + return windowUtils.serviceWorkersTestingEnabled; + }, + /** * Prepare to enter a nested event loop by disabling debuggee events. */ diff --git a/toolkit/locales/en-US/chrome/global/devtools/toolbox.dtd b/toolkit/locales/en-US/chrome/global/devtools/toolbox.dtd index 1823170eb4..ac06f7aa25 100644 --- a/toolkit/locales/en-US/chrome/global/devtools/toolbox.dtd +++ b/toolkit/locales/en-US/chrome/global/devtools/toolbox.dtd @@ -93,6 +93,12 @@ + + + + diff --git a/toolkit/modules/sessionstore/FormData.jsm b/toolkit/modules/sessionstore/FormData.jsm index 0180acbe62..3d8983cbf4 100644 --- a/toolkit/modules/sessionstore/FormData.jsm +++ b/toolkit/modules/sessionstore/FormData.jsm @@ -328,7 +328,12 @@ let FormDataInternal = { } } else if (aValue && aValue.fileList && aValue.type == "file" && aNode.type == "file") { - aNode.mozSetFileNameArray(aValue.fileList, aValue.fileList.length); + try { + // FIXME (bug 1122855): This won't work in content processes. + aNode.mozSetFileNameArray(aValue.fileList, aValue.fileList.length); + } catch (e) { + Cu.reportError("mozSetFileNameArray: " + e); + } eventType = "input"; } else if (Array.isArray(aValue) && aNode.options) { Array.forEach(aNode.options, function(opt, index) { diff --git a/toolkit/mozapps/update/common/errors.h b/toolkit/mozapps/update/common/errors.h index c284fd481b..8bd10a3f5f 100644 --- a/toolkit/mozapps/update/common/errors.h +++ b/toolkit/mozapps/update/common/errors.h @@ -53,28 +53,40 @@ #define SERVICE_UPDATER_NOT_FIXED_DRIVE 31 #define SERVICE_COULD_NOT_LOCK_UPDATER 32 #define SERVICE_INSTALLDIR_ERROR 33 -#define SERVICE_COULD_NOT_COPY_UPDATER 49 #define NO_INSTALLDIR_ERROR 34 #define WRITE_ERROR_ACCESS_DENIED 35 // #define WRITE_ERROR_SHARING_VIOLATION 36 // Replaced with errors 46-48 #define WRITE_ERROR_CALLBACK_APP 37 -#define INVALID_UPDATER_STATUS_CODE 38 #define UNEXPECTED_BZIP_ERROR 39 #define UNEXPECTED_MAR_ERROR 40 #define UNEXPECTED_BSPATCH_ERROR 41 #define UNEXPECTED_FILE_OPERATION_ERROR 42 #define FILESYSTEM_MOUNT_READWRITE_ERROR 43 -#define FOTA_GENERAL_ERROR 44 -#define FOTA_UNKNOWN_ERROR 45 -#define WRITE_ERROR_SHARING_VIOLATION_SIGNALED 46 -#define WRITE_ERROR_SHARING_VIOLATION_NOPROCESSFORPID 47 -#define WRITE_ERROR_SHARING_VIOLATION_NOPID 48 +#define DELETE_ERROR_EXPECTED_DIR 46 +#define DELETE_ERROR_EXPECTED_FILE 47 +#define RENAME_ERROR_EXPECTED_FILE 48 + +// Error codes 24-33 and 49 are for the Windows maintenance service. +#define SERVICE_COULD_NOT_COPY_UPDATER 49 + +#define WRITE_ERROR_FILE_COPY 61 +#define WRITE_ERROR_DELETE_FILE 62 +#define WRITE_ERROR_OPEN_PATCH_FILE 63 +#define WRITE_ERROR_PATCH_FILE 64 +#define WRITE_ERROR_APPLY_DIR_PATH 65 +#define WRITE_ERROR_CALLBACK_PATH 66 +#define WRITE_ERROR_FILE_ACCESS_DENIED 67 +#define WRITE_ERROR_DIR_ACCESS_DENIED 68 +#define WRITE_ERROR_DELETE_BACKUP 69 +#define WRITE_ERROR_EXTRACT 70 #define REMOVE_FILE_SPEC_ERROR 71 #define INVALID_STAGED_PARENT_ERROR 72 +// Error codes 80 through 99 are reserved for nsUpdateService.js + // The following error codes are only used by updater.exe -// when a fallback key exists and XPCShell tests are being run. +// when a fallback key exists for tests. #define FALLBACKKEY_UNKNOWN_ERROR 100 #define FALLBACKKEY_REGPATH_ERROR 101 #define FALLBACKKEY_NOKEY_ERROR 102 diff --git a/toolkit/profile/nsToolkitProfileService.cpp b/toolkit/profile/nsToolkitProfileService.cpp index eebf078ebd..e318b64623 100644 --- a/toolkit/profile/nsToolkitProfileService.cpp +++ b/toolkit/profile/nsToolkitProfileService.cpp @@ -676,7 +676,7 @@ NS_LockProfilePath(nsIFile* aPath, nsIFile* aTempPath, nsresult rv = lock->Init(aPath, aTempPath, aUnlocker); if (NS_FAILED(rv)) return rv; - NS_ADDREF(*aResult = lock); + lock.forget(aResult); return NS_OK; } @@ -904,7 +904,7 @@ nsToolkitProfileService::CreateProfileInternal(nsIFile* aRootDir, new nsToolkitProfile(aName, rootDir, localDir, last, aForExternalApp); if (!profile) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*aResult = profile); + profile.forget(aResult); return NS_OK; } @@ -1108,8 +1108,9 @@ XRE_GetFileFromPath(const char *aPath, nsIFile* *aResult) nsCOMPtr lfMac = do_QueryInterface(lf, &rv); if (NS_SUCCEEDED(rv)) { rv = lfMac->InitWithCFURL(fullPath); - if (NS_SUCCEEDED(rv)) - NS_ADDREF(*aResult = lf); + if (NS_SUCCEEDED(rv)) { + lf.forget(aResult); + } } } CFRelease(fullPath); diff --git a/toolkit/system/gnome/nsGConfService.cpp b/toolkit/system/gnome/nsGConfService.cpp index 9c94535534..5e7d9ed9c8 100644 --- a/toolkit/system/gnome/nsGConfService.cpp +++ b/toolkit/system/gnome/nsGConfService.cpp @@ -190,7 +190,7 @@ nsGConfService::GetStringList(const nsACString &aKey, nsIArray** aResult) } g_slist_free(list); - NS_ADDREF(*aResult = items); + items.forget(aResult); return NS_OK; } diff --git a/toolkit/system/gnome/nsGIOService.cpp b/toolkit/system/gnome/nsGIOService.cpp index 53cead7f77..3033f9310d 100644 --- a/toolkit/system/gnome/nsGIOService.cpp +++ b/toolkit/system/gnome/nsGIOService.cpp @@ -142,7 +142,7 @@ nsGIOMimeApp::GetSupportedURISchemes(nsIUTF8StringEnumerator** aSchemes) uri_schemes++; } - NS_ADDREF(*aSchemes = array); + array.forget(aSchemes); return NS_OK; } diff --git a/toolkit/system/gnome/nsGSettingsService.cpp b/toolkit/system/gnome/nsGSettingsService.cpp index a697d9f5e8..669104a2fc 100644 --- a/toolkit/system/gnome/nsGSettingsService.cpp +++ b/toolkit/system/gnome/nsGSettingsService.cpp @@ -272,7 +272,7 @@ nsGSettingsCollection::GetStringList(const nsACString& aKey, nsIArray** aResult) const gchar ** gs_strings = g_variant_get_strv(value, nullptr); if (!gs_strings) { // empty array - NS_ADDREF(*aResult = items); + items.forget(aResult); g_variant_unref(value); return NS_OK; } @@ -288,7 +288,7 @@ nsGSettingsCollection::GetStringList(const nsACString& aKey, nsIArray** aResult) p_gs_strings++; } g_free(gs_strings); - NS_ADDREF(*aResult = items); + items.forget(aResult); g_variant_unref(value); return NS_OK; } diff --git a/toolkit/xre/nsAndroidStartup.cpp b/toolkit/xre/nsAndroidStartup.cpp index 59cea09255..678f58df3d 100644 --- a/toolkit/xre/nsAndroidStartup.cpp +++ b/toolkit/xre/nsAndroidStartup.cpp @@ -65,7 +65,7 @@ GoannaStart(void *data, const nsXREAppData *appData) if (result) LOG("XRE_main returned %d", result); - mozilla::widget::GoannaAppShell::NotifyXreExit(); + mozilla::widget::GeckoAppShell::NotifyXreExit(); free(targs[0]); free(data); diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 276f961772..0fceafa57c 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -1549,7 +1549,7 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative, SaveToEnv("MOZ_LAUNCHED_CHILD=1"); #if defined(MOZ_WIDGET_ANDROID) - mozilla::widget::GoannaAppShell::ScheduleRestart(); + mozilla::widget::GeckoAppShell::ScheduleRestart(); #else #if defined(XP_MACOSX) CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true); @@ -1687,7 +1687,7 @@ ProfileLockedDialog(nsIFile* aProfileDir, nsIFile* aProfileLocalDir, if (aUnlocker) { int32_t button; #ifdef MOZ_WIDGET_ANDROID - mozilla::widget::GoannaAppShell::KillAnyZombies(); + mozilla::widget::GeckoAppShell::KillAnyZombies(); button = 0; #else const uint32_t flags = @@ -1716,7 +1716,7 @@ ProfileLockedDialog(nsIFile* aProfileDir, nsIFile* aProfileLocalDir, } } else { #ifdef MOZ_WIDGET_ANDROID - if (mozilla::widget::GoannaAppShell::UnlockProfile()) { + if (mozilla::widget::GeckoAppShell::UnlockProfile()) { return NS_LockProfilePath(aProfileDir, aProfileLocalDir, nullptr, aResult); } diff --git a/toolkit/xre/nsUpdateDriver.cpp b/toolkit/xre/nsUpdateDriver.cpp index 403ee74c68..86f1cd6939 100644 --- a/toolkit/xre/nsUpdateDriver.cpp +++ b/toolkit/xre/nsUpdateDriver.cpp @@ -194,7 +194,7 @@ GetXULRunnerStubPath(const char* argv0, nsIFile* *aResult) if (NS_FAILED(rv)) return rv; - NS_ADDREF(*aResult = static_cast(lfm.get())); + lfm.forget(aResult); return NS_OK; } #endif /* XP_MACOSX */ diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp index c1df66f0b2..44933c0f84 100644 --- a/toolkit/xre/nsXREDirProvider.cpp +++ b/toolkit/xre/nsXREDirProvider.cpp @@ -393,7 +393,7 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent, } if (NS_SUCCEEDED(rv) && file) { - NS_ADDREF(*aFile = file); + file.forget(aFile); return NS_OK; } @@ -456,7 +456,7 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent, } } - NS_ADDREF(*aFile = file); + file.forget(aFile); return NS_OK; } @@ -522,7 +522,7 @@ nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult) appEnum = nullptr; } else if (rv != NS_SUCCESS_AGGREGATE_RESULT) { - NS_ADDREF(*aResult = appEnum); + appEnum.forget(aResult); return NS_OK; } } @@ -531,7 +531,7 @@ nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult) rv = GetFilesInternal(aProperty, getter_AddRefs(xreEnum)); if (NS_FAILED(rv)) { if (appEnum) { - NS_ADDREF(*aResult = appEnum); + appEnum.forget(aResult); return NS_SUCCESS_AGGREGATE_RESULT; } @@ -1065,7 +1065,7 @@ nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult) return NS_ERROR_FAILURE; } - NS_ADDREF(*aResult = localDir); + localDir.forget(aResult); return NS_OK; #elif XP_WIN @@ -1105,7 +1105,7 @@ nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult) gAppData->vendor : gAppData->name))) && NS_SUCCEEDED(localDir->Append(NS_LITERAL_STRING("updates"))) && NS_SUCCEEDED(localDir->Append(pathHash))) { - NS_ADDREF(*aResult = localDir); + localDir.forget(aResult); return NS_OK; } @@ -1158,7 +1158,7 @@ nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult) #endif // XP_WIN #endif - NS_ADDREF(*aResult = updRoot); + updRoot.forget(aResult); return NS_OK; } @@ -1302,7 +1302,7 @@ nsXREDirProvider::GetSysUserExtensionsDirectory(nsIFile** aFile) rv = EnsureDirectoryExists(localDir); NS_ENSURE_SUCCESS(rv, rv); - NS_ADDREF(*aFile = localDir); + localDir.forget(aFile); return NS_OK; } @@ -1350,7 +1350,7 @@ nsXREDirProvider::GetSystemExtensionsDirectory(nsIFile** aFile) NS_ENSURE_SUCCESS(rv, rv); #endif - NS_ADDREF(*aFile = localDir); + localDir.forget(aFile); return NS_OK; } #endif @@ -1376,7 +1376,7 @@ nsXREDirProvider::GetUserDataDirectory(nsIFile** aFile, bool aLocal, rv = EnsureDirectoryExists(localDir); NS_ENSURE_SUCCESS(rv, rv); - NS_ADDREF(*aFile = localDir); + localDir.forget(aFile); return NS_OK; } @@ -1444,7 +1444,7 @@ nsXREDirProvider::GetProfileDefaultsDir(nsIFile* *aResult) rv = defaultsDir->AppendNative(NS_LITERAL_CSTRING("profile")); NS_ENSURE_SUCCESS(rv, rv); - NS_ADDREF(*aResult = defaultsDir); + defaultsDir.forget(aResult); return NS_OK; } diff --git a/tools/profiler/platform.cpp b/tools/profiler/platform.cpp index b7bd8a49a6..c83c5274ed 100644 --- a/tools/profiler/platform.cpp +++ b/tools/profiler/platform.cpp @@ -70,7 +70,7 @@ static mozilla::StaticAutoPtr // The name that identifies the goanna thread for calls to // profiler_register_thread. -static const char * gGoannaThreadName = "GoannaMain"; +static const char * gGeckoThreadName = "GoannaMain"; void Sampler::Startup() { sRegisteredThreads = new std::vector(); @@ -426,7 +426,7 @@ bool is_main_thread_name(const char* aName) { if (!aName) { return false; } - return strcmp(aName, gGoannaThreadName) == 0; + return strcmp(aName, gGeckoThreadName) == 0; } #ifdef HAVE_VA_COPY @@ -492,7 +492,7 @@ void mozilla_sampler_init(void* stackTop) bool isMainThread = true; Sampler::RegisterCurrentThread(isMainThread ? - gGoannaThreadName : "Application Thread", + gGeckoThreadName : "Application Thread", stack, isMainThread, stackTop); // Read mode settings from MOZ_PROFILER_MODE and interval diff --git a/uriloader/exthandler/android/nsAndroidHandlerApp.cpp b/uriloader/exthandler/android/nsAndroidHandlerApp.cpp index bb3d84d53b..9feb918f4a 100644 --- a/uriloader/exthandler/android/nsAndroidHandlerApp.cpp +++ b/uriloader/exthandler/android/nsAndroidHandlerApp.cpp @@ -76,7 +76,7 @@ nsAndroidHandlerApp::LaunchWithURI(nsIURI *aURI, nsIInterfaceRequestor *aWindowC { nsCString uriSpec; aURI->GetSpec(uriSpec); - return widget::GoannaAppShell::OpenUriExternal( + return widget::GeckoAppShell::OpenUriExternal( uriSpec, mMimeType, mPackageName, mClassName, mAction, EmptyString()) ? NS_OK : NS_ERROR_FAILURE; } @@ -84,7 +84,7 @@ nsAndroidHandlerApp::LaunchWithURI(nsIURI *aURI, nsIInterfaceRequestor *aWindowC NS_IMETHODIMP nsAndroidHandlerApp::Share(const nsAString & data, const nsAString & title) { - return widget::GoannaAppShell::OpenUriExternal( + return widget::GeckoAppShell::OpenUriExternal( data, mMimeType, mPackageName, mClassName, mAction, EmptyString()) ? NS_OK : NS_ERROR_FAILURE; } diff --git a/uriloader/exthandler/android/nsExternalSharingAppService.cpp b/uriloader/exthandler/android/nsExternalSharingAppService.cpp index 771c01299d..c6a67f2cc6 100644 --- a/uriloader/exthandler/android/nsExternalSharingAppService.cpp +++ b/uriloader/exthandler/android/nsExternalSharingAppService.cpp @@ -31,7 +31,7 @@ nsExternalSharingAppService::ShareWithDefault(const nsAString & data, { NS_NAMED_LITERAL_STRING(sendAction, "android.intent.action.SEND"); const nsString emptyString = EmptyString(); - return widget::GoannaAppShell::OpenUriExternal(data, + return widget::GeckoAppShell::OpenUriExternal(data, mime, emptyString, emptyString, sendAction, title) ? NS_OK : NS_ERROR_FAILURE; } diff --git a/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp b/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp index 2f5820129c..2ffedb613c 100644 --- a/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp +++ b/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp @@ -36,7 +36,7 @@ nsMIMEInfoAndroid::LoadUriInternal(nsIURI * aURI) mimeType = NS_ConvertUTF8toUTF16(mType); } - if (widget::GoannaAppShell::OpenUriExternal( + if (widget::GeckoAppShell::OpenUriExternal( NS_ConvertUTF8toUTF16(uriSpec), mimeType, EmptyString(), EmptyString(), EmptyString(), EmptyString())) { return NS_OK; diff --git a/widget/cocoa/nsAppShell.h b/widget/cocoa/nsAppShell.h index 10655376ec..d9af98f413 100644 --- a/widget/cocoa/nsAppShell.h +++ b/widget/cocoa/nsAppShell.h @@ -50,7 +50,7 @@ protected: virtual void ScheduleNativeEventCallback(); virtual bool ProcessNextNativeEvent(bool aMayWait); - static void ProcessGoannaEvents(void* aInfo); + static void ProcessGeckoEvents(void* aInfo); protected: CFMutableArrayRef mAutoreleasePools; diff --git a/widget/cocoa/nsAppShell.mm b/widget/cocoa/nsAppShell.mm index 3648cd25dc..eb9389dea6 100644 --- a/widget/cocoa/nsAppShell.mm +++ b/widget/cocoa/nsAppShell.mm @@ -291,7 +291,7 @@ nsAppShell::Init() bzero(&context, sizeof(context)); // context.version = 0; context.info = this; - context.perform = ProcessGoannaEvents; + context.perform = ProcessGeckoEvents; mCFRunLoopSource = ::CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context); NS_ENSURE_STATE(mCFRunLoopSource); @@ -327,7 +327,7 @@ nsAppShell::Init() NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } -// ProcessGoannaEvents +// ProcessGeckoEvents // // The "perform" target of mCFRunLoop, called when mCFRunLoopSource is // signalled from ScheduleNativeEventCallback. @@ -338,10 +338,10 @@ nsAppShell::Init() // // protected static void -nsAppShell::ProcessGoannaEvents(void* aInfo) +nsAppShell::ProcessGeckoEvents(void* aInfo) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - PROFILER_LABEL("Events", "ProcessGoannaEvents", + PROFILER_LABEL("Events", "ProcessGeckoEvents", js::ProfileEntry::Category::EVENTS); nsAppShell* self = static_cast (aInfo); @@ -394,10 +394,10 @@ nsAppShell::ProcessGoannaEvents(void* aInfo) atStart:NO]; // Normally every call to ScheduleNativeEventCallback() results in - // exactly one call to ProcessGoannaEvents(). So each Release() here + // exactly one call to ProcessGeckoEvents(). So each Release() here // normally balances exactly one AddRef() in ScheduleNativeEventCallback(). // But if Exit() is called just after ScheduleNativeEventCallback(), the - // corresponding call to ProcessGoannaEvents() will never happen. We check + // corresponding call to ProcessGeckoEvents() will never happen. We check // for this possibility in two different places -- here and in Exit() // itself. If we find here that Exit() has been called (that mTerminated // is true), it's because we've been called recursively, that Exit() was @@ -405,7 +405,7 @@ nsAppShell::ProcessGoannaEvents(void* aInfo) // the recursion. In this case we'll never be called again, and we balance // here any extra calls to ScheduleNativeEventCallback(). // - // When ProcessGoannaEvents() is called recursively, it's because of a + // When ProcessGeckoEvents() is called recursively, it's because of a // call to ScheduleNativeEventCallback() from NativeEventCallback(). We // balance the "extra" AddRefs here (rather than always in Exit()) in order // to ensure that 'self' stays alive until the end of this method. We also @@ -420,14 +420,14 @@ nsAppShell::ProcessGoannaEvents(void* aInfo) while (releaseCount-- > self->mNativeEventCallbackDepth) self->Release(); } else { - // As best we can tell, every call to ProcessGoannaEvents() is triggered + // As best we can tell, every call to ProcessGeckoEvents() is triggered // by a call to ScheduleNativeEventCallback(). But we've seen a few // (non-reproducible) cases of double-frees that *might* have been caused - // by spontaneous calls (from the OS) to ProcessGoannaEvents(). So we + // by spontaneous calls (from the OS) to ProcessGeckoEvents(). So we // deal with that possibility here. if (PR_ATOMIC_DECREMENT(&self->mNativeEventScheduledDepth) < 0) { PR_ATOMIC_SET(&self->mNativeEventScheduledDepth, 0); - NS_WARNING("Spontaneous call to ProcessGoannaEvents()!"); + NS_WARNING("Spontaneous call to ProcessGeckoEvents()!"); } else { self->Release(); } @@ -466,14 +466,14 @@ nsAppShell::WillTerminate() // // In nsBaseAppShell.cpp, the mNativeEventPending variable is used to // ensure that ScheduleNativeEventCallback() is called no more than once -// per call to NativeEventCallback(). ProcessGoannaEvents() can skip its +// per call to NativeEventCallback(). ProcessGeckoEvents() can skip its // call to NativeEventCallback() if processing of Goanna events by native // means is suspended (using nsIAppShell::SuspendNative()), which will // suspend calls from nsBaseAppShell::OnDispatchedEvent() to // ScheduleNativeEventCallback(). But when Goanna event processing by // native means is resumed (in ResumeNative()), an extra call is made to // ScheduleNativeEventCallback() (from ResumeNative()). This triggers -// another call to ProcessGoannaEvents(), which calls NativeEventCallback(), +// another call to ProcessGeckoEvents(), which calls NativeEventCallback(), // and nsBaseAppShell::OnDispatchedEvent() resumes calling // ScheduleNativeEventCallback(). // @@ -487,12 +487,12 @@ nsAppShell::ScheduleNativeEventCallback() return; // Each AddRef() here is normally balanced by exactly one Release() in - // ProcessGoannaEvents(). But there are exceptions, for which see - // ProcessGoannaEvents() and Exit(). + // ProcessGeckoEvents(). But there are exceptions, for which see + // ProcessGeckoEvents() and Exit(). NS_ADDREF_THIS(); PR_ATOMIC_INCREMENT(&mNativeEventScheduledDepth); - // This will invoke ProcessGoannaEvents on the main thread. + // This will invoke ProcessGeckoEvents on the main thread. ::CFRunLoopSourceSignal(mCFRunLoopSource); ::CFRunLoopWakeUp(mCFRunLoop); @@ -506,7 +506,7 @@ extern "C" EventAttributes GetEventAttributes(EventRef inEvent); // ProcessNextNativeEvent // // If aMayWait is false, process a single native event. If it is true, run -// the native run loop until stopped by ProcessGoannaEvents. +// the native run loop until stopped by ProcessGeckoEvents. // // Returns true if more events are waiting in the native event queue. // @@ -632,7 +632,7 @@ nsAppShell::ProcessNextNativeEvent(bool aMayWait) // the native run loop until the application quits). Since (unlike the base // class's Run() method) we don't process any Goanna events here, they need // to be processed elsewhere (in NativeEventCallback(), called from -// ProcessGoannaEvents()). +// ProcessGeckoEvents()). // // Camino called [NSApp run] on its own (via NSApplicationMain()), and so // didn't call nsAppShell::Run(). @@ -692,10 +692,10 @@ nsAppShell::Exit(void) [NSApp stop:nullptr]; // A call to Exit() just after a call to ScheduleNativeEventCallback() - // prevents the (normally) matching call to ProcessGoannaEvents() from - // happening. If we've been called from ProcessGoannaEvents() (as usually + // prevents the (normally) matching call to ProcessGeckoEvents() from + // happening. If we've been called from ProcessGeckoEvents() (as usually // happens), we take care of it there. But if we have an unbalanced call - // to ScheduleNativeEventCallback() and ProcessGoannaEvents() isn't on the + // to ScheduleNativeEventCallback() and ProcessGeckoEvents() isn't on the // stack, we need to take care of the problem here. if (!mNativeEventCallbackDepth && mNativeEventScheduledDepth) { int32_t releaseCount = PR_ATOMIC_SET(&mNativeEventScheduledDepth, 0); diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 7ca3179b31..6d2d113070 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -145,9 +145,9 @@ static uint32_t gNumberOfWidgetsNeedingEventThread = 0; // set up a goanna mouse event based on a cocoa mouse event - (void) convertCocoaMouseWheelEvent:(NSEvent*)aMouseEvent - toGoannaEvent:(WidgetWheelEvent*)outWheelEvent; + toGeckoEvent:(WidgetWheelEvent*)outWheelEvent; - (void) convertCocoaMouseEvent:(NSEvent*)aMouseEvent - toGoannaEvent:(WidgetInputEvent*)outGoannaEvent; + toGeckoEvent:(WidgetInputEvent*)outGeckoEvent; - (NSMenu*)contextMenu; @@ -3914,24 +3914,24 @@ NSEvent* gLastDragMouseDownEvent = nil; float deltaY = [anEvent deltaY]; // up=1.0, down=-1.0 // Setup the "swipe" event. - WidgetSimpleGestureEvent goannaEvent(true, NS_SIMPLE_GESTURE_SWIPE, + WidgetSimpleGestureEvent geckoEvent(true, NS_SIMPLE_GESTURE_SWIPE, mGoannaChild); - [self convertCocoaMouseEvent:anEvent toGoannaEvent:&goannaEvent]; + [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; // Record the left/right direction. if (deltaX > 0.0) - goannaEvent.direction |= nsIDOMSimpleGestureEvent::DIRECTION_LEFT; + geckoEvent.direction |= nsIDOMSimpleGestureEvent::DIRECTION_LEFT; else if (deltaX < 0.0) - goannaEvent.direction |= nsIDOMSimpleGestureEvent::DIRECTION_RIGHT; + geckoEvent.direction |= nsIDOMSimpleGestureEvent::DIRECTION_RIGHT; // Record the up/down direction. if (deltaY > 0.0) - goannaEvent.direction |= nsIDOMSimpleGestureEvent::DIRECTION_UP; + geckoEvent.direction |= nsIDOMSimpleGestureEvent::DIRECTION_UP; else if (deltaY < 0.0) - goannaEvent.direction |= nsIDOMSimpleGestureEvent::DIRECTION_DOWN; + geckoEvent.direction |= nsIDOMSimpleGestureEvent::DIRECTION_DOWN; // Send the event. - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -3984,12 +3984,12 @@ NSEvent* gLastDragMouseDownEvent = nil; } // Setup the event. - WidgetSimpleGestureEvent goannaEvent(true, msg, mGoannaChild); - goannaEvent.delta = deltaZ; - [self convertCocoaMouseEvent:anEvent toGoannaEvent:&goannaEvent]; + WidgetSimpleGestureEvent geckoEvent(true, msg, mGoannaChild); + geckoEvent.delta = deltaZ; + [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; // Send the event. - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); // Keep track of the cumulative magnification for the final "magnify" event. mCumulativeMagnification += deltaZ; @@ -4008,13 +4008,13 @@ NSEvent* gLastDragMouseDownEvent = nil; nsAutoRetainCocoaObject kungFuDeathGrip(self); // Setup the "double tap" event. - WidgetSimpleGestureEvent goannaEvent(true, NS_SIMPLE_GESTURE_TAP, + WidgetSimpleGestureEvent geckoEvent(true, NS_SIMPLE_GESTURE_TAP, mGoannaChild); - [self convertCocoaMouseEvent:anEvent toGoannaEvent:&goannaEvent]; - goannaEvent.clickCount = 1; + [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; + geckoEvent.clickCount = 1; // Send the event. - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); // Clear the gesture state mGestureState = eGestureState_None; @@ -4051,17 +4051,17 @@ NSEvent* gLastDragMouseDownEvent = nil; } // Setup the event. - WidgetSimpleGestureEvent goannaEvent(true, msg, mGoannaChild); - [self convertCocoaMouseEvent:anEvent toGoannaEvent:&goannaEvent]; - goannaEvent.delta = -rotation; + WidgetSimpleGestureEvent geckoEvent(true, msg, mGoannaChild); + [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; + geckoEvent.delta = -rotation; if (rotation > 0.0) { - goannaEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_COUNTERCLOCKWISE; + geckoEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_COUNTERCLOCKWISE; } else { - goannaEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_CLOCKWISE; + geckoEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_CLOCKWISE; } // Send the event. - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); // Keep track of the cumulative rotation for the final "rotate" event. mCumulativeRotation += rotation; @@ -4087,31 +4087,31 @@ NSEvent* gLastDragMouseDownEvent = nil; case eGestureState_MagnifyGesture: { // Setup the "magnify" event. - WidgetSimpleGestureEvent goannaEvent(true, NS_SIMPLE_GESTURE_MAGNIFY, + WidgetSimpleGestureEvent geckoEvent(true, NS_SIMPLE_GESTURE_MAGNIFY, mGoannaChild); - goannaEvent.delta = mCumulativeMagnification; - [self convertCocoaMouseEvent:anEvent toGoannaEvent:&goannaEvent]; + geckoEvent.delta = mCumulativeMagnification; + [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; // Send the event. - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); } break; case eGestureState_RotateGesture: { // Setup the "rotate" event. - WidgetSimpleGestureEvent goannaEvent(true, NS_SIMPLE_GESTURE_ROTATE, + WidgetSimpleGestureEvent geckoEvent(true, NS_SIMPLE_GESTURE_ROTATE, mGoannaChild); - [self convertCocoaMouseEvent:anEvent toGoannaEvent:&goannaEvent]; - goannaEvent.delta = -mCumulativeRotation; + [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; + geckoEvent.delta = -mCumulativeRotation; if (mCumulativeRotation > 0.0) { - goannaEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_COUNTERCLOCKWISE; + geckoEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_COUNTERCLOCKWISE; } else { - goannaEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_CLOCKWISE; + geckoEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_CLOCKWISE; } // Send the event. - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); } break; @@ -4155,13 +4155,13 @@ NSEvent* gLastDragMouseDownEvent = nil; if (!mGoannaChild) return false; - WidgetSimpleGestureEvent goannaEvent(true, aMsg, mGoannaChild); - goannaEvent.direction = aDirection; - goannaEvent.delta = aDelta; - goannaEvent.allowedDirections = *aAllowedDirections; - [self convertCocoaMouseEvent:aEvent toGoannaEvent:&goannaEvent]; - bool eventCancelled = mGoannaChild->DispatchWindowEvent(goannaEvent); - *aAllowedDirections = goannaEvent.allowedDirections; + WidgetSimpleGestureEvent geckoEvent(true, aMsg, mGoannaChild); + geckoEvent.direction = aDirection; + geckoEvent.delta = aDelta; + geckoEvent.allowedDirections = *aAllowedDirections; + [self convertCocoaMouseEvent:aEvent toGeckoEvent:&geckoEvent]; + bool eventCancelled = mGoannaChild->DispatchWindowEvent(geckoEvent); + *aAllowedDirections = geckoEvent.allowedDirections; return eventCancelled; // event cancelled == swipe should start } @@ -4473,9 +4473,9 @@ NSEvent* gLastDragMouseDownEvent = nil; NSUInteger modifierFlags = [theEvent modifierFlags]; - WidgetMouseEvent goannaEvent(true, NS_MOUSE_BUTTON_DOWN, mGoannaChild, + WidgetMouseEvent geckoEvent(true, NS_MOUSE_BUTTON_DOWN, mGoannaChild, WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGoannaEvent:&goannaEvent]; + [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; NSInteger clickCount = [theEvent clickCount]; if (mBlockedLastMouseDown && clickCount > 1) { @@ -4483,14 +4483,14 @@ NSEvent* gLastDragMouseDownEvent = nil; // blocked. clickCount--; } - goannaEvent.clickCount = clickCount; + geckoEvent.clickCount = clickCount; if (modifierFlags & NSControlKeyMask) - goannaEvent.button = WidgetMouseEvent::eRightButton; + geckoEvent.button = WidgetMouseEvent::eRightButton; else - goannaEvent.button = WidgetMouseEvent::eLeftButton; + geckoEvent.button = WidgetMouseEvent::eLeftButton; - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); mBlockedLastMouseDown = NO; // XXX maybe call markedTextSelectionChanged:client: here? @@ -4507,20 +4507,20 @@ NSEvent* gLastDragMouseDownEvent = nil; nsAutoRetainCocoaObject kungFuDeathGrip(self); - WidgetMouseEvent goannaEvent(true, NS_MOUSE_BUTTON_UP, mGoannaChild, + WidgetMouseEvent geckoEvent(true, NS_MOUSE_BUTTON_UP, mGoannaChild, WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGoannaEvent:&goannaEvent]; + [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; if ([theEvent modifierFlags] & NSControlKeyMask) - goannaEvent.button = WidgetMouseEvent::eRightButton; + geckoEvent.button = WidgetMouseEvent::eRightButton; else - goannaEvent.button = WidgetMouseEvent::eLeftButton; + geckoEvent.button = WidgetMouseEvent::eLeftButton; // This might destroy our widget (and null out mGoannaChild). - bool defaultPrevented = mGoannaChild->DispatchWindowEvent(goannaEvent); + bool defaultPrevented = mGoannaChild->DispatchWindowEvent(geckoEvent); // Check to see if we are double-clicking in the titlebar. CGFloat locationInTitlebar = [[self window] frame].size.height - [theEvent locationInWindow].y; - LayoutDeviceIntPoint pos = goannaEvent.refPoint; + LayoutDeviceIntPoint pos = geckoEvent.refPoint; if (!defaultPrevented && [theEvent clickCount] == 2 && mGoannaChild->GetDraggableRegion().Contains(pos.x, pos.y) && [[self window] isKindOfClass:[ToolbarWindow class]] && @@ -4638,11 +4638,11 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, if (!mGoannaChild) return; - WidgetMouseEvent goannaEvent(true, NS_MOUSE_MOVE, mGoannaChild, + WidgetMouseEvent geckoEvent(true, NS_MOUSE_MOVE, mGoannaChild, WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGoannaEvent:&goannaEvent]; + [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -4656,11 +4656,11 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, gLastDragView = self; - WidgetMouseEvent goannaEvent(true, NS_MOUSE_MOVE, mGoannaChild, + WidgetMouseEvent geckoEvent(true, NS_MOUSE_MOVE, mGoannaChild, WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGoannaEvent:&goannaEvent]; + [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); // Note, sending the above event might have destroyed our widget since we didn't retain. // Fine so long as we don't access any local variables from here on. @@ -4682,13 +4682,13 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, return; // The right mouse went down, fire off a right mouse down event to goanna - WidgetMouseEvent goannaEvent(true, NS_MOUSE_BUTTON_DOWN, mGoannaChild, + WidgetMouseEvent geckoEvent(true, NS_MOUSE_BUTTON_DOWN, mGoannaChild, WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGoannaEvent:&goannaEvent]; - goannaEvent.button = WidgetMouseEvent::eRightButton; - goannaEvent.clickCount = [theEvent clickCount]; + [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; + geckoEvent.button = WidgetMouseEvent::eRightButton; + geckoEvent.clickCount = [theEvent clickCount]; - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); if (!mGoannaChild) return; @@ -4705,14 +4705,14 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, if (!mGoannaChild) return; - WidgetMouseEvent goannaEvent(true, NS_MOUSE_BUTTON_UP, mGoannaChild, + WidgetMouseEvent geckoEvent(true, NS_MOUSE_BUTTON_UP, mGoannaChild, WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGoannaEvent:&goannaEvent]; - goannaEvent.button = WidgetMouseEvent::eRightButton; - goannaEvent.clickCount = [theEvent clickCount]; + [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; + geckoEvent.button = WidgetMouseEvent::eRightButton; + geckoEvent.clickCount = [theEvent clickCount]; nsAutoRetainCocoaObject kungFuDeathGrip(self); - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -4722,14 +4722,14 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, if (!mGoannaChild) return; - WidgetMouseEvent goannaEvent(true, NS_MOUSE_MOVE, mGoannaChild, + WidgetMouseEvent geckoEvent(true, NS_MOUSE_MOVE, mGoannaChild, WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGoannaEvent:&goannaEvent]; - goannaEvent.button = WidgetMouseEvent::eRightButton; + [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; + geckoEvent.button = WidgetMouseEvent::eRightButton; // send event into Goanna by going directly to the // the widget. - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); } - (void)otherMouseDown:(NSEvent *)theEvent @@ -4745,13 +4745,13 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, if (!mGoannaChild) return; - WidgetMouseEvent goannaEvent(true, NS_MOUSE_BUTTON_DOWN, mGoannaChild, + WidgetMouseEvent geckoEvent(true, NS_MOUSE_BUTTON_DOWN, mGoannaChild, WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGoannaEvent:&goannaEvent]; - goannaEvent.button = WidgetMouseEvent::eMiddleButton; - goannaEvent.clickCount = [theEvent clickCount]; + [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; + geckoEvent.button = WidgetMouseEvent::eMiddleButton; + geckoEvent.clickCount = [theEvent clickCount]; - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -4761,13 +4761,13 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, if (!mGoannaChild) return; - WidgetMouseEvent goannaEvent(true, NS_MOUSE_BUTTON_UP, mGoannaChild, + WidgetMouseEvent geckoEvent(true, NS_MOUSE_BUTTON_UP, mGoannaChild, WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGoannaEvent:&goannaEvent]; - goannaEvent.button = WidgetMouseEvent::eMiddleButton; + [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; + geckoEvent.button = WidgetMouseEvent::eMiddleButton; nsAutoRetainCocoaObject kungFuDeathGrip(self); - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); } - (void)otherMouseDragged:(NSEvent*)theEvent @@ -4775,14 +4775,14 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, if (!mGoannaChild) return; - WidgetMouseEvent goannaEvent(true, NS_MOUSE_MOVE, mGoannaChild, + WidgetMouseEvent geckoEvent(true, NS_MOUSE_MOVE, mGoannaChild, WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGoannaEvent:&goannaEvent]; - goannaEvent.button = WidgetMouseEvent::eMiddleButton; + [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; + geckoEvent.button = WidgetMouseEvent::eMiddleButton; // send event into Goanna by going directly to the // the widget. - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); } static int32_t RoundUp(double aDouble) @@ -4794,7 +4794,7 @@ static int32_t RoundUp(double aDouble) - (void)sendWheelStartOrStop:(uint32_t)msg forEvent:(NSEvent *)theEvent { WidgetWheelEvent wheelEvent(true, msg, mGoannaChild); - [self convertCocoaMouseWheelEvent:theEvent toGoannaEvent:&wheelEvent]; + [self convertCocoaMouseWheelEvent:theEvent toGeckoEvent:&wheelEvent]; mExpectingWheelStop = (msg == NS_WHEEL_START); mGoannaChild->DispatchWindowEvent(wheelEvent); } @@ -4841,12 +4841,12 @@ static int32_t RoundUp(double aDouble) } WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, mGoannaChild); - [self convertCocoaMouseWheelEvent:theEvent toGoannaEvent:&wheelEvent]; + [self convertCocoaMouseWheelEvent:theEvent toGeckoEvent:&wheelEvent]; wheelEvent.lineOrPageDeltaX = RoundUp(-[theEvent deltaX]); wheelEvent.lineOrPageDeltaY = RoundUp(-[theEvent deltaY]); - // wheelEvent.deltaMode was set by convertCocoaMouseWheelEvent:toGoannaEvent: + // wheelEvent.deltaMode was set by convertCocoaMouseWheelEvent:toGeckoEvent: // and depends on whether the current scrolling device supports pixel deltas. if (wheelEvent.deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL) { double scale = mGoannaChild->BackingScaleFactor(); @@ -5006,11 +5006,11 @@ static int32_t RoundUp(double aDouble) return nil; } - WidgetMouseEvent goannaEvent(true, NS_CONTEXTMENU, mGoannaChild, + WidgetMouseEvent geckoEvent(true, NS_CONTEXTMENU, mGoannaChild, WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGoannaEvent:&goannaEvent]; - goannaEvent.button = WidgetMouseEvent::eRightButton; - mGoannaChild->DispatchWindowEvent(goannaEvent); + [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; + geckoEvent.button = WidgetMouseEvent::eRightButton; + mGoannaChild->DispatchWindowEvent(geckoEvent); if (!mGoannaChild) return nil; @@ -5036,9 +5036,9 @@ static int32_t RoundUp(double aDouble) } - (void) convertCocoaMouseWheelEvent:(NSEvent*)aMouseEvent - toGoannaEvent:(WidgetWheelEvent*)outWheelEvent + toGeckoEvent:(WidgetWheelEvent*)outWheelEvent { - [self convertCocoaMouseEvent:aMouseEvent toGoannaEvent:outWheelEvent]; + [self convertCocoaMouseEvent:aMouseEvent toGeckoEvent:outWheelEvent]; bool usePreciseDeltas = nsCocoaUtils::HasPreciseScrollingDeltas(aMouseEvent) && Preferences::GetBool("mousewheel.enable_pixel_scrolling", true); @@ -5049,23 +5049,23 @@ static int32_t RoundUp(double aDouble) } - (void) convertCocoaMouseEvent:(NSEvent*)aMouseEvent - toGoannaEvent:(WidgetInputEvent*)outGoannaEvent + toGeckoEvent:(WidgetInputEvent*)outGeckoEvent { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - NS_ASSERTION(outGoannaEvent, "convertCocoaMouseEvent:toGoannaEvent: requires non-null aoutGoannaEvent"); - if (!outGoannaEvent) + NS_ASSERTION(outGeckoEvent, "convertCocoaMouseEvent:toGeckoEvent: requires non-null aoutGeckoEvent"); + if (!outGeckoEvent) return; - nsCocoaUtils::InitInputEvent(*outGoannaEvent, aMouseEvent); + nsCocoaUtils::InitInputEvent(*outGeckoEvent, aMouseEvent); // convert point to view coordinate system NSPoint locationInWindow = nsCocoaUtils::EventLocationForWindow(aMouseEvent, [self window]); - outGoannaEvent->refPoint = LayoutDeviceIntPoint::FromUntyped( + outGeckoEvent->refPoint = LayoutDeviceIntPoint::FromUntyped( [self convertWindowCoordinates:locationInWindow]); - WidgetMouseEventBase* mouseEvent = outGoannaEvent->AsMouseEventBase(); + WidgetMouseEventBase* mouseEvent = outGeckoEvent->AsMouseEventBase(); mouseEvent->buttons = 0; NSUInteger mouseButtons = [NSEvent pressedMouseButtons]; @@ -5455,10 +5455,10 @@ static int32_t RoundUp(double aDouble) if (!mGoannaChild) return YES; - WidgetMouseEvent goannaEvent(true, NS_MOUSE_ACTIVATE, mGoannaChild, + WidgetMouseEvent geckoEvent(true, NS_MOUSE_ACTIVATE, mGoannaChild, WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:aEvent toGoannaEvent:&goannaEvent]; - return !mGoannaChild->DispatchWindowEvent(goannaEvent); + [self convertCocoaMouseEvent:aEvent toGeckoEvent:&geckoEvent]; + return !mGoannaChild->DispatchWindowEvent(geckoEvent); } // We must always call through to our superclass, even when mGoannaChild is @@ -5623,18 +5623,18 @@ static int32_t RoundUp(double aDouble) } // set up goanna event - WidgetDragEvent goannaEvent(true, aMessage, mGoannaChild); - nsCocoaUtils::InitInputEvent(goannaEvent, [NSApp currentEvent]); + WidgetDragEvent geckoEvent(true, aMessage, mGoannaChild); + nsCocoaUtils::InitInputEvent(geckoEvent, [NSApp currentEvent]); // Use our own coordinates in the goanna event. // Convert event from goanna global coords to goanna view coords. NSPoint draggingLoc = [aSender draggingLocation]; - goannaEvent.refPoint = LayoutDeviceIntPoint::FromUntyped( + geckoEvent.refPoint = LayoutDeviceIntPoint::FromUntyped( [self convertWindowCoordinates:draggingLoc]); nsAutoRetainCocoaObject kungFuDeathGrip(self); - mGoannaChild->DispatchWindowEvent(goannaEvent); + mGoannaChild->DispatchWindowEvent(geckoEvent); if (!mGoannaChild) return NSDragOperationNone; diff --git a/widget/nsBaseAppShell.cpp b/widget/nsBaseAppShell.cpp index 5430920503..5d4544ab28 100644 --- a/widget/nsBaseAppShell.cpp +++ b/widget/nsBaseAppShell.cpp @@ -94,14 +94,14 @@ nsBaseAppShell::NativeEventCallback() IncrementEventloopNestingLevel(); EventloopNestingState prevVal = mEventloopNestingState; NS_ProcessPendingEvents(thread, THREAD_EVENT_STARVATION_LIMIT); - mProcessedGoannaEvents = true; + mProcessedGeckoEvents = true; mEventloopNestingState = prevVal; mBlockNativeEvent = prevBlockNativeEvent; // Continue processing pending events later (we don't want to starve the // embedders event loop). if (NS_HasPendingEvents(thread)) - DoProcessMoreGoannaEvents(); + DoProcessMoreGeckoEvents(); DecrementEventloopNestingLevel(); } @@ -109,7 +109,7 @@ nsBaseAppShell::NativeEventCallback() // Note, this is currently overidden on windows, see comments in nsAppShell for // details. void -nsBaseAppShell::DoProcessMoreGoannaEvents() +nsBaseAppShell::DoProcessMoreGeckoEvents() { OnDispatchedEvent(nullptr); } @@ -267,7 +267,7 @@ nsBaseAppShell::OnProcessNextEvent(nsIThreadInternal *thr, bool mayWait, bool needEvent = mayWait; // Reset prior to invoking DoProcessNextNativeEvent which might cause // NativeEventCallback to process goanna events. - mProcessedGoannaEvents = false; + mProcessedGeckoEvents = false; if (mFavorPerf <= 0 && start > mSwitchTime + mStarvationDelay) { // Favor pending native events @@ -285,7 +285,7 @@ nsBaseAppShell::OnProcessNextEvent(nsIThreadInternal *thr, bool mayWait, } } - while (!NS_HasPendingEvents(thr) && !mProcessedGoannaEvents) { + while (!NS_HasPendingEvents(thr) && !mProcessedGeckoEvents) { // If we have been asked to exit from Run, then we should not wait for // events to process. Note that an inner nested event loop causes // 'mayWait' to become false too, through 'mBlockedWait'. diff --git a/widget/nsBaseAppShell.h b/widget/nsBaseAppShell.h index e5ab4d62df..51553a76be 100644 --- a/widget/nsBaseAppShell.h +++ b/widget/nsBaseAppShell.h @@ -49,7 +49,7 @@ protected: * trigger goanna event processing when there are pending goanna * events. */ - virtual void DoProcessMoreGoannaEvents(); + virtual void DoProcessMoreGeckoEvents(); /** * Implemented by subclasses. Invoke NativeEventCallback from a native @@ -151,7 +151,7 @@ private: * Tracks whether we have processed any goanna events in NativeEventCallback so * that we can avoid erroneously entering a blocking loop waiting for goanna * events to show up during OnProcessNextEvent. This is required because on - * OS X ProcessGoannaEvents may be invoked inside the context of + * OS X ProcessGeckoEvents may be invoked inside the context of * ProcessNextNativeEvent and may result in NativeEventCallback being invoked * and in turn invoking NS_ProcessPendingEvents. Because * ProcessNextNativeEvent may be invoked prior to the NS_HasPendingEvents @@ -162,7 +162,7 @@ private: * call to DoProcessNextNativeEvent. It is set to true by * NativeEventCallback after calling NS_ProcessPendingEvents. */ - bool mProcessedGoannaEvents; + bool mProcessedGeckoEvents; }; #endif // nsBaseAppShell_h__ diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index 89dfd2121f..3cebd5c994 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -1399,16 +1399,6 @@ nsBaseWidget::ShowsResizeIndicator(nsIntRect* aResizerRect) return false; } -NS_METHOD nsBaseWidget::RegisterTouchWindow() -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_METHOD nsBaseWidget::UnregisterTouchWindow() -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - NS_IMETHODIMP nsBaseWidget::OverrideSystemMouseScrollSpeed(double aOriginalDeltaX, double aOriginalDeltaY, diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index 3efc7fcf86..52d212cf3e 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -229,8 +229,6 @@ public: NS_IMETHOD AttachViewToTopLevel(bool aUseAttachedEvents) override; virtual nsIWidgetListener* GetAttachedWidgetListener() override; virtual void SetAttachedWidgetListener(nsIWidgetListener* aListener) override; - NS_IMETHOD RegisterTouchWindow() override; - NS_IMETHOD UnregisterTouchWindow() override; NS_IMETHOD_(TextEventDispatcher*) GetTextEventDispatcher() override final; // Helper function for dispatching events which are not processed by APZ, diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index 7c6a1c2467..b53675ecf1 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -932,9 +932,6 @@ class nsIWidget : public nsISupports { */ NS_IMETHOD SetParent(nsIWidget* aNewParent) = 0; - NS_IMETHOD RegisterTouchWindow() = 0; - NS_IMETHOD UnregisterTouchWindow() = 0; - /** * Return the parent Widget of this Widget or nullptr if this is a * top level window diff --git a/widget/windows/WinMouseScrollHandler.cpp.bak b/widget/windows/WinMouseScrollHandler.cpp.bak new file mode 100644 index 0000000000..47565a2407 --- /dev/null +++ b/widget/windows/WinMouseScrollHandler.cpp.bak @@ -0,0 +1,1595 @@ +/* -*- 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/. */ + +#include "mozilla/DebugOnly.h" + +#include "prlog.h" + +#include "WinMouseScrollHandler.h" +#include "nsWindow.h" +#include "nsWindowDefs.h" +#include "KeyboardLayout.h" +#include "WinUtils.h" +#include "nsGkAtoms.h" +#include "nsIDOMWindowUtils.h" +#include "nsIDOMWheelEvent.h" + +#include "mozilla/MiscEvents.h" +#include "mozilla/MouseEvents.h" +#include "mozilla/Preferences.h" +#include "mozilla/WindowsVersion.h" + +#include + +namespace mozilla { +namespace widget { + +#ifdef PR_LOGGING +PRLogModuleInfo* gMouseScrollLog = nullptr; + +static const char* GetBoolName(bool aBool) +{ + return aBool ? "TRUE" : "FALSE"; +} + +static void LogKeyStateImpl() +{ + if (!PR_LOG_TEST(gMouseScrollLog, PR_LOG_DEBUG)) { + return; + } + BYTE keyboardState[256]; + if (::GetKeyboardState(keyboardState)) { + for (size_t i = 0; i < ArrayLength(keyboardState); i++) { + if (keyboardState[i]) { + PR_LOG(gMouseScrollLog, PR_LOG_DEBUG, + (" Current key state: keyboardState[0x%02X]=0x%02X (%s)", + i, keyboardState[i], + ((keyboardState[i] & 0x81) == 0x81) ? "Pressed and Toggled" : + (keyboardState[i] & 0x80) ? "Pressed" : + (keyboardState[i] & 0x01) ? "Toggled" : "Unknown")); + } + } + } else { + PR_LOG(gMouseScrollLog, PR_LOG_DEBUG, + ("MouseScroll::Device::Elantech::HandleKeyMessage(): Failed to print " + "current keyboard state")); + } +} + +#define LOG_KEYSTATE() LogKeyStateImpl() +#else // PR_LOGGING +#define LOG_KEYSTATE() +#endif + +MouseScrollHandler* MouseScrollHandler::sInstance = nullptr; + +bool MouseScrollHandler::Device::sFakeScrollableWindowNeeded = false; + +bool MouseScrollHandler::Device::Elantech::sUseSwipeHack = false; +bool MouseScrollHandler::Device::Elantech::sUsePinchHack = false; +DWORD MouseScrollHandler::Device::Elantech::sZoomUntil = 0; + +bool MouseScrollHandler::Device::SetPoint::sMightBeUsing = false; + +// The duration until timeout of events transaction. The value is 1.5 sec, +// it's just a magic number, it was suggested by Logitech's engineer, see +// bug 605648 comment 90. +#define DEFAULT_TIMEOUT_DURATION 1500 + +/****************************************************************************** + * + * MouseScrollHandler + * + ******************************************************************************/ + +/* static */ +POINTS +MouseScrollHandler::GetCurrentMessagePos() +{ + if (SynthesizingEvent::IsSynthesizing()) { + return sInstance->mSynthesizingEvent->GetCursorPoint(); + } + DWORD pos = ::GetMessagePos(); + return MAKEPOINTS(pos); +} + +// Get rid of the GetMessagePos() API. +#define GetMessagePos() + +/* static */ +void +MouseScrollHandler::Initialize() +{ +#ifdef PR_LOGGING + if (!gMouseScrollLog) { + gMouseScrollLog = PR_NewLogModule("MouseScrollHandlerWidgets"); + } +#endif + Device::Init(); +} + +/* static */ +void +MouseScrollHandler::Shutdown() +{ + delete sInstance; + sInstance = nullptr; +} + +/* static */ +MouseScrollHandler* +MouseScrollHandler::GetInstance() +{ + if (!sInstance) { + sInstance = new MouseScrollHandler(); + } + return sInstance; +} + +MouseScrollHandler::MouseScrollHandler() : + mIsWaitingInternalMessage(false), + mSynthesizingEvent(nullptr) +{ + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll: Creating an instance, this=%p, sInstance=%p", + this, sInstance)); +} + +MouseScrollHandler::~MouseScrollHandler() +{ + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll: Destroying an instance, this=%p, sInstance=%p", + this, sInstance)); + + delete mSynthesizingEvent; +} + +/* static */ +bool +MouseScrollHandler::NeedsMessage(UINT aMsg) +{ + switch (aMsg) { + case WM_SETTINGCHANGE: + case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: + case WM_HSCROLL: + case WM_VSCROLL: + case MOZ_WM_MOUSEVWHEEL: + case MOZ_WM_MOUSEHWHEEL: + case MOZ_WM_HSCROLL: + case MOZ_WM_VSCROLL: + case WM_KEYDOWN: + case WM_KEYUP: + return true; + } + return false; +} + +/* static */ +bool +MouseScrollHandler::ProcessMessage(nsWindowBase* aWidget, UINT msg, + WPARAM wParam, LPARAM lParam, + MSGResult& aResult) +{ + Device::Elantech::UpdateZoomUntil(); + + switch (msg) { + case WM_SETTINGCHANGE: + if (!sInstance) { + return false; + } + if (wParam == SPI_SETWHEELSCROLLLINES || + wParam == SPI_SETWHEELSCROLLCHARS) { + sInstance->mSystemSettings.MarkDirty(); + } + return false; + + case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: + GetInstance()-> + ProcessNativeMouseWheelMessage(aWidget, msg, wParam, lParam); + sInstance->mSynthesizingEvent->NotifyNativeMessageHandlingFinished(); + // We don't need to call next wndproc for WM_MOUSEWHEEL and + // WM_MOUSEHWHEEL. We should consume them always. If the messages + // would be handled by our window again, it caused making infinite + // message loop. + aResult.mConsumed = true; + aResult.mResult = (msg != WM_MOUSEHWHEEL); + return true; + + case WM_HSCROLL: + case WM_VSCROLL: + aResult.mConsumed = + GetInstance()->ProcessNativeScrollMessage(aWidget, msg, wParam, lParam); + sInstance->mSynthesizingEvent->NotifyNativeMessageHandlingFinished(); + aResult.mResult = 0; + return true; + + case MOZ_WM_MOUSEVWHEEL: + case MOZ_WM_MOUSEHWHEEL: + GetInstance()->HandleMouseWheelMessage(aWidget, msg, wParam, lParam); + sInstance->mSynthesizingEvent->NotifyInternalMessageHandlingFinished(); + // Doesn't need to call next wndproc for internal wheel message. + aResult.mConsumed = true; + return true; + + case MOZ_WM_HSCROLL: + case MOZ_WM_VSCROLL: + GetInstance()-> + HandleScrollMessageAsMouseWheelMessage(aWidget, msg, wParam, lParam); + sInstance->mSynthesizingEvent->NotifyInternalMessageHandlingFinished(); + // Doesn't need to call next wndproc for internal scroll message. + aResult.mConsumed = true; + return true; + + case WM_KEYDOWN: + case WM_KEYUP: + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ProcessMessage(): aWidget=%p, " + "msg=%s(0x%04X), wParam=0x%02X, ::GetMessageTime()=%d", + aWidget, msg == WM_KEYDOWN ? "WM_KEYDOWN" : + msg == WM_KEYUP ? "WM_KEYUP" : "Unknown", msg, wParam, + ::GetMessageTime())); + LOG_KEYSTATE(); + if (Device::Elantech::HandleKeyMessage(aWidget, msg, wParam)) { + aResult.mResult = 0; + aResult.mConsumed = true; + return true; + } + return false; + + default: + return false; + } +} + +/* static */ +nsresult +MouseScrollHandler::SynthesizeNativeMouseScrollEvent(nsWindowBase* aWidget, + const LayoutDeviceIntPoint& aPoint, + uint32_t aNativeMessage, + int32_t aDelta, + uint32_t aModifierFlags, + uint32_t aAdditionalFlags) +{ + bool useFocusedWindow = + !(aAdditionalFlags & nsIDOMWindowUtils::MOUSESCROLL_PREFER_WIDGET_AT_POINT); + + POINT pt; + pt.x = aPoint.x; + pt.y = aPoint.y; + + HWND target = useFocusedWindow ? ::WindowFromPoint(pt) : ::GetFocus(); + NS_ENSURE_TRUE(target, NS_ERROR_FAILURE); + + WPARAM wParam = 0; + LPARAM lParam = 0; + switch (aNativeMessage) { + case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: { + lParam = MAKELPARAM(pt.x, pt.y); + WORD mod = 0; + if (aModifierFlags & (nsIWidget::CTRL_L | nsIWidget::CTRL_R)) { + mod |= MK_CONTROL; + } + if (aModifierFlags & (nsIWidget::SHIFT_L | nsIWidget::SHIFT_R)) { + mod |= MK_SHIFT; + } + wParam = MAKEWPARAM(mod, aDelta); + break; + } + case WM_VSCROLL: + case WM_HSCROLL: + lParam = (aAdditionalFlags & + nsIDOMWindowUtils::MOUSESCROLL_WIN_SCROLL_LPARAM_NOT_NULL) ? + reinterpret_cast(target) : 0; + wParam = aDelta; + break; + default: + return NS_ERROR_INVALID_ARG; + } + + // Ensure to make the instance. + GetInstance(); + + BYTE kbdState[256]; + memset(kbdState, 0, sizeof(kbdState)); + + nsAutoTArray keySequence; + WinUtils::SetupKeyModifiersSequence(&keySequence, aModifierFlags); + + for (uint32_t i = 0; i < keySequence.Length(); ++i) { + uint8_t key = keySequence[i].mGeneral; + uint8_t keySpecific = keySequence[i].mSpecific; + kbdState[key] = 0x81; // key is down and toggled on if appropriate + if (keySpecific) { + kbdState[keySpecific] = 0x81; + } + } + + if (!sInstance->mSynthesizingEvent) { + sInstance->mSynthesizingEvent = new SynthesizingEvent(); + } + + POINTS pts; + pts.x = static_cast(pt.x); + pts.y = static_cast(pt.y); + return sInstance->mSynthesizingEvent-> + Synthesize(pts, target, aNativeMessage, wParam, lParam, kbdState); +} + +/* static */ +void +MouseScrollHandler::InitEvent(nsWindowBase* aWidget, + WidgetGUIEvent& aEvent, + nsIntPoint* aPoint) +{ + NS_ENSURE_TRUE_VOID(aWidget); + nsIntPoint point; + if (aPoint) { + point = *aPoint; + } else { + POINTS pts = GetCurrentMessagePos(); + POINT pt; + pt.x = pts.x; + pt.y = pts.y; + ::ScreenToClient(aWidget->GetWindowHandle(), &pt); + point.x = pt.x; + point.y = pt.y; + } + aWidget->InitEvent(aEvent, &point); +} + +/* static */ +ModifierKeyState +MouseScrollHandler::GetModifierKeyState(UINT aMessage) +{ + ModifierKeyState result; + // Assume the Control key is down if the Elantech touchpad has sent the + // mis-ordered WM_KEYDOWN/WM_MOUSEWHEEL messages. (See the comment in + // MouseScrollHandler::Device::Elantech::HandleKeyMessage().) + if ((aMessage == MOZ_WM_MOUSEVWHEEL || aMessage == WM_MOUSEWHEEL) && + !result.IsControl() && Device::Elantech::IsZooming()) { + result.Set(MODIFIER_CONTROL); + } + return result; +} + +POINT +MouseScrollHandler::ComputeMessagePos(UINT aMessage, + WPARAM aWParam, + LPARAM aLParam) +{ + POINT point; + if (Device::SetPoint::IsGetMessagePosResponseValid(aMessage, + aWParam, aLParam)) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ComputeMessagePos: Using ::GetCursorPos()")); + ::GetCursorPos(&point); + } else { + POINTS pts = GetCurrentMessagePos(); + point.x = pts.x; + point.y = pts.y; + } + return point; +} + +void +MouseScrollHandler::ProcessNativeMouseWheelMessage(nsWindowBase* aWidget, + UINT aMessage, + WPARAM aWParam, + LPARAM aLParam) +{ + if (SynthesizingEvent::IsSynthesizing()) { + mSynthesizingEvent->NativeMessageReceived(aWidget, aMessage, + aWParam, aLParam); + } + + POINT point = ComputeMessagePos(aMessage, aWParam, aLParam); + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ProcessNativeMouseWheelMessage: aWidget=%p, " + "aMessage=%s, wParam=0x%08X, lParam=0x%08X, point: { x=%d, y=%d }", + aWidget, aMessage == WM_MOUSEWHEEL ? "WM_MOUSEWHEEL" : + aMessage == WM_MOUSEHWHEEL ? "WM_MOUSEHWHEEL" : + aMessage == WM_VSCROLL ? "WM_VSCROLL" : "WM_HSCROLL", + aWParam, aLParam, point.x, point.y)); + LOG_KEYSTATE(); + + HWND underCursorWnd = ::WindowFromPoint(point); + if (!underCursorWnd) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ProcessNativeMouseWheelMessage: " + "No window is not found under the cursor")); + return; + } + + if (Device::Elantech::IsPinchHackNeeded() && + Device::Elantech::IsHelperWindow(underCursorWnd)) { + // The Elantech driver places a window right underneath the cursor + // when sending a WM_MOUSEWHEEL event to us as part of a pinch-to-zoom + // gesture. We detect that here, and search for our window that would + // be beneath the cursor if that window wasn't there. + underCursorWnd = WinUtils::FindOurWindowAtPoint(point); + if (!underCursorWnd) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ProcessNativeMouseWheelMessage: " + "Our window is not found under the Elantech helper window")); + return; + } + } + + // Handle most cases first. If the window under mouse cursor is our window + // except plugin window (MozillaWindowClass), we should handle the message + // on the window. + if (WinUtils::IsOurProcessWindow(underCursorWnd)) { + nsWindowBase* destWindow = WinUtils::GetNSWindowBasePtr(underCursorWnd); + if (!destWindow) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ProcessNativeMouseWheelMessage: " + "Found window under the cursor isn't managed by nsWindow...")); + HWND wnd = ::GetParent(underCursorWnd); + for (; wnd; wnd = ::GetParent(wnd)) { + destWindow = WinUtils::GetNSWindowBasePtr(wnd); + if (destWindow) { + break; + } + } + if (!wnd) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ProcessNativeMouseWheelMessage: Our window which is " + "managed by nsWindow is not found under the cursor")); + return; + } + } + + MOZ_ASSERT(destWindow, "destWindow must not be NULL"); + + // If the found window is our plugin window, it means that the message + // has been handled by the plugin but not consumed. We should handle the + // message on its parent window. However, note that the DOM event may + // cause accessing the plugin. Therefore, we should unlock the plugin + // process by using PostMessage(). + if (destWindow->IsPlugin()) { + destWindow = destWindow->GetParentWindowBase(false); + if (!destWindow) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ProcessNativeMouseWheelMessage: " + "Our window which is a parent of a plugin window is not found")); + return; + } + } + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ProcessNativeMouseWheelMessage: Succeeded, " + "Posting internal message to an nsWindow (%p)...", + destWindow)); + mIsWaitingInternalMessage = true; + UINT internalMessage = WinUtils::GetInternalMessage(aMessage); + ::PostMessage(destWindow->GetWindowHandle(), internalMessage, + aWParam, aLParam); + return; + } + + // If the window under cursor is not in our process, it means: + // 1. The window may be a plugin window (GoannaPluginWindow or its descendant). + // 2. The window may be another application's window. + HWND pluginWnd = WinUtils::FindOurProcessWindow(underCursorWnd); + if (!pluginWnd) { + // If there is no plugin window in ancestors of the window under cursor, + // the window is for another applications (case 2). + // We don't need to handle this message. + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ProcessNativeMouseWheelMessage: " + "Our window is not found under the cursor")); + return; + } + + // If we're a plugin window (MozillaWindowClass) and cursor in this window, + // the message shouldn't go to plugin's wndproc again. So, we should handle + // it on parent window. However, note that the DOM event may cause accessing + // the plugin. Therefore, we should unlock the plugin process by using + // PostMessage(). + if (aWidget->IsPlugin() && + aWidget->GetWindowHandle() == pluginWnd) { + nsWindowBase* destWindow = aWidget->GetParentWindowBase(false); + if (!destWindow) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ProcessNativeMouseWheelMessage: Our normal window which " + "is a parent of this plugin window is not found")); + return; + } + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ProcessNativeMouseWheelMessage: Succeeded, " + "Posting internal message to an nsWindow (%p) which is parent of this " + "plugin window...", + destWindow)); + mIsWaitingInternalMessage = true; + UINT internalMessage = WinUtils::GetInternalMessage(aMessage); + ::PostMessage(destWindow->GetWindowHandle(), internalMessage, + aWParam, aLParam); + return; + } + + // If the window is a part of plugin, we should post the message to it. + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ProcessNativeMouseWheelMessage: Succeeded, " + "Redirecting the message to a window which is a plugin child window")); + ::PostMessage(underCursorWnd, aMessage, aWParam, aLParam); +} + +bool +MouseScrollHandler::ProcessNativeScrollMessage(nsWindowBase* aWidget, + UINT aMessage, + WPARAM aWParam, + LPARAM aLParam) +{ + if (aLParam || mUserPrefs.IsScrollMessageHandledAsWheelMessage()) { + // Scroll message generated by Thinkpad Trackpoint Driver or similar + // Treat as a mousewheel message and scroll appropriately + ProcessNativeMouseWheelMessage(aWidget, aMessage, aWParam, aLParam); + // Always consume the scroll message if we try to emulate mouse wheel + // action. + return true; + } + + if (SynthesizingEvent::IsSynthesizing()) { + mSynthesizingEvent->NativeMessageReceived(aWidget, aMessage, + aWParam, aLParam); + } + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ProcessNativeScrollMessage: aWidget=%p, " + "aMessage=%s, wParam=0x%08X, lParam=0x%08X", + aWidget, aMessage == WM_VSCROLL ? "WM_VSCROLL" : "WM_HSCROLL", + aWParam, aLParam)); + + // Scroll message generated by external application + WidgetContentCommandEvent commandEvent(true, NS_CONTENT_COMMAND_SCROLL, + aWidget); + + commandEvent.mScroll.mIsHorizontal = (aMessage == WM_HSCROLL); + + switch (LOWORD(aWParam)) { + case SB_LINEUP: // SB_LINELEFT + commandEvent.mScroll.mUnit = + WidgetContentCommandEvent::eCmdScrollUnit_Line; + commandEvent.mScroll.mAmount = -1; + break; + case SB_LINEDOWN: // SB_LINERIGHT + commandEvent.mScroll.mUnit = + WidgetContentCommandEvent::eCmdScrollUnit_Line; + commandEvent.mScroll.mAmount = 1; + break; + case SB_PAGEUP: // SB_PAGELEFT + commandEvent.mScroll.mUnit = + WidgetContentCommandEvent::eCmdScrollUnit_Page; + commandEvent.mScroll.mAmount = -1; + break; + case SB_PAGEDOWN: // SB_PAGERIGHT + commandEvent.mScroll.mUnit = + WidgetContentCommandEvent::eCmdScrollUnit_Page; + commandEvent.mScroll.mAmount = 1; + break; + case SB_TOP: // SB_LEFT + commandEvent.mScroll.mUnit = + WidgetContentCommandEvent::eCmdScrollUnit_Whole; + commandEvent.mScroll.mAmount = -1; + break; + case SB_BOTTOM: // SB_RIGHT + commandEvent.mScroll.mUnit = + WidgetContentCommandEvent::eCmdScrollUnit_Whole; + commandEvent.mScroll.mAmount = 1; + break; + default: + return false; + } + // XXX If this is a plugin window, we should dispatch the event from + // parent window. + aWidget->DispatchContentCommandEvent(&commandEvent); + return true; +} + +void +MouseScrollHandler::HandleMouseWheelMessage(nsWindowBase* aWidget, + UINT aMessage, + WPARAM aWParam, + LPARAM aLParam) +{ + MOZ_ASSERT( + (aMessage == MOZ_WM_MOUSEVWHEEL || aMessage == MOZ_WM_MOUSEHWHEEL), + "HandleMouseWheelMessage must be called with " + "MOZ_WM_MOUSEVWHEEL or MOZ_WM_MOUSEHWHEEL"); + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::HandleMouseWheelMessage: aWidget=%p, " + "aMessage=MOZ_WM_MOUSE%sWHEEL, aWParam=0x%08X, aLParam=0x%08X", + aWidget, aMessage == MOZ_WM_MOUSEVWHEEL ? "V" : "H", + aWParam, aLParam)); + + mIsWaitingInternalMessage = false; + + EventInfo eventInfo(aWidget, WinUtils::GetNativeMessage(aMessage), + aWParam, aLParam); + if (!eventInfo.CanDispatchWheelEvent()) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::HandleMouseWheelMessage: Cannot dispatch the events")); + mLastEventInfo.ResetTransaction(); + return; + } + + // Discard the remaining delta if current wheel message and last one are + // received by different window or to scroll different direction or + // different unit scroll. Furthermore, if the last event was too old. + if (!mLastEventInfo.CanContinueTransaction(eventInfo)) { + mLastEventInfo.ResetTransaction(); + } + + mLastEventInfo.RecordEvent(eventInfo); + + ModifierKeyState modKeyState = GetModifierKeyState(aMessage); + + // Grab the widget, it might be destroyed by a DOM event handler. + nsRefPtr kungFuDethGrip(aWidget); + + WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, aWidget); + if (mLastEventInfo.InitWheelEvent(aWidget, wheelEvent, modKeyState)) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::HandleMouseWheelMessage: dispatching " + "NS_WHEEL_WHEEL event")); + Widget->DispatchWheelEvent(&wheelEvent); + if (aWidget->Destroyed()) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::HandleMouseWheelMessage: The window was destroyed " + "by NS_WHEEL_WHEEL event")); + mLastEventInfo.ResetTransaction(); + return; + } + } +#ifdef PR_LOGGING + else { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::HandleMouseWheelMessage: NS_WHEEL_WHEEL event is not " + "dispatched")); + } +#endif +} + +void +MouseScrollHandler::HandleScrollMessageAsMouseWheelMessage(nsWindowBase* aWidget, + UINT aMessage, + WPARAM aWParam, + LPARAM aLParam) +{ + MOZ_ASSERT( + (aMessage == MOZ_WM_VSCROLL || aMessage == MOZ_WM_HSCROLL), + "HandleScrollMessageAsMouseWheelMessage must be called with " + "MOZ_WM_VSCROLL or MOZ_WM_HSCROLL"); + + mIsWaitingInternalMessage = false; + + ModifierKeyState modKeyState = GetModifierKeyState(aMessage); + + WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, aWidget); + double& delta = + (aMessage == MOZ_WM_VSCROLL) ? wheelEvent.deltaY : wheelEvent.deltaX; + int32_t& lineOrPageDelta = + (aMessage == MOZ_WM_VSCROLL) ? wheelEvent.lineOrPageDeltaY : + wheelEvent.lineOrPageDeltaX; + + delta = 1.0; + lineOrPageDelta = 1; + + switch (LOWORD(aWParam)) { + case SB_PAGEUP: + delta = -1.0; + lineOrPageDelta = -1; + case SB_PAGEDOWN: + wheelEvent.deltaMode = nsIDOMWheelEvent::DOM_DELTA_PAGE; + break; + + case SB_LINEUP: + delta = -1.0; + lineOrPageDelta = -1; + case SB_LINEDOWN: + wheelEvent.deltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE; + break; + + default: + return; + } + modKeyState.InitInputEvent(wheelEvent); + // XXX Current mouse position may not be same as when the original message + // is received. We need to know the actual mouse cursor position when + // the original message was received. + InitEvent(aWidget, wheelEvent); + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::HandleScrollMessageAsMouseWheelMessage: aWidget=%p, " + "aMessage=MOZ_WM_%sSCROLL, aWParam=0x%08X, aLParam=0x%08X, " + "wheelEvent { refPoint: { x: %d, y: %d }, deltaX: %f, deltaY: %f, " + "lineOrPageDeltaX: %d, lineOrPageDeltaY: %d, " + "isShift: %s, isControl: %s, isAlt: %s, isMeta: %s }", + aWidget, (aMessage == MOZ_WM_VSCROLL) ? "V" : "H", aWParam, aLParam, + wheelEvent.refPoint.x, wheelEvent.refPoint.y, + wheelEvent.deltaX, wheelEvent.deltaY, + wheelEvent.lineOrPageDeltaX, wheelEvent.lineOrPageDeltaY, + GetBoolName(wheelEvent.IsShift()), + GetBoolName(wheelEvent.IsControl()), + GetBoolName(wheelEvent.IsAlt()), + GetBoolName(wheelEvent.IsMeta()))); + + aWidget->DispatchWheelEvent(&wheelEvent); +} + +/****************************************************************************** + * + * EventInfo + * + ******************************************************************************/ + +MouseScrollHandler::EventInfo::EventInfo(nsWindowBase* aWidget, + UINT aMessage, + WPARAM aWParam, LPARAM aLParam) +{ + MOZ_ASSERT(aMessage == WM_MOUSEWHEEL || aMessage == WM_MOUSEHWHEEL, + "EventInfo must be initialized with WM_MOUSEWHEEL or WM_MOUSEHWHEEL"); + + MouseScrollHandler::GetInstance()->mSystemSettings.Init(); + + mIsVertical = (aMessage == WM_MOUSEWHEEL); + mIsPage = MouseScrollHandler::sInstance-> + mSystemSettings.IsPageScroll(mIsVertical); + mDelta = (short)HIWORD(aWParam); + mWnd = aWidget->GetWindowHandle(); + mTimeStamp = TimeStamp::Now(); +} + +bool +MouseScrollHandler::EventInfo::CanDispatchWheelEvent() const +{ + if (!GetScrollAmount()) { + // XXX I think that we should dispatch mouse wheel events even if the + // operation will not scroll because the wheel operation really happened + // and web application may want to handle the event for non-scroll action. + return false; + } + + return (mDelta != 0); +} + +int32_t +MouseScrollHandler::EventInfo::GetScrollAmount() const +{ + if (mIsPage) { + return 1; + } + return MouseScrollHandler::sInstance-> + mSystemSettings.GetScrollAmount(mIsVertical); +} + +/****************************************************************************** + * + * LastEventInfo + * + ******************************************************************************/ + +bool +MouseScrollHandler::LastEventInfo::CanContinueTransaction( + const EventInfo& aNewEvent) +{ + int32_t timeout = MouseScrollHandler::sInstance-> + mUserPrefs.GetMouseScrollTransactionTimeout(); + return !mWnd || + (mWnd == aNewEvent.GetWindowHandle() && + IsPositive() == aNewEvent.IsPositive() && + mIsVertical == aNewEvent.IsVertical() && + mIsPage == aNewEvent.IsPage() && + (timeout < 0 || + TimeStamp::Now() - mTimeStamp <= + TimeDuration::FromMilliseconds(timeout))); +} + +void +MouseScrollHandler::LastEventInfo::ResetTransaction() +{ + if (!mWnd) { + return; + } + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::LastEventInfo::ResetTransaction()")); + + mWnd = nullptr; + mAccumulatedDelta = 0; +} + +void +MouseScrollHandler::LastEventInfo::RecordEvent(const EventInfo& aEvent) +{ + mWnd = aEvent.GetWindowHandle(); + mDelta = aEvent.GetNativeDelta(); + mIsVertical = aEvent.IsVertical(); + mIsPage = aEvent.IsPage(); + mTimeStamp = TimeStamp::Now(); +} + +/* static */ +int32_t +MouseScrollHandler::LastEventInfo::RoundDelta(double aDelta) +{ + return (aDelta >= 0) ? (int32_t)floor(aDelta) : (int32_t)ceil(aDelta); +} + +bool +MouseScrollHandler::LastEventInfo::InitWheelEvent( + nsWindowBase* aWidget, + WidgetWheelEvent& aWheelEvent, + const ModifierKeyState& aModKeyState) +{ + MOZ_ASSERT(aWheelEvent.message == NS_WHEEL_WHEEL); + + // XXX Why don't we use lParam value? We should use lParam value because + // our internal message is always posted by original message handler. + // So, GetMessagePos() may return different cursor position. + InitEvent(aWidget, aWheelEvent); + + aModKeyState.InitInputEvent(aWheelEvent); + + // Our positive delta value means to bottom or right. + // But positive native delta value means to top or right. + // Use orienter for computing our delta value with native delta value. + int32_t orienter = mIsVertical ? -1 : 1; + + aWheelEvent.deltaMode = mIsPage ? nsIDOMWheelEvent::DOM_DELTA_PAGE : + nsIDOMWheelEvent::DOM_DELTA_LINE; + + double& delta = mIsVertical ? aWheelEvent.deltaY : aWheelEvent.deltaX; + int32_t& lineOrPageDelta = mIsVertical ? aWheelEvent.lineOrPageDeltaY : + aWheelEvent.lineOrPageDeltaX; + + double nativeDeltaPerUnit = + mIsPage ? static_cast(WHEEL_DELTA) : + static_cast(WHEEL_DELTA) / GetScrollAmount(); + + delta = static_cast(mDelta) * orienter / nativeDeltaPerUnit; + mAccumulatedDelta += mDelta; + lineOrPageDelta = + mAccumulatedDelta * orienter / RoundDelta(nativeDeltaPerUnit); + mAccumulatedDelta -= + lineOrPageDelta * orienter * RoundDelta(nativeDeltaPerUnit); + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::LastEventInfo::InitWheelEvent: aWidget=%p, " + "aWheelEvent { refPoint: { x: %d, y: %d }, deltaX: %f, deltaY: %f, " + "lineOrPageDeltaX: %d, lineOrPageDeltaY: %d, " + "isShift: %s, isControl: %s, isAlt: %s, isMeta: %s }, " + "mAccumulatedDelta: %d", + aWidget, aWheelEvent.refPoint.x, aWheelEvent.refPoint.y, + aWheelEvent.deltaX, aWheelEvent.deltaY, + aWheelEvent.lineOrPageDeltaX, aWheelEvent.lineOrPageDeltaY, + GetBoolName(aWheelEvent.IsShift()), + GetBoolName(aWheelEvent.IsControl()), + GetBoolName(aWheelEvent.IsAlt()), + GetBoolName(aWheelEvent.IsMeta()), mAccumulatedDelta)); + + return (delta != 0); +} + +/****************************************************************************** + * + * SystemSettings + * + ******************************************************************************/ + +void +MouseScrollHandler::SystemSettings::Init() +{ + if (mInitialized) { + return; + } + + mInitialized = true; + + MouseScrollHandler::UserPrefs& userPrefs = + MouseScrollHandler::sInstance->mUserPrefs; + + mScrollLines = userPrefs.GetOverriddenVerticalScrollAmout(); + if (mScrollLines >= 0) { + // overridden by the pref. + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::SystemSettings::Init(): mScrollLines is overridden by " + "the pref: %d", + mScrollLines)); + } else if (!::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, + &mScrollLines, 0)) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::SystemSettings::Init(): ::SystemParametersInfo(" + "SPI_GETWHEELSCROLLLINES) failed")); + mScrollLines = 3; + } + + if (mScrollLines > WHEEL_DELTA) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::SystemSettings::Init(): the result of " + "::SystemParametersInfo(SPI_GETWHEELSCROLLLINES) is too large: %d", + mScrollLines)); + // sScrollLines usually equals 3 or 0 (for no scrolling) + // However, if sScrollLines > WHEEL_DELTA, we assume that + // the mouse driver wants a page scroll. The docs state that + // sScrollLines should explicitly equal WHEEL_PAGESCROLL, but + // since some mouse drivers use an arbitrary large number instead, + // we have to handle that as well. + mScrollLines = WHEEL_PAGESCROLL; + } + + mScrollChars = userPrefs.GetOverriddenHorizontalScrollAmout(); + if (mScrollChars >= 0) { + // overridden by the pref. + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::SystemSettings::Init(): mScrollChars is overridden by " + "the pref: %d", + mScrollChars)); + } else if (!::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, + &mScrollChars, 0)) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::SystemSettings::Init(): ::SystemParametersInfo(" + "SPI_GETWHEELSCROLLCHARS) failed, %s", + IsVistaOrLater() ? + "this is unexpected on Vista or later" : + "but on XP or earlier, this is not a problem")); + mScrollChars = 1; + } + + if (mScrollChars > WHEEL_DELTA) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::SystemSettings::Init(): the result of " + "::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS) is too large: %d", + mScrollChars)); + // See the comments for the case mScrollLines > WHEEL_DELTA. + mScrollChars = WHEEL_PAGESCROLL; + } + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::SystemSettings::Init(): initialized, " + "mScrollLines=%d, mScrollChars=%d", + mScrollLines, mScrollChars)); +} + +void +MouseScrollHandler::SystemSettings::MarkDirty() +{ + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScrollHandler::SystemSettings::MarkDirty(): " + "Marking SystemSettings dirty")); + mInitialized = false; + // When system settings are changed, we should reset current transaction. + MOZ_ASSERT(sInstance, + "Must not be called at initializing MouseScrollHandler"); + MouseScrollHandler::sInstance->mLastEventInfo.ResetTransaction(); +} + +/****************************************************************************** + * + * UserPrefs + * + ******************************************************************************/ + +MouseScrollHandler::UserPrefs::UserPrefs() : + mInitialized(false) +{ + // We need to reset mouse wheel transaction when all of mousewheel related + // prefs are changed. + DebugOnly rv = + Preferences::RegisterCallback(OnChange, "mousewheel.", this); + MOZ_ASSERT(NS_SUCCEEDED(rv), + "Failed to register callback for mousewheel."); +} + +MouseScrollHandler::UserPrefs::~UserPrefs() +{ + DebugOnly rv = + Preferences::UnregisterCallback(OnChange, "mousewheel.", this); + MOZ_ASSERT(NS_SUCCEEDED(rv), + "Failed to unregister callback for mousewheel."); +} + +void +MouseScrollHandler::UserPrefs::Init() +{ + if (mInitialized) { + return; + } + + mInitialized = true; + + mScrollMessageHandledAsWheelMessage = + Preferences::GetBool("mousewheel.emulate_at_wm_scroll", false); + mOverriddenVerticalScrollAmount = + Preferences::GetInt("mousewheel.windows.vertical_amount_override", -1); + mOverriddenHorizontalScrollAmount = + Preferences::GetInt("mousewheel.windows.horizontal_amount_override", -1); + mMouseScrollTransactionTimeout = + Preferences::GetInt("mousewheel.windows.transaction.timeout", + DEFAULT_TIMEOUT_DURATION); + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::UserPrefs::Init(): initialized, " + "mScrollMessageHandledAsWheelMessage=%s, " + "mOverriddenVerticalScrollAmount=%d, " + "mOverriddenHorizontalScrollAmount=%d, " + "mMouseScrollTransactionTimeout=%d", + GetBoolName(mScrollMessageHandledAsWheelMessage), + mOverriddenVerticalScrollAmount, mOverriddenHorizontalScrollAmount, + mMouseScrollTransactionTimeout)); +} + +void +MouseScrollHandler::UserPrefs::MarkDirty() +{ + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScrollHandler::UserPrefs::MarkDirty(): Marking UserPrefs dirty")); + mInitialized = false; + // Some prefs might override system settings, so, we should mark them dirty. + MouseScrollHandler::sInstance->mSystemSettings.MarkDirty(); + // When user prefs for mousewheel are changed, we should reset current + // transaction. + MOZ_ASSERT(sInstance, + "Must not be called at initializing MouseScrollHandler"); + MouseScrollHandler::sInstance->mLastEventInfo.ResetTransaction(); +} + +/****************************************************************************** + * + * Device + * + ******************************************************************************/ + +/* static */ +bool +MouseScrollHandler::Device::GetWorkaroundPref(const char* aPrefName, + bool aValueIfAutomatic) +{ + if (!aPrefName) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::GetWorkaroundPref(): Failed, aPrefName is NULL")); + return aValueIfAutomatic; + } + + int32_t lHackValue = 0; + if (NS_FAILED(Preferences::GetInt(aPrefName, &lHackValue))) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::GetWorkaroundPref(): Preferences::GetInt() failed," + " aPrefName=\"%s\", aValueIfAutomatic=%s", + aPrefName, GetBoolName(aValueIfAutomatic))); + return aValueIfAutomatic; + } + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::GetWorkaroundPref(): Succeeded, " + "aPrefName=\"%s\", aValueIfAutomatic=%s, lHackValue=%d", + aPrefName, GetBoolName(aValueIfAutomatic), lHackValue)); + + switch (lHackValue) { + case 0: // disabled + return false; + case 1: // enabled + return true; + default: // -1: autodetect + return aValueIfAutomatic; + } +} + +/* static */ +void +MouseScrollHandler::Device::Init() +{ + sFakeScrollableWindowNeeded = + GetWorkaroundPref("ui.trackpoint_hack.enabled", + (TrackPoint::IsDriverInstalled() || + UltraNav::IsObsoleteDriverInstalled())); + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::Init(): sFakeScrollableWindowNeeded=%s", + GetBoolName(sFakeScrollableWindowNeeded))); + + Elantech::Init(); +} + +/****************************************************************************** + * + * Device::Elantech + * + ******************************************************************************/ + +/* static */ +void +MouseScrollHandler::Device::Elantech::Init() +{ + int32_t version = GetDriverMajorVersion(); + bool needsHack = + Device::GetWorkaroundPref("ui.elantech_gesture_hacks.enabled", + version != 0); + sUseSwipeHack = needsHack && version <= 7; + sUsePinchHack = needsHack && version <= 8; + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::Elantech::Init(): version=%d, sUseSwipeHack=%s, " + "sUsePinchHack=%s", + version, GetBoolName(sUseSwipeHack), GetBoolName(sUsePinchHack))); +} + +/* static */ +int32_t +MouseScrollHandler::Device::Elantech::GetDriverMajorVersion() +{ + wchar_t buf[40]; + // The driver version is found in one of these two registry keys. + bool foundKey = + WinUtils::GetRegistryKey(HKEY_CURRENT_USER, + L"Software\\Elantech\\MainOption", + L"DriverVersion", + buf, sizeof buf); + if (!foundKey) { + foundKey = + WinUtils::GetRegistryKey(HKEY_CURRENT_USER, + L"Software\\Elantech", + L"DriverVersion", + buf, sizeof buf); + } + + if (!foundKey) { + return 0; + } + + // Assume that the major version number can be found just after a space + // or at the start of the string. + for (wchar_t* p = buf; *p; p++) { + if (*p >= L'0' && *p <= L'9' && (p == buf || *(p - 1) == L' ')) { + return wcstol(p, nullptr, 10); + } + } + + return 0; +} + +/* static */ +bool +MouseScrollHandler::Device::Elantech::IsHelperWindow(HWND aWnd) +{ + // The helper window cannot be distinguished based on its window class, so we + // need to check if it is owned by the helper process, ETDCtrl.exe. + + const wchar_t* filenameSuffix = L"\\etdctrl.exe"; + const int filenameSuffixLength = 12; + + DWORD pid; + ::GetWindowThreadProcessId(aWnd, &pid); + + HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); + if (!hProcess) { + return false; + } + + bool result = false; + wchar_t path[256] = {L'\0'}; + if (::GetProcessImageFileNameW(hProcess, path, ArrayLength(path))) { + int pathLength = lstrlenW(path); + if (pathLength >= filenameSuffixLength) { + if (lstrcmpiW(path + pathLength - filenameSuffixLength, + filenameSuffix) == 0) { + result = true; + } + } + } + ::CloseHandle(hProcess); + + return result; +} + +/* static */ +bool +MouseScrollHandler::Device::Elantech::HandleKeyMessage(nsWindowBase* aWidget, + UINT aMsg, + WPARAM aWParam) +{ + // The Elantech touchpad driver understands three-finger swipe left and + // right gestures, and translates them into Page Up and Page Down key + // events for most applications. For Firefox 3.6, it instead sends + // Alt+Left and Alt+Right to trigger browser back/forward actions. As + // with the Thinkpad Driver hack in nsWindow::Create, the change in + // HWND structure makes Firefox not trigger the driver's heuristics + // any longer. + // + // The Elantech driver actually sends these messages for a three-finger + // swipe right: + // + // WM_KEYDOWN virtual_key = 0xCC or 0xFF (depending on driver version) + // WM_KEYDOWN virtual_key = VK_NEXT + // WM_KEYUP virtual_key = VK_NEXT + // WM_KEYUP virtual_key = 0xCC or 0xFF + // + // so we use the 0xCC or 0xFF key modifier to detect whether the Page Down + // is due to the gesture rather than a regular Page Down keypress. We then + // pretend that we should dispatch "Go Forward" command. Similarly + // for VK_PRIOR and "Go Back" command. + if (sUseSwipeHack && + (aWParam == VK_NEXT || aWParam == VK_PRIOR) && + (IS_VK_DOWN(0xFF) || IS_VK_DOWN(0xCC))) { + if (aMsg == WM_KEYDOWN) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::Elantech::HandleKeyMessage(): Dispatching " + "%s command event", + aWParam == VK_NEXT ? "Forward" : "Back")); + + WidgetCommandEvent commandEvent(true, nsGkAtoms::onAppCommand, + (aWParam == VK_NEXT) ? nsGkAtoms::Forward : nsGkAtoms::Back, aWidget); + InitEvent(aWidget, commandEvent); + aWidget->DispatchWindowEvent(&commandEvent); + } +#ifdef PR_LOGGING + else { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::Elantech::HandleKeyMessage(): Consumed")); + } +#endif + return true; // consume the message (doesn't need to dispatch key events) + } + + // Version 8 of the Elantech touchpad driver sends these messages for + // zoom gestures: + // + // WM_KEYDOWN virtual_key = 0xCC time = 10 + // WM_KEYDOWN virtual_key = VK_CONTROL time = 10 + // WM_MOUSEWHEEL time = ::GetTickCount() + // WM_KEYUP virtual_key = VK_CONTROL time = 10 + // WM_KEYUP virtual_key = 0xCC time = 10 + // + // The result of this is that we process all of the WM_KEYDOWN/WM_KEYUP + // messages first because their timestamps make them appear to have + // been sent before the WM_MOUSEWHEEL message. To work around this, + // we store the current time when we process the WM_KEYUP message and + // assume that any WM_MOUSEWHEEL message with a timestamp before that + // time is one that should be processed as if the Control key was down. + if (sUsePinchHack && aMsg == WM_KEYUP && + aWParam == VK_CONTROL && ::GetMessageTime() == 10) { + // We look only at the bottom 31 bits of the system tick count since + // GetMessageTime returns a LONG, which is signed, so we want values + // that are more easily comparable. + sZoomUntil = ::GetTickCount() & 0x7FFFFFFF; + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::Elantech::HandleKeyMessage(): sZoomUntil=%d", + sZoomUntil)); + } + + return false; +} + +/* static */ +void +MouseScrollHandler::Device::Elantech::UpdateZoomUntil() +{ + if (!sZoomUntil) { + return; + } + + // For the Elantech Touchpad Zoom Gesture Hack, we should check that the + // system time (32-bit milliseconds) hasn't wrapped around. Otherwise we + // might get into the situation where wheel events for the next 50 days of + // system uptime are assumed to be Ctrl+Wheel events. (It is unlikely that + // we would get into that state, because the system would already need to be + // up for 50 days and the Control key message would need to be processed just + // before the system time overflow and the wheel message just after.) + // + // We also take the chance to reset sZoomUntil if we simply have passed that + // time. + LONG msgTime = ::GetMessageTime(); + if ((sZoomUntil >= 0x3fffffffu && DWORD(msgTime) < 0x40000000u) || + (sZoomUntil < DWORD(msgTime))) { + sZoomUntil = 0; + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::Elantech::UpdateZoomUntil(): " + "sZoomUntil was reset")); + } +} + +/* static */ +bool +MouseScrollHandler::Device::Elantech::IsZooming() +{ + // Assume the Control key is down if the Elantech touchpad has sent the + // mis-ordered WM_KEYDOWN/WM_MOUSEWHEEL messages. (See the comment in + // OnKeyUp.) + return (sZoomUntil && static_cast(::GetMessageTime()) < sZoomUntil); +} + +/****************************************************************************** + * + * Device::TrackPoint + * + ******************************************************************************/ + +/* static */ +bool +MouseScrollHandler::Device::TrackPoint::IsDriverInstalled() +{ + if (WinUtils::HasRegistryKey(HKEY_CURRENT_USER, + L"Software\\Lenovo\\TrackPoint")) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::TrackPoint::IsDriverInstalled(): " + "Lenovo's TrackPoint driver is found")); + return true; + } + + if (WinUtils::HasRegistryKey(HKEY_CURRENT_USER, + L"Software\\Alps\\Apoint\\TrackPoint")) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::TrackPoint::IsDriverInstalled(): " + "Alps's TrackPoint driver is found")); + } + + return false; +} + +/****************************************************************************** + * + * Device::UltraNav + * + ******************************************************************************/ + +/* static */ +bool +MouseScrollHandler::Device::UltraNav::IsObsoleteDriverInstalled() +{ + if (WinUtils::HasRegistryKey(HKEY_CURRENT_USER, + L"Software\\Lenovo\\UltraNav")) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::UltraNav::IsObsoleteDriverInstalled(): " + "Lenovo's UltraNav driver is found")); + return true; + } + + bool installed = false; + if (WinUtils::HasRegistryKey(HKEY_CURRENT_USER, + L"Software\\Synaptics\\SynTPEnh\\UltraNavUSB")) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::UltraNav::IsObsoleteDriverInstalled(): " + "Synaptics's UltraNav (USB) driver is found")); + installed = true; + } else if (WinUtils::HasRegistryKey(HKEY_CURRENT_USER, + L"Software\\Synaptics\\SynTPEnh\\UltraNavPS2")) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::UltraNav::IsObsoleteDriverInstalled(): " + "Synaptics's UltraNav (PS/2) driver is found")); + installed = true; + } + + if (!installed) { + return false; + } + + wchar_t buf[40]; + bool foundKey = + WinUtils::GetRegistryKey(HKEY_LOCAL_MACHINE, + L"Software\\Synaptics\\SynTP\\Install", + L"DriverVersion", + buf, sizeof buf); + if (!foundKey) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::UltraNav::IsObsoleteDriverInstalled(): " + "Failed to get UltraNav driver version")); + return false; + } + + int majorVersion = wcstol(buf, nullptr, 10); + int minorVersion = 0; + wchar_t* p = wcschr(buf, L'.'); + if (p) { + minorVersion = wcstol(p + 1, nullptr, 10); + } + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::UltraNav::IsObsoleteDriverInstalled(): " + "found driver version = %d.%d", + majorVersion, minorVersion)); + return majorVersion < 15 || (majorVersion == 15 && minorVersion == 0); +} + +/****************************************************************************** + * + * Device::SetPoint + * + ******************************************************************************/ + +/* static */ +bool +MouseScrollHandler::Device::SetPoint::IsGetMessagePosResponseValid( + UINT aMessage, + WPARAM aWParam, + LPARAM aLParam) +{ + if (aMessage != WM_MOUSEHWHEEL) { + return false; + } + + POINTS pts = MouseScrollHandler::GetCurrentMessagePos(); + LPARAM messagePos = MAKELPARAM(pts.x, pts.y); + + // XXX We should check whether SetPoint is installed or not by registry. + + // SetPoint, Logitech (Logicool) mouse driver, (confirmed with 4.82.11 and + // MX-1100) always sets 0 to the lParam of WM_MOUSEHWHEEL. The driver SENDs + // one message at first time, this time, ::GetMessagePos() works fine. + // Then, we will return 0 (0 means we process it) to the message. Then, the + // driver will POST the same messages continuously during the wheel tilted. + // But ::GetMessagePos() API always returns (0, 0) for them, even if the + // actual mouse cursor isn't 0,0. Therefore, we cannot trust the result of + // ::GetMessagePos API if the sender is SetPoint. + if (!sMightBeUsing && !aLParam && aLParam != messagePos && + ::InSendMessage()) { + sMightBeUsing = true; + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::SetPoint::IsGetMessagePosResponseValid(): " + "Might using SetPoint")); + } else if (sMightBeUsing && aLParam != 0 && ::InSendMessage()) { + // The user has changed the mouse from Logitech's to another one (e.g., + // the user has changed to the touchpad of the notebook. + sMightBeUsing = false; + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::SetPoint::IsGetMessagePosResponseValid(): " + "Might stop using SetPoint")); + } + return (sMightBeUsing && !aLParam && !messagePos); +} + +/****************************************************************************** + * + * SynthesizingEvent + * + ******************************************************************************/ + +/* static */ +bool +MouseScrollHandler::SynthesizingEvent::IsSynthesizing() +{ + return MouseScrollHandler::sInstance && + MouseScrollHandler::sInstance->mSynthesizingEvent && + MouseScrollHandler::sInstance->mSynthesizingEvent->mStatus != + NOT_SYNTHESIZING; +} + +nsresult +MouseScrollHandler::SynthesizingEvent::Synthesize(const POINTS& aCursorPoint, + HWND aWnd, + UINT aMessage, + WPARAM aWParam, + LPARAM aLParam, + const BYTE (&aKeyStates)[256]) +{ + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScrollHandler::SynthesizingEvent::Synthesize(): aCursorPoint: { " + "x: %d, y: %d }, aWnd=0x%X, aMessage=0x%04X, aWParam=0x%08X, " + "aLParam=0x%08X, IsSynthesized()=%s, mStatus=%s", + aCursorPoint.x, aCursorPoint.y, aWnd, aMessage, aWParam, aLParam, + GetBoolName(IsSynthesizing()), GetStatusName())); + + if (IsSynthesizing()) { + return NS_ERROR_NOT_AVAILABLE; + } + + ::GetKeyboardState(mOriginalKeyState); + + // Note that we cannot use ::SetCursorPos() because it works asynchronously. + // We should SEND the message for reducing the possibility of receiving + // unexpected message which were not sent from here. + mCursorPoint = aCursorPoint; + + mWnd = aWnd; + mMessage = aMessage; + mWParam = aWParam; + mLParam = aLParam; + + memcpy(mKeyState, aKeyStates, sizeof(mKeyState)); + ::SetKeyboardState(mKeyState); + + mStatus = SENDING_MESSAGE; + + // Don't assume that aWnd is always managed by nsWindow. It might be + // a plugin window. + ::SendMessage(aWnd, aMessage, aWParam, aLParam); + + return NS_OK; +} + +void +MouseScrollHandler::SynthesizingEvent::NativeMessageReceived(nsWindowBase* aWidget, + UINT aMessage, + WPARAM aWParam, + LPARAM aLParam) +{ + if (mStatus == SENDING_MESSAGE && mMessage == aMessage && + mWParam == aWParam && mLParam == aLParam) { + mStatus = NATIVE_MESSAGE_RECEIVED; + if (aWidget && aWidget->GetWindowHandle() == mWnd) { + return; + } + // If the target window is not ours and received window is our plugin + // window, it comes from child window of the plugin. + if (aWidget && aWidget->IsPlugin() && + !WinUtils::GetNSWindowBasePtr(mWnd)) { + return; + } + // Otherwise, the message may not be sent by us. + } + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScrollHandler::SynthesizingEvent::NativeMessageReceived(): " + "aWidget=%p, aWidget->GetWindowHandle()=0x%X, mWnd=0x%X, " + "aMessage=0x%04X, aWParam=0x%08X, aLParam=0x%08X, mStatus=%s", + aWidget, aWidget ? aWidget->GetWindowHandle() : 0, mWnd, + aMessage, aWParam, aLParam, GetStatusName())); + + // We failed to receive our sent message, we failed to do the job. + Finish(); + + return; +} + +void +MouseScrollHandler::SynthesizingEvent::NotifyNativeMessageHandlingFinished() +{ + if (!IsSynthesizing()) { + return; + } + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScrollHandler::SynthesizingEvent::" + "NotifyNativeMessageHandlingFinished(): IsWaitingInternalMessage=%s", + GetBoolName(MouseScrollHandler::IsWaitingInternalMessage()))); + + if (MouseScrollHandler::IsWaitingInternalMessage()) { + mStatus = INTERNAL_MESSAGE_POSTED; + return; + } + + // If the native message handler didn't post our internal message, + // we our job is finished. + // TODO: When we post the message to plugin window, there is remaning job. + Finish(); +} + +void +MouseScrollHandler::SynthesizingEvent::NotifyInternalMessageHandlingFinished() +{ + if (!IsSynthesizing()) { + return; + } + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScrollHandler::SynthesizingEvent::" + "NotifyInternalMessageHandlingFinished()")); + + Finish(); +} + +void +MouseScrollHandler::SynthesizingEvent::Finish() +{ + if (!IsSynthesizing()) { + return; + } + + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScrollHandler::SynthesizingEvent::Finish()")); + + // Restore the original key state. + ::SetKeyboardState(mOriginalKeyState); + + mStatus = NOT_SYNTHESIZING; +} + +} // namespace widget +} // namespace mozilla diff --git a/widget/windows/nsAppShell.cpp b/widget/windows/nsAppShell.cpp index b49d3fd09d..7971f82544 100644 --- a/widget/windows/nsAppShell.cpp +++ b/widget/windows/nsAppShell.cpp @@ -180,7 +180,7 @@ nsAppShell::Exit(void) } void -nsAppShell::DoProcessMoreGoannaEvents() +nsAppShell::DoProcessMoreGeckoEvents() { // Called by nsBaseAppShell's NativeEventCallback() after it has finished // processing pending goanna events and there are still goanna events pending @@ -231,7 +231,7 @@ bool nsAppShell::ProcessNextNativeEvent(bool mayWait) { // Notify ipc we are spinning a (possibly nested) goanna event loop. - mozilla::ipc::MessageChannel::NotifyGoannaEventDispatch(); + mozilla::ipc::MessageChannel::NotifyGeckoEventDispatch(); bool gotMessage = false; @@ -294,7 +294,7 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) // See DoProcessNextNativeEvent, mEventloopNestingLevel will be // one when a modal loop unwinds. if (mNativeCallbackPending && mEventloopNestingLevel == 1) - DoProcessMoreGoannaEvents(); + DoProcessMoreGeckoEvents(); // Check for starved native callbacks. If we haven't processed one // of these events in NATIVE_EVENT_STARVATION_LIMIT, fire one off. diff --git a/widget/windows/nsAppShell.h b/widget/windows/nsAppShell.h index 874090711c..bc3833ba15 100644 --- a/widget/windows/nsAppShell.h +++ b/widget/windows/nsAppShell.h @@ -30,7 +30,7 @@ public: typedef mozilla::Mutex Mutex; nsresult Init(); - void DoProcessMoreGoannaEvents(); + void DoProcessMoreGeckoEvents(); static UINT GetTaskbarButtonCreatedMessage(); diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index f6f28df68d..0087d872ad 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -1292,28 +1292,30 @@ void nsWindow::SetThemeRegion() /************************************************************** * - * SECTION: nsIWidget::RegisterTouchWindow, - * nsIWidget::UnregisterTouchWindow, and helper functions - * - * Used to register the native window to receive touch events + * SECTION: Touch and APZ-related functions * **************************************************************/ -NS_METHOD nsWindow::RegisterTouchWindow() { +void nsWindow::ConfigureAPZCTreeManager() +{ + nsBaseWidget::ConfigureAPZCTreeManager(); + + // When APZ is enabled, we can actually enable raw touch events because we + // have code that can deal with them properly. If APZ is not enabled, this + // function doesn't get called, and |mGesture| will take care of touch-based + // scrolling. Note that RegisterTouchWindow may still do nothing depending + // on touch/pointer events prefs, and so it is possible to enable APZ without + // also enabling touch support. + RegisterTouchWindow(); +} + +void nsWindow::RegisterTouchWindow() { if (Preferences::GetInt("dom.w3c_touch_events.enabled", 0) || gIsPointerEventsEnabled) { mTouchWindow = true; mGesture.RegisterTouchWindow(mWnd); ::EnumChildWindows(mWnd, nsWindow::RegisterTouchForDescendants, 0); } - return NS_OK; -} - -NS_METHOD nsWindow::UnregisterTouchWindow() { - mTouchWindow = false; - mGesture.UnregisterTouchWindow(mWnd); - ::EnumChildWindows(mWnd, nsWindow::UnregisterTouchForDescendants, 0); - return NS_OK; } BOOL CALLBACK nsWindow::RegisterTouchForDescendants(HWND aWnd, LPARAM aMsg) { @@ -1323,13 +1325,6 @@ BOOL CALLBACK nsWindow::RegisterTouchForDescendants(HWND aWnd, LPARAM aMsg) { return TRUE; } -BOOL CALLBACK nsWindow::UnregisterTouchForDescendants(HWND aWnd, LPARAM aMsg) { - nsWindow* win = WinUtils::GetNSWindowPtr(aWnd); - if (win) - win->mGesture.UnregisterTouchWindow(aWnd); - return TRUE; -} - /************************************************************** * * SECTION: nsIWidget::Move, nsIWidget::Resize, @@ -6268,13 +6263,13 @@ bool nsWindow::OnTouch(WPARAM wParam, LPARAM lParam) // Dispatch touch start and move event if we have one. if (touchEventToSend) { - DispatchEvent(touchEventToSend, status); + status = DispatchAPZAwareEvent(touchEventToSend); delete touchEventToSend; } // Dispatch touch end event if we have one. if (touchEndEventToSend) { - DispatchEvent(touchEndEventToSend, status); + status = DispatchAPZAwareEvent(touchEndEventToSend); delete touchEndEventToSend; } } diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h index f597c6385a..b29dc268c3 100644 --- a/widget/windows/nsWindow.h +++ b/widget/windows/nsWindow.h @@ -183,8 +183,6 @@ public: const InputContextAction& aAction); NS_IMETHOD_(InputContext) GetInputContext(); NS_IMETHOD GetToggledKeyState(uint32_t aKeyCode, bool* aLEDState); - NS_IMETHOD RegisterTouchWindow(); - NS_IMETHOD UnregisterTouchWindow(); #ifdef MOZ_XUL virtual void SetTransparencyMode(nsTransparencyMode aMode); virtual nsTransparencyMode GetTransparencyMode(); @@ -287,6 +285,8 @@ protected: virtual ~nsWindow(); virtual void WindowUsesOMTC() override; + virtual void ConfigureAPZCTreeManager() override; + void RegisterTouchWindow(); virtual nsresult NotifyIMEInternal( const IMENotification& aIMENotification) override; diff --git a/xpcom/base/nsIException.idl b/xpcom/base/nsIException.idl index 1f9702d2ec..c576b9adbb 100644 --- a/xpcom/base/nsIException.idl +++ b/xpcom/base/nsIException.idl @@ -10,8 +10,6 @@ #include "nsISupports.idl" -[ptr] native JSContext(JSContext); - [scriptable, uuid(4371b5bf-6845-487f-8d9d-3f1e4a9badd2)] interface nsIStackFrame : nsISupports { @@ -26,20 +24,12 @@ interface nsIStackFrame : nsISupports readonly attribute AUTF8String sourceLine; readonly attribute nsIStackFrame caller; - // Returns the first frame whose principals are subsumed by the caller's - // principals. - [noscript, implicit_jscontext] readonly attribute nsIStackFrame sanitized; - // Returns a formatted stack string that looks like the sort of // string that would be returned by .stack on JS Error objects. // Only works on JS-language stack frames. readonly attribute AString formattedStack; AUTF8String toString(); - - // Return whether this stack frame can be accessed by the caller. This is - // safe to call on non-main threads, but will always report "yes" there. - [noscript, notxpcom, nostdcall] boolean callerSubsumes(in JSContext aCx); }; [scriptable, uuid(1caf1461-be1d-4b79-a552-5292b6bf3c35)] diff --git a/xpcom/base/nsSystemInfo.cpp b/xpcom/base/nsSystemInfo.cpp index 96ae171f3b..b6909807f5 100644 --- a/xpcom/base/nsSystemInfo.cpp +++ b/xpcom/base/nsSystemInfo.cpp @@ -294,7 +294,7 @@ nsSystemInfo::Init() "android/os/Build", "HARDWARE", str)) { SetPropertyAsAString(NS_LITERAL_STRING("hardware"), str); } - bool isTablet = mozilla::widget::GoannaAppShell::IsTablet(); + bool isTablet = mozilla::widget::GeckoAppShell::IsTablet(); SetPropertyAsBool(NS_LITERAL_STRING("tablet"), isTablet); // NSPR "version" is the kernel version. For Android we want the Android version. // Rename SDK version to version and put the kernel version into kernel_version. diff --git a/xpcom/components/ManifestParser.cpp b/xpcom/components/ManifestParser.cpp index 939f09669d..b9d1aace04 100644 --- a/xpcom/components/ManifestParser.cpp +++ b/xpcom/components/ManifestParser.cpp @@ -581,7 +581,7 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf, mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "RELEASE", osVersion); - isTablet = mozilla::widget::GoannaAppShell::IsTablet(); + isTablet = mozilla::widget::GeckoAppShell::IsTablet(); } #endif diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp index 404e34016e..b417582215 100644 --- a/xpcom/io/nsLocalFileUnix.cpp +++ b/xpcom/io/nsLocalFileUnix.cpp @@ -2044,7 +2044,7 @@ nsLocalFile::Launch() } nsAutoCString fileUri = NS_LITERAL_CSTRING("file://") + mPath; - return widget::GoannaAppShell::OpenUriExternal( + return widget::GeckoAppShell::OpenUriExternal( NS_ConvertUTF8toUTF16(fileUri), NS_ConvertUTF8toUTF16(type), EmptyString(), diff --git a/xpcom/reflect/xptcall/md/unix/moz.build b/xpcom/reflect/xptcall/md/unix/moz.build index fbdc8533c6..ed5252720c 100644 --- a/xpcom/reflect/xptcall/md/unix/moz.build +++ b/xpcom/reflect/xptcall/md/unix/moz.build @@ -258,7 +258,7 @@ if CONFIG['OS_ARCH'] == 'OpenBSD' and CONFIG['OS_TEST'] == 'sparc': 'xptcstubs_sparc_openbsd.cpp', ] -if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD', 'Linux') and CONFIG['OS_TEST'] == 'sparc64': +if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD', 'NetBSD', 'Linux') and CONFIG['OS_TEST'] == 'sparc64': SOURCES += [ 'xptcinvoke_asm_sparc64_openbsd.s', 'xptcinvoke_sparc64_openbsd.cpp', diff --git a/xpfe/appshell/nsContentTreeOwner.cpp b/xpfe/appshell/nsContentTreeOwner.cpp index c91dc0d2a3..fd3a649db5 100644 --- a/xpfe/appshell/nsContentTreeOwner.cpp +++ b/xpfe/appshell/nsContentTreeOwner.cpp @@ -809,7 +809,7 @@ NS_IMETHODIMP nsContentTreeOwner::SetTitle(const char16_t* aTitle) nsIDocument* document = docShellElement->OwnerDoc(); ErrorResult rv; document->SetTitle(title, rv); - return rv.ErrorCode(); + return rv.StealNSResult(); } return mXULWindow->SetTitle(title.get()); diff --git a/xpfe/appshell/nsWindowMediator.cpp b/xpfe/appshell/nsWindowMediator.cpp index 3f7861c6c8..319c6d4ead 100644 --- a/xpfe/appshell/nsWindowMediator.cpp +++ b/xpfe/appshell/nsWindowMediator.cpp @@ -221,15 +221,14 @@ nsWindowMediator::GetZOrderDOMWindowEnumerator( NS_ENSURE_ARG_POINTER(_retval); NS_ENSURE_STATE(mReady); - nsAppShellWindowEnumerator *enumerator; + nsRefPtr enumerator; if (aFrontToBack) enumerator = new nsASDOMWindowFrontToBackEnumerator(aWindowType, *this); else enumerator = new nsASDOMWindowBackToFrontEnumerator(aWindowType, *this); - if (enumerator) - return CallQueryInterface(enumerator, _retval); - return NS_ERROR_OUT_OF_MEMORY; + enumerator.forget(_retval); + return NS_OK; } NS_IMETHODIMP @@ -241,15 +240,14 @@ nsWindowMediator::GetZOrderXULWindowEnumerator( NS_ENSURE_ARG_POINTER(_retval); NS_ENSURE_STATE(mReady); - nsAppShellWindowEnumerator *enumerator; + nsRefPtr enumerator; if (aFrontToBack) enumerator = new nsASXULWindowFrontToBackEnumerator(aWindowType, *this); else enumerator = new nsASXULWindowBackToFrontEnumerator(aWindowType, *this); - if (enumerator) - return CallQueryInterface(enumerator, _retval); - return NS_ERROR_OUT_OF_MEMORY; + enumerator.forget(_retval); + return NS_OK; } int32_t diff --git a/xpfe/components/directory/nsDirectoryViewer.cpp b/xpfe/components/directory/nsDirectoryViewer.cpp index 97a36fc399..78d90f26c4 100644 --- a/xpfe/components/directory/nsDirectoryViewer.cpp +++ b/xpfe/components/directory/nsDirectoryViewer.cpp @@ -153,8 +153,9 @@ nsHTTPIndex::OnFTPControlLog(bool server, const char *msg) NS_ENSURE_TRUE(globalObject, NS_OK); // We're going to run script via JS_CallFunctionName, so we need an - // AutoEntryScript. This is Goanna specific and not in any spec. - dom::AutoEntryScript aes(globalObject); + // AutoEntryScript. This is Gecko specific and not in any spec. + dom::AutoEntryScript aes(globalObject, + "nsHTTPIndex OnFTPControlLog"); JSContext* cx = aes.cx(); JS::Rooted global(cx, JS::CurrentGlobalOrNull(cx)); @@ -226,8 +227,9 @@ nsHTTPIndex::OnStartRequest(nsIRequest *request, nsISupports* aContext) NS_ENSURE_TRUE(globalObject, NS_ERROR_FAILURE); // We might run script via JS_SetProperty, so we need an AutoEntryScript. - // This is Goanna specific and not in any spec. - dom::AutoEntryScript aes(globalObject); + // This is Gecko specific and not in any spec. + dom::AutoEntryScript aes(globalObject, + "nsHTTPIndex set HTTPIndex property"); JSContext* cx = aes.cx(); JS::Rooted global(cx, JS::CurrentGlobalOrNull(cx)); @@ -1288,7 +1290,7 @@ nsDirectoryViewerFactory::CreateInstance(const char *aCommand, if (NS_FAILED(rv)) return rv; nsXPIDLCString contractID; - rv = catMan->GetCategoryEntry("Goanna-Content-Viewers", "application/vnd.mozilla.xul+xml", + rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", "application/vnd.mozilla.xul+xml", getter_Copies(contractID)); if (NS_FAILED(rv)) return rv; @@ -1348,7 +1350,7 @@ nsDirectoryViewerFactory::CreateInstance(const char *aCommand, if (NS_FAILED(rv)) return rv; nsXPIDLCString contractID; - rv = catMan->GetCategoryEntry("Goanna-Content-Viewers", "text/html", + rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", "text/html", getter_Copies(contractID)); if (NS_FAILED(rv)) return rv; diff --git a/xpfe/components/windowds/nsWindowDataSource.cpp b/xpfe/components/windowds/nsWindowDataSource.cpp index 7ee126e6b2..8c51a2f10e 100644 --- a/xpfe/components/windowds/nsWindowDataSource.cpp +++ b/xpfe/components/windowds/nsWindowDataSource.cpp @@ -365,7 +365,8 @@ NS_IMETHODIMP nsWindowDataSource::GetTarget(nsIRDFResource *aSource, nsIRDFResou if (NS_FAILED(rv)) return(rv); if (!indexInt) return(NS_ERROR_FAILURE); - return CallQueryInterface(indexInt, _retval); + indexInt.forget(_retval); + return NS_OK; } return mInner->GetTarget(aSource, aProperty, aTruthValue, _retval);