Permalink
Browse files

Sessions: Update frontend to interface with the session-based protocol.

  • Loading branch information...
1 parent 32bf6d1 commit b0a4c3d93ea84ff2cf0d5f0721fa68e65d12a032 @rjbailey rjbailey committed Jan 6, 2014
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 University of Washington. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University of Washington nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.CaptureSessionObject = function(uid)
+{
+ this.uid = uid;
+
+ this._recordings = [];
+ this._dataLoaded = false;
+}
+
+WebInspector.CaptureSessionObject.prototype = {
+ constructor: WebInspector.CaptureSessionObject,
+ __proto__: WebInspector.Object.prototype,
+
+ // Public
+
+ get recordings() {
+ return this._recordings.slice();
+ },
+
+ append: function(recording)
+ {
+ this._recordings.push(recording);
+ },
+
+ insert: function(position, recording)
+ {
+ this._recordings.splice(position, 0, recording);
+ },
+
+ remove: function(position)
+ {
+ this._recordings.splice(position, 1);
+ },
+
+ loadData: function(data)
+ {
+ console.assert(this.uid === data.sessionId, "CaptureSessionObject ID doesn't match serialized session ID.", data);
+
+ this._dateCreated = new Date(data.dateCreated);
+ this._dataLoaded = true;
+
+ console.assert(data.recordings, "Missing recordings list in serialized recording.", data);
+ this._recordings = data.recordings;
+ },
+
+ dataLoaded: function()
+ {
+ return this._dataLoaded;
+ },
+
+ get dateCreated()
+ {
+ return this._dateCreated;
+ },
+
+ filename: function()
+ {
+ return "CaptureSession-" + this.dateCreated.toISO8601Compact() + ".webreplay";
+ },
+
+ displayName: function()
+ {
+ return WebInspector.UIString("Capture Session %d", this.uid) || WebInspector.UIString("(uninitialized)");
+ }
+};
@@ -437,6 +437,7 @@
<script src="RecordingCalculator.js"></script>
<script src="LiveRecordingObject.js"></script>
<script src="SerializedRecordingObject.js"></script>
+ <script src="CaptureSessionObject.js"></script>
<script src="ReplayInputDataProvider.js"></script>
<script src="ReplayInputGraph.js"></script>
<script src="HorizontalPointMarker.js"></script>
@@ -34,16 +34,24 @@ WebInspector.RecordingsManager = function()
// this manager is not reset when the main frame reloads,
// so initialization is inlined into the constructor.
+ this._sessions = [];
+ this._sessionsByUID = {};
+
this._recordings = [];
this._recordingsByUID = {};
- // load recordings that may already be available on backend.
+ // load recordings and sessions that may already be available on backend.
ReplayAgent.getAvailableRecordings(this._updateAvailableRecordings.bind(this));
+ ReplayAgent.getAvailableSessions(this._updateAvailableSessions.bind(this));
}
WebInspector.RecordingsManager.Event = {
+ SessionAdded: "recordings-manager-session-added",
+ SessionRemoved: "recordings-manager-session-removed",
RecordingAdded: "recordings-manager-recording-added",
- RecordingRemoved: "recordings-manager-recording-removed"
+ RecordingRemoved: "recordings-manager-recording-removed",
+ RecordingAddedToSession: "recordings-manager-recording-added-to-session",
+ RecordingRemovedFromSession: "recordings-manager-recording-removed-from-session"
};
WebInspector.RecordingsManager.prototype = {
@@ -52,6 +60,10 @@ WebInspector.RecordingsManager.prototype = {
// Public
+ get sessions() {
+ return this._sessions.slice();
+ },
+
get recordings() {
return this._recordings.slice();
},
@@ -81,7 +93,46 @@ WebInspector.RecordingsManager.prototype = {
});
},
- addRecording: function(uid) {
+ addSession: function(uid)
+ {
+ console.assert(uid >= 0, "tried to add session with invalid uid: "+uid);
+
+ if (this._sessionsByUID[uid])
+ return;
+
+ // asynchronously load all data for each new session as it's added, and
+ // defer any events that cause the data to be accessed.
+ var newSession = new WebInspector.CaptureSessionObject(uid);
+ this._sessionsByUID[uid] = newSession;
+ this._sessions.push(newSession);
+
+ var loadDataForSession = function(session, error, data) {
+ if (error) {
+ console.error("Couldn't load data for session "+session.uid+":"+error);
+ return;
+ }
+
+ session.loadData(data);
+ this.dispatchEventToListeners(WebInspector.RecordingsManager.Event.SessionAdded, session);
+ };
+
+ ReplayAgent.getSerializedSession(uid, loadDataForSession.bind(this, newSession));
+ },
+
+ removeSession: function(uid)
+ {
+ // FIXME: implement this.
+ },
+
+ getSessionWithUID: function(uid)
+ {
+ console.assert(uid >= 0, "invalid uid in request for session.");
+ console.assert(this._sessionsByUID[uid], "no session exists with the requested uid: "+uid);
+ return this._sessionsByUID[uid];
+ },
+
+ addRecording: function(uid)
+ {
console.assert(uid > 0, "tried to add recording with invalid uid: "+uid);
if (this._recordingsByUID[uid])
@@ -108,19 +159,56 @@ WebInspector.RecordingsManager.prototype = {
ReplayAgent.getSerializedRecording(uid, loadDataForRecording.bind(this, newRecording));
},
- removeRecording: function(recording) {
+ removeRecording: function(recording)
+ {
// FIXME: implement this (see old RecordingsModel.js).
// It depends on AsyncTaskScheduler to safely remove recordings that may be already loaded.
},
getRecordingWithUID: function(uid)
{
console.assert(uid > 0, "invalid uid in request for recording.");
+ console.assert(this._recordingsByUID[uid], "no recording exists with the requested uid: "+uid);
return this._recordingsByUID[uid];
},
+ addRecordingToSession: function(sessionId, recordingId, recordingIndex)
+ {
+ var session = this.getSessionWithUID(sessionId);
+ var recording = this.getRecordingWithUID(recordingId);
+ session.insert(recordingIndex, recording);
+ this.dispatchEventToListeners(WebInspector.RecordingsManager.Event.RecordingAddedToSession, {
+ session: session,
+ recording: recording
+ });
+ },
+
+ removeRecordingFromSession: function(sessionId, recordingIndex)
+ {
+ var session = this.getSessionWithUID(sessionId);
+ var recording = session.recordings[recordingIndex];
+ session.remove(recordingIndex);
+ this.dispatchEventToListeners(WebInspector.RecordingsManager.Event.RecordingRemovedFromSession, {
+ session: session,
+ recording: recording
+ });
+ },
+
// Private
+ _deleteEntryForSession: function(session)
+ {
+ this._sessions.splice(this._sessions.indexOf(session), 1);
+ delete this._sessionsByUID[session.uid];
+ },
+
+ _updateAvailableSessions: function(error, data)
+ {
+ for (var i = 0; i < data.length; ++i) {
+ this.addSession(data[i]);
+ }
+ },
+
_deleteEntryForRecording: function(recording)
{
this._recordings.splice(this._recordings.indexOf(recording), 1);
@@ -167,7 +167,7 @@ WebInspector.ReplayDashboardView.prototype = {
_ejectButtonClicked: function(event)
{
- WebInspector.replayManager.unloadRecordingSoon();
+ WebInspector.replayManager.ejectRecordingSoon();
},
_captureStarted: function()
@@ -108,6 +108,11 @@ WebInspector.ReplayManager.prototype = {
return this._replayState === WebInspector.ReplayManager.ReplayState.ReplayPausedAtInput;
},
+ get activeSession()
+ {
+ return this._activeSession;
+ },
+
get createdRecording()
{
console.assert(this.isCapturing, "ReplayManager.createdRecording only available when capturing is in progress.");
@@ -130,6 +135,11 @@ WebInspector.ReplayManager.prototype = {
this._replaySpeed = value;
},
+ get currentRecordingIndex()
+ {
+ return this._currentRecordingIndex;
+ },
+
get currentMarkIndex()
{
return this._currentMarkIndex;
@@ -145,9 +155,9 @@ WebInspector.ReplayManager.prototype = {
this.scheduler.enqueue(new WebInspector.ReplayManager.AsyncTasks.StopCapture());
},
- unloadRecordingSoon: function()
+ ejectRecordingSoon: function()
{
- this.scheduler.enqueue(new WebInspector.ReplayManager.AsyncTasks.UnloadRecording());
+ this.scheduler.enqueue(new WebInspector.ReplayManager.AsyncTasks.EjectRecording());
},
pausePlaybackSoon: function()
@@ -184,6 +194,9 @@ WebInspector.ReplayManager.prototype = {
delete this._activeRecording;
this.unsuppressBreakpoints();
this.dispatchEventToListeners(WebInspector.ReplayManager.Event.CaptureStopped);
+
+ this.recordingLoaded(this._activeSession.recordings[0].uid);
+ this._currentRecordingIndex = 0;
},
playbackStarted: function()
@@ -224,8 +237,9 @@ WebInspector.ReplayManager.prototype = {
this.dispatchEventToListeners(WebInspector.ReplayManager.Event.PlaybackError, data);
},
- playbackHitMark: function(markIndex)
+ playbackHitLocation: function(recordingIndex, markIndex)
{
+ this._currentRecordingIndex = recordingIndex;
this._setReplayCursor(markIndex);
},
@@ -238,6 +252,15 @@ WebInspector.ReplayManager.prototype = {
this.dispatchEventToListeners(WebInspector.ReplayManager.Event.RecordingUnloaded, unloadedRecording);
},
+ sessionLoaded: function(sessionId)
+ {
+ var session = WebInspector.recordingsManager.getSessionWithUID(sessionId);
+ console.assert(session, "Unknown session loaded:", session);
+
+ this._activeSession = session;
+ this.dispatchEventToListeners(WebInspector.ReplayManager.Event.SessionLoaded, this.activeSession);
+ },
+
recordingLoaded: function(uid)
{
var setActiveRecording = function() {
@@ -291,11 +314,12 @@ WebInspector.ReplayManager.prototype = {
ReplayAgent.loadRecording(recording.uid);
},
- unloadRecording: function()
+ ejectRecording: function()
{
- console.assert(this.loadedRecording, "Can't unload recording because none is loaded");
+ console.assert(this.loadedRecording, "Can't eject recording because none is loaded");
// TODO: receiving !wasAllowed should trigger task error.
- ReplayAgent.unloadRecording();
+ ReplayAgent.removeRecordingFromSession(this._activeSession.uid, this._currentRecordingIndex);
+ this.recordingUnloaded();
},
createRecording: function()
@@ -316,7 +340,7 @@ WebInspector.ReplayManager.prototype = {
{
// TODO: save replay start and end mark indices here
this.dispatchEventToListeners(WebInspector.ReplayManager.Event.PlaybackWillStart);
- ReplayAgent.replayUpToMarkIndex(index, this.replaySpeed === WebInspector.ReplayManager.ReplaySpeed.Seeking);
+ ReplayAgent.replayUpToLocation(this._currentRecordingIndex, index, this.replaySpeed === WebInspector.ReplayManager.ReplaySpeed.Seeking);
},
replayToCompletion: function()
@@ -352,7 +376,6 @@ WebInspector.ReplayManager.AsyncTasks.StartCapture = function() {
var task = new WebInspector.AsyncTask("StartCapture")
// if replaying, stop playback as the first subtask.
.chain("stopPlaybackIfNeeded", WebInspector.ReplayManager.AsyncTaskSteps.StopPlaybackIfNeeded)
- .chain("unloadRecordingIfNeeded", WebInspector.ReplayManager.AsyncTaskSteps.UnloadRecordingIfNeeded)
.chain("suppressBreakpoints", WebInspector.ReplayManager.AsyncTaskSteps.SuppressBreakpoints)
.chain("resumeDebuggerIfPaused", WebInspector.ReplayManager.AsyncTaskSteps.ResumeDebuggerIfPaused)
.chain("requestStartCapture", function(cb) {
@@ -383,11 +406,11 @@ WebInspector.ReplayManager.AsyncTasks.LoadRecording = function()
return new WebInspector.AsyncTask("not implemented", function(cb) { return cb(); });
};
-WebInspector.ReplayManager.AsyncTasks.UnloadRecording = function()
+WebInspector.ReplayManager.AsyncTasks.EjectRecording = function()
{
- return new WebInspector.AsyncTask("UnloadRecording")
+ return new WebInspector.AsyncTask("EjectRecording")
.chain("stopPlaybackIfNeeded", WebInspector.ReplayManager.AsyncTaskSteps.StopPlaybackIfNeeded)
- .chain("unloadRecordingIfNeeded", WebInspector.ReplayManager.AsyncTaskSteps.UnloadRecordingIfNeeded);
+ .chain("doEjectRecording", WebInspector.ReplayManager.AsyncTaskSteps.DoEjectRecording);
};
WebInspector.ReplayManager.AsyncTasks.ReplayToIndex = function()
@@ -490,11 +513,11 @@ WebInspector.ReplayManager.AsyncTaskSteps.UnsuppressBreakpoints = function(cb)
DebuggerAgent.causesRecompilation(cb);
};
-WebInspector.ReplayManager.AsyncTaskSteps.UnloadRecordingIfNeeded = function(cb)
+WebInspector.ReplayManager.AsyncTaskSteps.DoEjectRecording = function(cb)
{
if (!WebInspector.replayManager.canReplay)
return cb();
WebInspector.replayManager.addSingleFireEventListener(WebInspector.ReplayManager.Event.RecordingUnloaded, cb);
- WebInspector.replayManager.unloadRecording();
+ WebInspector.replayManager.ejectRecording();
};

0 comments on commit b0a4c3d

Please sign in to comment.