Commit 2333b3e0 authored by timothy@apple.com's avatar timothy@apple.com

Implement state cookie support for WebInspector.TimelineSidebarPanel.

https://bugs.webkit.org/show_bug.cgi?id=126921

Reviewed by Joseph Pecoraro.

* UserInterface/DebuggerSidebarPanel.js:
(WebInspector.DebuggerSidebarPanel.prototype.restoreStateFromCookie):
Drive-by fix to pass along relaxedMatchDelay to the superclass.

* UserInterface/Main.js:
(WebInspector.loaded):
(WebInspector._provisionalLoadStarted):
Listen for ProvisionalLoadStarted instead of ProvisionalLoadCommitted to save the cookie
before the TimelineRecording is reset and clears the UI.

* UserInterface/NavigationSidebarPanel.js:
(WebInspector.NavigationSidebarPanel.prototype.get restoringState): Added.
(WebInspector.NavigationSidebarPanel.prototype.restoreStateFromCookie.finalAttemptToRestoreViewStateFromCookie):
Delete _pendingViewStateCookie since this was the final attempt.
(WebInspector.NavigationSidebarPanel.prototype.restoreStateFromCookie):
(WebInspector.NavigationSidebarPanel.prototype._isTreeElementWithoutRepresentedObject): Block string represented objects.
(WebInspector.NavigationSidebarPanel.prototype._checkElementsForPendingViewStateCookie):

* UserInterface/OverviewTimelineView.js:
(WebInspector.OverviewTimelineView.prototype._treeElementSelected):

* UserInterface/ResourceSidebarPanel.js:
(WebInspector.ResourceSidebarPanel.prototype.treeElementForRepresentedObject):
Drive-by fix to null check parentFrame since it can be null. Was causing an exception while working on this.

* UserInterface/SourceCodeTimeline.js:
(WebInspector.SourceCodeTimeline):
(WebInspector.SourceCodeTimeline.prototype.saveIdentityToCookie):

* UserInterface/TimelineSidebarPanel.js:
(WebInspector.TimelineSidebarPanel.prototype.canShowDifferentContentView):
(WebInspector.TimelineSidebarPanel.prototype.saveStateToCookie):
(WebInspector.TimelineSidebarPanel.prototype.restoreStateFromCookie):

