bug 610736 - Port a number of recent places changes, r=Neil
This commit is contained in:
Родитель
2ead581044
Коммит
cb5a80d3f1
|
@ -102,12 +102,14 @@ nsBrowserStatusHandler.prototype =
|
|||
this.feedsMenu = null;
|
||||
},
|
||||
|
||||
// nsIXULBrowserWindow
|
||||
setJSStatus : function(status)
|
||||
{
|
||||
this.jsStatus = status;
|
||||
this.updateStatusField();
|
||||
},
|
||||
|
||||
// nsIXULBrowserWindow
|
||||
setJSDefaultStatus : function(status)
|
||||
{
|
||||
this.jsDefaultStatus = status;
|
||||
|
@ -120,6 +122,7 @@ nsBrowserStatusHandler.prototype =
|
|||
this.updateStatusField();
|
||||
},
|
||||
|
||||
// nsIXULBrowserWindow
|
||||
setOverLink : function(link, context)
|
||||
{
|
||||
this.overLink = link;
|
||||
|
@ -133,6 +136,12 @@ nsBrowserStatusHandler.prototype =
|
|||
this.statusTextField.setAttribute('crop', 'end');
|
||||
},
|
||||
|
||||
// nsIXULBrowserWindow
|
||||
// Called before links are navigated to to allow us to retarget them if needed.
|
||||
onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
|
||||
return originalTarget;
|
||||
},
|
||||
|
||||
updateStatusField : function()
|
||||
{
|
||||
var text = this.overLink || this.status || this.jsStatus || this.jsDefaultStatus || this.defaultStatus;
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="init();"
|
||||
onunload="SidebarUtils.clearURLFromStatusBar();"
|
||||
onunload="SidebarUtils.setMouseoverURL('');"
|
||||
elementtofocus="search-box">
|
||||
|
||||
<script type="application/javascript"
|
||||
|
@ -83,7 +83,7 @@
|
|||
onkeypress="SidebarUtils.handleTreeKeyPress(event);"
|
||||
onclick="SidebarUtils.handleTreeClick(this, event, true);"
|
||||
onmousemove="SidebarUtils.handleTreeMouseMove(event);"
|
||||
onmouseout="SidebarUtils.clearURLFromStatusBar();">
|
||||
onmouseout="SidebarUtils.setMouseoverURL('');">
|
||||
<treecols>
|
||||
<treecol id="title" flex="1" primary="true" hideheader="true"/>
|
||||
</treecols>
|
||||
|
|
|
@ -354,7 +354,7 @@
|
|||
<toolbox id="searchModifiers" hidden="true">
|
||||
<toolbar id="organizerScopeBar" xpfe="false"
|
||||
class="chromeclass-toolbar" align="center">
|
||||
<label id="scopeBarTitle" value="&search.label;"/>
|
||||
<label id="scopeBarTitle" value="&search.in.label;"/>
|
||||
<button id="scopeBarAll" class="small-margin"
|
||||
type="radio" group="scopeBar"
|
||||
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
|
||||
|
|
|
@ -691,7 +691,12 @@ var gEditItemOverlay = {
|
|||
|
||||
// Here we update either the item title or its cached static title
|
||||
var newTitle = this._element("userEnteredName").label;
|
||||
if (this._getItemStaticTitle() != newTitle) {
|
||||
if (!newTitle &&
|
||||
PlacesUtils.bookmarks.getFolderIdForItem(this._itemId) == PlacesUtils.tagsFolderId) {
|
||||
// We don't allow setting an empty title for a tag, restore the old one.
|
||||
this._initNamePicker();
|
||||
}
|
||||
else if (this._getItemStaticTitle() != newTitle) {
|
||||
this._mayUpdateFirstEditField("namePicker");
|
||||
if (PlacesUtils.microsummaries.hasMicrosummary(this._itemId)) {
|
||||
// Note: this implicitly also takes care of the microsummary->static
|
||||
|
@ -1001,20 +1006,16 @@ var gEditItemOverlay = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Splits "tagsField" element value, returning an array of valid tag strings.
|
||||
*
|
||||
* @return Array of tag strings found in the field value.
|
||||
*/
|
||||
_getTagsArrayFromTagField: function EIO__getTagsArrayFromTagField() {
|
||||
// we don't require the leading space (after each comma)
|
||||
var tags = this._element("tagsField").value.split(",");
|
||||
for (var i=0; i < tags.length; i++) {
|
||||
// remove trailing and leading spaces
|
||||
tags[i] = tags[i].replace(/^\s+/, "").replace(/\s+$/, "");
|
||||
|
||||
// remove empty entries from the array.
|
||||
if (tags[i] == "") {
|
||||
tags.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return tags;
|
||||
let tags = this._element("tagsField").value;
|
||||
return tags.trim()
|
||||
.split(/\s*,\s*/) // Split on commas and remove spaces.
|
||||
.filter(function (tag) tag.length > 0); // Kill empty tags.
|
||||
},
|
||||
|
||||
newFolder: function EIO_newFolder() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
// /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -116,6 +116,14 @@
|
|||
isPhishingURL(ceParams.linkNode, false, href))
|
||||
return false;
|
||||
handleLinkClick(event, href, ceParams.linkNode);
|
||||
|
||||
// Mark the page as a user followed link. This is done so that history can
|
||||
// distinguish automatic embed visits from user activated ones. For example
|
||||
// pages loaded in frames are embed visits and lost with the session, while
|
||||
// visits across frames should be preserved.
|
||||
try {
|
||||
PlacesUIUtils.markPageAsFollowedLink(href);
|
||||
} catch (ex) { /* Skip invalid URIs. */ }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -125,6 +133,7 @@
|
|||
!pref.getBoolPref("general.autoScroll")) {
|
||||
middleMousePaste(event);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,11 +53,11 @@
|
|||
<page id="history-panel" orient="vertical"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="HistoryCommonInit();"
|
||||
onunload="SidebarUtils.clearURLFromStatusBar();"
|
||||
onunload="SidebarUtils.setMouseoverURL('');"
|
||||
elementtofocus="search-box">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://communicator/content/history/sidebarUtils.js"/>
|
||||
src="chrome://communicator/content/places/sidebarUtils.js"/>
|
||||
|
||||
<commandset id="editMenuCommands"/>
|
||||
<commandset id="placesCommands"/>
|
||||
|
@ -87,7 +87,7 @@
|
|||
onkeypress="SidebarUtils.handleTreeKeyPress(event);"
|
||||
onclick="SidebarUtils.handleTreeClick(this, event, true);"
|
||||
onmousemove="SidebarUtils.handleTreeMouseMove(event);"
|
||||
onmouseout="SidebarUtils.clearURLFromStatusBar();">
|
||||
onmouseout="SidebarUtils.setMouseoverURL('');">
|
||||
<treecols context="">
|
||||
<treecol label="&col.title.label;" id="Name" flex="4"
|
||||
persist="width hidden ordinal sortActive sortDirection"/>
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Places Organizer.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Google Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005-2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dan Mills <thunder@mozilla.com> (Ported from history-panel.js)
|
||||
* Marco Bonardo <mak77@supereva.it>
|
||||
* Robert Kaiser <kairo@kairo.at>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var SidebarUtils = {
|
||||
handleTreeClick: function SU_handleTreeClick(aTree, aEvent, aGutterSelect) {
|
||||
// right-clicks are not handled here
|
||||
if (aEvent.button == 2)
|
||||
return;
|
||||
|
||||
var tbo = aTree.treeBoxObject;
|
||||
var row = { }, col = { }, obj = { };
|
||||
tbo.getCellAt(aEvent.clientX, aEvent.clientY, row, col, obj);
|
||||
|
||||
if (row.value == -1 || obj.value == "twisty")
|
||||
return;
|
||||
|
||||
var mouseInGutter = false;
|
||||
if (aGutterSelect) {
|
||||
var x = { }, y = { }, w = { }, h = { };
|
||||
tbo.getCoordsForCellItem(row.value, col.value, "image",
|
||||
x, y, w, h);
|
||||
mouseInGutter = aEvent.clientX < x.value;
|
||||
}
|
||||
|
||||
var openWhere = whereToOpenLink(aEvent, false, true);
|
||||
|
||||
var isContainer = tbo.view.isContainer(row.value);
|
||||
var openInTabs = isContainer &&
|
||||
(openWhere == "tab" || openWhere == "tabshifted") &&
|
||||
PlacesUtils.hasChildURIs(tbo.view.nodeForTreeIndex(row.value));
|
||||
|
||||
if (aEvent.button == 0 && isContainer && !openInTabs) {
|
||||
tbo.view.toggleOpenState(row.value);
|
||||
return;
|
||||
}
|
||||
else if (!mouseInGutter && openInTabs &&
|
||||
aEvent.originalTarget.localName == "treechildren") {
|
||||
tbo.view.selection.select(row.value);
|
||||
PlacesUIUtils.openContainerNodeInTabs(aTree.selectedNode, aEvent);
|
||||
}
|
||||
else if (!mouseInGutter && !isContainer &&
|
||||
aEvent.originalTarget.localName == "treechildren") {
|
||||
// Clear all other selection since we're loading a link now. We must
|
||||
// do this *before* attempting to load the link since openURL uses
|
||||
// selection as an indication of which link to load.
|
||||
tbo.view.selection.select(row.value);
|
||||
PlacesUIUtils.openNodeWithEvent(aTree.selectedNode, aEvent);
|
||||
}
|
||||
},
|
||||
|
||||
handleTreeKeyPress: function SU_handleTreeKeyPress(aEvent) {
|
||||
if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN)
|
||||
PlacesUIUtils.openNodeWithEvent(aEvent.target.selectedNode, aEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
* The following function displays the URL of a node that is being
|
||||
* hovered over.
|
||||
*/
|
||||
handleTreeMouseMove: function SU_handleTreeMouseMove(aEvent) {
|
||||
if (aEvent.target.localName != "treechildren")
|
||||
return;
|
||||
|
||||
var tree = aEvent.target.parentNode;
|
||||
var tbo = tree.treeBoxObject;
|
||||
var row = { }, col = { }, obj = { };
|
||||
tbo.getCellAt(aEvent.clientX, aEvent.clientY, row, col, obj);
|
||||
|
||||
// row.value is -1 when the mouse is hovering an empty area within the tree.
|
||||
// To avoid showing a URL from a previously hovered node,
|
||||
// for a currently hovered non-url node, we must clear the URL from the
|
||||
// status bar in these cases.
|
||||
if (row.value != -1) {
|
||||
var cell = tree.view.nodeForTreeIndex(row.value);
|
||||
if (PlacesUtils.nodeIsURI(cell))
|
||||
window.top.XULBrowserWindow.setOverLink(cell.uri, null);
|
||||
else
|
||||
this.clearURLFromStatusBar();
|
||||
}
|
||||
else
|
||||
this.clearURLFromStatusBar();
|
||||
},
|
||||
|
||||
clearURLFromStatusBar: function SU_clearURLFromStatusBar() {
|
||||
if (window.top.XULBrowserWindow)
|
||||
window.top.XULBrowserWindow.setOverLink("", null);
|
||||
}
|
||||
};
|
|
@ -153,7 +153,6 @@ comm.jar:
|
|||
content/communicator/history/history-panel.xul (history/history-panel.xul)
|
||||
content/communicator/history/places.css (history/places.css)
|
||||
content/communicator/history/placesOverlay.xul (history/placesOverlay.xul)
|
||||
content/communicator/history/sidebarUtils.js (history/sidebarUtils.js)
|
||||
content/communicator/history/tree.xml (history/tree.xml)
|
||||
content/communicator/history/treeView.js (history/treeView.js)
|
||||
* content/communicator/history/utils.js (history/utils.js)
|
||||
|
|
|
@ -111,21 +111,20 @@ var SidebarUtils = {
|
|||
tbo.getCellAt(aEvent.clientX, aEvent.clientY, row, col, obj);
|
||||
|
||||
// row.value is -1 when the mouse is hovering an empty area within the tree.
|
||||
// To avoid showing a URL from a previously hovered node,
|
||||
// for a currently hovered non-url node, we must clear the URL from the
|
||||
// status bar in these cases.
|
||||
// To avoid showing a URL from a previously hovered node for a currently
|
||||
// hovered non-url node, we must clear the moused-over URL in these cases.
|
||||
if (row.value != -1) {
|
||||
var cell = tree.view.nodeForTreeIndex(row.value);
|
||||
if (PlacesUtils.nodeIsURI(cell))
|
||||
window.top.XULBrowserWindow.setOverLink(cell.uri, null);
|
||||
var node = tree.view.nodeForTreeIndex(row.value);
|
||||
if (PlacesUtils.nodeIsURI(node))
|
||||
this.setMouseoverURL(node.uri);
|
||||
else
|
||||
this.clearURLFromStatusBar();
|
||||
this.setMouseoverURL("");
|
||||
}
|
||||
else
|
||||
this.clearURLFromStatusBar();
|
||||
this.setMouseoverURL("");
|
||||
},
|
||||
|
||||
clearURLFromStatusBar: function SU_clearURLFromStatusBar() {
|
||||
window.top.XULBrowserWindow.setOverLink("", null);
|
||||
setMouseoverURL: function SU_setMouseoverURL(aURL) {
|
||||
window.top.XULBrowserWindow.setOverLink(aURL, null);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -721,7 +721,7 @@ var PlacesUIUtils = {
|
|||
* This is actually used to distinguish user-initiated visits in frames
|
||||
* so automatic visits can be correctly ignored.
|
||||
*/
|
||||
markPageAsFollowedLink: function PUIU_markPageAsUserClicked(aURL) {
|
||||
markPageAsFollowedLink: function PUIU_markPageAsFollowedLink(aURL) {
|
||||
PlacesUtils.history.QueryInterface(Components.interfaces.nsIBrowserHistory)
|
||||
.markPageAsFollowedLink(this.createFixedURI(aURL));
|
||||
},
|
||||
|
|
|
@ -91,6 +91,10 @@ _BROWSER_FILES = \
|
|||
browser_526613.js \
|
||||
browser_528776.js \
|
||||
browser_isempty.js \
|
||||
browser_markPageAsFollowedLink.js \
|
||||
framedPage.html \
|
||||
frameLeft.html \
|
||||
frameRight.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests that visits across frames are correctly represented in the database.
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
const BASE_URL = "http://mochi.test:8888/browser/suite/common/tests/browser";
|
||||
const PAGE_URL = BASE_URL + "/framedPage.html";
|
||||
const LEFT_URL = BASE_URL + "/frameLeft.html";
|
||||
const RIGHT_URL = BASE_URL + "/frameRight.html";
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
let gTabLoaded = false;
|
||||
let gLeftFrameVisited = false;
|
||||
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData)
|
||||
{
|
||||
let url = aSubject.QueryInterface(Ci.nsIURI).spec;
|
||||
if (url == LEFT_URL ) {
|
||||
is(getTransitionForUrl(url), PlacesUtils.history.TRANSITION_EMBED,
|
||||
"Frames should get a EMBED transition.");
|
||||
gLeftFrameVisited = true;
|
||||
maybeClickLink();
|
||||
}
|
||||
else if (url == RIGHT_URL ) {
|
||||
is(getTransitionForUrl(url), PlacesUtils.history.TRANSITION_FRAMED_LINK,
|
||||
"User activated visits should get a FRAMED_LINK transition.");
|
||||
finish();
|
||||
}
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
|
||||
};
|
||||
Services.obs.addObserver(observer, "uri-visit-saved", false);
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedTab = gBrowser.addTab(PAGE_URL);
|
||||
let frameCount = 0;
|
||||
gBrowser.selectedTab.linkedBrowser.addEventListener("DOMContentLoaded",
|
||||
function (event)
|
||||
{
|
||||
// Wait for all the frames.
|
||||
if (frameCount++ < 2)
|
||||
return;
|
||||
gBrowser.selectedTab.linkedBrowser.removeEventListener("DOMContentLoaded", arguments.callee, false)
|
||||
gTabLoaded = true;
|
||||
maybeClickLink();
|
||||
}, false
|
||||
);
|
||||
}
|
||||
|
||||
function maybeClickLink() {
|
||||
if (gTabLoaded && gLeftFrameVisited) {
|
||||
// Click on the link in the left frame to cause a page load in the
|
||||
// right frame.
|
||||
EventUtils.sendMouseEvent({type: "click"}, "clickme", content.frames[0]);
|
||||
}
|
||||
}
|
||||
|
||||
function getTransitionForUrl(aUrl)
|
||||
{
|
||||
let dbConn = PlacesUtils.history
|
||||
.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
let stmt = dbConn.createStatement(
|
||||
"SELECT visit_type FROM moz_historyvisits_view WHERE place_id = " +
|
||||
"(SELECT id FROM moz_places_view WHERE url = :page_url)");
|
||||
stmt.params.page_url = aUrl;
|
||||
try {
|
||||
ok(stmt.executeStep(), "Found the visit in the database");
|
||||
return stmt.row.visit_type;
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
registerCleanupFunction(function ()
|
||||
{
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
Services.obs.removeObserver(observer, "uri-visit-saved");
|
||||
})
|
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Left frame</title>
|
||||
</head>
|
||||
<body>
|
||||
<a id="clickme" href="frameRight.html" target="right">Open page in the right frame.</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Right Frame</title>
|
||||
</head>
|
||||
<body>
|
||||
This is the right frame.
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Framed page</title>
|
||||
</head>
|
||||
<frameset cols="*,*">
|
||||
<frame name="left" src="frameLeft.html">
|
||||
<frame name="right" src="about:mozilla">
|
||||
</frameset>
|
||||
</html>
|
|
@ -85,6 +85,8 @@
|
|||
|
||||
<!ENTITY search.label "Search:">
|
||||
<!ENTITY search.placeholder "Search Bookmarks">
|
||||
|
||||
<!ENTITY search.in.label "Search in:">
|
||||
<!ENTITY search.scopeFolder.label "Selected Folder">
|
||||
<!ENTITY search.scopeFolder.accesskey "r">
|
||||
<!ENTITY search.scopeBookmarks.label "Bookmarks">
|
||||
|
|
Загрузка…
Ссылка в новой задаче