зеркало из https://github.com/mozilla/gecko-dev.git
Merge fx-team to m-c. a=merge
This commit is contained in:
Коммит
b2d76b60ec
|
@ -48,7 +48,7 @@ AppValidator.prototype._getPackagedManifestFile = function () {
|
|||
let hasJsonManifest = jsonManifestFile.exists() && jsonManifestFile.isFile();
|
||||
|
||||
if (!hasAppManifest && !hasJsonManifest) {
|
||||
this.error(strings.GetStringFromName("validator.wrongManifestFileName"));
|
||||
this.error(strings.GetStringFromName("validator.noManifestFile"));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -338,7 +338,7 @@ let PerformanceController = {
|
|||
*/
|
||||
exportRecording: Task.async(function*(_, recording, file) {
|
||||
yield recording.exportRecording(file);
|
||||
this.emit(EVENTS.RECORDING_EXPORTED, recording);
|
||||
this.emit(EVENTS.RECORDING_EXPORTED, recording, file);
|
||||
}),
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
let test = Task.async(function*() {
|
||||
var { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
|
||||
var { EVENTS, PerformanceController, PerformanceView, DetailsView, DetailsSubview } = panel.panelWin;
|
||||
var { $, EVENTS, PerformanceController, PerformanceView, DetailsView, DetailsSubview } = panel.panelWin;
|
||||
|
||||
// Enable allocations to test the memory-calltree and memory-flamegraph.
|
||||
Services.prefs.setBoolPref(ALLOCATIONS_PREF, true);
|
||||
|
@ -45,6 +45,13 @@ let test = Task.async(function*() {
|
|||
yield exported;
|
||||
ok(true, "The recording data appears to have been successfully saved.");
|
||||
|
||||
// Check if the imported file name has tmpprofile in it as the file
|
||||
// names also has different suffix to avoid conflict
|
||||
|
||||
let displayedName = $(".recording-item-title").getAttribute("value");
|
||||
ok(/^tmpprofile/.test(displayedName), "File has expected display name after import");
|
||||
ok(!/\.json$/.test(displayedName), "Display name does not have .json in it");
|
||||
|
||||
// Import recording.
|
||||
|
||||
let rerendered = waitForWidgetsRendered(panel);
|
||||
|
|
|
@ -18,12 +18,14 @@ let RecordingsView = Heritage.extend(WidgetMethods, {
|
|||
this._onNewRecording = this._onNewRecording.bind(this);
|
||||
this._onSaveButtonClick = this._onSaveButtonClick.bind(this);
|
||||
this._onRecordingsCleared = this._onRecordingsCleared.bind(this);
|
||||
this._onRecordingExported = this._onRecordingExported.bind(this);
|
||||
|
||||
this.emptyText = L10N.getStr("noRecordingsText");
|
||||
|
||||
PerformanceController.on(EVENTS.RECORDING_STATE_CHANGE, this._onRecordingStateChange);
|
||||
PerformanceController.on(EVENTS.NEW_RECORDING, this._onNewRecording);
|
||||
PerformanceController.on(EVENTS.RECORDINGS_CLEARED, this._onRecordingsCleared);
|
||||
PerformanceController.on(EVENTS.RECORDING_EXPORTED, this._onRecordingExported);
|
||||
this.widget.addEventListener("select", this._onSelect, false);
|
||||
},
|
||||
|
||||
|
@ -34,6 +36,7 @@ let RecordingsView = Heritage.extend(WidgetMethods, {
|
|||
PerformanceController.off(EVENTS.RECORDING_STATE_CHANGE, this._onRecordingStateChange);
|
||||
PerformanceController.off(EVENTS.NEW_RECORDING, this._onNewRecording);
|
||||
PerformanceController.off(EVENTS.RECORDINGS_CLEARED, this._onRecordingsCleared);
|
||||
PerformanceController.off(EVENTS.RECORDING_EXPORTED, this._onRecordingExported);
|
||||
this.widget.removeEventListener("select", this._onSelect, false);
|
||||
},
|
||||
|
||||
|
@ -197,6 +200,15 @@ let RecordingsView = Heritage.extend(WidgetMethods, {
|
|||
}});
|
||||
},
|
||||
|
||||
_onRecordingExported: function (_, recording, file) {
|
||||
if (recording.isConsole()) {
|
||||
return;
|
||||
}
|
||||
let recordingItem = this.getItemForPredicate(e => e.attachment === recording);
|
||||
let titleNode = $(".recording-item-title", recordingItem.target);
|
||||
titleNode.setAttribute("value", file.leafName.replace(/\..+$/, ""));
|
||||
},
|
||||
|
||||
toString: () => "[object RecordingsView]"
|
||||
});
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ project.installing=Installing…
|
|||
project.installed=Installed!
|
||||
validator.nonExistingFolder=The project folder doesn't exists
|
||||
validator.expectProjectFolder=The project folder ends up being a file
|
||||
validator.wrongManifestFileName=A manifest file is required at project root folder, named either 'manifest.webapp' for packaged apps or 'manifest.json' for addons.
|
||||
validator.noManifestFile=A manifest file is required at project root folder, named either 'manifest.webapp' for packaged apps or 'manifest.json' for add-ons.
|
||||
validator.invalidManifestURL=Invalid manifest URL '%S'
|
||||
# LOCALIZATION NOTE (validator.invalidManifestJSON, validator.noAccessManifestURL):
|
||||
# %1$S is the error message, %2$S is the URI of the manifest.
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
#include "nsSHistory.h"
|
||||
#include "nsDocShellEditorData.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "timeline/JavascriptTimelineMarker.h"
|
||||
|
||||
// Helper Classes
|
||||
#include "nsError.h"
|
||||
|
@ -1601,7 +1602,7 @@ nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI,
|
|||
(void)aLoadInfo->GetLoadType(<);
|
||||
// Get the appropriate LoadType from nsIDocShellLoadInfo type
|
||||
loadType = ConvertDocShellLoadInfoToLoadType(lt);
|
||||
|
||||
|
||||
nsCOMPtr<nsISupports> owner;
|
||||
aLoadInfo->GetOwner(getter_AddRefs(owner));
|
||||
requestingPrincipal = do_QueryInterface(owner);
|
||||
|
@ -13763,51 +13764,6 @@ nsDocShell::GetOpener()
|
|||
return opener;
|
||||
}
|
||||
|
||||
class JavascriptTimelineMarker : public TimelineMarker
|
||||
{
|
||||
public:
|
||||
JavascriptTimelineMarker(nsDocShell* aDocShell, const char* aName,
|
||||
const char* aReason,
|
||||
const char16_t* aFunctionName,
|
||||
const char16_t* aFileName,
|
||||
uint32_t aLineNumber)
|
||||
: TimelineMarker(aDocShell, aName, TRACING_INTERVAL_START,
|
||||
NS_ConvertUTF8toUTF16(aReason),
|
||||
NO_STACK)
|
||||
, mFunctionName(aFunctionName)
|
||||
, mFileName(aFileName)
|
||||
, mLineNumber(aLineNumber)
|
||||
{
|
||||
}
|
||||
|
||||
void AddDetails(JSContext* aCx, mozilla::dom::ProfileTimelineMarker& aMarker)
|
||||
override
|
||||
{
|
||||
aMarker.mCauseName.Construct(GetCause());
|
||||
|
||||
if (!mFunctionName.IsEmpty() || !mFileName.IsEmpty()) {
|
||||
RootedDictionary<ProfileTimelineStackFrame> stackFrame(aCx);
|
||||
stackFrame.mLine.Construct(mLineNumber);
|
||||
stackFrame.mSource.Construct(mFileName);
|
||||
stackFrame.mFunctionDisplayName.Construct(mFunctionName);
|
||||
|
||||
JS::Rooted<JS::Value> newStack(aCx);
|
||||
if (ToJSValue(aCx, stackFrame, &newStack)) {
|
||||
if (newStack.isObject()) {
|
||||
aMarker.mStack = &newStack.toObject();
|
||||
}
|
||||
} else {
|
||||
JS_ClearPendingException(aCx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsString mFunctionName;
|
||||
nsString mFileName;
|
||||
uint32_t mLineNumber;
|
||||
};
|
||||
|
||||
void
|
||||
nsDocShell::NotifyJSRunToCompletionStart(const char* aReason,
|
||||
const char16_t* aFunctionName,
|
||||
|
@ -13818,10 +13774,8 @@ nsDocShell::NotifyJSRunToCompletionStart(const char* aReason,
|
|||
|
||||
// If first start, mark interval start.
|
||||
if (timelineOn && mJSRunToCompletionDepth == 0) {
|
||||
mozilla::UniquePtr<TimelineMarker> marker =
|
||||
MakeUnique<JavascriptTimelineMarker>(this, "Javascript", aReason,
|
||||
aFunctionName, aFilename,
|
||||
aLineNumber);
|
||||
UniquePtr<TimelineMarker> marker = MakeUnique<JavascriptTimelineMarker>(
|
||||
aReason, aFunctionName, aFilename, aLineNumber, MarkerTracingType::START);
|
||||
TimelineConsumers::AddMarkerForDocShell(this, Move(marker));
|
||||
}
|
||||
mJSRunToCompletionDepth++;
|
||||
|
@ -13835,7 +13789,7 @@ nsDocShell::NotifyJSRunToCompletionStop()
|
|||
// If last stop, mark interval end.
|
||||
mJSRunToCompletionDepth--;
|
||||
if (timelineOn && mJSRunToCompletionDepth == 0) {
|
||||
TimelineConsumers::AddMarkerForDocShell(this, "Javascript", TRACING_INTERVAL_END);
|
||||
TimelineConsumers::AddMarkerForDocShell(this, "Javascript", MarkerTracingType::END);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,9 +33,9 @@
|
|||
#include "nsAutoPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "timeline/TimelineMarker.h"
|
||||
#include "timeline/TimelineConsumers.h"
|
||||
#include "timeline/ObservedDocShell.h"
|
||||
#include "timeline/TimelineConsumers.h"
|
||||
#include "timeline/TimelineMarker.h"
|
||||
|
||||
// Threshold value in ms for META refresh based redirects
|
||||
#define REFRESH_REDIRECT_TIMER 15000
|
||||
|
@ -275,14 +275,14 @@ private:
|
|||
// be very fast, so instead of using a Map or having to search for some
|
||||
// docshell-specific markers storage, a pointer to an `ObservedDocShell` is
|
||||
// is stored on docshells directly.
|
||||
friend void mozilla::TimelineConsumers::AddConsumer(nsDocShell* aDocShell);
|
||||
friend void mozilla::TimelineConsumers::RemoveConsumer(nsDocShell* aDocShell);
|
||||
friend void mozilla::TimelineConsumers::AddConsumer(nsDocShell*);
|
||||
friend void mozilla::TimelineConsumers::RemoveConsumer(nsDocShell*);
|
||||
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
|
||||
nsDocShell* aDocShell, const char* aName, TracingMetadata aMetaData);
|
||||
nsDocShell*, const char*, MarkerTracingType);
|
||||
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
|
||||
nsDocShell* aDocShell, const char* aName, const TimeStamp& aTime, TracingMetadata aMetaData);
|
||||
nsDocShell*, const char*, const TimeStamp&, MarkerTracingType);
|
||||
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
|
||||
nsDocShell* aDocShell, UniquePtr<TimelineMarker>&& aMarker);
|
||||
nsDocShell*, UniquePtr<TimelineMarker>&&);
|
||||
|
||||
public:
|
||||
// Tell the favicon service that aNewURI has the same favicon as aOldURI.
|
||||
|
|
|
@ -22,7 +22,7 @@ AutoGlobalTimelineMarker::AutoGlobalTimelineMarker(const char* aName
|
|||
return;
|
||||
}
|
||||
|
||||
TimelineConsumers::AddMarkerForAllObservedDocShells(mName, TRACING_INTERVAL_START);
|
||||
TimelineConsumers::AddMarkerForAllObservedDocShells(mName, MarkerTracingType::START);
|
||||
}
|
||||
|
||||
AutoGlobalTimelineMarker::~AutoGlobalTimelineMarker()
|
||||
|
@ -31,7 +31,7 @@ AutoGlobalTimelineMarker::~AutoGlobalTimelineMarker()
|
|||
return;
|
||||
}
|
||||
|
||||
TimelineConsumers::AddMarkerForAllObservedDocShells(mName, TRACING_INTERVAL_END);
|
||||
TimelineConsumers::AddMarkerForAllObservedDocShells(mName, MarkerTracingType::END);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace mozilla {
|
|||
// Similar to `AutoTimelineMarker`, but adds its traced marker to all docshells,
|
||||
// not a single particular one. This is useful for operations that aren't
|
||||
// associated with any one particular doc shell, or when it isn't clear which
|
||||
// doc shell triggered the operation.
|
||||
// docshell triggered the operation.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
|
|
|
@ -25,7 +25,7 @@ AutoTimelineMarker::AutoTimelineMarker(nsIDocShell* aDocShell, const char* aName
|
|||
}
|
||||
|
||||
mDocShell = static_cast<nsDocShell*>(aDocShell);
|
||||
TimelineConsumers::AddMarkerForDocShell(mDocShell, mName, TRACING_INTERVAL_START);
|
||||
TimelineConsumers::AddMarkerForDocShell(mDocShell, mName, MarkerTracingType::START);
|
||||
}
|
||||
|
||||
AutoTimelineMarker::~AutoTimelineMarker()
|
||||
|
@ -34,7 +34,7 @@ AutoTimelineMarker::~AutoTimelineMarker()
|
|||
return;
|
||||
}
|
||||
|
||||
TimelineConsumers::AddMarkerForDocShell(mDocShell, mName, TRACING_INTERVAL_END);
|
||||
TimelineConsumers::AddMarkerForDocShell(mDocShell, mName, MarkerTracingType::END);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* -*- 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_ConsoleTimelineMarker_h_
|
||||
#define mozilla_ConsoleTimelineMarker_h_
|
||||
|
||||
#include "TimelineMarker.h"
|
||||
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ConsoleTimelineMarker : public TimelineMarker
|
||||
{
|
||||
public:
|
||||
explicit ConsoleTimelineMarker(const nsAString& aCause,
|
||||
MarkerTracingType aTracingType)
|
||||
: TimelineMarker("ConsoleTime", aTracingType)
|
||||
, mCause(aCause)
|
||||
{
|
||||
// Stack is captured by default on the "start" marker. Explicitly also
|
||||
// capture stack on the "end" marker.
|
||||
if (aTracingType == MarkerTracingType::END) {
|
||||
CaptureStack();
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool Equals(const TimelineMarker& aOther) override
|
||||
{
|
||||
if (!TimelineMarker::Equals(aOther)) {
|
||||
return false;
|
||||
}
|
||||
// Console markers must have matching causes as well. It is safe to perform
|
||||
// a static_cast here as the previous equality check ensures that this is
|
||||
// a console marker instance.
|
||||
return mCause == static_cast<const ConsoleTimelineMarker*>(&aOther)->mCause;
|
||||
}
|
||||
|
||||
virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) override
|
||||
{
|
||||
if (GetTracingType() == MarkerTracingType::START) {
|
||||
aMarker.mCauseName.Construct(mCause);
|
||||
} else {
|
||||
aMarker.mEndStack = GetStack();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsString mCause;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ConsoleTimelineMarker_h_
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- 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_EventTimelineMarker_h_
|
||||
#define mozilla_EventTimelineMarker_h_
|
||||
|
||||
#include "TimelineMarker.h"
|
||||
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class EventTimelineMarker : public TimelineMarker
|
||||
{
|
||||
public:
|
||||
explicit EventTimelineMarker(const nsAString& aType,
|
||||
uint16_t aPhase,
|
||||
MarkerTracingType aTracingType)
|
||||
: TimelineMarker("DOMEvent", aTracingType)
|
||||
, mType(aType)
|
||||
, mPhase(aPhase)
|
||||
{}
|
||||
|
||||
virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) override
|
||||
{
|
||||
if (GetTracingType() == MarkerTracingType::START) {
|
||||
aMarker.mType.Construct(mType);
|
||||
aMarker.mEventPhase.Construct(mPhase);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsString mType;
|
||||
uint16_t mPhase;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_EventTimelineMarker_h_
|
|
@ -0,0 +1,62 @@
|
|||
/* -*- 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_JavascriptTimelineMarker_h_
|
||||
#define mozilla_JavascriptTimelineMarker_h_
|
||||
|
||||
#include "TimelineMarker.h"
|
||||
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
|
||||
#include "mozilla/dom/RootedDictionary.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class JavascriptTimelineMarker : public TimelineMarker
|
||||
{
|
||||
public:
|
||||
explicit JavascriptTimelineMarker(const char* aReason,
|
||||
const char16_t* aFunctionName,
|
||||
const char16_t* aFileName,
|
||||
uint32_t aLineNumber,
|
||||
MarkerTracingType aTracingType)
|
||||
: TimelineMarker("Javascript", aTracingType, MarkerStackRequest::NO_STACK)
|
||||
, mCause(NS_ConvertUTF8toUTF16(aReason))
|
||||
, mFunctionName(aFunctionName)
|
||||
, mFileName(aFileName)
|
||||
, mLineNumber(aLineNumber)
|
||||
{}
|
||||
|
||||
virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) override
|
||||
{
|
||||
aMarker.mCauseName.Construct(mCause);
|
||||
|
||||
if (!mFunctionName.IsEmpty() || !mFileName.IsEmpty()) {
|
||||
dom::RootedDictionary<dom::ProfileTimelineStackFrame> stackFrame(aCx);
|
||||
stackFrame.mLine.Construct(mLineNumber);
|
||||
stackFrame.mSource.Construct(mFileName);
|
||||
stackFrame.mFunctionDisplayName.Construct(mFunctionName);
|
||||
|
||||
JS::Rooted<JS::Value> newStack(aCx);
|
||||
if (ToJSValue(aCx, stackFrame, &newStack)) {
|
||||
if (newStack.isObject()) {
|
||||
aMarker.mStack = &newStack.toObject();
|
||||
}
|
||||
} else {
|
||||
JS_ClearPendingException(aCx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsString mCause;
|
||||
nsString mFunctionName;
|
||||
nsString mFileName;
|
||||
uint32_t mLineNumber;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_JavascriptTimelineMarker_h_
|
|
@ -0,0 +1,45 @@
|
|||
/* -*- 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_LayerTimelineMarker_h_
|
||||
#define mozilla_LayerTimelineMarker_h_
|
||||
|
||||
#include "TimelineMarker.h"
|
||||
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class LayerTimelineMarker : public TimelineMarker
|
||||
{
|
||||
public:
|
||||
explicit LayerTimelineMarker(const nsIntRegion& aRegion)
|
||||
: TimelineMarker("Layer", MarkerTracingType::HELPER_EVENT)
|
||||
, mRegion(aRegion)
|
||||
{}
|
||||
|
||||
~LayerTimelineMarker()
|
||||
{}
|
||||
|
||||
void AddLayerRectangles(dom::Sequence<dom::ProfileTimelineLayerRect>& aRectangles)
|
||||
{
|
||||
nsIntRegionRectIterator it(mRegion);
|
||||
while (const nsIntRect* iterRect = it.Next()) {
|
||||
dom::ProfileTimelineLayerRect rect;
|
||||
rect.mX = iterRect->X();
|
||||
rect.mY = iterRect->Y();
|
||||
rect.mWidth = iterRect->Width();
|
||||
rect.mHeight = iterRect->Height();
|
||||
aRectangles.AppendElement(rect, fallible);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsIntRegion mRegion;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_LayerTimelineMarker_h_
|
|
@ -7,6 +7,7 @@
|
|||
#include "ObservedDocShell.h"
|
||||
|
||||
#include "TimelineMarker.h"
|
||||
#include "LayerTimelineMarker.h"
|
||||
#include "mozilla/Move.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -38,9 +39,9 @@ ObservedDocShell::PopMarkers(JSContext* aCx,
|
|||
for (uint32_t i = 0; i < mTimelineMarkers.Length(); ++i) {
|
||||
UniquePtr<TimelineMarker>& startPayload = mTimelineMarkers[i];
|
||||
|
||||
// If this is a TRACING_TIMESTAMP marker, there's no corresponding END
|
||||
// If this is a TIMESTAMP marker, there's no corresponding END,
|
||||
// as it's a single unit of time, not a duration.
|
||||
if (startPayload->GetMetaData() == TRACING_TIMESTAMP) {
|
||||
if (startPayload->GetTracingType() == MarkerTracingType::TIMESTAMP) {
|
||||
dom::ProfileTimelineMarker* marker = aStore.AppendElement();
|
||||
marker->mName = NS_ConvertUTF8toUTF16(startPayload->GetName());
|
||||
marker->mStart = startPayload->GetTime();
|
||||
|
@ -52,7 +53,7 @@ ObservedDocShell::PopMarkers(JSContext* aCx,
|
|||
|
||||
// Whenever a START marker is found, look for the corresponding END
|
||||
// and build a {name,start,end} JS object.
|
||||
if (startPayload->GetMetaData() == TRACING_INTERVAL_START) {
|
||||
if (startPayload->GetTracingType() == MarkerTracingType::START) {
|
||||
bool hasSeenEnd = false;
|
||||
|
||||
// "Paint" markers are different because painting is handled at root
|
||||
|
@ -80,17 +81,18 @@ ObservedDocShell::PopMarkers(JSContext* aCx,
|
|||
|
||||
// Look for "Layer" markers to stream out "Paint" markers.
|
||||
if (startIsPaintType && endIsLayerType) {
|
||||
LayerTimelineMarker* layerPayload = static_cast<LayerTimelineMarker*>(endPayload.get());
|
||||
layerPayload->AddLayerRectangles(layerRectangles);
|
||||
hasSeenLayerType = true;
|
||||
endPayload->AddLayerRectangles(layerRectangles);
|
||||
}
|
||||
if (!startPayload->Equals(*endPayload)) {
|
||||
continue;
|
||||
}
|
||||
if (endPayload->GetMetaData() == TRACING_INTERVAL_START) {
|
||||
if (endPayload->GetTracingType() == MarkerTracingType::START) {
|
||||
++markerDepth;
|
||||
continue;
|
||||
}
|
||||
if (endPayload->GetMetaData() == TRACING_INTERVAL_END) {
|
||||
if (endPayload->GetTracingType() == MarkerTracingType::END) {
|
||||
if (markerDepth > 0) {
|
||||
--markerDepth;
|
||||
continue;
|
||||
|
|
|
@ -4,16 +4,17 @@
|
|||
* 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 ObservedDocShell_h_
|
||||
#define ObservedDocShell_h_
|
||||
#ifndef mozilla_ObservedDocShell_h_
|
||||
#define mozilla_ObservedDocShell_h_
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/nsRefPtr.h"
|
||||
|
||||
class nsDocShell;
|
||||
class TimelineMarker;
|
||||
|
||||
namespace mozilla {
|
||||
class TimelineMarker;
|
||||
|
||||
namespace dom {
|
||||
struct ProfileTimelineMarker;
|
||||
}
|
||||
|
@ -39,4 +40,4 @@ public:
|
|||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* ObservedDocShell_h_ */
|
||||
#endif /* mozilla_ObservedDocShell_h_ */
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/* -*- 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_RestyleTimelineMarker_h_
|
||||
#define mozilla_RestyleTimelineMarker_h_
|
||||
|
||||
#include "TimelineMarker.h"
|
||||
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class RestyleTimelineMarker : public TimelineMarker
|
||||
{
|
||||
public:
|
||||
explicit RestyleTimelineMarker(nsRestyleHint aRestyleHint,
|
||||
MarkerTracingType aTracingType)
|
||||
: TimelineMarker("Styles", aTracingType)
|
||||
{
|
||||
if (aRestyleHint) {
|
||||
mRestyleHint.AssignWithConversion(RestyleManager::RestyleHintToString(aRestyleHint));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) override
|
||||
{
|
||||
if (GetTracingType() == MarkerTracingType::START) {
|
||||
aMarker.mRestyleHint.Construct(mRestyleHint);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoString mRestyleHint;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_RestyleTimelineMarker_h_
|
|
@ -68,10 +68,10 @@ TimelineConsumers::GetKnownDocShells(Vector<nsRefPtr<nsDocShell>>& aStore)
|
|||
void
|
||||
TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
|
||||
const char* aName,
|
||||
TracingMetadata aMetaData)
|
||||
MarkerTracingType aTracingType)
|
||||
{
|
||||
if (aDocShell->IsObserved()) {
|
||||
aDocShell->mObserved->AddMarker(Move(MakeUnique<TimelineMarker>(aDocShell, aName, aMetaData)));
|
||||
aDocShell->mObserved->AddMarker(Move(MakeUnique<TimelineMarker>(aName, aTracingType)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,10 +79,10 @@ void
|
|||
TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
|
||||
const char* aName,
|
||||
const TimeStamp& aTime,
|
||||
TracingMetadata aMetaData)
|
||||
MarkerTracingType aTracingType)
|
||||
{
|
||||
if (aDocShell->IsObserved()) {
|
||||
aDocShell->mObserved->AddMarker(Move(MakeUnique<TimelineMarker>(aDocShell, aName, aTime, aMetaData)));
|
||||
aDocShell->mObserved->AddMarker(Move(MakeUnique<TimelineMarker>(aName, aTime, aTracingType)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,18 +98,18 @@ TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
|
|||
void
|
||||
TimelineConsumers::AddMarkerForDocShell(nsIDocShell* aDocShell,
|
||||
const char* aName,
|
||||
TracingMetadata aMetaData)
|
||||
MarkerTracingType aTracingType)
|
||||
{
|
||||
AddMarkerForDocShell(static_cast<nsDocShell*>(aDocShell), aName, aMetaData);
|
||||
AddMarkerForDocShell(static_cast<nsDocShell*>(aDocShell), aName, aTracingType);
|
||||
}
|
||||
|
||||
void
|
||||
TimelineConsumers::AddMarkerForDocShell(nsIDocShell* aDocShell,
|
||||
const char* aName,
|
||||
const TimeStamp& aTime,
|
||||
TracingMetadata aMetaData)
|
||||
MarkerTracingType aTracingType)
|
||||
{
|
||||
AddMarkerForDocShell(static_cast<nsDocShell*>(aDocShell), aName, aTime, aMetaData);
|
||||
AddMarkerForDocShell(static_cast<nsDocShell*>(aDocShell), aName, aTime, aTracingType);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -122,18 +122,18 @@ TimelineConsumers::AddMarkerForDocShell(nsIDocShell* aDocShell,
|
|||
void
|
||||
TimelineConsumers::AddMarkerForDocShellsList(Vector<nsRefPtr<nsDocShell>>& aDocShells,
|
||||
const char* aName,
|
||||
TracingMetadata aMetaData)
|
||||
MarkerTracingType aTracingType)
|
||||
{
|
||||
for (Vector<nsRefPtr<nsDocShell>>::Range range = aDocShells.all();
|
||||
!range.empty();
|
||||
range.popFront()) {
|
||||
AddMarkerForDocShell(range.front(), aName, aMetaData);
|
||||
AddMarkerForDocShell(range.front(), aName, aTracingType);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimelineConsumers::AddMarkerForAllObservedDocShells(const char* aName,
|
||||
TracingMetadata aMetaData)
|
||||
MarkerTracingType aTracingType)
|
||||
{
|
||||
Vector<nsRefPtr<nsDocShell>> docShells;
|
||||
if (!GetKnownDocShells(docShells)) {
|
||||
|
@ -142,7 +142,7 @@ TimelineConsumers::AddMarkerForAllObservedDocShells(const char* aName,
|
|||
return;
|
||||
}
|
||||
|
||||
AddMarkerForDocShellsList(docShells, aName, aMetaData);
|
||||
AddMarkerForDocShellsList(docShells, aName, aTracingType);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -10,14 +10,16 @@
|
|||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
#include "TimelineMarkerEnums.h"
|
||||
|
||||
class nsDocShell;
|
||||
class nsIDocShell;
|
||||
class TimelineMarker;
|
||||
|
||||
namespace mozilla {
|
||||
class ObservedDocShell;
|
||||
class TimelineMarker;
|
||||
|
||||
class TimelineConsumers
|
||||
{
|
||||
|
@ -46,19 +48,19 @@ public:
|
|||
// relevant for a specific docshell.
|
||||
static void AddMarkerForDocShell(nsDocShell* aDocShell,
|
||||
const char* aName,
|
||||
TracingMetadata aMetaData);
|
||||
MarkerTracingType aTracingType);
|
||||
static void AddMarkerForDocShell(nsIDocShell* aDocShell,
|
||||
const char* aName,
|
||||
TracingMetadata aMetaData);
|
||||
MarkerTracingType aTracingType);
|
||||
|
||||
static void AddMarkerForDocShell(nsDocShell* aDocShell,
|
||||
const char* aName,
|
||||
const TimeStamp& aTime,
|
||||
TracingMetadata aMetaData);
|
||||
MarkerTracingType aTracingType);
|
||||
static void AddMarkerForDocShell(nsIDocShell* aDocShell,
|
||||
const char* aName,
|
||||
const TimeStamp& aTime,
|
||||
TracingMetadata aMetaData);
|
||||
MarkerTracingType aTracingType);
|
||||
|
||||
// These methods register and receive ownership of an already created marker,
|
||||
// relevant for a specific docshell.
|
||||
|
@ -70,12 +72,12 @@ public:
|
|||
// This method creates custom markers, relevant for a list of docshells.
|
||||
static void AddMarkerForDocShellsList(Vector<nsRefPtr<nsDocShell>>& aDocShells,
|
||||
const char* aName,
|
||||
TracingMetadata aMetaData);
|
||||
MarkerTracingType aTracingType);
|
||||
|
||||
// This method creates custom markers, none of which have to be tied to a
|
||||
// particular docshell.
|
||||
static void AddMarkerForAllObservedDocShells(const char* aName,
|
||||
TracingMetadata aMetaData);
|
||||
MarkerTracingType aTracingType);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -4,50 +4,61 @@
|
|||
* 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 "nsDocShell.h"
|
||||
#include "TimelineMarker.h"
|
||||
|
||||
TimelineMarker::TimelineMarker(nsDocShell* aDocShell, const char* aName,
|
||||
TracingMetadata aMetaData)
|
||||
namespace mozilla {
|
||||
|
||||
TimelineMarker::TimelineMarker(const char* aName,
|
||||
MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest)
|
||||
: mName(aName)
|
||||
, mMetaData(aMetaData)
|
||||
, mTracingType(aTracingType)
|
||||
{
|
||||
MOZ_COUNT_CTOR(TimelineMarker);
|
||||
MOZ_ASSERT(aName);
|
||||
aDocShell->Now(&mTime);
|
||||
if (aMetaData == TRACING_INTERVAL_START || aMetaData == TRACING_TIMESTAMP) {
|
||||
CaptureStack();
|
||||
}
|
||||
SetCurrentTime();
|
||||
CaptureStackIfNecessary(aTracingType, aStackRequest);
|
||||
}
|
||||
|
||||
TimelineMarker::TimelineMarker(nsDocShell* aDocShell, const char* aName,
|
||||
const mozilla::TimeStamp& aTime,
|
||||
TracingMetadata aMetaData)
|
||||
: TimelineMarker(aDocShell, aName, aMetaData)
|
||||
{
|
||||
bool isInconsistent = false;
|
||||
mTime = (aTime - mozilla::TimeStamp::ProcessCreation(isInconsistent)).ToMilliseconds();
|
||||
}
|
||||
|
||||
TimelineMarker::TimelineMarker(nsDocShell* aDocShell, const char* aName,
|
||||
TracingMetadata aMetaData,
|
||||
const nsAString& aCause,
|
||||
TimelineStackRequest aStackRequest)
|
||||
TimelineMarker::TimelineMarker(const char* aName,
|
||||
const TimeStamp& aTime,
|
||||
MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest)
|
||||
: mName(aName)
|
||||
, mMetaData(aMetaData)
|
||||
, mCause(aCause)
|
||||
, mTracingType(aTracingType)
|
||||
{
|
||||
MOZ_COUNT_CTOR(TimelineMarker);
|
||||
MOZ_ASSERT(aName);
|
||||
aDocShell->Now(&mTime);
|
||||
if ((aMetaData == TRACING_INTERVAL_START ||
|
||||
aMetaData == TRACING_TIMESTAMP) &&
|
||||
aStackRequest != NO_STACK) {
|
||||
CaptureStack();
|
||||
}
|
||||
SetCustomTime(aTime);
|
||||
CaptureStackIfNecessary(aTracingType, aStackRequest);
|
||||
}
|
||||
|
||||
TimelineMarker::~TimelineMarker()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TimelineMarker);
|
||||
}
|
||||
|
||||
void
|
||||
TimelineMarker::SetCurrentTime()
|
||||
{
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
SetCustomTime(now);
|
||||
}
|
||||
|
||||
void
|
||||
TimelineMarker::SetCustomTime(const TimeStamp& aTime)
|
||||
{
|
||||
bool isInconsistent = false;
|
||||
mTime = (aTime - TimeStamp::ProcessCreation(isInconsistent)).ToMilliseconds();
|
||||
}
|
||||
|
||||
void
|
||||
TimelineMarker::CaptureStackIfNecessary(MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest)
|
||||
{
|
||||
if ((aTracingType == MarkerTracingType::START ||
|
||||
aTracingType == MarkerTracingType::TIMESTAMP) &&
|
||||
aStackRequest != MarkerStackRequest::NO_STACK) {
|
||||
CaptureStack();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -4,66 +4,54 @@
|
|||
* 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 TimelineMarker_h_
|
||||
#define TimelineMarker_h_
|
||||
#ifndef mozilla_TimelineMarker_h_
|
||||
#define mozilla_TimelineMarker_h_
|
||||
|
||||
#include "nsString.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "jsapi.h"
|
||||
#include "TimelineMarkerEnums.h"
|
||||
|
||||
class nsDocShell;
|
||||
|
||||
// Objects of this type can be added to the timeline. The class can
|
||||
// also be subclassed to let a given marker creator provide custom
|
||||
// details.
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
struct ProfileTimelineMarker;
|
||||
}
|
||||
|
||||
// Objects of this type can be added to the timeline if there is an interested
|
||||
// consumer. The class can also be subclassed to let a given marker creator
|
||||
// provide custom details.
|
||||
class TimelineMarker
|
||||
{
|
||||
public:
|
||||
enum TimelineStackRequest { STACK, NO_STACK };
|
||||
TimelineMarker(const char* aName,
|
||||
MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
|
||||
|
||||
TimelineMarker(nsDocShell* aDocShell, const char* aName,
|
||||
TracingMetadata aMetaData);
|
||||
|
||||
TimelineMarker(nsDocShell* aDocShell, const char* aName,
|
||||
const mozilla::TimeStamp& aTime,
|
||||
TracingMetadata aMetaData);
|
||||
|
||||
TimelineMarker(nsDocShell* aDocShell, const char* aName,
|
||||
TracingMetadata aMetaData,
|
||||
const nsAString& aCause,
|
||||
TimelineStackRequest aStackRequest = STACK);
|
||||
TimelineMarker(const char* aName,
|
||||
const TimeStamp& aTime,
|
||||
MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
|
||||
|
||||
virtual ~TimelineMarker();
|
||||
|
||||
// Check whether two markers should be considered the same,
|
||||
// for the purpose of pairing start and end markers. Normally
|
||||
// this definition suffices.
|
||||
// Check whether two markers should be considered the same, for the purpose
|
||||
// of pairing start and end markers. Normally this definition suffices.
|
||||
virtual bool Equals(const TimelineMarker& aOther)
|
||||
{
|
||||
return strcmp(mName, aOther.mName) == 0;
|
||||
}
|
||||
|
||||
// Add details specific to this marker type to aMarker. The
|
||||
// standard elements have already been set. This method is
|
||||
// called on both the starting and ending markers of a pair.
|
||||
// Ordinarily the ending marker doesn't need to do anything
|
||||
// here.
|
||||
virtual void AddDetails(JSContext* aCx,
|
||||
mozilla::dom::ProfileTimelineMarker& aMarker)
|
||||
// Add details specific to this marker type to aMarker. The standard elements
|
||||
// have already been set. This method is called on both the starting and
|
||||
// ending markers of a pair. Ordinarily the ending marker doesn't need to do
|
||||
// anything here.
|
||||
virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker)
|
||||
{}
|
||||
|
||||
virtual void AddLayerRectangles(
|
||||
mozilla::dom::Sequence<mozilla::dom::ProfileTimelineLayerRect>&)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("can only be called on layer markers");
|
||||
}
|
||||
|
||||
const char* GetName() const { return mName; }
|
||||
TracingMetadata GetMetaData() const { return mMetaData; }
|
||||
DOMHighResTimeStamp GetTime() const { return mTime; }
|
||||
const nsString& GetCause() const { return mCause; }
|
||||
MarkerTracingType GetTracingType() const { return mTracingType; }
|
||||
|
||||
JSObject* GetStack()
|
||||
{
|
||||
|
@ -89,15 +77,21 @@ protected:
|
|||
|
||||
private:
|
||||
const char* mName;
|
||||
TracingMetadata mMetaData;
|
||||
DOMHighResTimeStamp mTime;
|
||||
nsString mCause;
|
||||
MarkerTracingType mTracingType;
|
||||
|
||||
// While normally it is not a good idea to make a persistent root,
|
||||
// in this case changing nsDocShell to participate in cycle
|
||||
// collection was deemed too invasive, and the markers are only held
|
||||
// here temporarily to boot.
|
||||
JS::PersistentRooted<JSObject*> mStackTrace;
|
||||
|
||||
void SetCurrentTime();
|
||||
void SetCustomTime(const TimeStamp& aTime);
|
||||
void CaptureStackIfNecessary(MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest);
|
||||
};
|
||||
|
||||
#endif /* TimelineMarker_h_ */
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_TimelineMarker_h_ */
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/* -*- 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_TimelineMarkerEnums_h_
|
||||
#define mozilla_TimelineMarkerEnums_h_
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum class MarkerTracingType {
|
||||
START,
|
||||
END,
|
||||
TIMESTAMP,
|
||||
HELPER_EVENT
|
||||
};
|
||||
|
||||
enum class MarkerStackRequest {
|
||||
STACK,
|
||||
NO_STACK
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_TimelineMarkerEnums_h_
|
|
@ -0,0 +1,36 @@
|
|||
/* -*- 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_TimestampTimelineMarker_h_
|
||||
#define mozilla_TimestampTimelineMarker_h_
|
||||
|
||||
#include "TimelineMarker.h"
|
||||
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class TimestampTimelineMarker : public TimelineMarker
|
||||
{
|
||||
public:
|
||||
explicit TimestampTimelineMarker(const nsAString& aCause)
|
||||
: TimelineMarker("TimeStamp", MarkerTracingType::TIMESTAMP)
|
||||
, mCause(aCause)
|
||||
{}
|
||||
|
||||
virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) override
|
||||
{
|
||||
if (!mCause.IsEmpty()) {
|
||||
aMarker.mCauseName.Construct(mCause);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsString mCause;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_TimestampTimelineMarker_h_
|
|
@ -7,9 +7,16 @@
|
|||
EXPORTS.mozilla += [
|
||||
'AutoGlobalTimelineMarker.h',
|
||||
'AutoTimelineMarker.h',
|
||||
'ConsoleTimelineMarker.h',
|
||||
'EventTimelineMarker.h',
|
||||
'JavascriptTimelineMarker.h',
|
||||
'LayerTimelineMarker.h',
|
||||
'ObservedDocShell.h',
|
||||
'RestyleTimelineMarker.h',
|
||||
'TimelineConsumers.h',
|
||||
'TimelineMarker.h',
|
||||
'TimelineMarkerEnums.h',
|
||||
'TimestampTimelineMarker.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsDocShell.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "mozilla/ConsoleTimelineMarker.h"
|
||||
#include "mozilla/TimestampTimelineMarker.h"
|
||||
|
||||
#include "nsIConsoleAPIStorage.h"
|
||||
#include "nsIDOMWindowUtils.h"
|
||||
|
@ -985,59 +987,6 @@ ReifyStack(nsIStackFrame* aStack, nsTArray<ConsoleStackEntry>& aRefiedStack)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class ConsoleTimelineMarker : public TimelineMarker
|
||||
{
|
||||
public:
|
||||
ConsoleTimelineMarker(nsDocShell* aDocShell,
|
||||
TracingMetadata aMetaData,
|
||||
const nsAString& aCause)
|
||||
: TimelineMarker(aDocShell, "ConsoleTime", aMetaData, aCause)
|
||||
{
|
||||
if (aMetaData == TRACING_INTERVAL_END) {
|
||||
CaptureStack();
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool Equals(const TimelineMarker& aOther) override
|
||||
{
|
||||
if (!TimelineMarker::Equals(aOther)) {
|
||||
return false;
|
||||
}
|
||||
// Console markers must have matching causes as well.
|
||||
return GetCause() == aOther.GetCause();
|
||||
}
|
||||
|
||||
virtual void AddDetails(JSContext* aCx,
|
||||
mozilla::dom::ProfileTimelineMarker& aMarker) override
|
||||
{
|
||||
if (GetMetaData() == TRACING_INTERVAL_START) {
|
||||
aMarker.mCauseName.Construct(GetCause());
|
||||
} else {
|
||||
aMarker.mEndStack = GetStack();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TimestampTimelineMarker : public TimelineMarker
|
||||
{
|
||||
public:
|
||||
TimestampTimelineMarker(nsDocShell* aDocShell,
|
||||
TracingMetadata aMetaData,
|
||||
const nsAString& aCause)
|
||||
: TimelineMarker(aDocShell, "TimeStamp", aMetaData, aCause)
|
||||
{
|
||||
MOZ_ASSERT(aMetaData == TRACING_TIMESTAMP);
|
||||
}
|
||||
|
||||
virtual void AddDetails(JSContext* aCx,
|
||||
mozilla::dom::ProfileTimelineMarker& aMarker) override
|
||||
{
|
||||
if (!GetCause().IsEmpty()) {
|
||||
aMarker.mCauseName.Construct(GetCause());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Queue a call to a console method. See the CALL_DELAY constant.
|
||||
void
|
||||
Console::Method(JSContext* aCx, MethodName aMethodName,
|
||||
|
@ -1144,8 +1093,7 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
|
|||
key.init(aCx, jsString);
|
||||
}
|
||||
|
||||
mozilla::UniquePtr<TimelineMarker> marker =
|
||||
MakeUnique<TimestampTimelineMarker>(docShell, TRACING_TIMESTAMP, key);
|
||||
UniquePtr<TimelineMarker> marker = MakeUnique<TimestampTimelineMarker>(key);
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
|
||||
}
|
||||
// For `console.time(foo)` and `console.timeEnd(foo)`
|
||||
|
@ -1155,10 +1103,9 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
|
|||
if (jsString) {
|
||||
nsAutoJSString key;
|
||||
if (key.init(aCx, jsString)) {
|
||||
mozilla::UniquePtr<TimelineMarker> marker =
|
||||
MakeUnique<ConsoleTimelineMarker>(docShell,
|
||||
aMethodName == MethodTime ? TRACING_INTERVAL_START : TRACING_INTERVAL_END,
|
||||
key);
|
||||
UniquePtr<TimelineMarker> marker = MakeUnique<ConsoleTimelineMarker>(
|
||||
key, aMethodName == MethodTime ? MarkerTracingType::START
|
||||
: MarkerTracingType::END);
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/TimelineConsumers.h"
|
||||
#include "mozilla/EventTimelineMarker.h"
|
||||
|
||||
#include "EventListenerService.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
@ -1056,29 +1057,6 @@ EventListenerManager::GetDocShellForTarget()
|
|||
return docShell;
|
||||
}
|
||||
|
||||
class EventTimelineMarker : public TimelineMarker
|
||||
{
|
||||
public:
|
||||
EventTimelineMarker(nsDocShell* aDocShell, TracingMetadata aMetaData,
|
||||
uint16_t aPhase, const nsAString& aCause)
|
||||
: TimelineMarker(aDocShell, "DOMEvent", aMetaData, aCause)
|
||||
, mPhase(aPhase)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void AddDetails(JSContext* aCx,
|
||||
mozilla::dom::ProfileTimelineMarker& aMarker) override
|
||||
{
|
||||
if (GetMetaData() == TRACING_INTERVAL_START) {
|
||||
aMarker.mType.Construct(GetCause());
|
||||
aMarker.mEventPhase.Construct(mPhase);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint16_t mPhase;
|
||||
};
|
||||
|
||||
/**
|
||||
* Causes a check for event listeners and processing by them if they exist.
|
||||
* @param an event listener
|
||||
|
@ -1149,9 +1127,8 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
|||
(*aDOMEvent)->GetType(typeStr);
|
||||
uint16_t phase;
|
||||
(*aDOMEvent)->GetEventPhase(&phase);
|
||||
mozilla::UniquePtr<TimelineMarker> marker =
|
||||
MakeUnique<EventTimelineMarker>(ds, TRACING_INTERVAL_START,
|
||||
phase, typeStr);
|
||||
UniquePtr<TimelineMarker> marker = MakeUnique<EventTimelineMarker>(
|
||||
typeStr, phase, MarkerTracingType::START);
|
||||
TimelineConsumers::AddMarkerForDocShell(ds, Move(marker));
|
||||
}
|
||||
}
|
||||
|
@ -1163,7 +1140,7 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
|
|||
|
||||
if (isTimelineRecording) {
|
||||
nsDocShell* ds = static_cast<nsDocShell*>(docShell.get());
|
||||
TimelineConsumers::AddMarkerForDocShell(ds, "DOMEvent", TRACING_INTERVAL_END);
|
||||
TimelineConsumers::AddMarkerForDocShell(ds, "DOMEvent", MarkerTracingType::END);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "nsPrintfCString.h"
|
||||
#include "nsRenderingContext.h"
|
||||
#include "nsSVGIntegrationUtils.h"
|
||||
#include "mozilla/LayerTimelineMarker.h"
|
||||
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/ReverseIterator.h"
|
||||
|
@ -5497,36 +5498,6 @@ static void DrawForcedBackgroundColor(DrawTarget& aDrawTarget,
|
|||
}
|
||||
}
|
||||
|
||||
class LayerTimelineMarker : public TimelineMarker
|
||||
{
|
||||
public:
|
||||
LayerTimelineMarker(nsDocShell* aDocShell, const nsIntRegion& aRegion)
|
||||
: TimelineMarker(aDocShell, "Layer", TRACING_EVENT)
|
||||
, mRegion(aRegion)
|
||||
{
|
||||
}
|
||||
|
||||
~LayerTimelineMarker()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void AddLayerRectangles(mozilla::dom::Sequence<mozilla::dom::ProfileTimelineLayerRect>& aRectangles) override
|
||||
{
|
||||
nsIntRegionRectIterator it(mRegion);
|
||||
while (const nsIntRect* iterRect = it.Next()) {
|
||||
mozilla::dom::ProfileTimelineLayerRect rect;
|
||||
rect.mX = iterRect->X();
|
||||
rect.mY = iterRect->Y();
|
||||
rect.mWidth = iterRect->Width();
|
||||
rect.mHeight = iterRect->Height();
|
||||
aRectangles.AppendElement(rect, fallible);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsIntRegion mRegion;
|
||||
};
|
||||
|
||||
/*
|
||||
* A note on residual transforms:
|
||||
*
|
||||
|
@ -5687,8 +5658,7 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer,
|
|||
bool isRecording;
|
||||
docShell->GetRecordProfileTimelineMarkers(&isRecording);
|
||||
if (isRecording) {
|
||||
mozilla::UniquePtr<TimelineMarker> marker =
|
||||
MakeUnique<LayerTimelineMarker>(docShell, aRegionToDraw);
|
||||
UniquePtr<TimelineMarker> marker = MakeUnique<LayerTimelineMarker>(aRegionToDraw);
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ struct EventRadiusPrefs
|
|||
bool mRepositionEventCoords;
|
||||
bool mTouchClusterDetectionEnabled;
|
||||
uint32_t mLimitReadableSize;
|
||||
uint32_t mKeepLimitSizeForCluster;
|
||||
};
|
||||
|
||||
static EventRadiusPrefs sMouseEventRadiusPrefs;
|
||||
|
@ -130,6 +131,9 @@ GetPrefsFor(EventClassID aEventClassID)
|
|||
|
||||
nsPrintfCString limitReadableSizePref("ui.zoomedview.limitReadableSize", prefBranch);
|
||||
Preferences::AddUintVarCache(&prefs->mLimitReadableSize, limitReadableSizePref.get(), 8);
|
||||
|
||||
nsPrintfCString keepLimitSize("ui.zoomedview.keepLimitSize", prefBranch);
|
||||
Preferences::AddUintVarCache(&prefs->mKeepLimitSizeForCluster, keepLimitSize.get(), 16);
|
||||
}
|
||||
|
||||
return prefs;
|
||||
|
@ -356,6 +360,21 @@ static bool IsElementPresent(nsTArray<nsIFrame*>& aCandidates, const nsAutoStrin
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsLargeElement(nsIFrame* aFrame, const EventRadiusPrefs* aPrefs)
|
||||
{
|
||||
uint32_t keepLimitSizeForCluster = aPrefs->mKeepLimitSizeForCluster;
|
||||
nsSize frameSize = aFrame->GetSize();
|
||||
nsPresContext* pc = aFrame->PresContext();
|
||||
nsIPresShell* presShell = pc->PresShell();
|
||||
float cumulativeResolution = presShell->GetCumulativeResolution();
|
||||
if ((pc->AppUnitsToGfxUnits(frameSize.height) * cumulativeResolution) > keepLimitSizeForCluster &&
|
||||
(pc->AppUnitsToGfxUnits(frameSize.width) * cumulativeResolution) > keepLimitSizeForCluster) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static nsIFrame*
|
||||
GetClosest(nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
|
||||
const nsRect& aTargetRect, const EventRadiusPrefs* aPrefs,
|
||||
|
@ -413,7 +432,8 @@ GetClosest(nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
|
|||
// and "for" attribute is present in label element, search the frame list for the "for" element
|
||||
// If this element is present in the current list, do not count the frame in
|
||||
// the cluster elements counter
|
||||
if (labelTargetId.IsEmpty() || !IsElementPresent(aCandidates, labelTargetId)) {
|
||||
if ((labelTargetId.IsEmpty() || !IsElementPresent(aCandidates, labelTargetId)) &&
|
||||
!IsLargeElement(f, aPrefs)) {
|
||||
if (std::find(mContentsInCluster.begin(), mContentsInCluster.end(), clickableContent) == mContentsInCluster.end()) {
|
||||
mContentsInCluster.push_back(clickableContent);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "RestyleManager.h"
|
||||
#include "RestyleTrackerInlines.h"
|
||||
#include "nsTransitionManager.h"
|
||||
#include "mozilla/RestyleTimelineMarker.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -97,31 +98,6 @@ struct RestyleCollector {
|
|||
#endif
|
||||
};
|
||||
|
||||
class RestyleTimelineMarker : public TimelineMarker
|
||||
{
|
||||
public:
|
||||
RestyleTimelineMarker(nsDocShell* aDocShell,
|
||||
TracingMetadata aMetaData,
|
||||
nsRestyleHint aRestyleHint)
|
||||
: TimelineMarker(aDocShell, "Styles", aMetaData)
|
||||
{
|
||||
if (aRestyleHint) {
|
||||
mRestyleHint.AssignWithConversion(RestyleManager::RestyleHintToString(aRestyleHint));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void AddDetails(JSContext* aCx,
|
||||
mozilla::dom::ProfileTimelineMarker& aMarker) override
|
||||
{
|
||||
if (GetMetaData() == TRACING_INTERVAL_START) {
|
||||
aMarker.mRestyleHint.Construct(mRestyleHint);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoString mRestyleHint;
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
CollectRestyles(nsISupports* aElement,
|
||||
nsAutoPtr<RestyleTracker::RestyleData>& aData,
|
||||
|
@ -358,10 +334,8 @@ RestyleTracker::DoProcessRestyles()
|
|||
}
|
||||
|
||||
if (isTimelineRecording) {
|
||||
mozilla::UniquePtr<TimelineMarker> marker =
|
||||
MakeUnique<RestyleTimelineMarker>(docShell,
|
||||
TRACING_INTERVAL_START,
|
||||
data->mRestyleHint);
|
||||
UniquePtr<TimelineMarker> marker = MakeUnique<RestyleTimelineMarker>(
|
||||
data->mRestyleHint, MarkerTracingType::START);
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
|
||||
}
|
||||
|
||||
|
@ -376,10 +350,8 @@ RestyleTracker::DoProcessRestyles()
|
|||
AddRestyleRootsIfAwaitingRestyle(data->mDescendants);
|
||||
|
||||
if (isTimelineRecording) {
|
||||
mozilla::UniquePtr<TimelineMarker> marker =
|
||||
MakeUnique<RestyleTimelineMarker>(docShell,
|
||||
TRACING_INTERVAL_END,
|
||||
data->mRestyleHint);
|
||||
UniquePtr<TimelineMarker> marker = MakeUnique<RestyleTimelineMarker>(
|
||||
data->mRestyleHint, MarkerTracingType::END);
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
|
||||
}
|
||||
}
|
||||
|
@ -423,10 +395,8 @@ RestyleTracker::DoProcessRestyles()
|
|||
}
|
||||
#endif
|
||||
if (isTimelineRecording) {
|
||||
mozilla::UniquePtr<TimelineMarker> marker =
|
||||
MakeUnique<RestyleTimelineMarker>(docShell,
|
||||
TRACING_INTERVAL_START,
|
||||
currentRestyle->mRestyleHint);
|
||||
UniquePtr<TimelineMarker> marker = MakeUnique<RestyleTimelineMarker>(
|
||||
currentRestyle->mRestyleHint, MarkerTracingType::START);
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
|
||||
}
|
||||
|
||||
|
@ -436,10 +406,8 @@ RestyleTracker::DoProcessRestyles()
|
|||
currentRestyle->mRestyleHintData);
|
||||
|
||||
if (isTimelineRecording) {
|
||||
mozilla::UniquePtr<TimelineMarker> marker =
|
||||
MakeUnique<RestyleTimelineMarker>(docShell,
|
||||
TRACING_INTERVAL_END,
|
||||
currentRestyle->mRestyleHint);
|
||||
UniquePtr<TimelineMarker> marker = MakeUnique<RestyleTimelineMarker>(
|
||||
currentRestyle->mRestyleHint, MarkerTracingType::END);
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8984,7 +8984,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
|
|||
|
||||
nsDocShell* docShell = static_cast<nsDocShell*>(GetPresContext()->GetDocShell());
|
||||
if (docShell) {
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow", TRACING_INTERVAL_START);
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow", MarkerTracingType::START);
|
||||
}
|
||||
|
||||
if (mReflowContinueTimer) {
|
||||
|
@ -9161,7 +9161,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
|
|||
}
|
||||
|
||||
if (docShell) {
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow", TRACING_INTERVAL_END);
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow", MarkerTracingType::END);
|
||||
}
|
||||
return !interrupted;
|
||||
}
|
||||
|
|
|
@ -1708,7 +1708,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
|
|||
for (nsDocShell* docShell : profilingDocShells) {
|
||||
// For the sake of the profile timeline's simplicity, this is flagged as
|
||||
// paint even if it includes creating display lists
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, "Paint", TRACING_INTERVAL_START);
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, "Paint", MarkerTracingType::START);
|
||||
}
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
|
||||
|
@ -1725,7 +1725,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
|
|||
}
|
||||
#endif
|
||||
for (nsDocShell* docShell : profilingDocShells) {
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, "Paint", TRACING_INTERVAL_END);
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell, "Paint", MarkerTracingType::END);
|
||||
}
|
||||
|
||||
if (nsContentUtils::XPConnect()) {
|
||||
|
|
|
@ -415,6 +415,7 @@ pref("font.size.inflation.minTwips", 0);
|
|||
pref("browser.ui.zoom.force-user-scalable", false);
|
||||
|
||||
pref("ui.zoomedview.enabled", true);
|
||||
pref("ui.zoomedview.keepLimitSize", 16); // value in layer pixels, used to not keep the large elements in the cluster list (Bug 1191041)
|
||||
pref("ui.zoomedview.limitReadableSize", 8); // value in layer pixels
|
||||
pref("ui.zoomedview.defaultZoomFactor", 2);
|
||||
pref("ui.zoomedview.simplified", true); // Do not display all the zoomed view controls
|
||||
|
|
|
@ -241,7 +241,7 @@ public class ZoomedView extends FrameLayout implements LayerView.DynamicToolbarL
|
|||
touchListener = new ZoomedViewTouchListener();
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(this,
|
||||
"Gesture:clusteredLinksClicked", "Window:Resize", "Content:LocationChange",
|
||||
"Gesture:CloseZoomedView");
|
||||
"Gesture:CloseZoomedView", "Browser:ZoomToPageWidth", "Browser:ZoomToRect");
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
|
@ -250,7 +250,7 @@ public class ZoomedView extends FrameLayout implements LayerView.DynamicToolbarL
|
|||
ThreadUtils.removeCallbacksFromUiThread(requestRenderRunnable);
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(this,
|
||||
"Gesture:clusteredLinksClicked", "Window:Resize", "Content:LocationChange",
|
||||
"Gesture:CloseZoomedView");
|
||||
"Gesture:CloseZoomedView", "Browser:ZoomToPageWidth", "Browser:ZoomToRect");
|
||||
}
|
||||
|
||||
// This method (onFinishInflate) is called only when the zoomed view class is used inside
|
||||
|
@ -562,8 +562,13 @@ public class ZoomedView extends FrameLayout implements LayerView.DynamicToolbarL
|
|||
}
|
||||
|
||||
public void stopZoomDisplay(boolean withAnimation) {
|
||||
// If "startZoomDisplay" is running and not totally completed (Gecko thread is still
|
||||
// running and "showZoomedView" has not yet been called), the zoomed view will be
|
||||
// displayed after this call and it should not.
|
||||
// Force the stop of the zoomed view, changing the shouldSetVisibleOnUpdate flag
|
||||
// before the test of the visibility.
|
||||
shouldSetVisibleOnUpdate = false;
|
||||
if (getVisibility() == View.VISIBLE) {
|
||||
shouldSetVisibleOnUpdate = false;
|
||||
hideZoomedView(withAnimation);
|
||||
ThreadUtils.removeCallbacksFromUiThread(requestRenderRunnable);
|
||||
if (layerView != null) {
|
||||
|
@ -616,7 +621,9 @@ public class ZoomedView extends FrameLayout implements LayerView.DynamicToolbarL
|
|||
refreshZoomedViewSize(metrics);
|
||||
} else if (event.equals("Content:LocationChange")) {
|
||||
stopZoomDisplay(false);
|
||||
} else if (event.equals("Gesture:CloseZoomedView")) {
|
||||
} else if (event.equals("Gesture:CloseZoomedView") ||
|
||||
event.equals("Browser:ZoomToPageWidth") ||
|
||||
event.equals("Browser:ZoomToRect")) {
|
||||
stopZoomDisplay(true);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
|
|
|
@ -123,13 +123,24 @@ this.Async = {
|
|||
Services.obs.addObserver(function onQuitApplication() {
|
||||
Services.obs.removeObserver(onQuitApplication, "quit-application");
|
||||
Async.checkAppReady = function() {
|
||||
throw Components.Exception("App. Quitting", Cr.NS_ERROR_ABORT);
|
||||
let exception = Components.Exception("App. Quitting", Cr.NS_ERROR_ABORT);
|
||||
exception.appIsShuttingDown = true;
|
||||
throw exception;
|
||||
};
|
||||
}, "quit-application", false);
|
||||
// In the common case, checkAppReady just returns true
|
||||
return (Async.checkAppReady = function() { return true; })();
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the passed exception is one raised by checkAppReady. Typically
|
||||
* this will be used in exception handlers to allow such exceptions to
|
||||
* make their way to the top frame and allow the app to actually terminate.
|
||||
*/
|
||||
isShutdownException(exception) {
|
||||
return exception && exception.appIsShuttingDown === true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the two things you need to make an asynchronous call synchronous
|
||||
* by spinning the event loop.
|
||||
|
|
|
@ -667,7 +667,7 @@ this.BrowserIDManager.prototype = {
|
|||
this._ensureValidToken().then(cb, cb);
|
||||
try {
|
||||
cb.wait();
|
||||
} catch (ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
this._log.error("Failed to fetch a token for authentication", ex);
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -307,7 +307,7 @@ Store.prototype = {
|
|||
// originating exception.
|
||||
// ex.cause will carry its stack with it when rethrown.
|
||||
throw ex.cause;
|
||||
} catch (ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
this._log.warn("Failed to apply incoming record " + record.id);
|
||||
this._log.warn("Encountered exception: " + Utils.exceptionStr(ex));
|
||||
failed.push(record.id);
|
||||
|
@ -992,7 +992,7 @@ SyncEngine.prototype = {
|
|||
this._tracker.ignoreAll = true;
|
||||
try {
|
||||
failed = failed.concat(this._store.applyIncomingBatch(applyBatch));
|
||||
} catch (ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
// Catch any error that escapes from applyIncomingBatch. At present
|
||||
// those will all be abort events.
|
||||
this._log.warn("Got exception " + Utils.exceptionStr(ex) +
|
||||
|
@ -1086,7 +1086,7 @@ SyncEngine.prototype = {
|
|||
self._log.warn("Reconciliation failed: aborting incoming processing.");
|
||||
failed.push(item.id);
|
||||
aborting = ex.cause;
|
||||
} catch (ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
self._log.warn("Failed to reconcile incoming record " + item.id);
|
||||
self._log.warn("Encountered exception: " + Utils.exceptionStr(ex));
|
||||
failed.push(item.id);
|
||||
|
@ -1458,8 +1458,7 @@ SyncEngine.prototype = {
|
|||
|
||||
out.encrypt(this.service.collectionKeys.keyForCollection(this.name));
|
||||
up.pushData(out);
|
||||
}
|
||||
catch(ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
this._log.warn("Error creating record: " + Utils.exceptionStr(ex));
|
||||
}
|
||||
|
||||
|
@ -1550,8 +1549,7 @@ SyncEngine.prototype = {
|
|||
try {
|
||||
this._log.trace("Trying to decrypt a record from the server..");
|
||||
test.get();
|
||||
}
|
||||
catch(ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
this._log.debug("Failed test decrypt: " + Utils.exceptionStr(ex));
|
||||
}
|
||||
|
||||
|
|
|
@ -256,7 +256,7 @@ BookmarksEngine.prototype = {
|
|||
stmt.params.id = id;
|
||||
let rows = Async.querySpinningly(stmt, ["url"]);
|
||||
url = rows.length == 0 ? "<not found>" : rows[0].url;
|
||||
} catch (ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
if (ex instanceof Ci.mozIStorageError) {
|
||||
url = `<failed: Storage error: ${ex.message} (${ex.result})>`;
|
||||
} else {
|
||||
|
@ -441,7 +441,7 @@ BookmarksEngine.prototype = {
|
|||
let guidMap;
|
||||
try {
|
||||
guidMap = this._buildGUIDMap();
|
||||
} catch (ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
this._log.warn("Got exception \"" + Utils.exceptionStr(ex) +
|
||||
"\" building GUID map." +
|
||||
" Skipping all other incoming items.");
|
||||
|
|
|
@ -222,7 +222,7 @@ HistoryStore.prototype = {
|
|||
} else {
|
||||
shouldApply = this._recordToPlaceInfo(record);
|
||||
}
|
||||
} catch(ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
failed.push(record.id);
|
||||
shouldApply = false;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ Cu.import("resource://services-sync/record.js");
|
|||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/engines.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-common/async.js");
|
||||
|
||||
this.LoginRec = function LoginRec(collection, id) {
|
||||
CryptoWrapper.call(this, collection, id);
|
||||
|
@ -67,7 +68,7 @@ PasswordEngine.prototype = {
|
|||
// record success.
|
||||
Svc.Prefs.set("deletePwdFxA", true);
|
||||
Svc.Prefs.reset("deletePwd"); // The old prefname we previously used.
|
||||
} catch (ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
this._log.debug("Password deletes failed: " + Utils.exceptionStr(ex));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ Cu.import("resource://gre/modules/Promise.jsm");
|
|||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://gre/modules/Log.jsm");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-common/async.js");
|
||||
|
||||
// Lazy import to prevent unnecessary load on startup.
|
||||
for (let symbol of ["BulkKeyBundle", "SyncKeyBundle"]) {
|
||||
|
@ -457,7 +458,7 @@ IdentityManager.prototype = {
|
|||
// cache.
|
||||
try {
|
||||
service.recordManager.get(service.storageURL + "meta/fxa_credentials");
|
||||
} catch (ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
this._log.warn("Failed to pre-fetch the migration sentinel", ex);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -23,6 +23,7 @@ Cu.import("resource://services-sync/constants.js");
|
|||
Cu.import("resource://services-sync/keys.js");
|
||||
Cu.import("resource://services-sync/resource.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-common/async.js");
|
||||
|
||||
this.WBORecord = function WBORecord(collection, id) {
|
||||
this.data = {};
|
||||
|
@ -235,7 +236,7 @@ RecordManager.prototype = {
|
|||
record.deserialize(this.response);
|
||||
|
||||
return this.set(url, record);
|
||||
} catch(ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
this._log.debug("Failed to import record: " + Utils.exceptionStr(ex));
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -403,7 +403,7 @@ Resource.prototype = {
|
|||
try {
|
||||
this._doRequest(action, data, callback);
|
||||
return Async.waitForSyncCallback(cb);
|
||||
} catch(ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
// Combine the channel stack with this request stack. Need to create
|
||||
// a new error object for that.
|
||||
let error = Error(ex.message);
|
||||
|
@ -556,7 +556,7 @@ ChannelListener.prototype = {
|
|||
|
||||
try {
|
||||
this._onProgress();
|
||||
} catch (ex) {
|
||||
} catch (ex if !Async.isShutdownException(ex)) {
|
||||
this._log.warn("Got exception calling onProgress handler during fetch of "
|
||||
+ req.URI.spec);
|
||||
this._log.debug(CommonUtils.exceptionStr(ex));
|
||||
|
|
|
@ -2415,15 +2415,17 @@ let GuidHelper = {
|
|||
if (cached !== undefined)
|
||||
return cached;
|
||||
|
||||
let conn = yield PlacesUtils.promiseDBConnection();
|
||||
let itemId = yield PlacesUtils.withConnectionWrapper("GuidHelper.getItemId",
|
||||
Task.async(function* (db) {
|
||||
let rows = yield db.executeCached(
|
||||
"SELECT b.id, b.guid from moz_bookmarks b WHERE b.guid = :guid LIMIT 1",
|
||||
{ guid: aGuid });
|
||||
if (rows.length == 0)
|
||||
throw new Error("no item found for the given GUID");
|
||||
|
||||
let rows = yield conn.executeCached(
|
||||
"SELECT b.id, b.guid from moz_bookmarks b WHERE b.guid = :guid LIMIT 1",
|
||||
{ guid: aGuid });
|
||||
if (rows.length == 0)
|
||||
throw new Error("no item found for the given GUID");
|
||||
return rows[0].getResultByName("id");
|
||||
}));
|
||||
|
||||
let itemId = rows[0].getResultByName("id");
|
||||
this.updateCache(itemId, aGuid);
|
||||
return itemId;
|
||||
}),
|
||||
|
@ -2433,15 +2435,18 @@ let GuidHelper = {
|
|||
if (cached !== undefined)
|
||||
return cached;
|
||||
|
||||
let conn = yield PlacesUtils.promiseDBConnection();
|
||||
let guid = yield PlacesUtils.withConnectionWrapper("GuidHelper.getItemGuid",
|
||||
Task.async(function* (db) {
|
||||
|
||||
let rows = yield conn.executeCached(
|
||||
"SELECT b.id, b.guid from moz_bookmarks b WHERE b.id = :id LIMIT 1",
|
||||
{ id: aItemId });
|
||||
if (rows.length == 0)
|
||||
throw new Error("no item found for the given itemId");
|
||||
let rows = yield db.executeCached(
|
||||
"SELECT b.id, b.guid from moz_bookmarks b WHERE b.id = :id LIMIT 1",
|
||||
{ id: aItemId });
|
||||
if (rows.length == 0)
|
||||
throw new Error("no item found for the given itemId");
|
||||
|
||||
return rows[0].getResultByName("guid");
|
||||
}));
|
||||
|
||||
let guid = rows[0].getResultByName("guid");
|
||||
this.updateCache(aItemId, guid);
|
||||
return guid;
|
||||
}),
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// This is testing the frankenstein situation Sync forces Places into.
|
||||
// Sync does runInBatchMode() and before the callback returns the Places async
|
||||
// APIs are used (either by Sync itself, or by any other code in the system)
|
||||
// As seen in bug 1197856 and bug 1190131.
|
||||
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
|
||||
// This function "waits" for a promise to resolve by spinning a nested event
|
||||
// loop.
|
||||
function waitForPromise(promise) {
|
||||
let thread = Cc["@mozilla.org/thread-manager;1"].getService().currentThread;
|
||||
|
||||
let finalResult, finalException;
|
||||
|
||||
promise.then(result => {
|
||||
finalResult = result;
|
||||
}, err => {
|
||||
finalException = err;
|
||||
});
|
||||
|
||||
// Keep waiting until our callback is triggered (unless the app is quitting).
|
||||
while (!finalResult && !finalException) {
|
||||
thread.processNextEvent(true);
|
||||
}
|
||||
if (finalException) {
|
||||
throw finalException;
|
||||
}
|
||||
return finalResult;
|
||||
}
|
||||
|
||||
add_test(function() {
|
||||
let testCompleted = false;
|
||||
PlacesUtils.bookmarks.runInBatchMode({
|
||||
runBatched() {
|
||||
// create a bookmark.
|
||||
let info = { parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/" };
|
||||
let insertPromise = PlacesUtils.bookmarks.insert(info);
|
||||
let bookmark = waitForPromise(insertPromise);
|
||||
// Check we got a bookmark (bookmark creation failed completely in
|
||||
// bug 1190131)
|
||||
equal(bookmark.url, info.url);
|
||||
// Check the promiseItemGuid and promiseItemId helpers - failure in these
|
||||
// was the underlying reason for the failure.
|
||||
let id = waitForPromise(PlacesUtils.promiseItemId(bookmark.guid));
|
||||
let guid = waitForPromise(PlacesUtils.promiseItemGuid(id));
|
||||
equal(guid, bookmark.guid, "id and guid round-tripped correctly");
|
||||
testCompleted = true;
|
||||
}
|
||||
}, null);
|
||||
// make sure we tested what we think we tested.
|
||||
ok(testCompleted);
|
||||
run_next_test();
|
||||
});
|
|
@ -66,6 +66,7 @@ skip-if = os == "android"
|
|||
# Bug 676989: test hangs consistently on Android
|
||||
skip-if = os == "android"
|
||||
[test_async_history_api.js]
|
||||
[test_async_in_batchmode.js]
|
||||
[test_async_transactions.js]
|
||||
skip-if = (os == "win" && os_version == "5.1") # Bug 1158887
|
||||
[test_autocomplete_stopSearch_no_throw.js]
|
||||
|
|
|
@ -1091,9 +1091,9 @@ nsView::DidCompositeWindow(const TimeStamp& aCompositeStart,
|
|||
nsIDocShell* docShell = context->GetDocShell();
|
||||
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell,
|
||||
"Composite", aCompositeStart, TRACING_INTERVAL_START);
|
||||
"Composite", aCompositeStart, MarkerTracingType::START);
|
||||
TimelineConsumers::AddMarkerForDocShell(docShell,
|
||||
"Composite", aCompositeEnd, TRACING_INTERVAL_END);
|
||||
"Composite", aCompositeEnd, MarkerTracingType::END);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче