Bug 591905: Update back/forward buttons correctly after inner-frame navigations. r=Unfocused, a=blocks-betaN

This commit is contained in:
Dave Townsend 2011-02-09 10:25:41 -08:00
Родитель 3466d984e0
Коммит 3ab5eca652
3 изменённых файлов: 246 добавлений и 32 удалений

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

@ -505,7 +505,7 @@ var gViewController = {
statePopped: function(e) {
// If this is a navigation to a previous state then load that state
if (e.state) {
this.loadViewInternal(e.state.view, e.state.previousView);
this.loadViewInternal(e.state.view, e.state.previousView, e.state);
return;
}
@ -542,11 +542,12 @@ var gViewController = {
if (aViewId == this.currentViewId)
return;
gHistory.pushState({
var state = {
view: aViewId,
previousView: this.currentViewId
}, document.title);
this.loadViewInternal(aViewId, this.currentViewId);
};
gHistory.pushState(state);
this.loadViewInternal(aViewId, this.currentViewId, state);
},
// Replaces the existing view with a new one, rewriting the current history
@ -555,25 +556,27 @@ var gViewController = {
if (aViewId == this.currentViewId)
return;
gHistory.replaceState({
var state = {
view: aViewId,
previousView: null
}, document.title);
this.loadViewInternal(aViewId, null);
};
gHistory.replaceState(state);
this.loadViewInternal(aViewId, null, state);
},
loadInitialView: function(aViewId) {
gHistory.replaceState({
var state = {
view: aViewId,
previousView: null
}, document.title);
};
gHistory.replaceState(state);
this.loadViewInternal(aViewId, null);
this.loadViewInternal(aViewId, null, state);
this.initialViewSelected = true;
notifyInitialized();
},
loadViewInternal: function(aViewId, aPreviousView) {
loadViewInternal: function(aViewId, aPreviousView, aState) {
var view = this.parseViewId(aViewId);
if (!view.type || !(view.type in this.viewObjects))
@ -602,7 +605,7 @@ var gViewController = {
this.viewPort.selectedPanel = this.currentViewObj.node;
this.viewPort.selectedPanel.setAttribute("loading", "true");
this.currentViewObj.show(view.param, ++this.currentViewRequest);
this.currentViewObj.show(view.param, ++this.currentViewRequest, aState);
},
// Moves back in the document history and removes the current history entry
@ -1640,7 +1643,7 @@ var gDiscoverView = {
Ci.nsIWebProgress.NOTIFY_STATE_ALL);
if (self.loaded)
self._loadBrowser(notifyInitialized);
self._loadURL(self.homepageURL.spec, notifyInitialized);
else
notifyInitialized();
}
@ -1673,11 +1676,18 @@ var gDiscoverView = {
});
},
show: function() {
show: function(aParam, aRequest, aState) {
gViewController.updateCommands();
// If we're being told to load a specific URL then just do that
if (aState && "url" in aState) {
this.loaded = true;
this._loadURL(aState.url);
}
// If the view has loaded before and the error page is not visible then
// there is nothing else to do
if (this.loaded && this.node.selectedPanel != this._error) {
gViewController.updateCommands();
gViewController.notifyViewChanged();
return;
}
@ -1691,7 +1701,8 @@ var gDiscoverView = {
return;
}
this._loadBrowser(gViewController.notifyViewChanged.bind(gViewController));
this._loadURL(this.homepageURL.spec,
gViewController.notifyViewChanged.bind(gViewController));
},
hide: function() { },
@ -1700,16 +1711,12 @@ var gDiscoverView = {
this.node.selectedPanel = this._error;
},
_loadBrowser: function(aCallback) {
this.node.selectedPanel = this._loading;
_loadURL: function(aURL, aCallback) {
if (aCallback)
this._loadListeners.push(aCallback);
if (this._browser.currentURI.equals(this.homepageURL))
this._browser.reload();
else
this._browser.goHome();
this._browser.loadURIWithFlags(aURL,
Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY);
},
onLocationChange: function(aWebProgress, aRequest, aLocation) {
@ -1717,6 +1724,26 @@ var gDiscoverView = {
if (aLocation.spec == "about:blank")
return;
// When using the real session history the inner-frame will update the
// session history automatically, if using the fake history though it must
// be manually updated
if (gHistory == FakeHistory) {
var docshell = aWebProgress.QueryInterface(Ci.nsIDocShell);
var state = {
view: "addons://discover/",
url: aLocation.spec
};
var replaceHistory = Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY << 16;
if (docshell.loadType & replaceHistory)
gHistory.replaceState(state);
else
gHistory.pushState(state);
}
gViewController.updateCommands();
// If the hostname is the same as the new location's host and either the
// default scheme is insecure or the new location is secure then continue
// with the load
@ -1744,13 +1771,18 @@ var gDiscoverView = {
},
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
// Only care about the network stop status events
if (!(aStateFlags & (Ci.nsIWebProgressListener.STATE_IS_NETWORK)) ||
!(aStateFlags & (Ci.nsIWebProgressListener.STATE_STOP)))
// Only care about the network events
if (!(aStateFlags & (Ci.nsIWebProgressListener.STATE_IS_NETWORK)))
return;
// If this is the start of network activity then show the loading page
if (aStateFlags & (Ci.nsIWebProgressListener.STATE_START))
this.node.selectedPanel = this._loading;
// Ignore anything except stop events
if (!(aStateFlags & (Ci.nsIWebProgressListener.STATE_STOP)))
return;
// Sometimes we stop getting onLocationChange events so we must redo the
// url tests here (bug 602256)
var location = this._browser.currentURI;
// Consider the successful load of about:blank as still loading
@ -1761,9 +1793,7 @@ var gDiscoverView = {
// same as the default hostname or the default scheme is secure and the new
// scheme is insecure then show the error page
if (!Components.isSuccessCode(aStatus) ||
(aRequest && aRequest instanceof Ci.nsIHttpChannel && !aRequest.requestSucceeded) ||
location.host != this.homepageURL.host ||
(this.homepageURL.schemeIs("https") && !location.schemeIs("https"))) {
(aRequest && aRequest instanceof Ci.nsIHttpChannel && !aRequest.requestSucceeded)) {
this.showError();
} else {
// Got a successful load, make sure the browser is visible

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

@ -6,11 +6,62 @@
* Tests that history navigation works for the add-ons manager.
*/
const PREF_DISCOVERURL = "extensions.webservice.discoverURL";
const MAIN_URL = "https://example.com/" + RELATIVE_DIR + "discovery.html";
const SECOND_URL = "https://example.com/" + RELATIVE_DIR + "releaseNotes.xhtml";
var gLoadCompleteCallback = null;
var gProgressListener = {
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
// Only care about the network stop status events
if (!(aStateFlags & (Ci.nsIWebProgressListener.STATE_IS_NETWORK)) ||
!(aStateFlags & (Ci.nsIWebProgressListener.STATE_STOP)))
return;
if (gLoadCompleteCallback)
executeSoon(gLoadCompleteCallback);
gLoadCompleteCallback = null;
},
onLocationChange: function() { },
onSecurityChange: function() { },
onProgressChange: function() { },
onStatusChange: function() { },
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference]),
};
function waitForLoad(aManager, aCallback) {
var browser = aManager.document.getElementById("discover-browser");
browser.addProgressListener(gProgressListener);
gLoadCompleteCallback = function() {
browser.removeProgressListener(gProgressListener);
aCallback();
};
}
function clickLink(aManager, aId, aCallback) {
waitForLoad(aManager, aCallback);
var browser = aManager.document.getElementById("discover-browser");
var link = browser.contentDocument.getElementById(aId);
EventUtils.sendMouseEvent({type: "click"}, link);
}
function test() {
requestLongerTimeout(2);
waitForExplicitFinish();
Services.prefs.setCharPref(PREF_DISCOVERURL, MAIN_URL);
registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF_DISCOVERURL);
});
var gProvider = new MockProvider();
gProvider.createAddons([{
id: "test1@tests.mozilla.org",
@ -96,6 +147,22 @@ function is_in_detail(aManager, view, canGoBack, canGoForward) {
check_state(aManager, canGoBack, canGoForward);
}
function is_in_discovery(aManager, url, canGoBack, canGoForward) {
var browser = aManager.document.getElementById("discover-browser");
is(aManager.document.getElementById("discover-view").selectedPanel, browser,
"Browser should be visible");
var spec = browser.currentURI.spec;
var pos = spec.indexOf("#");
if (pos != -1)
spec = spec.substring(0, pos);
is(spec, url, "Should have loaded the right url");
check_state(aManager, canGoBack, canGoForward);
}
function double_click_addon_element(aManager, aId) {
var addon = get_addon_element(aManager, aId);
addon.parentNode.ensureElementIsVisible(addon);
@ -620,7 +687,7 @@ add_test(function() {
close_manager(aManager, function() {
open_manager(null, function(aManager) {
info("Part 1");
info("Part 2");
is_in_list(aManager, "addons://list/plugin", false, false);
close_manager(aManager, run_next_test);
@ -629,6 +696,119 @@ add_test(function() {
});
});
// Tests that navigating the discovery page works when that was the first view
add_test(function() {
open_manager("addons://discover/", function(aManager) {
info("1");
is_in_discovery(aManager, MAIN_URL, false, false);
clickLink(aManager, "link-good", function() {
info("2");
is_in_discovery(aManager, SECOND_URL, true, false);
waitForLoad(aManager, function() {
info("3");
is_in_discovery(aManager, MAIN_URL, false, true);
waitForLoad(aManager, function() {
is_in_discovery(aManager, SECOND_URL, true, false);
EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-plugins"), { }, aManager);
wait_for_view_load(aManager, function(aManager) {
is_in_list(aManager, "addons://list/plugin", true, false);
go_back(aManager);
wait_for_view_load(aManager, function(aManager) {
is_in_discovery(aManager, SECOND_URL, true, true);
go_back(aManager);
waitForLoad(aManager, function() {
is_in_discovery(aManager, MAIN_URL, false, true);
close_manager(aManager, run_next_test);
});
});
});
});
go_forward(aManager);
});
go_back(aManager);
});
});
});
// Tests that navigating the discovery page works when that was the second view
add_test(function() {
open_manager("addons://list/plugin", function(aManager) {
is_in_list(aManager, "addons://list/plugin", false, false);
EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-discover"), { }, aManager);
wait_for_view_load(aManager, function(aManager) {
is_in_discovery(aManager, MAIN_URL, true, false);
clickLink(aManager, "link-good", function() {
is_in_discovery(aManager, SECOND_URL, true, false);
waitForLoad(aManager, function() {
is_in_discovery(aManager, MAIN_URL, true, true);
waitForLoad(aManager, function() {
is_in_discovery(aManager, SECOND_URL, true, false);
EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-plugins"), { }, aManager);
wait_for_view_load(aManager, function(aManager) {
is_in_list(aManager, "addons://list/plugin", true, false);
go_back(aManager);
wait_for_view_load(aManager, function(aManager) {
is_in_discovery(aManager, SECOND_URL, true, true);
go_back(aManager);
waitForLoad(aManager, function() {
is_in_discovery(aManager, MAIN_URL, true, true);
go_back(aManager);
wait_for_view_load(aManager, function(aManager) {
is_in_list(aManager, "addons://list/plugin", false, true);
go_forward(aManager);
wait_for_view_load(aManager, function(aManager) {
is_in_discovery(aManager, MAIN_URL, true, true);
waitForLoad(aManager, function() {
is_in_discovery(aManager, SECOND_URL, true, true);
close_manager(aManager, run_next_test);
});
go_forward(aManager);
});
});
});
});
});
});
go_forward(aManager);
});
go_back(aManager);
});
});
});
});
// Tests that when displaying in-content and opened in the background the back
// and forward buttons still appear when switching tabs
add_test(function() {

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

@ -178,6 +178,10 @@ function clickLink(aId, aCallback) {
var link = browser.contentDocument.getElementById(aId);
EventUtils.sendMouseEvent({type: "click"}, link);
executeSoon(function() {
ok(isLoading(), "Clicking a link should show the loading pane");
});
}
// Tests that switching to the discovery view displays the right url