This commit is contained in:
Ryan VanderMeulen 2015-08-31 15:16:41 -04:00
Родитель 3f41652388 e14eb49e91
Коммит b2d76b60ec
46 изменённых файлов: 629 добавлений и 370 удалений

Просмотреть файл

@ -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(&lt);
// 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);
}
}