diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js index 85297dfdc2d..5190df96a06 100644 --- a/toolkit/mozapps/extensions/content/extensions.js +++ b/toolkit/mozapps/extensions/content/extensions.js @@ -823,9 +823,10 @@ var gViewController = { isEnabled: function(aAddon) { return !!aAddon && (gViewController.currentViewObj != gDetailView); }, - doCommand: function(aAddon) { + doCommand: function(aAddon, aScrollToPreferences) { gViewController.loadView("addons://detail/" + - encodeURIComponent(aAddon.id)); + encodeURIComponent(aAddon.id) + + (aScrollToPreferences ? "/preferences" : "")); } }, @@ -964,7 +965,7 @@ var gViewController = { }, doCommand: function(aAddon) { if (aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE) { - gViewController.commands.cmd_showItemDetails.doCommand(aAddon); + gViewController.commands.cmd_showItemDetails.doCommand(aAddon, true); return; } var optionsURL = aAddon.optionsURL; @@ -2565,7 +2566,7 @@ var gDetailView = { } }, - _updateView: function(aAddon, aIsRemote) { + _updateView: function(aAddon, aIsRemote, aScrollToPreferences) { this._updatePrefs.addObserver("", this, false); this.clearLoading(); @@ -2738,7 +2739,7 @@ var gDetailView = { } } - this.fillSettingsRows(); + this.fillSettingsRows(aScrollToPreferences); this.updateState(); @@ -2747,6 +2748,13 @@ var gDetailView = { }, show: function(aAddonId, aRequest) { + let index = aAddonId.indexOf("/preferences"); + let scrollToPreferences = false; + if (index >= 0) { + aAddonId = aAddonId.substring(0, index); + scrollToPreferences = true; + } + var self = this; this._loadingTimer = setTimeout(function() { self.node.setAttribute("loading-extended", true); @@ -2759,7 +2767,7 @@ var gDetailView = { return; if (aAddon) { - self._updateView(aAddon, false); + self._updateView(aAddon, false, scrollToPreferences); return; } @@ -2878,7 +2886,7 @@ var gDetailView = { rows.removeChild(rows.lastChild); }, - fillSettingsRows: function () { + fillSettingsRows: function (aScrollToPreferences) { this.emptySettingsRows(); if (this._addon.optionsType != AddonManager.OPTIONS_TYPE_INLINE) return; @@ -2952,11 +2960,31 @@ var gDetailView = { if (firstSetting) firstSetting.clientTop; Services.obs.notifyObservers(document, "addon-options-displayed", gDetailView._addon.id); + if (aScrollToPreferences) + gDetailView.scrollToPreferencesRows(); }, false); } else { if (firstSetting) firstSetting.clientTop; Services.obs.notifyObservers(document, "addon-options-displayed", this._addon.id); + if (aScrollToPreferences) + gDetailView.scrollToPreferencesRows(); + } + }, + + scrollToPreferencesRows: function() { + // We find this row, rather than remembering it from above, + // in case it has been changed by the observers. + let firstRow = gDetailView.node.querySelector('setting[first-row="true"]'); + if (firstRow) { + let top = firstRow.boxObject.y; + top -= parseInt(window.getComputedStyle(firstRow, null).getPropertyValue("margin-top")); + + let detailViewBoxObject = gDetailView.node.boxObject; + top -= detailViewBoxObject.y; + + detailViewBoxObject.QueryInterface(Ci.nsIScrollBoxObject); + detailViewBoxObject.scrollTo(0, top); } }, diff --git a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js index 7cf8dea2874..9b0825d30a5 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js +++ b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js @@ -23,6 +23,9 @@ var observer = { var setting = aSubject.querySelector("rows > setting[first-row] ~ setting"); var input = gManagerWindow.document.getAnonymousElementByAttribute(setting, "class", "setting-label"); isnot(input, null, "XBL binding should be applied"); + + // Add some extra height to the scrolling pane to ensure that it needs to scroll when appropriate. + gManagerWindow.document.getElementById("detail-controls").style.marginBottom = "1000px"; } } }; @@ -39,6 +42,17 @@ function installAddon(aCallback) { }, "application/x-xpinstall"); } +function checkScrolling(aShouldHaveScrolled) { + var detailView = gManagerWindow.document.getElementById("detail-view"); + var boxObject = detailView.boxObject; + boxObject.QueryInterface(Ci.nsIScrollBoxObject); + ok(detailView.scrollHeight > boxObject.height, "Page should require scrolling"); + if (aShouldHaveScrolled) + isnot(detailView.scrollTop, 0, "Page should have scrolled"); + else + is(detailView.scrollTop, 0, "Page should not have scrolled"); +} + function test() { waitForExplicitFinish(); @@ -147,14 +161,15 @@ add_test(function() { wait_for_view_load(gManagerWindow, function() { is(observer.lastData, "inlinesettings1@tests.mozilla.org", "Observer notification should have fired"); + is(gManagerWindow.gViewController.currentViewId, + "addons://detail/inlinesettings1%40tests.mozilla.org/preferences", + "Current view should scroll to preferences"); + checkScrolling(true); var grid = gManagerWindow.document.getElementById("detail-grid"); var settings = grid.querySelectorAll("rows > setting"); is(settings.length, SETTINGS_ROWS, "Grid should have settings children"); - // Force bindings to apply - settings[0].clientTop; - ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute"); Services.prefs.setBoolPref("extensions.inlinesettings1.bool", false); var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[0], "anonid", "input"); @@ -288,9 +303,6 @@ add_test(function() { var settings = grid.querySelectorAll("rows > setting"); is(settings.length, 4, "Grid should have settings children"); - // Force bindings to apply - settings[0].clientTop; - ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute"); Services.prefs.setBoolPref("extensions.inlinesettings3.radioBool", false); var radios = settings[0].getElementsByTagName("radio"); @@ -354,9 +366,6 @@ add_test(function() { var settings = grid.querySelectorAll("rows > setting"); is(settings.length, 5, "Grid should have settings children"); - // Force bindings to apply - settings[0].clientTop; - var node = settings[0]; node = settings[0]; is_element_hidden(node, "Unsupported settings should not be visible"); @@ -439,10 +448,15 @@ add_test(function() { var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org"); addon.parentNode.ensureElementIsVisible(addon); - var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn"); EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); wait_for_view_load(gManagerWindow, function() { + is(gManagerWindow.gViewController.currentViewId, + "addons://detail/inlinesettings1%40tests.mozilla.org", + "Current view should not scroll to preferences"); + checkScrolling(false); + var grid = gManagerWindow.document.getElementById("detail-grid"); var settings = grid.querySelectorAll("rows > setting"); is(settings.length, SETTINGS_ROWS, "Grid should have settings children");