* UserInterface/TreeOutline.js:
(TreeOutline.prototype._forgetTreeElement):
Drive-by fix to clear selectedTreeElement if it is removed from the tree. Was causing removed TreeElements to be
saved as a cookie since it was still the selected item.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@162413 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent bf02b452
2014-01-13 Timothy Hatcher <timothy@apple.com>
Implement state cookie support for WebInspector.TimelineSidebarPanel.
https://bugs.webkit.org/show_bug.cgi?id=126921
Reviewed by Joseph Pecoraro.
* UserInterface/DebuggerSidebarPanel.js:
(WebInspector.DebuggerSidebarPanel.prototype.restoreStateFromCookie):
Drive-by fix to pass along relaxedMatchDelay to the superclass.
* UserInterface/Main.js:
(WebInspector.loaded):
(WebInspector._provisionalLoadStarted):
Listen for ProvisionalLoadStarted instead of ProvisionalLoadCommitted to save the cookie
before the TimelineRecording is reset and clears the UI.
* UserInterface/NavigationSidebarPanel.js:
(WebInspector.NavigationSidebarPanel.prototype.get restoringState): Added.
(WebInspector.NavigationSidebarPanel.prototype.restoreStateFromCookie.finalAttemptToRestoreViewStateFromCookie):
Delete _pendingViewStateCookie since this was the final attempt.
(WebInspector.NavigationSidebarPanel.prototype.restoreStateFromCookie):
(WebInspector.NavigationSidebarPanel.prototype._isTreeElementWithoutRepresentedObject): Block string represented objects.
(WebInspector.NavigationSidebarPanel.prototype._checkElementsForPendingViewStateCookie):
* UserInterface/OverviewTimelineView.js:
(WebInspector.OverviewTimelineView.prototype._treeElementSelected):
* UserInterface/ResourceSidebarPanel.js:
(WebInspector.ResourceSidebarPanel.prototype.treeElementForRepresentedObject):
Drive-by fix to null check parentFrame since it can be null. Was causing an exception while working on this.
* UserInterface/SourceCodeTimeline.js:
(WebInspector.SourceCodeTimeline):
(WebInspector.SourceCodeTimeline.prototype.saveIdentityToCookie):
* UserInterface/TimelineSidebarPanel.js:
(WebInspector.TimelineSidebarPanel.prototype.canShowDifferentContentView):
(WebInspector.TimelineSidebarPanel.prototype.saveStateToCookie):
(WebInspector.TimelineSidebarPanel.prototype.restoreStateFromCookie):
* UserInterface/TreeOutline.js:
(TreeOutline.prototype._forgetTreeElement):
Drive-by fix to clear selectedTreeElement if it is removed from the tree. Was causing removed TreeElements to be
saved as a cookie since it was still the selected item.
2014-01-11 Timothy Hatcher <timothy@apple.com>
Implement bar graph rendering for WebInspector.OverviewTimelineView.
......
......@@ -158,7 +158,7 @@ WebInspector.DebuggerSidebarPanel.prototype = {
WebInspector.NavigationSidebarPanel.prototype.saveStateToCookie.call(this, cookie);
},
restoreStateFromCookie: function(cookie)
restoreStateFromCookie: function(cookie, relaxedMatchDelay)
{
console.assert(cookie);
......@@ -168,7 +168,7 @@ WebInspector.DebuggerSidebarPanel.prototype = {
else if (cookie[WebInspector.DebuggerSidebarPanel.SelectedAllUncaughtExceptionsCookieKey])
this._allUncaughtExceptionsBreakpointTreeElement.revealAndSelect();
else
WebInspector.NavigationSidebarPanel.prototype.restoreStateFromCookie.call(this, cookie);
WebInspector.NavigationSidebarPanel.prototype.restoreStateFromCookie.call(this, cookie, relaxedMatchDelay);
},
// Private
......
......@@ -78,6 +78,10 @@ WebInspector.loaded = function()
WebInspector.CSSCompletions.requestCSSNameCompletions();
this._generateDisclosureTriangleImages();
// Listen for the ProvisionalLoadStarted event before registering for events so our code gets called before any managers or sidebars.
// This lets us save a state cookie before any managers or sidebars do any resets that would affect state (namely TimelineManager).
WebInspector.Frame.addEventListener(WebInspector.Frame.Event.ProvisionalLoadStarted, this._provisionalLoadStarted, this);
// Create the singleton managers next, before the user interface elements, so the user interface can register
// as event listeners on these managers.
this.branchManager = new WebInspector.BranchManager;
......@@ -106,7 +110,6 @@ WebInspector.loaded = function()
this.frameResourceManager.addEventListener(WebInspector.FrameResourceManager.Event.MainFrameDidChange, this._mainFrameDidChange, this);
WebInspector.Frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
WebInspector.Frame.addEventListener(WebInspector.Frame.Event.ProvisionalLoadCommitted, this._provisionalLoadCommitted, this);
document.addEventListener("DOMContentLoaded", this.contentLoaded.bind(this));
......@@ -721,7 +724,7 @@ WebInspector._mainResourceDidChange = function(event)
this.updateWindowTitle();
}
WebInspector._provisionalLoadCommitted = function(event)
WebInspector._provisionalLoadStarted = function(event)
{
if (!event.target.isMainFrame())
return;
......
......@@ -152,6 +152,11 @@ WebInspector.NavigationSidebarPanel.prototype = {
return this._filterBar;
},
get restoringState()
{
return this._restoringState;
},
createContentTreeOutline: function(dontHideByDefault, suppressFiltering)
{
var contentTreeOutlineElement = document.createElement("ol");
......@@ -224,6 +229,7 @@ WebInspector.NavigationSidebarPanel.prototype = {
restoreStateFromCookie: function(cookie, relaxedMatchDelay)
{
this._pendingViewStateCookie = cookie;
this._restoringState = true;
// Check if any existing tree elements in any outline match the cookie.
this._checkOutlinesForPendingViewStateCookie();
......@@ -231,10 +237,15 @@ WebInspector.NavigationSidebarPanel.prototype = {
if (this._finalAttemptToRestoreViewStateTimeout)
clearTimeout(this._finalAttemptToRestoreViewStateTimeout);
var finalAttemptToRestoreViewStateFromCookie = function() {
function finalAttemptToRestoreViewStateFromCookie()
{
delete this._finalAttemptToRestoreViewStateTimeout;
this._checkOutlinesForPendingViewStateCookie(true);
};
delete this._pendingViewStateCookie;
delete this._restoringState;
}
// If the specific tree element wasn't found, we may need to wait for the resources
// to be registered. We try one last time (match type only) after an arbitrary amount of timeout.
......@@ -563,7 +574,9 @@ WebInspector.NavigationSidebarPanel.prototype = {
_isTreeElementWithoutRepresentedObject: function(treeElement)
{
return treeElement instanceof WebInspector.FolderTreeElement
|| treeElement instanceof WebInspector.DatabaseHostTreeElement;
|| treeElement instanceof WebInspector.DatabaseHostTreeElement
|| typeof treeElement.representedObject === "string"
|| treeElement.representedObject instanceof String;
},
_checkOutlinesForPendingViewStateCookie: function(matchTypeOnly)
......@@ -627,10 +640,20 @@ WebInspector.NavigationSidebarPanel.prototype = {
}, this);
if (matchedElement) {
matchedElement.revealAndSelect();
matchedElement.revealAndSelect(true, false);
delete this._pendingViewStateCookie;
if (this._finalAttemptToRestoreViewStateTimeout)
// Delay clearing the restoringState flag until the next runloop so listeners
// checking for it in this runloop still know state was being restored.
setTimeout(function() {
delete this._restoringState;
}.bind(this));
if (this._finalAttemptToRestoreViewStateTimeout) {
clearTimeout(this._finalAttemptToRestoreViewStateTimeout);
delete this._finalAttemptToRestoreViewStateTimeout;
}
}
}
};
......
......@@ -273,6 +273,9 @@ WebInspector.OverviewTimelineView.prototype = {
_treeElementSelected: function(treeElement, selectedByUser)
{
if (!WebInspector.timelineSidebarPanel.canShowDifferentContentView())
return;
if (treeElement instanceof WebInspector.FolderTreeElement)
return;
......
......@@ -217,7 +217,7 @@ WebInspector.ResourceSidebarPanel.prototype = {
// A custom implementation is needed for this since the frames are populated lazily.
// The Frame is used as the representedObject instead of the main resource in our tree.
if (representedObject instanceof WebInspector.Resource && representedObject.parentFrame.mainResource === representedObject)
if (representedObject instanceof WebInspector.Resource && representedObject.parentFrame && representedObject.parentFrame.mainResource === representedObject)
representedObject = representedObject.parentFrame;
function isAncestor(ancestor, resourceOrFrame)
......
......@@ -28,6 +28,7 @@ WebInspector.SourceCodeTimeline = function(sourceCode, sourceCodeLocation, recor
WebInspector.Timeline.call(this);
console.assert(sourceCode);
console.assert(!sourceCodeLocation || sourceCodeLocation.sourceCode === sourceCode);
console.assert(recordType);
this._sourceCode = sourceCode;
......@@ -36,6 +37,14 @@ WebInspector.SourceCodeTimeline = function(sourceCode, sourceCodeLocation, recor
this._recordEventType = recordEventType || null;
};
WebInspector.SourceCodeTimeline.TypeIdentifier = "source-code-timeline";
WebInspector.SourceCodeTimeline.SourceCodeURLCookieKey = "source-code-timeline-source-code-url";
WebInspector.SourceCodeTimeline.SourceCodeLocationLineCookieKey = "source-code-timeline-source-code-location-line";
WebInspector.SourceCodeTimeline.SourceCodeLocationColumnCookieKey = "source-code-timeline-source-code-location-column";
WebInspector.SourceCodeTimeline.SourceCodeURLCookieKey = "source-code-timeline-source-code-url";
WebInspector.SourceCodeTimeline.RecordTypeCookieKey = "source-code-timeline-record-type";
WebInspector.SourceCodeTimeline.RecordEventTypeCookieKey = "source-code-timeline-record-event-type";
WebInspector.SourceCodeTimeline.prototype = {
constructor: WebInspector.SourceCodeTimeline,
__proto__: WebInspector.Timeline.prototype,
......@@ -60,5 +69,14 @@ WebInspector.SourceCodeTimeline.prototype = {
get recordEventType()
{
return this._recordEventType;
},
saveIdentityToCookie: function(cookie)
{
cookie[WebInspector.SourceCodeTimeline.SourceCodeURLCookieKey] = this._sourceCode.url ? this._sourceCode.url.hash : null;
cookie[WebInspector.SourceCodeTimeline.SourceCodeLocationLineCookieKey] = this._sourceCodeLocation ? this._sourceCodeLocation.lineNumber : null;
cookie[WebInspector.SourceCodeTimeline.SourceCodeLocationColumnCookieKey] = this._sourceCodeLocation ? this._sourceCodeLocation.columnNumber : null;
cookie[WebInspector.SourceCodeTimeline.RecordTypeCookieKey] = this._recordType || null;
cookie[WebInspector.SourceCodeTimeline.RecordEventTypeCookieKey] = this._recordEventType || null;
}
};
......@@ -107,6 +107,9 @@ WebInspector.TimelineSidebarPanel.NetworkIconStyleClass = "network-icon";
WebInspector.TimelineSidebarPanel.ColorsIconStyleClass = "colors-icon";
WebInspector.TimelineSidebarPanel.ScriptIconStyleClass = "script-icon";
WebInspector.TimelineSidebarPanel.TimelineContentViewShowingStyleClass = "timeline-content-view-showing";
WebInspector.TimelineSidebarPanel.ShowingTimelineContentViewCookieKey = "timeline-sidebar-panel-showing-timeline-content-view";
WebInspector.TimelineSidebarPanel.SelectedTimelineViewIdentifierCookieKey = "timeline-sidebar-panel-selected-timeline-view-identifier";
WebInspector.TimelineSidebarPanel.OverviewTimelineIdentifierCookieValue = "overview";
WebInspector.TimelineSidebarPanel.prototype = {
constructor: WebInspector.TimelineSidebarPanel,
......@@ -177,6 +180,48 @@ WebInspector.TimelineSidebarPanel.prototype = {
this._stripeBackgroundElement.style.height = contentHeight + "px";
},
canShowDifferentContentView: function()
{
return !this.restoringState || !this._restoredShowingTimelineContentView;
},
saveStateToCookie: function(cookie)
{
console.assert(cookie);
cookie[WebInspector.timelineSidebarPanel.ShowingTimelineContentViewCookieKey] = WebInspector.contentBrowser.currentContentView instanceof WebInspector.TimelineContentView;
var selectedTreeElement = this._timelinesTreeOutline.selectedTreeElement;
if (selectedTreeElement)
cookie[WebInspector.TimelineSidebarPanel.SelectedTimelineViewIdentifierCookieKey] = selectedTreeElement.representedObject;
else
cookie[WebInspector.TimelineSidebarPanel.SelectedTimelineViewIdentifierCookieKey] = WebInspector.TimelineSidebarPanel.OverviewTimelineIdentifierCookieValue;
WebInspector.NavigationSidebarPanel.prototype.saveStateToCookie.call(this, cookie);
},
restoreStateFromCookie: function(cookie, relaxedMatchDelay)
{
console.assert(cookie);
// The _timelineContentView is not ready on initial load, so delay the restore.
// This matches the delayed work in the WebInspector.TimelineSidebarPanel constructor.
if (!this._timelineContentView) {
setTimeout(this.restoreStateFromCookie.bind(this, cookie, relaxedMatchDelay), 0);
return;
}
this._restoredShowingTimelineContentView = cookie[WebInspector.timelineSidebarPanel.ShowingTimelineContentViewCookieKey];
var selectedTimelineViewIdentifier = cookie[WebInspector.TimelineSidebarPanel.SelectedTimelineViewIdentifierCookieKey];
if (selectedTimelineViewIdentifier === WebInspector.TimelineSidebarPanel.OverviewTimelineIdentifierCookieValue)
this.showTimelineOverview();
else
this.showTimelineView(selectedTimelineViewIdentifier);
WebInspector.NavigationSidebarPanel.prototype.restoreStateFromCookie.call(this, cookie, relaxedMatchDelay);
},
// Private
_timelinesTreeElementSelected: function(treeElement, selectedByUser)
......
......@@ -276,6 +276,8 @@ TreeOutline.prototype._rememberTreeElement = function(element)
TreeOutline.prototype._forgetTreeElement = function(element)
{
if (this.selectedTreeElement === element)
this.selectedTreeElement = null;
if (this._knownTreeElements[element.identifier])
this._knownTreeElements[element.identifier].remove(element, true);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment