/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=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/. */ #ifndef mozilla_dom_Console_h #define mozilla_dom_Console_h #include "mozilla/dom/BindingDeclarations.h" #include "mozilla/ErrorResult.h" #include "mozilla/JSObjectHolder.h" #include "nsCycleCollectionParticipant.h" #include "nsDataHashtable.h" #include "nsHashKeys.h" #include "nsIObserver.h" #include "nsWrapperCache.h" #include "nsDOMNavigationTiming.h" #include "nsPIDOMWindow.h" class nsIConsoleAPIStorage; class nsIPrincipal; namespace mozilla { namespace dom { class ConsoleCallData; class ConsoleRunnable; class ConsoleCallDataRunnable; class ConsoleProfileRunnable; struct ConsoleStackEntry; class Console final : public nsIObserver , public nsWrapperCache { ~Console(); public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Console) NS_DECL_NSIOBSERVER explicit Console(nsPIDOMWindow* aWindow); // WebIDL methods nsISupports* GetParentObject() const { return mWindow; } virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; void Log(JSContext* aCx, const Sequence& aData); void Info(JSContext* aCx, const Sequence& aData); void Warn(JSContext* aCx, const Sequence& aData); void Error(JSContext* aCx, const Sequence& aData); void Exception(JSContext* aCx, const Sequence& aData); void Debug(JSContext* aCx, const Sequence& aData); void Table(JSContext* aCx, const Sequence& aData); void Trace(JSContext* aCx); void Dir(JSContext* aCx, const Sequence& aData); void Dirxml(JSContext* aCx, const Sequence& aData); void Group(JSContext* aCx, const Sequence& aData); void GroupCollapsed(JSContext* aCx, const Sequence& aData); void GroupEnd(JSContext* aCx, const Sequence& aData); void Time(JSContext* aCx, const JS::Handle aTime); void TimeEnd(JSContext* aCx, const JS::Handle aTime); void TimeStamp(JSContext* aCx, const JS::Handle aData); void Profile(JSContext* aCx, const Sequence& aData); void ProfileEnd(JSContext* aCx, const Sequence& aData); void Assert(JSContext* aCx, bool aCondition, const Sequence& aData); void Count(JSContext* aCx, const Sequence& aData); void NoopMethod(); private: enum MethodName { MethodLog, MethodInfo, MethodWarn, MethodError, MethodException, MethodDebug, MethodTable, MethodTrace, MethodDir, MethodDirxml, MethodGroup, MethodGroupCollapsed, MethodGroupEnd, MethodTime, MethodTimeEnd, MethodTimeStamp, MethodAssert, MethodCount }; void Method(JSContext* aCx, MethodName aName, const nsAString& aString, const Sequence& aData); void ProcessCallData(ConsoleCallData* aData, JS::Handle aGlobal, const Sequence& aArguments); // If the first JS::Value of the array is a string, this method uses it to // format a string. The supported sequences are: // %s - string // %d,%i - integer // %f - double // %o,%O - a JS object. // %c - style string. // The output is an array where any object is a separated item, the rest is // unified in a format string. // Example if the input is: // "string: %s, integer: %d, object: %o, double: %d", 's', 1, window, 0.9 // The output will be: // [ "string: s, integer: 1, object: ", window, ", double: 0.9" ] // // The aStyles array is populated with the style strings that the function // finds based the format string. The index of the styles matches the indexes // of elements that need the custom styling from aSequence. For elements with // no custom styling the array is padded with null elements. bool ProcessArguments(JSContext* aCx, const Sequence& aData, Sequence& aSequence, Sequence& aStyles) const; void MakeFormatString(nsCString& aFormat, int32_t aInteger, int32_t aMantissa, char aCh) const; // Stringify and Concat all the JS::Value in a single string using ' ' as // separator. void ComposeGroupName(JSContext* aCx, const Sequence& aData, nsAString& aName) const; JS::Value StartTimer(JSContext* aCx, const JS::Value& aName, DOMHighResTimeStamp aTimestamp); JS::Value StopTimer(JSContext* aCx, const JS::Value& aName, DOMHighResTimeStamp aTimestamp); // The method populates a Sequence from an array of JS::Value. bool ArgumentsToValueList(const Sequence& aData, Sequence& aSequence) const; void ProfileMethod(JSContext* aCx, const nsAString& aAction, const Sequence& aData); JS::Value IncreaseCounter(JSContext* aCx, const ConsoleStackEntry& aFrame, const Sequence& aArguments); bool ShouldIncludeStackTrace(MethodName aMethodName) const; JSObject* GetOrCreateSandbox(JSContext* aCx, nsIPrincipal* aPrincipal); void RegisterConsoleCallData(ConsoleCallData* aData); void UnregisterConsoleCallData(ConsoleCallData* aData); // All these nsCOMPtr are touched on main-thread only. nsCOMPtr mWindow; nsCOMPtr mStorage; RefPtr mSandbox; // Touched on main-thread only. nsDataHashtable mTimerRegistry; // Touched on main-thread only. nsDataHashtable mCounterRegistry; // Raw pointers because ConsoleCallData manages its own // registration/unregistration. nsTArray mConsoleCallDataArray; uint64_t mOuterID; uint64_t mInnerID; friend class ConsoleCallData; friend class ConsoleRunnable; friend class ConsoleCallDataRunnable; friend class ConsoleProfileRunnable; }; } // namespace dom } // namespace mozilla #endif /* mozilla_dom_Console_h */