mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Merge mozilla-central to services-central.
This commit is contained in:
commit
697a053b1c
15
Makefile.in
15
Makefile.in
@ -203,6 +203,21 @@ codesighs:
|
||||
# defined in package-name.mk
|
||||
export MOZ_SOURCE_STAMP
|
||||
|
||||
#XXX: this is a hack, since we don't want to clobber for MSVC
|
||||
# PGO support, but we can't do this test in client.mk
|
||||
ifneq ($(OS_ARCH)_$(GNU_CC), WINNT_)
|
||||
# No point in clobbering if PGO has been explicitly disabled.
|
||||
ifndef NO_PROFILE_GUIDED_OPTIMIZE
|
||||
maybe_clobber_profiledbuild: clean
|
||||
else
|
||||
maybe_clobber_profiledbuild:
|
||||
endif
|
||||
else
|
||||
maybe_clobber_profiledbuild:
|
||||
endif
|
||||
|
||||
.PHONY: maybe_clobber_profiledbuild
|
||||
|
||||
# Look for R_386_PC32 relocations in shared libs, these
|
||||
# break x86_64 builds and SELinux users.
|
||||
ifeq ($(OS_TARGET)_$(TARGET_XPCOM_ABI),Linux_x86-gcc3)
|
||||
|
@ -881,7 +881,7 @@ pref("browser.privatebrowsing.dont_prompt_on_enter", false);
|
||||
pref("browser.bookmarks.editDialog.firstEditField", "namePicker");
|
||||
|
||||
// base url for the wifi geolocation network provider
|
||||
pref("geo.wifi.uri", "https://www.google.com/loc/json");
|
||||
pref("geo.wifi.uri", "https://maps.googleapis.com/maps/api/browserlocation/json");
|
||||
pref("geo.wifi.protocol", 0);
|
||||
|
||||
// Whether to use a panel that looks like an OS X sheet for customization
|
||||
|
@ -1631,7 +1631,7 @@ BaseTemplates.AttrTag =
|
||||
" ",
|
||||
domplate.SPAN({"class": "nodeName editable"}, "$attr.nodeName"),
|
||||
"="",
|
||||
domplate.SPAN({"class": "nodeValue editable"}, "$attr.nodeValue"),
|
||||
domplate.SPAN({"class": "nodeValue editable", "data-attributeName": "$attr.nodeName"}, "$attr.nodeValue"),
|
||||
""");
|
||||
|
||||
BaseTemplates.TextTag =
|
||||
|
@ -7,5 +7,8 @@
|
||||
<link rel="stylesheet" href="chrome://browser/skin/inspector.css" type="text/css"/>
|
||||
</head>
|
||||
<body role="application">
|
||||
<div id="attribute-editor">
|
||||
<input id="attribute-editor-input" />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -26,6 +26,7 @@
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
* Julian Viereck <jviereck@mozilla.com>
|
||||
* Paul Rouget <paul@mozilla.com>
|
||||
* Kyle Simpson <ksimpson@mozilla.com>
|
||||
*
|
||||
* 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
|
||||
@ -70,6 +71,11 @@ const INSPECTOR_NOTIFICATIONS = {
|
||||
|
||||
// Fires once the Inspector is closed.
|
||||
CLOSED: "inspector-closed",
|
||||
|
||||
// Event notifications for the attribute-value editor
|
||||
EDITOR_OPENED: "inspector-editor-opened",
|
||||
EDITOR_CLOSED: "inspector-editor-closed",
|
||||
EDITOR_SAVED: "inspector-editor-saved",
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -591,6 +597,8 @@ var InspectorUI = {
|
||||
this.ioBox = new InsideOutBox(this, this.treePanelDiv);
|
||||
this.ioBox.createObjectBox(this.win.document.documentElement);
|
||||
this.treeLoaded = true;
|
||||
this.editingContext = null;
|
||||
this.editingEvents = {};
|
||||
|
||||
// initialize the highlighter
|
||||
this.initializeHighlighter();
|
||||
@ -614,6 +622,7 @@ var InspectorUI = {
|
||||
this.treeIFrame.setAttribute("flex", "1");
|
||||
this.treeIFrame.setAttribute("type", "content");
|
||||
this.treeIFrame.setAttribute("onclick", "InspectorUI.onTreeClick(event)");
|
||||
this.treeIFrame.setAttribute("ondblclick", "InspectorUI.onTreeDblClick(event);");
|
||||
this.treeIFrame = this.treePanel.insertBefore(this.treeIFrame, resizerBox);
|
||||
}
|
||||
|
||||
@ -817,6 +826,11 @@ var InspectorUI = {
|
||||
*/
|
||||
closeInspectorUI: function IUI_closeInspectorUI(aKeepStore)
|
||||
{
|
||||
// if currently editing an attribute value, closing the
|
||||
// highlighter/HTML panel dismisses the editor
|
||||
if (this.editingContext)
|
||||
this.closeEditor();
|
||||
|
||||
if (this.closing || !this.win || !this.browser) {
|
||||
return;
|
||||
}
|
||||
@ -854,8 +868,11 @@ var InspectorUI = {
|
||||
delete this.treeBrowserDocument;
|
||||
}
|
||||
|
||||
if (this.treeIFrame)
|
||||
if (this.treeIFrame) {
|
||||
let parent = this.treeIFrame.parentNode;
|
||||
parent.removeChild(this.treeIFrame);
|
||||
delete this.treeIFrame;
|
||||
}
|
||||
delete this.ioBox;
|
||||
|
||||
if (this.domplate) {
|
||||
@ -879,6 +896,8 @@ var InspectorUI = {
|
||||
this.treeLoaded = false;
|
||||
|
||||
this.treePanel.addEventListener("popuphidden", function treePanelHidden() {
|
||||
this.removeEventListener("popuphidden", treePanelHidden, false);
|
||||
|
||||
InspectorUI.closing = false;
|
||||
Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.CLOSED, null);
|
||||
}, false);
|
||||
@ -893,6 +912,11 @@ var InspectorUI = {
|
||||
*/
|
||||
startInspecting: function IUI_startInspecting()
|
||||
{
|
||||
// if currently editing an attribute value, starting
|
||||
// "live inspection" mode closes the editor
|
||||
if (this.editingContext)
|
||||
this.closeEditor();
|
||||
|
||||
document.getElementById("inspector-inspect-toolbutton").checked = true;
|
||||
this.attachPageListeners();
|
||||
this.inspecting = true;
|
||||
@ -933,6 +957,11 @@ var InspectorUI = {
|
||||
*/
|
||||
select: function IUI_select(aNode, forceUpdate, aScroll)
|
||||
{
|
||||
// if currently editing an attribute value, using the
|
||||
// highlighter dismisses the editor
|
||||
if (this.editingContext)
|
||||
this.closeEditor();
|
||||
|
||||
if (!aNode)
|
||||
aNode = this.defaultSelection;
|
||||
|
||||
@ -1044,6 +1073,17 @@ var InspectorUI = {
|
||||
*/
|
||||
onTreeClick: function IUI_onTreeClick(aEvent)
|
||||
{
|
||||
// if currently editing an attribute value, clicking outside
|
||||
// the editor dismisses the editor
|
||||
if (this.editingContext) {
|
||||
this.closeEditor();
|
||||
|
||||
// clicking outside the editor ONLY closes the editor
|
||||
// so, cancel the rest of the processing of this event
|
||||
aEvent.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
let node;
|
||||
let target = aEvent.target;
|
||||
let hitTwisty = false;
|
||||
@ -1068,6 +1108,220 @@ var InspectorUI = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle double-click events in the html tree panel.
|
||||
* (double-clicking an attribute value allows it to be edited)
|
||||
* @param aEvent
|
||||
* The mouse event.
|
||||
*/
|
||||
onTreeDblClick: function IUI_onTreeDblClick(aEvent)
|
||||
{
|
||||
// if already editing an attribute value, double-clicking elsewhere
|
||||
// in the tree is the same as a click, which dismisses the editor
|
||||
if (this.editingContext)
|
||||
this.closeEditor();
|
||||
|
||||
let target = aEvent.target;
|
||||
|
||||
if (this.hasClass(target, "nodeValue")) {
|
||||
let repObj = this.getRepObject(target);
|
||||
let attrName = target.getAttribute("data-attributeName");
|
||||
let attrVal = target.innerHTML;
|
||||
|
||||
this.editAttributeValue(target, repObj, attrName, attrVal);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts the editor for an attribute value.
|
||||
* @param aAttrObj
|
||||
* The DOM object representing the attribute value in the HTML Tree
|
||||
* @param aRepObj
|
||||
* The original DOM (target) object being inspected/edited
|
||||
* @param aAttrName
|
||||
* The name of the attribute being edited
|
||||
* @param aAttrVal
|
||||
* The current value of the attribute being edited
|
||||
*/
|
||||
editAttributeValue:
|
||||
function IUI_editAttributeValue(aAttrObj, aRepObj, aAttrName, aAttrVal)
|
||||
{
|
||||
let editor = this.treeBrowserDocument.getElementById("attribute-editor");
|
||||
let editorInput =
|
||||
this.treeBrowserDocument.getElementById("attribute-editor-input");
|
||||
let attrDims = aAttrObj.getBoundingClientRect();
|
||||
// figure out actual viewable viewport dimensions (sans scrollbars)
|
||||
let viewportWidth = this.treeBrowserDocument.documentElement.clientWidth;
|
||||
let viewportHeight = this.treeBrowserDocument.documentElement.clientHeight;
|
||||
|
||||
// saves the editing context for use when the editor is saved/closed
|
||||
this.editingContext = {
|
||||
attrObj: aAttrObj,
|
||||
repObj: aRepObj,
|
||||
attrName: aAttrName
|
||||
};
|
||||
|
||||
// highlight attribute-value node in tree while editing
|
||||
this.addClass(aAttrObj, "editingAttributeValue");
|
||||
|
||||
// show the editor
|
||||
this.addClass(editor, "editing");
|
||||
|
||||
// offset the editor below the attribute-value node being edited
|
||||
let editorVeritcalOffset = 2;
|
||||
|
||||
// keep the editor comfortably within the bounds of the viewport
|
||||
let editorViewportBoundary = 5;
|
||||
|
||||
// outer editor is sized based on the <input> box inside it
|
||||
editorInput.style.width = Math.min(attrDims.width, viewportWidth -
|
||||
editorViewportBoundary) + "px";
|
||||
editorInput.style.height = Math.min(attrDims.height, viewportHeight -
|
||||
editorViewportBoundary) + "px";
|
||||
let editorDims = editor.getBoundingClientRect();
|
||||
|
||||
// calculate position for the editor according to the attribute node
|
||||
let editorLeft = attrDims.left + this.treeIFrame.contentWindow.scrollX -
|
||||
// center the editor against the attribute value
|
||||
((editorDims.width - attrDims.width) / 2);
|
||||
let editorTop = attrDims.top + this.treeIFrame.contentWindow.scrollY +
|
||||
attrDims.height + editorVeritcalOffset;
|
||||
|
||||
// but, make sure the editor stays within the visible viewport
|
||||
editorLeft = Math.max(0, Math.min(
|
||||
(this.treeIFrame.contentWindow.scrollX +
|
||||
viewportWidth - editorDims.width),
|
||||
editorLeft)
|
||||
);
|
||||
editorTop = Math.max(0, Math.min(
|
||||
(this.treeIFrame.contentWindow.scrollY +
|
||||
viewportHeight - editorDims.height),
|
||||
editorTop)
|
||||
);
|
||||
|
||||
// position the editor
|
||||
editor.style.left = editorLeft + "px";
|
||||
editor.style.top = editorTop + "px";
|
||||
|
||||
// set and select the text
|
||||
editorInput.value = aAttrVal;
|
||||
editorInput.select();
|
||||
|
||||
// listen for editor specific events
|
||||
this.bindEditorEvent(editor, "click", function(aEvent) {
|
||||
aEvent.stopPropagation();
|
||||
});
|
||||
this.bindEditorEvent(editor, "dblclick", function(aEvent) {
|
||||
aEvent.stopPropagation();
|
||||
});
|
||||
this.bindEditorEvent(editor, "keypress",
|
||||
this.handleEditorKeypress.bind(this));
|
||||
|
||||
// event notification
|
||||
Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.EDITOR_OPENED,
|
||||
null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle binding an event handler for the editor.
|
||||
* (saves the callback for easier unbinding later)
|
||||
* @param aEditor
|
||||
* The DOM object for the editor
|
||||
* @param aEventName
|
||||
* The name of the event to listen for
|
||||
* @param aEventCallback
|
||||
* The callback to bind to the event (and also to save for later
|
||||
* unbinding)
|
||||
*/
|
||||
bindEditorEvent:
|
||||
function IUI_bindEditorEvent(aEditor, aEventName, aEventCallback)
|
||||
{
|
||||
this.editingEvents[aEventName] = aEventCallback;
|
||||
aEditor.addEventListener(aEventName, aEventCallback, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle unbinding an event handler from the editor.
|
||||
* (unbinds the previously bound and saved callback)
|
||||
* @param aEditor
|
||||
* The DOM object for the editor
|
||||
* @param aEventName
|
||||
* The name of the event being listened for
|
||||
*/
|
||||
unbindEditorEvent: function IUI_unbindEditorEvent(aEditor, aEventName)
|
||||
{
|
||||
aEditor.removeEventListener(aEventName, this.editingEvents[aEventName],
|
||||
false);
|
||||
this.editingEvents[aEventName] = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle keypress events in the editor.
|
||||
* @param aEvent
|
||||
* The keyboard event.
|
||||
*/
|
||||
handleEditorKeypress: function IUI_handleEditorKeypress(aEvent)
|
||||
{
|
||||
if (aEvent.which == KeyEvent.DOM_VK_RETURN) {
|
||||
this.saveEditor();
|
||||
} else if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE) {
|
||||
this.closeEditor();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the editor and cleanup.
|
||||
*/
|
||||
closeEditor: function IUI_closeEditor()
|
||||
{
|
||||
let editor = this.treeBrowserDocument.getElementById("attribute-editor");
|
||||
let editorInput =
|
||||
this.treeBrowserDocument.getElementById("attribute-editor-input");
|
||||
|
||||
// remove highlight from attribute-value node in tree
|
||||
this.removeClass(this.editingContext.attrObj, "editingAttributeValue");
|
||||
|
||||
// hide editor
|
||||
this.removeClass(editor, "editing");
|
||||
|
||||
// stop listening for editor specific events
|
||||
this.unbindEditorEvent(editor, "click");
|
||||
this.unbindEditorEvent(editor, "dblclick");
|
||||
this.unbindEditorEvent(editor, "keypress");
|
||||
|
||||
// clean up after the editor
|
||||
editorInput.value = "";
|
||||
editorInput.blur();
|
||||
this.editingContext = null;
|
||||
this.editingEvents = {};
|
||||
|
||||
// event notification
|
||||
Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.EDITOR_CLOSED,
|
||||
null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Commit the edits made in the editor, then close it.
|
||||
*/
|
||||
saveEditor: function IUI_saveEditor()
|
||||
{
|
||||
let editorInput =
|
||||
this.treeBrowserDocument.getElementById("attribute-editor-input");
|
||||
|
||||
// set the new attribute value on the original target DOM element
|
||||
this.editingContext.repObj.setAttribute(this.editingContext.attrName,
|
||||
editorInput.value);
|
||||
|
||||
// update the HTML tree attribute value
|
||||
this.editingContext.attrObj.innerHTML = editorInput.value;
|
||||
|
||||
// event notification
|
||||
Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.EDITOR_SAVED,
|
||||
null);
|
||||
|
||||
this.closeEditor();
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach event listeners to content window and child windows to enable
|
||||
* highlighting and click to stop inspection.
|
||||
|
@ -79,7 +79,8 @@ nsContextMenu.prototype = {
|
||||
|
||||
this.hasPageMenu = false;
|
||||
if (!aIsShift) {
|
||||
this.hasPageMenu = PageMenu.init(this.target, aXulMenu);
|
||||
this.hasPageMenu = PageMenu.maybeBuildAndAttachMenu(this.target,
|
||||
aXulMenu);
|
||||
}
|
||||
|
||||
this.isFrameImage = document.getElementById("isFrameImage");
|
||||
|
46
browser/base/content/tabview/content.js
Normal file
46
browser/base/content/tabview/content.js
Normal file
@ -0,0 +1,46 @@
|
||||
/* ***** 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 content.js.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Tim Taubert <ttaubert@mozilla.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
addEventListener("DOMWillOpenModalDialog", function (event) {
|
||||
// (event.isTrusted == true) when the event is generated by a user action
|
||||
// and does not originate from a script.
|
||||
if (event.isTrusted) {
|
||||
// we're intentionally sending a synchronous message to handle this event
|
||||
// as quick as possible, switch the selected tab and hide the tabview
|
||||
// before the modal dialog is shown
|
||||
sendSyncMessage("Panorama:DOMWillOpenModalDialog");
|
||||
}
|
||||
}, true);
|
@ -231,7 +231,7 @@ function GroupItem(listOfEls, options) {
|
||||
.appendTo(appTabTrayContainer);
|
||||
|
||||
AllTabs.tabs.forEach(function(xulTab) {
|
||||
if (xulTab.pinned && xulTab.ownerDocument.defaultView == gWindow)
|
||||
if (xulTab.pinned)
|
||||
self.addAppTab(xulTab, {dontAdjustTray: true});
|
||||
});
|
||||
|
||||
@ -744,9 +744,13 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// ----------
|
||||
// Function: _unhide
|
||||
// Shows the hidden group.
|
||||
_unhide: function GroupItem__unhide() {
|
||||
let self = this;
|
||||
|
||||
//
|
||||
// Parameters:
|
||||
// options - various options (see below)
|
||||
//
|
||||
// Possible options:
|
||||
// immediately - true when no animations should be used
|
||||
_unhide: function GroupItem__unhide(options) {
|
||||
this._cancelFadeAwayUndoButtonTimer();
|
||||
this.hidden = false;
|
||||
this.$undoContainer.remove();
|
||||
@ -754,20 +758,31 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
this.droppable(true);
|
||||
this.setTrenches(this.bounds);
|
||||
|
||||
iQ(this.container).show().animate({
|
||||
"-moz-transform": "scale(1)",
|
||||
"opacity": 1
|
||||
}, {
|
||||
duration: 170,
|
||||
complete: function() {
|
||||
self._children.forEach(function(child) {
|
||||
iQ(child.container).show();
|
||||
});
|
||||
let self = this;
|
||||
|
||||
UI.setActive(self);
|
||||
self._sendToSubscribers("groupShown", { groupItemId: self.id });
|
||||
}
|
||||
});
|
||||
let finalize = function () {
|
||||
self._children.forEach(function(child) {
|
||||
iQ(child.container).show();
|
||||
});
|
||||
|
||||
UI.setActive(self);
|
||||
self._sendToSubscribers("groupShown", { groupItemId: self.id });
|
||||
};
|
||||
|
||||
let $container = iQ(this.container).show();
|
||||
|
||||
if (!options || !options.immediately) {
|
||||
$container.animate({
|
||||
"-moz-transform": "scale(1)",
|
||||
"opacity": 1
|
||||
}, {
|
||||
duration: 170,
|
||||
complete: finalize
|
||||
});
|
||||
} else {
|
||||
$container.css({"-moz-transform": "none", opacity: 1});
|
||||
finalize();
|
||||
}
|
||||
|
||||
GroupItems.updateGroupCloseButtons();
|
||||
},
|
||||
@ -785,15 +800,29 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
let remainingGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||
return (groupItem != self && groupItem.getChildren().length);
|
||||
});
|
||||
|
||||
let tab = null;
|
||||
|
||||
if (!gBrowser._numPinnedTabs && !remainingGroups.length) {
|
||||
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||
return (groupItem != self && !groupItem.getChildren().length);
|
||||
});
|
||||
let group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
|
||||
group.newTab(null, { closedLastTab: true });
|
||||
tab = group.newTab(null, {dontZoomIn: true});
|
||||
}
|
||||
|
||||
this.destroy();
|
||||
let closed = this.destroy();
|
||||
|
||||
if (!tab)
|
||||
return;
|
||||
|
||||
if (closed) {
|
||||
// Let's make the new tab the selected tab.
|
||||
UI.goToTab(tab);
|
||||
} else {
|
||||
// Remove the new tab and group, if this group is no longer closed.
|
||||
tab._tabViewTabItem.parent.destroy({immediately: true});
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -806,6 +835,10 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
//
|
||||
// Options:
|
||||
// immediately - (bool) if true, no animation will be used
|
||||
//
|
||||
// Returns true if the groupItem has been closed, or false otherwise. A group
|
||||
// could not have been closed due to a tab with an onUnload handler (that
|
||||
// waits for user interaction).
|
||||
destroy: function GroupItem_destroy(options) {
|
||||
let self = this;
|
||||
|
||||
@ -814,14 +847,11 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// In other words, the group "close" event is fired before all browser
|
||||
// tabs in the group are closed. The below code would fire the group "close"
|
||||
// event only after all browser tabs in that group are closed.
|
||||
let shouldRemoveTabItems = [];
|
||||
let toClose = this._children.concat();
|
||||
toClose.forEach(function(child) {
|
||||
this._children.concat().forEach(function(child) {
|
||||
child.removeSubscriber("close", self._onChildClose);
|
||||
|
||||
let removed = child.close(true);
|
||||
if (removed) {
|
||||
shouldRemoveTabItems.push(child);
|
||||
if (child.close(true)) {
|
||||
self.remove(child, { dontArrange: true });
|
||||
} else {
|
||||
// child.removeSubscriber() must be called before child.close(),
|
||||
// therefore we call child.addSubscriber() if the tab is not removed.
|
||||
@ -829,15 +859,14 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
}
|
||||
});
|
||||
|
||||
if (shouldRemoveTabItems.length != toClose.length) {
|
||||
// remove children without the assiciated tab and show the group item
|
||||
shouldRemoveTabItems.forEach(function(child) {
|
||||
self.remove(child, { dontArrange: true });
|
||||
});
|
||||
if (this._children.length) {
|
||||
if (this.hidden)
|
||||
this.$undoContainer.fadeOut(function() { self._unhide() });
|
||||
|
||||
this.$undoContainer.fadeOut(function() { self._unhide() });
|
||||
return false;
|
||||
} else {
|
||||
this.close(options);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
@ -1818,13 +1847,16 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// Parameters:
|
||||
// url - the new tab should open this url as well
|
||||
// options - the options object
|
||||
// dontZoomIn - set to true to not zoom into the newly created tab
|
||||
// closedLastTab - boolean indicates the last tab has just been closed
|
||||
newTab: function GroupItem_newTab(url, options) {
|
||||
if (options && options.closedLastTab)
|
||||
UI.closedLastTabInTabView = true;
|
||||
|
||||
UI.setActive(this, { dontSetActiveTabInGroup: true });
|
||||
gBrowser.loadOneTab(url || "about:blank", { inBackground: false });
|
||||
|
||||
let dontZoomIn = !!(options && options.dontZoomIn);
|
||||
return gBrowser.loadOneTab(url || "about:blank", { inBackground: dontZoomIn });
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -1926,13 +1958,13 @@ let GroupItems = {
|
||||
let self = this;
|
||||
|
||||
// setup attr modified handler, and prepare for its uninit
|
||||
function handleAttrModified(xulTab) {
|
||||
self._handleAttrModified(xulTab);
|
||||
function handleAttrModified(event) {
|
||||
self._handleAttrModified(event.target);
|
||||
}
|
||||
|
||||
// make sure any closed tabs are removed from the delay update list
|
||||
function handleClose(xulTab) {
|
||||
let idx = self._delayedModUpdates.indexOf(xulTab);
|
||||
function handleClose(event) {
|
||||
let idx = self._delayedModUpdates.indexOf(event.target);
|
||||
if (idx != -1)
|
||||
self._delayedModUpdates.splice(idx, 1);
|
||||
}
|
||||
@ -2040,7 +2072,7 @@ let GroupItems = {
|
||||
// Function: _updateAppTabIcons
|
||||
// Update images of any apptab icons that point to passed in xultab
|
||||
_updateAppTabIcons: function GroupItems__updateAppTabIcons(xulTab) {
|
||||
if (xulTab.ownerDocument.defaultView != gWindow || !xulTab.pinned)
|
||||
if (!xulTab.pinned)
|
||||
return;
|
||||
|
||||
let iconUrl = this.getAppTabFavIconUrl(xulTab);
|
||||
|
@ -1,183 +0,0 @@
|
||||
/* ***** 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 TabView AllTabs.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Edward Lee <edilee@mozilla.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let EXPORTED_SYMBOLS = ["AllTabs"];
|
||||
|
||||
let AllTabs = {
|
||||
// ----------
|
||||
// Function: toString
|
||||
// Prints [AllTabs] for debug use
|
||||
toString: function AllTabs_toString() {
|
||||
return "[AllTabs]";
|
||||
},
|
||||
|
||||
/**
|
||||
* Get an array of all tabs from all tabbrowser windows.
|
||||
*
|
||||
* @usage let numAllTabs = AllTabs.tabs.length;
|
||||
* AllTabs.tabs.forEach(handleAllTabs);
|
||||
*/
|
||||
get tabs() {
|
||||
// Get tabs from each browser window and flatten them into one array
|
||||
return Array.concat.apply(null, browserWindows.map(function(browserWindow) {
|
||||
return Array.filter(browserWindow.gBrowser.tabs, function (tab) !tab.closing);
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach a callback for a given tab event.
|
||||
*
|
||||
* @param eventName
|
||||
* Name of the corresponding Tab* Event; one of "attrModified",
|
||||
* "close", "move", "open", "select", "pinned", "unpinned".
|
||||
* @param callback
|
||||
* Callback that gets called with the tab as the first argument and
|
||||
* the event as the second argument.
|
||||
* @usage AllTabs.register("change", function handleChange(tab, event) {});
|
||||
*/
|
||||
register: function register(eventName, callback) {
|
||||
// Either add additional callbacks or create the first entry
|
||||
let listeners = eventListeners[events[eventName]];
|
||||
if (listeners)
|
||||
listeners.push(callback);
|
||||
else
|
||||
eventListeners[events[eventName]] = [callback];
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a callback for a given tab event.
|
||||
*
|
||||
* @param eventName
|
||||
* Name of the corresponding Tab* Event; one of "attrModified",
|
||||
* "close", "move", "open", "select", "pinned", "unpinned".
|
||||
* @param callback
|
||||
* The callback given for the original AllTabs.register call.
|
||||
* @usage AllTabs.unregister("close", handleClose);
|
||||
*/
|
||||
unregister: function unregister(eventName, callback) {
|
||||
// Nothing to remove for this event
|
||||
let listeners = eventListeners[events[eventName]];
|
||||
if (!listeners)
|
||||
return;
|
||||
|
||||
// Can only remove a callback if we have it
|
||||
let index = listeners.indexOf(callback);
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
listeners.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
__defineGetter__("browserWindows", function browserWindows() {
|
||||
let browserWindows = [];
|
||||
let windows = Services.wm.getEnumerator("navigator:browser");
|
||||
while (windows.hasMoreElements())
|
||||
browserWindows.push(windows.getNext());
|
||||
return browserWindows;
|
||||
});
|
||||
|
||||
let events = {
|
||||
attrModified: "TabAttrModified",
|
||||
close: "TabClose",
|
||||
move: "TabMove",
|
||||
open: "TabOpen",
|
||||
select: "TabSelect",
|
||||
pinned: "TabPinned",
|
||||
unpinned: "TabUnpinned"
|
||||
};
|
||||
let eventListeners = {};
|
||||
|
||||
function registerBrowserWindow(browserWindow) {
|
||||
for each (let event in events)
|
||||
browserWindow.addEventListener(event, tabEventListener, true);
|
||||
|
||||
browserWindow.addEventListener("unload", unregisterBrowserWindow, false);
|
||||
}
|
||||
|
||||
function unregisterBrowserWindow(unloadEvent) {
|
||||
let browserWindow = unloadEvent.currentTarget;
|
||||
|
||||
for each (let event in events)
|
||||
browserWindow.removeEventListener(event, tabEventListener, true);
|
||||
|
||||
browserWindow.removeEventListener("unload", unregisterBrowserWindow, false);
|
||||
}
|
||||
|
||||
function tabEventListener(event) {
|
||||
// Make sure we've gotten listeners before trying to call
|
||||
let listeners = eventListeners[event.type];
|
||||
if (!listeners)
|
||||
return;
|
||||
|
||||
let tab = event.target;
|
||||
|
||||
// Make a copy of the listeners, so it can't change as we call back
|
||||
listeners.slice().forEach(function (callback) {
|
||||
try {
|
||||
callback(tab, event);
|
||||
}
|
||||
// Don't let failing callbacks stop us but report the failure
|
||||
catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function observer(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "domwindowopened":
|
||||
subject.addEventListener("load", function onLoad() {
|
||||
subject.removeEventListener("load", onLoad, false);
|
||||
|
||||
// Now that the window has loaded, only register on browser windows
|
||||
let doc = subject.document.documentElement;
|
||||
if (doc.getAttribute("windowtype") == "navigator:browser")
|
||||
registerBrowserWindow(subject);
|
||||
}, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Register listeners on all browser windows and future ones
|
||||
browserWindows.forEach(registerBrowserWindow);
|
||||
Services.obs.addObserver(observer, "domwindowopened", false);
|
@ -520,6 +520,9 @@ function createSearchTabMacher() {
|
||||
}
|
||||
|
||||
function hideSearch(event) {
|
||||
if (!isSearchEnabled())
|
||||
return;
|
||||
|
||||
iQ("#searchbox").val("");
|
||||
iQ("#searchshade").hide();
|
||||
iQ("#search").hide();
|
||||
|
@ -79,9 +79,6 @@ let Storage = {
|
||||
|
||||
// ___ Tabs
|
||||
AllTabs.tabs.forEach(function(tab) {
|
||||
if (tab.ownerDocument.defaultView != gWindow)
|
||||
return;
|
||||
|
||||
self.saveTab(tab, null);
|
||||
});
|
||||
|
||||
|
@ -478,29 +478,22 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// closing tab doesn't belong to a group and no empty group, create a new
|
||||
// one for the new tab.
|
||||
if (!groupClose && gBrowser.tabs.length == 1) {
|
||||
let group;
|
||||
if (this.tab._tabViewTabItem.parent) {
|
||||
group = this.tab._tabViewTabItem.parent;
|
||||
} else {
|
||||
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||
return (!groupItem.getChildren().length);
|
||||
});
|
||||
group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
|
||||
}
|
||||
let group = this.tab._tabViewTabItem.parent;
|
||||
group.newTab(null, { closedLastTab: true });
|
||||
}
|
||||
|
||||
// when "TabClose" event is fired, the browser tab is about to close and our
|
||||
// item "close" is fired before the browser tab actually get closed.
|
||||
// Therefore, we need "tabRemoved" event below.
|
||||
gBrowser.removeTab(this.tab);
|
||||
let tabNotClosed =
|
||||
Array.some(gBrowser.tabs, function(tab) { return tab == this.tab; }, this);
|
||||
if (!tabNotClosed)
|
||||
let tabClosed = !this.tab;
|
||||
|
||||
if (tabClosed)
|
||||
this._sendToSubscribers("tabRemoved");
|
||||
|
||||
// No need to explicitly delete the tab data, becasue sessionstore data
|
||||
// associated with the tab will automatically go away
|
||||
return !tabNotClosed;
|
||||
return tabClosed;
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -746,27 +739,26 @@ let TabItems = {
|
||||
this.tempCanvas.height = 112;
|
||||
|
||||
// When a tab is opened, create the TabItem
|
||||
this._eventListeners["open"] = function(tab) {
|
||||
if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
|
||||
return;
|
||||
this._eventListeners.open = function (event) {
|
||||
let tab = event.target;
|
||||
|
||||
self.link(tab);
|
||||
if (!tab.pinned)
|
||||
self.link(tab);
|
||||
}
|
||||
// When a tab's content is loaded, show the canvas and hide the cached data
|
||||
// if necessary.
|
||||
this._eventListeners["attrModified"] = function(tab) {
|
||||
if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
|
||||
return;
|
||||
this._eventListeners.attrModified = function (event) {
|
||||
let tab = event.target;
|
||||
|
||||
self.update(tab);
|
||||
if (!tab.pinned)
|
||||
self.update(tab);
|
||||
}
|
||||
// When a tab is closed, unlink.
|
||||
this._eventListeners["close"] = function(tab) {
|
||||
if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
|
||||
return;
|
||||
this._eventListeners.close = function (event) {
|
||||
let tab = event.target;
|
||||
|
||||
// XXX bug #635975 - don't unlink the tab if the dom window is closing.
|
||||
if (!UI.isDOMWindowClosing)
|
||||
if (!tab.pinned && !UI.isDOMWindowClosing)
|
||||
self.unlink(tab);
|
||||
}
|
||||
for (let name in this._eventListeners) {
|
||||
@ -774,8 +766,8 @@ let TabItems = {
|
||||
}
|
||||
|
||||
// For each tab, create the link.
|
||||
AllTabs.tabs.forEach(function(tab) {
|
||||
if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
|
||||
AllTabs.tabs.forEach(function (tab) {
|
||||
if (tab.pinned)
|
||||
return;
|
||||
|
||||
self.link(tab, {immediately: true});
|
||||
|
@ -5,7 +5,6 @@ const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource:///modules/tabview/AllTabs.jsm");
|
||||
Cu.import("resource:///modules/tabview/utils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
@ -44,6 +43,30 @@ var gTabViewDeck = gWindow.document.getElementById("tab-view-deck");
|
||||
var gBrowserPanel = gWindow.document.getElementById("browser-panel");
|
||||
var gTabViewFrame = gWindow.document.getElementById("tab-view");
|
||||
|
||||
let AllTabs = {
|
||||
_events: {
|
||||
attrModified: "TabAttrModified",
|
||||
close: "TabClose",
|
||||
move: "TabMove",
|
||||
open: "TabOpen",
|
||||
select: "TabSelect",
|
||||
pinned: "TabPinned",
|
||||
unpinned: "TabUnpinned"
|
||||
},
|
||||
|
||||
get tabs() {
|
||||
return Array.filter(gBrowser.tabs, function (tab) !tab.closing);
|
||||
},
|
||||
|
||||
register: function AllTabs_register(eventName, callback) {
|
||||
gBrowser.tabContainer.addEventListener(this._events[eventName], callback, false);
|
||||
},
|
||||
|
||||
unregister: function AllTabs_unregister(eventName, callback) {
|
||||
gBrowser.tabContainer.removeEventListener(this._events[eventName], callback, false);
|
||||
}
|
||||
};
|
||||
|
||||
# NB: Certain files need to evaluate before others
|
||||
|
||||
#include iq.js
|
||||
|
@ -26,6 +26,7 @@
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
* Sean Dunn <seanedunn@yahoo.com>
|
||||
* Tim Taubert <tim.taubert@gmx.de>
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
*
|
||||
* 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
|
||||
@ -80,6 +81,10 @@ let UI = {
|
||||
// If true, a closed tab has just been restored.
|
||||
restoredClosedTab: false,
|
||||
|
||||
// Variable: _isChangingVisibility
|
||||
// Tracks whether we're currently in the process of showing/hiding the tabview.
|
||||
_isChangingVisibility: false,
|
||||
|
||||
// Variable: _reorderTabItemsOnShow
|
||||
// Keeps track of the <GroupItem>s which their tab items' tabs have been moved
|
||||
// and re-orders the tab items when switching to TabView.
|
||||
@ -234,6 +239,15 @@ let UI = {
|
||||
self.uninit();
|
||||
});
|
||||
|
||||
// ___ setup DOMWillOpenModalDialog message handler
|
||||
let mm = gWindow.messageManager;
|
||||
let callback = this._onDOMWillOpenModalDialog.bind(this);
|
||||
mm.addMessageListener("Panorama:DOMWillOpenModalDialog", callback);
|
||||
|
||||
this._cleanupFunctions.push(function () {
|
||||
mm.removeMessageListener("Panorama:DOMWillOpenModalDialog", callback);
|
||||
});
|
||||
|
||||
// ___ setup key handlers
|
||||
this._setTabViewFrameKeyHandlers();
|
||||
|
||||
@ -276,6 +290,10 @@ let UI = {
|
||||
self._save();
|
||||
}, false);
|
||||
|
||||
// ___ load frame script
|
||||
let frameScript = "chrome://browser/content/tabview-content.js";
|
||||
gWindow.messageManager.loadFrameScript(frameScript, true);
|
||||
|
||||
// ___ Done
|
||||
this._frameInitialized = true;
|
||||
this._save();
|
||||
@ -481,9 +499,11 @@ let UI = {
|
||||
// Parameters:
|
||||
// zoomOut - true for zoom out animation, false for nothing.
|
||||
showTabView: function UI_showTabView(zoomOut) {
|
||||
if (this.isTabViewVisible())
|
||||
if (this.isTabViewVisible() || this._isChangingVisibility)
|
||||
return;
|
||||
|
||||
this._isChangingVisibility = true;
|
||||
|
||||
// initialize the direction of the page
|
||||
this._initPageDirection();
|
||||
|
||||
@ -526,6 +546,7 @@ let UI = {
|
||||
self.setActive(item);
|
||||
|
||||
self._resize(true);
|
||||
self._isChangingVisibility = false;
|
||||
dispatchEvent(event);
|
||||
|
||||
// Flush pending updates
|
||||
@ -535,6 +556,7 @@ let UI = {
|
||||
});
|
||||
} else {
|
||||
self.clearActiveTab();
|
||||
self._isChangingVisibility = false;
|
||||
dispatchEvent(event);
|
||||
|
||||
// Flush pending updates
|
||||
@ -551,9 +573,11 @@ let UI = {
|
||||
// Function: hideTabView
|
||||
// Hides TabView and shows the main browser UI.
|
||||
hideTabView: function UI_hideTabView() {
|
||||
if (!this.isTabViewVisible())
|
||||
if (!this.isTabViewVisible() || this._isChangingVisibility)
|
||||
return;
|
||||
|
||||
this._isChangingVisibility = true;
|
||||
|
||||
// another tab might be select if user decides to stay on a page when
|
||||
// a onclose confirmation prompts.
|
||||
GroupItems.removeHiddenGroups();
|
||||
@ -580,6 +604,8 @@ let UI = {
|
||||
#endif
|
||||
Storage.saveVisibilityData(gWindow, "false");
|
||||
|
||||
this._isChangingVisibility = false;
|
||||
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("tabviewhidden", true, false);
|
||||
dispatchEvent(event);
|
||||
@ -685,6 +711,7 @@ let UI = {
|
||||
}
|
||||
} else if (topic == "private-browsing-change-granted") {
|
||||
if (data == "enter" || data == "exit") {
|
||||
hideSearch();
|
||||
self._privateBrowsing.transitionMode = data;
|
||||
self.storageBusy();
|
||||
}
|
||||
@ -710,9 +737,8 @@ let UI = {
|
||||
});
|
||||
|
||||
// TabOpen
|
||||
this._eventListeners.open = function(tab) {
|
||||
if (tab.ownerDocument.defaultView != gWindow)
|
||||
return;
|
||||
this._eventListeners.open = function (event) {
|
||||
let tab = event.target;
|
||||
|
||||
// if it's an app tab, add it to all the group items
|
||||
if (tab.pinned)
|
||||
@ -722,9 +748,8 @@ let UI = {
|
||||
};
|
||||
|
||||
// TabClose
|
||||
this._eventListeners.close = function(tab) {
|
||||
if (tab.ownerDocument.defaultView != gWindow)
|
||||
return;
|
||||
this._eventListeners.close = function (event) {
|
||||
let tab = event.target;
|
||||
|
||||
// if it's an app tab, remove it from all the group items
|
||||
if (tab.pinned)
|
||||
@ -756,21 +781,14 @@ let UI = {
|
||||
groupItem._children.length == 1 &&
|
||||
groupItem._children[0].tab == tab);
|
||||
|
||||
// 2) Take care of the case where you've closed the last tab in
|
||||
// an un-named groupItem, which means that the groupItem is gone (null) and
|
||||
// there are no visible tabs.
|
||||
let closingUnnamedGroup = (groupItem == null &&
|
||||
gBrowser.visibleTabs.length <= 1);
|
||||
|
||||
// 3) When a blank tab is active while restoring a closed tab the
|
||||
// 2) When a blank tab is active while restoring a closed tab the
|
||||
// blank tab gets removed. The active group is not closed as this is
|
||||
// where the restored tab goes. So do not show the TabView.
|
||||
let tabItem = tab && tab._tabViewTabItem;
|
||||
let closingBlankTabAfterRestore =
|
||||
(tabItem && tabItem.isRemovedAfterRestore);
|
||||
|
||||
if ((closingLastOfGroup || closingUnnamedGroup) &&
|
||||
!closingBlankTabAfterRestore) {
|
||||
if (closingLastOfGroup && !closingBlankTabAfterRestore) {
|
||||
// for the tab focus event to pick up.
|
||||
self._closedLastVisibleTab = true;
|
||||
self.showTabView();
|
||||
@ -780,9 +798,8 @@ let UI = {
|
||||
};
|
||||
|
||||
// TabMove
|
||||
this._eventListeners.move = function(tab) {
|
||||
if (tab.ownerDocument.defaultView != gWindow)
|
||||
return;
|
||||
this._eventListeners.move = function (event) {
|
||||
let tab = event.target;
|
||||
|
||||
if (GroupItems.groupItems.length > 0) {
|
||||
if (tab.pinned) {
|
||||
@ -797,26 +814,21 @@ let UI = {
|
||||
};
|
||||
|
||||
// TabSelect
|
||||
this._eventListeners.select = function(tab) {
|
||||
if (tab.ownerDocument.defaultView != gWindow)
|
||||
return;
|
||||
|
||||
self.onTabSelect(tab);
|
||||
this._eventListeners.select = function (event) {
|
||||
self.onTabSelect(event.target);
|
||||
};
|
||||
|
||||
// TabPinned
|
||||
this._eventListeners.pinned = function(tab) {
|
||||
if (tab.ownerDocument.defaultView != gWindow)
|
||||
return;
|
||||
this._eventListeners.pinned = function (event) {
|
||||
let tab = event.target;
|
||||
|
||||
TabItems.handleTabPin(tab);
|
||||
GroupItems.addAppTab(tab);
|
||||
};
|
||||
|
||||
// TabUnpinned
|
||||
this._eventListeners.unpinned = function(tab) {
|
||||
if (tab.ownerDocument.defaultView != gWindow)
|
||||
return;
|
||||
this._eventListeners.unpinned = function (event) {
|
||||
let tab = event.target;
|
||||
|
||||
TabItems.handleTabUnpin(tab);
|
||||
GroupItems.removeAppTab(tab);
|
||||
@ -890,8 +902,14 @@ let UI = {
|
||||
|
||||
// if TabView is visible but we didn't just close the last tab or
|
||||
// selected tab, show chrome.
|
||||
if (this.isTabViewVisible())
|
||||
if (this.isTabViewVisible()) {
|
||||
// Unhide the group of the tab the user is activating.
|
||||
if (tab && tab._tabViewTabItem && tab._tabViewTabItem.parent &&
|
||||
tab._tabViewTabItem.parent.hidden)
|
||||
tab._tabViewTabItem.parent._unhide({immediately: true});
|
||||
|
||||
this.hideTabView();
|
||||
}
|
||||
|
||||
// another tab might be selected when hideTabView() is invoked so a
|
||||
// validation is needed.
|
||||
@ -925,6 +943,27 @@ let UI = {
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: _onDOMWillOpenModalDialog
|
||||
// Called when a web page is about to show a modal dialog.
|
||||
_onDOMWillOpenModalDialog: function UI__onDOMWillOpenModalDialog(cx) {
|
||||
if (!this.isTabViewVisible())
|
||||
return;
|
||||
|
||||
let index = gBrowser.browsers.indexOf(cx.target);
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
let tab = gBrowser.tabs[index];
|
||||
|
||||
// When TabView is visible, we need to call onTabSelect to make sure that
|
||||
// TabView is hidden and that the correct group is activated. When a modal
|
||||
// dialog is shown for currently selected tab the onTabSelect event handler
|
||||
// is not called, so we need to do it.
|
||||
if (gBrowser.selectedTab == tab && this._currentTab == tab)
|
||||
this.onTabSelect(tab);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: setReorderTabsOnHide
|
||||
// Sets the groupItem which the tab items' tabs should be re-ordered when
|
||||
|
@ -177,6 +177,7 @@ _BROWSER_FILES = \
|
||||
browser_bug647886.js \
|
||||
browser_bug655584.js \
|
||||
browser_bug664672.js \
|
||||
browser_canonizeURL.js \
|
||||
browser_findbarClose.js \
|
||||
browser_keywordBookmarklets.js \
|
||||
browser_contextSearchTabPosition.js \
|
||||
|
54
browser/base/content/test/browser_canonizeURL.js
Normal file
54
browser/base/content/test/browser_canonizeURL.js
Normal file
@ -0,0 +1,54 @@
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
testNext();
|
||||
}
|
||||
|
||||
var pairs = [
|
||||
["example", "http://www.example.net/"],
|
||||
["ex-ample", "http://www.ex-ample.net/"],
|
||||
[" example ", "http://www.example.net/"],
|
||||
[" example/foo ", "http://www.example.net/foo"],
|
||||
[" example/foo bar ", "http://www.example.net/foo%20bar"],
|
||||
["example.net", "http://example.net/"],
|
||||
["http://example", "http://example/"],
|
||||
["example:8080", "http://example:8080/"],
|
||||
["ex-ample.foo", "http://ex-ample.foo/"],
|
||||
["example.foo/bar ", "http://example.foo/bar"],
|
||||
["1.1.1.1", "http://1.1.1.1/"],
|
||||
["ftp://example", "ftp://example/"],
|
||||
["ftp.example.bar", "ftp://ftp.example.bar/"],
|
||||
["ex ample", Services.search.originalDefaultEngine.getSubmission("ex ample").uri.spec],
|
||||
];
|
||||
|
||||
function testNext() {
|
||||
if (!pairs.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
let [inputValue, expectedURL] = pairs.shift();
|
||||
|
||||
gBrowser.addProgressListener({
|
||||
onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if (aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) {
|
||||
is(aRequest.originalURI.spec, expectedURL,
|
||||
"entering '" + inputValue + "' loads expected URL");
|
||||
|
||||
gBrowser.removeProgressListener(this);
|
||||
gBrowser.stop();
|
||||
|
||||
executeSoon(testNext);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
gURLBar.addEventListener("focus", function onFocus() {
|
||||
gURLBar.removeEventListener("focus", onFocus);
|
||||
EventUtils.synthesizeKey("VK_RETURN", { shiftKey: true });
|
||||
});
|
||||
|
||||
gBrowser.selectedBrowser.focus();
|
||||
gURLBar.inputField.value = inputValue;
|
||||
gURLBar.focus();
|
||||
}
|
@ -56,6 +56,7 @@ _BROWSER_FILES = \
|
||||
browser_inspector_treePanel_result.html \
|
||||
browser_inspector_registertools.js \
|
||||
browser_inspector_bug_665880.js \
|
||||
browser_inspector_editor.js \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
|
233
browser/base/content/test/inspector/browser_inspector_editor.js
Normal file
233
browser/base/content/test/inspector/browser_inspector_editor.js
Normal file
@ -0,0 +1,233 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*
|
||||
* Contributor(s):
|
||||
* Rob Campbell <rcampbell@mozilla.com>
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
* Kyle Simpson <ksimpson@mozilla.com>
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
let doc;
|
||||
let div;
|
||||
let editorTestSteps;
|
||||
|
||||
function doNextStep() {
|
||||
editorTestSteps.next();
|
||||
}
|
||||
|
||||
function setupEditorTests()
|
||||
{
|
||||
div = doc.createElement("div");
|
||||
div.setAttribute("id", "foobar");
|
||||
div.setAttribute("class", "barbaz");
|
||||
doc.body.appendChild(div);
|
||||
|
||||
Services.obs.addObserver(runEditorTests, INSPECTOR_NOTIFICATIONS.OPENED, false);
|
||||
InspectorUI.toggleInspectorUI();
|
||||
}
|
||||
|
||||
function runEditorTests()
|
||||
{
|
||||
Services.obs.removeObserver(runEditorTests, INSPECTOR_NOTIFICATIONS.OPENED, false);
|
||||
InspectorUI.stopInspecting();
|
||||
|
||||
// setup generator for async test steps
|
||||
editorTestSteps = doEditorTestSteps();
|
||||
|
||||
// add step listeners
|
||||
Services.obs.addObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_OPENED, false);
|
||||
Services.obs.addObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_CLOSED, false);
|
||||
Services.obs.addObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_SAVED, false);
|
||||
|
||||
// start the tests
|
||||
doNextStep();
|
||||
}
|
||||
|
||||
function doEditorTestSteps()
|
||||
{
|
||||
let editor = InspectorUI.treeBrowserDocument.getElementById("attribute-editor");
|
||||
let editorInput = InspectorUI.treeBrowserDocument.getElementById("attribute-editor-input");
|
||||
|
||||
// Step 1: grab and test the attribute-value nodes in the HTML panel, then open editor
|
||||
let attrValNode_id = InspectorUI.treeBrowserDocument.querySelectorAll(".nodeValue.editable[data-attributeName='id']")[0];
|
||||
let attrValNode_class = InspectorUI.treeBrowserDocument.querySelectorAll(".nodeValue.editable[data-attributeName='class']")[0];
|
||||
|
||||
is(attrValNode_id.innerHTML, "foobar", "Step 1: we have the correct `id` attribute-value node in the HTML panel");
|
||||
is(attrValNode_class.innerHTML, "barbaz", "we have the correct `class` attribute-value node in the HTML panel");
|
||||
|
||||
// double-click the `id` attribute-value node to open the editor
|
||||
executeSoon(function() {
|
||||
// firing 2 clicks right in a row to simulate a double-click
|
||||
EventUtils.synthesizeMouse(attrValNode_id, 2, 2, {clickCount: 2}, attrValNode_id.ownerDocument.defaultView);
|
||||
});
|
||||
|
||||
yield; // End of Step 1
|
||||
|
||||
|
||||
// Step 2: validate editing session, enter new attribute value into editor, and save input
|
||||
ok(InspectorUI.editingContext, "Step 2: editor session started");
|
||||
|
||||
let editorVisible = editor.classList.contains("editing");
|
||||
ok(editorVisible, "editor popup visible");
|
||||
|
||||
// check if the editor popup is "near" the correct position
|
||||
let editorDims = editor.getBoundingClientRect();
|
||||
let attrValNodeDims = attrValNode_id.getBoundingClientRect();
|
||||
let editorPositionOK = (editorDims.left >= (attrValNodeDims.left - editorDims.width - 5)) &&
|
||||
(editorDims.right <= (attrValNodeDims.right + editorDims.width + 5)) &&
|
||||
(editorDims.top >= (attrValNodeDims.top - editorDims.height - 5)) &&
|
||||
(editorDims.bottom <= (attrValNodeDims.bottom + editorDims.height + 5));
|
||||
|
||||
ok(editorPositionOK, "editor position acceptable");
|
||||
|
||||
// check to make sure the attribute-value node being edited is properly highlighted
|
||||
let attrValNodeHighlighted = attrValNode_id.classList.contains("editingAttributeValue");
|
||||
ok(attrValNodeHighlighted, "`id` attribute-value node is editor-highlighted");
|
||||
|
||||
is(InspectorUI.editingContext.repObj, div, "editor session has correct reference to div");
|
||||
is(InspectorUI.editingContext.attrObj, attrValNode_id, "editor session has correct reference to `id` attribute-value node in HTML panel");
|
||||
is(InspectorUI.editingContext.attrName, "id", "editor session knows correct attribute-name");
|
||||
|
||||
editorInput.value = "Hello World";
|
||||
editorInput.focus();
|
||||
|
||||
// hit <enter> to save the inputted value
|
||||
executeSoon(function() {
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, attrValNode_id.ownerDocument.defaultView);
|
||||
});
|
||||
|
||||
// two `yield` statements, to trap both the "SAVED" and "CLOSED" events that will be triggered
|
||||
yield;
|
||||
yield; // End of Step 2
|
||||
|
||||
|
||||
// Step 3: validate that the previous editing session saved correctly, then open editor on `class` attribute value
|
||||
ok(!InspectorUI.editingContext, "Step 3: editor session ended");
|
||||
editorVisible = editor.classList.contains("editing");
|
||||
ok(!editorVisible, "editor popup hidden");
|
||||
attrValNodeHighlighted = attrValNode_id.classList.contains("editingAttributeValue");
|
||||
ok(!attrValNodeHighlighted, "`id` attribute-value node is no longer editor-highlighted");
|
||||
is(div.getAttribute("id"), "Hello World", "`id` attribute-value successfully updated");
|
||||
is(attrValNode_id.innerHTML, "Hello World", "attribute-value node in HTML panel successfully updated");
|
||||
|
||||
// double-click the `class` attribute-value node to open the editor
|
||||
executeSoon(function() {
|
||||
// firing 2 clicks right in a row to simulate a double-click
|
||||
EventUtils.synthesizeMouse(attrValNode_class, 2, 2, {clickCount: 2}, attrValNode_class.ownerDocument.defaultView);
|
||||
});
|
||||
|
||||
yield; // End of Step 3
|
||||
|
||||
|
||||
// Step 4: enter value into editor, then hit <escape> to discard it
|
||||
ok(InspectorUI.editingContext, "Step 4: editor session started");
|
||||
editorVisible = editor.classList.contains("editing");
|
||||
ok(editorVisible, "editor popup visible");
|
||||
|
||||
is(InspectorUI.editingContext.attrObj, attrValNode_class, "editor session has correct reference to `class` attribute-value node in HTML panel");
|
||||
is(InspectorUI.editingContext.attrName, "class", "editor session knows correct attribute-name");
|
||||
|
||||
editorInput.value = "Hello World";
|
||||
editorInput.focus();
|
||||
|
||||
// hit <escape> to discard the inputted value
|
||||
executeSoon(function() {
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {}, attrValNode_class.ownerDocument.defaultView);
|
||||
});
|
||||
|
||||
yield; // End of Step 4
|
||||
|
||||
|
||||
// Step 5: validate that the previous editing session discarded correctly, then open editor on `id` attribute value again
|
||||
ok(!InspectorUI.editingContext, "Step 5: editor session ended");
|
||||
editorVisible = editor.classList.contains("editing");
|
||||
ok(!editorVisible, "editor popup hidden");
|
||||
is(div.getAttribute("class"), "barbaz", "`class` attribute-value *not* updated");
|
||||
is(attrValNode_class.innerHTML, "barbaz", "attribute-value node in HTML panel *not* updated");
|
||||
|
||||
// double-click the `id` attribute-value node to open the editor
|
||||
executeSoon(function() {
|
||||
// firing 2 clicks right in a row to simulate a double-click
|
||||
EventUtils.synthesizeMouse(attrValNode_id, 2, 2, {clickCount: 2}, attrValNode_id.ownerDocument.defaultView);
|
||||
});
|
||||
|
||||
yield; // End of Step 5
|
||||
|
||||
|
||||
// Step 6: validate that editor opened again, then test double-click inside of editor (should do nothing)
|
||||
ok(InspectorUI.editingContext, "Step 6: editor session started");
|
||||
editorVisible = editor.classList.contains("editing");
|
||||
ok(editorVisible, "editor popup visible");
|
||||
|
||||
// double-click on the editor input box
|
||||
executeSoon(function() {
|
||||
// firing 2 clicks right in a row to simulate a double-click
|
||||
EventUtils.synthesizeMouse(editorInput, 2, 2, {clickCount: 2}, editorInput.ownerDocument.defaultView);
|
||||
|
||||
// since the previous double-click is supposed to do nothing,
|
||||
// wait a brief moment, then move on to the next step
|
||||
executeSoon(function() {
|
||||
doNextStep();
|
||||
});
|
||||
});
|
||||
|
||||
yield; // End of Step 6
|
||||
|
||||
|
||||
// Step 7: validate that editing session is still correct, then enter a value and try a click
|
||||
// outside of editor (should cancel the editing session)
|
||||
ok(InspectorUI.editingContext, "Step 7: editor session still going");
|
||||
editorVisible = editor.classList.contains("editing");
|
||||
ok(editorVisible, "editor popup still visible");
|
||||
|
||||
editorInput.value = "all your base are belong to us";
|
||||
|
||||
// single-click the `class` attribute-value node
|
||||
executeSoon(function() {
|
||||
EventUtils.synthesizeMouse(attrValNode_class, 2, 2, {}, attrValNode_class.ownerDocument.defaultView);
|
||||
});
|
||||
|
||||
yield; // End of Step 7
|
||||
|
||||
|
||||
// Step 8: validate that the editor was closed and that the editing was not saved
|
||||
ok(!InspectorUI.editingContext, "Step 8: editor session ended");
|
||||
editorVisible = editor.classList.contains("editing");
|
||||
ok(!editorVisible, "editor popup hidden");
|
||||
is(div.getAttribute("id"), "Hello World", "`id` attribute-value *not* updated");
|
||||
is(attrValNode_id.innerHTML, "Hello World", "attribute-value node in HTML panel *not* updated");
|
||||
|
||||
// End of Step 8
|
||||
|
||||
// end of all steps, so clean up
|
||||
Services.obs.removeObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_OPENED, false);
|
||||
Services.obs.removeObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_CLOSED, false);
|
||||
Services.obs.removeObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_SAVED, false);
|
||||
|
||||
executeSoon(finishUp);
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
doc = div = null;
|
||||
InspectorUI.closeInspectorUI();
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
doc = content.document;
|
||||
waitForFocus(setupEditorTests, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,basic tests for html panel attribute-value editor";
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@ -111,6 +111,7 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug625269.js \
|
||||
browser_tabview_bug625424.js \
|
||||
browser_tabview_bug626368.js \
|
||||
browser_tabview_bug626455.js \
|
||||
browser_tabview_bug626525.js \
|
||||
browser_tabview_bug626791.js \
|
||||
browser_tabview_bug627239.js \
|
||||
@ -139,6 +140,7 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug649006.js \
|
||||
browser_tabview_bug649307.js \
|
||||
browser_tabview_bug649319.js \
|
||||
browser_tabview_bug650280.js \
|
||||
browser_tabview_bug650573.js \
|
||||
browser_tabview_bug651311.js \
|
||||
browser_tabview_bug654721.js \
|
||||
|
@ -1,15 +1,16 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource:///modules/tabview/AllTabs.jsm");
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let AllTabs;
|
||||
let newTab = gBrowser.addTab();
|
||||
|
||||
// TabPinned
|
||||
let pinned = function(tab) {
|
||||
let pinned = function (event) {
|
||||
let tab = event.target;
|
||||
|
||||
is(tab, newTab, "The tabs are the same after the tab is pinned");
|
||||
ok(tab.pinned, "The tab gets pinned");
|
||||
|
||||
@ -17,7 +18,9 @@ function test() {
|
||||
};
|
||||
|
||||
// TabUnpinned
|
||||
let unpinned = function(tab) {
|
||||
let unpinned = function (event) {
|
||||
let tab = event.target;
|
||||
|
||||
AllTabs.unregister("pinned", pinned);
|
||||
AllTabs.unregister("unpinned", unpinned);
|
||||
|
||||
@ -26,13 +29,17 @@ function test() {
|
||||
|
||||
// clean up and finish
|
||||
gBrowser.removeTab(tab);
|
||||
finish();
|
||||
hideTabView(finish);
|
||||
};
|
||||
|
||||
AllTabs.register("pinned", pinned);
|
||||
AllTabs.register("unpinned", unpinned);
|
||||
showTabView(function () {
|
||||
AllTabs = TabView.getContentWindow().AllTabs;
|
||||
|
||||
ok(!newTab.pinned, "The tab is not pinned");
|
||||
gBrowser.pinTab(newTab);
|
||||
AllTabs.register("pinned", pinned);
|
||||
AllTabs.register("unpinned", unpinned);
|
||||
|
||||
ok(!newTab.pinned, "The tab is not pinned");
|
||||
gBrowser.pinTab(newTab);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ function setupOne(win) {
|
||||
afterAllTabsLoaded(function () setupTwo(win), win);
|
||||
}
|
||||
|
||||
let restoreWin;
|
||||
let restoredWin;
|
||||
|
||||
function setupTwo(win) {
|
||||
let contentWindow = win.TabView.getContentWindow();
|
||||
|
@ -10,7 +10,7 @@ function test() {
|
||||
function part1(win) {
|
||||
registerCleanupFunction(function() win.close());
|
||||
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
let contentWindow = win.TabView.getContentWindow();
|
||||
is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
|
||||
|
||||
let originalTab = win.gBrowser.selectedTab;
|
||||
@ -71,15 +71,12 @@ function part2(win) {
|
||||
// switch the selected tab to new tab
|
||||
win.gBrowser.selectedTab = newTab;
|
||||
|
||||
whenTabViewIsHidden(function () {
|
||||
is(win.gBrowser.selectedTab, newTab, "The seleted tab should be the same as before (new tab)");
|
||||
win.close();
|
||||
finish();
|
||||
});
|
||||
|
||||
// show tabview
|
||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
|
||||
// hide tabview
|
||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
|
||||
})
|
||||
showTabView(function () {
|
||||
hideTabView(function () {
|
||||
is(win.gBrowser.selectedTab, newTab,
|
||||
"The selected tab should be the same as before (new tab)");
|
||||
waitForFocus(finish);
|
||||
}, win);
|
||||
}, win);
|
||||
}, win);
|
||||
}
|
||||
|
@ -21,9 +21,7 @@ function onTabViewShown() {
|
||||
|
||||
function testStayOnPage(contentWindow, groupItemOne, groupItemTwo) {
|
||||
whenDialogOpened(function (dialog) {
|
||||
groupItemTwo.addSubscriber("groupShown", function onShown() {
|
||||
groupItemTwo.removeSubscriber("groupShown", onShown);
|
||||
|
||||
executeSoon(function () {
|
||||
is(gBrowser.tabs.length, 2,
|
||||
"The total number of tab is 2 when staying on the page");
|
||||
is(contentWindow.TabItems.getItems().length, 2,
|
||||
|
@ -25,6 +25,7 @@ function test1() {
|
||||
is(groupItems.length, 1, "there is one groupItem");
|
||||
|
||||
whenTabViewIsHidden(function() {
|
||||
gBrowser.selectedTab = gBrowser.tabs[0];
|
||||
is(groupItems.length, 2, "there are two groupItems");
|
||||
closeGroupItem(groupItems[1], finish);
|
||||
});
|
||||
|
@ -18,6 +18,6 @@ function test() {
|
||||
cw.GroupItems.resumeArrange();
|
||||
ok(groupItem.isStacked(), 'groupItem is now stacked');
|
||||
|
||||
closeGroupItem(groupItem, finish);
|
||||
closeGroupItem(groupItem, function () hideTabView(finish));
|
||||
});
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ function test() {
|
||||
ok(!document.getElementById("context_openTabInWindow").disabled, "The 'Move to New Window' menu item is enabled");
|
||||
|
||||
let newTabTwo = gBrowser.selectedTab;
|
||||
gBrowser.selected = originalTab;
|
||||
gBrowser.selectedTab = originalTab;
|
||||
|
||||
gBrowser.removeTab(newTabOne);
|
||||
gBrowser.removeTab(newTabTwo);
|
||||
|
127
browser/base/content/test/tabview/browser_tabview_bug626455.js
Normal file
127
browser/base/content/test/tabview/browser_tabview_bug626455.js
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
*/
|
||||
|
||||
const TEST_URL = 'data:text/html,<script>window.onbeforeunload=' +
|
||||
'function(e){e.returnValue="?"}</script><body ' +
|
||||
'onunload="alert(\'onunload\')" onpagehide="' +
|
||||
'alert(\'onpagehide\')"></body>';
|
||||
|
||||
let contentWindow;
|
||||
let activeGroup;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
showTabView(function () {
|
||||
contentWindow = TabView.getContentWindow();
|
||||
activeGroup = contentWindow.GroupItems.getActiveGroupItem();
|
||||
|
||||
gBrowser.browsers[0].contentWindow.location =
|
||||
"data:text/html,<p>test for bug 626455, tab1";
|
||||
gBrowser.addTab(TEST_URL);
|
||||
|
||||
afterAllTabsLoaded(testStayOnPage);
|
||||
});
|
||||
}
|
||||
|
||||
function testStayOnPage() {
|
||||
whenDialogOpened(function (dialog) {
|
||||
// stay on page
|
||||
dialog.cancelDialog();
|
||||
|
||||
executeSoon(function () {
|
||||
showTabView(function () {
|
||||
is(gBrowser.tabs.length, 1,
|
||||
"The total number of tab is 1 when staying on the page");
|
||||
|
||||
let location = gBrowser.browsers[0].contentWindow.location.toString();
|
||||
isnot(location.indexOf("onbeforeunload"), -1,
|
||||
"The open tab is the expected one");
|
||||
|
||||
is(contentWindow.GroupItems.getActiveGroupItem(), activeGroup,
|
||||
"Active group is still the same");
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"Only one group is open");
|
||||
|
||||
// start the next test
|
||||
testLeavePage();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
closeGroupItem(activeGroup);
|
||||
}
|
||||
|
||||
function testLeavePage() {
|
||||
let dialogsAccepted = 0;
|
||||
|
||||
whenDialogOpened(function onDialogOpened(dialog) {
|
||||
if (++dialogsAccepted < 3)
|
||||
whenDialogOpened(onDialogOpened);
|
||||
|
||||
// Leave page
|
||||
dialog.acceptDialog();
|
||||
});
|
||||
|
||||
whenGroupClosed(activeGroup, finishTest);
|
||||
closeGroupItem(activeGroup);
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
is(gBrowser.tabs.length, 1,
|
||||
"The total number of tab is 1 after leaving the page");
|
||||
is(contentWindow.TabItems.getItems().length, 1,
|
||||
"The total number of tab items is 1 after leaving the page");
|
||||
|
||||
let location = gBrowser.browsers[0].contentWindow.location.toString();
|
||||
is(location, "about:blank", "The open tab is the expected one");
|
||||
|
||||
isnot(contentWindow.GroupItems.getActiveGroupItem(), activeGroup,
|
||||
"Active group is no longer the same");
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"Only one group is open");
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
// ----------
|
||||
function whenGroupClosed(group, callback) {
|
||||
group.addSubscriber("close", function onClose() {
|
||||
group.removeSubscriber("close", onClose);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
// ----------
|
||||
function whenDialogOpened(callback) {
|
||||
let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Ci.nsIWindowMediator);
|
||||
|
||||
let listener = {
|
||||
onCloseWindow: function () {},
|
||||
onWindowTitleChange: function () {},
|
||||
|
||||
onOpenWindow: function (xulWin) {
|
||||
let domWin = xulWin.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
|
||||
whenWindowLoaded(domWin, function () {
|
||||
let dialog = domWin.document.querySelector("dialog");
|
||||
if (dialog) {
|
||||
wm.removeListener(listener);
|
||||
callback(dialog);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
wm.addListener(listener);
|
||||
}
|
@ -15,7 +15,7 @@ function loadTabs (win) {
|
||||
function testTopOfStack(win) {
|
||||
registerCleanupFunction(function () { win.close(); });
|
||||
let cw = win.TabView.getContentWindow();
|
||||
groupItem = cw.GroupItems.getActiveGroupItem();
|
||||
let groupItem = cw.GroupItems.getActiveGroupItem();
|
||||
ok(!groupItem.isStacked(), 'groupItem is not stacked');
|
||||
groupItem.setSize(150, 150);
|
||||
groupItem.setUserSize();
|
||||
|
@ -0,0 +1,67 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let pb = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
|
||||
function test() {
|
||||
let cw;
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
if (cw)
|
||||
cw.hideSearch();
|
||||
|
||||
TabView.hide();
|
||||
pb.privateBrowsingEnabled = false;
|
||||
});
|
||||
|
||||
let enableSearch = function (callback) {
|
||||
if (cw.isSearchEnabled()) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
cw.addEventListener("tabviewsearchenabled", function onSearchEnabled() {
|
||||
cw.removeEventListener("tabviewsearchenabled", onSearchEnabled, false);
|
||||
executeSoon(callback);
|
||||
}, false);
|
||||
|
||||
cw.ensureSearchShown();
|
||||
};
|
||||
|
||||
let getSearchboxValue = function () {
|
||||
return cw.iQ("#searchbox").val();
|
||||
};
|
||||
|
||||
let prepareSearchbox = function (callback) {
|
||||
ok(!cw.isSearchEnabled(), "search is disabled");
|
||||
|
||||
enableSearch(function () {
|
||||
cw.iQ("#searchbox").val("moz");
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
let searchAndSwitchPBMode = function (callback) {
|
||||
prepareSearchbox(function () {
|
||||
togglePrivateBrowsing(function () {
|
||||
showTabView(function () {
|
||||
ok(!cw.isSearchEnabled(), "search is disabled");
|
||||
is(getSearchboxValue(), "", "search box is empty");
|
||||
callback();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
showTabView(function () {
|
||||
cw = TabView.getContentWindow();
|
||||
searchAndSwitchPBMode(function () {
|
||||
searchAndSwitchPBMode(function () {
|
||||
hideTabView(finish);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
@ -67,7 +67,7 @@ function test() {
|
||||
EventUtils.synthesizeMouse(target, 600, 5, {type: "mouseup"}, cw);
|
||||
|
||||
checkNumberOfGroupItems(2);
|
||||
next();
|
||||
closeGroupItem(cw.GroupItems.groupItems[1], next);
|
||||
}, win);
|
||||
}
|
||||
|
||||
|
@ -3,49 +3,32 @@
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
TabView.toggle();
|
||||
showTabView(onTabViewShown);
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
|
||||
function onTabViewShown() {
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
let contentWindow = TabView.getContentWindow();
|
||||
let [originalTab] = gBrowser.visibleTabs;
|
||||
|
||||
let createGroupItem = function (left, top, width, height) {
|
||||
let box = new contentWindow.Rect(left, top, width, height);
|
||||
let groupItem = new contentWindow.GroupItem([], {bounds: box, immediately: true});
|
||||
|
||||
contentWindow.UI.setActive(groupItem);
|
||||
gBrowser.loadOneTab("about:blank", {inBackground: true});
|
||||
|
||||
return groupItem;
|
||||
};
|
||||
|
||||
// create group one and two
|
||||
let boxOne = new contentWindow.Rect(20, 20, 300, 300);
|
||||
let groupOne = new contentWindow.GroupItem([], { bounds: boxOne });
|
||||
ok(groupOne.isEmpty(), "This group is empty");
|
||||
let groupOne = createGroupItem(20, 20, 300, 300);
|
||||
let groupTwo = createGroupItem(20, 400, 300, 300);
|
||||
|
||||
let boxTwo = new contentWindow.Rect(20, 400, 300, 300);
|
||||
let groupTwo = new contentWindow.GroupItem([], { bounds: boxTwo });
|
||||
|
||||
groupOne.addSubscriber("childAdded", function onChildAdded() {
|
||||
groupOne.removeSubscriber("childAdded", onChildAdded);
|
||||
groupTwo.newTab();
|
||||
waitForFocus(function () {
|
||||
addTest(contentWindow, groupOne.id, groupTwo.id, originalTab);
|
||||
});
|
||||
|
||||
let count = 0;
|
||||
let onTabViewShown = function() {
|
||||
if (count == 2) {
|
||||
window.removeEventListener("tabviewshown", onTabViewShown, false);
|
||||
addTest(contentWindow, groupOne.id, groupTwo.id, originalTab);
|
||||
}
|
||||
};
|
||||
let onTabViewHidden = function() {
|
||||
TabView.toggle();
|
||||
if (++count == 2)
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
};
|
||||
window.addEventListener("tabviewshown", onTabViewShown, false);
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
// open tab in group
|
||||
groupOne.newTab();
|
||||
}
|
||||
|
||||
function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
|
||||
@ -74,24 +57,13 @@ function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
|
||||
"The number of children in group one is decreased by 1");
|
||||
is(groupTwo.getChildren().length, ++groupTwoTabItemCount,
|
||||
"The number of children in group two is increased by 1");
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
groupTwo.closeAll();
|
||||
// close undo group
|
||||
let closeButton = groupTwo.$undoContainer.find(".close");
|
||||
EventUtils.sendMouseEvent(
|
||||
{ type: "click" }, closeButton[0], contentWindow);
|
||||
};
|
||||
groupTwo.addSubscriber("close", function onClose() {
|
||||
groupTwo.removeSubscriber("close", onClose);
|
||||
finish();
|
||||
|
||||
closeGroupItem(groupOne, function () {
|
||||
closeGroupItem(groupTwo, function () hideTabView(finish));
|
||||
});
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
gBrowser.selectedTab = originalTab;
|
||||
}
|
||||
|
||||
groupTwo.addSubscriber("childAdded", endGame);
|
||||
|
||||
simulateDragDrop(tabItem.container, offsetX, offsetY, contentWindow);
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,18 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let timerId;
|
||||
let newWin;
|
||||
|
||||
// ----------
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// launch tab view for the first time
|
||||
newWindowWithTabView(function() {}, function(win) {
|
||||
let panelSelected = false;
|
||||
registerCleanupFunction(function () ok(panelSelected, "panel is selected"));
|
||||
|
||||
let onLoad = function (win) {
|
||||
registerCleanupFunction(function () win.close());
|
||||
|
||||
newWin = win;
|
||||
|
||||
let onSelect = function(event) {
|
||||
@ -21,27 +24,26 @@ function test() {
|
||||
return;
|
||||
|
||||
deck.removeEventListener("select", onSelect, true);
|
||||
|
||||
whenTabViewIsShown(function() {
|
||||
executeSoon(function() {
|
||||
testMethodToHideAndShowTabView(function() {
|
||||
newWin.document.getElementById("menu_tabview").doCommand();
|
||||
}, function() {
|
||||
testMethodToHideAndShowTabView(function() {
|
||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, newWin);
|
||||
}, finish);
|
||||
});
|
||||
});
|
||||
}, win);
|
||||
panelSelected = true;
|
||||
};
|
||||
|
||||
let deck = win.document.getElementById("tab-view-deck");
|
||||
deck.addEventListener("select", onSelect, true);
|
||||
});
|
||||
};
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
newWin.close();
|
||||
});
|
||||
let onShow = function (win) {
|
||||
executeSoon(function() {
|
||||
testMethodToHideAndShowTabView(function() {
|
||||
newWin.document.getElementById("menu_tabview").doCommand();
|
||||
}, function() {
|
||||
testMethodToHideAndShowTabView(function() {
|
||||
EventUtils.synthesizeKey("E", { accelKey: true, shiftKey: true }, newWin);
|
||||
}, finish);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
newWindowWithTabView(onShow, onLoad);
|
||||
}
|
||||
|
||||
function testMethodToHideAndShowTabView(executeFunc, callback) {
|
||||
|
@ -49,9 +49,10 @@ function executeCopyCommand(command, expectedValue)
|
||||
is(input.value, expectedValue, "paste for command " + command);
|
||||
}
|
||||
|
||||
function invokeItemAction(ident)
|
||||
function invokeItemAction(generatedItemId)
|
||||
{
|
||||
var item = contextMenu.getElementsByAttribute("ident", ident)[0];
|
||||
var item = contextMenu.getElementsByAttribute("generateditemid",
|
||||
generatedItemId)[0];
|
||||
ok(item, "Got generated XUL menu item");
|
||||
item.doCommand();
|
||||
is(pagemenu.hasAttribute("hopeless"), false, "attribute got removed");
|
||||
@ -69,7 +70,7 @@ function getVisibleMenuItems(aMenu, aData) {
|
||||
if (key)
|
||||
key = key.toLowerCase();
|
||||
|
||||
var isGenerated = item.hasAttribute("generated");
|
||||
var isGenerated = item.hasAttribute("generateditemid");
|
||||
|
||||
if (item.nodeName == "menuitem") {
|
||||
var isSpellSuggestion = item.className == "spell-suggestion";
|
||||
|
@ -367,7 +367,7 @@
|
||||
|
||||
// Only add the suffix when the URL bar value isn't already "URL-like",
|
||||
// and only if we get a keyboard event, to match user expectations.
|
||||
if (!/^\s*(www|https?)\b|\/\s*$/i.test(url) &&
|
||||
if (/^\s*[^.:\/\s]+(?:\/.*|\s*)$/i.test(url) &&
|
||||
(aTriggeringEvent instanceof KeyEvent)) {
|
||||
#ifdef XP_MACOSX
|
||||
let accel = aTriggeringEvent.metaKey;
|
||||
@ -402,24 +402,15 @@
|
||||
|
||||
// Tack www. and suffix on. If user has appended directories, insert
|
||||
// suffix before them (bug 279035). Be careful not to get two slashes.
|
||||
// Also, don't add the suffix if it's in the original url (bug 233853).
|
||||
|
||||
let firstSlash = url.indexOf("/");
|
||||
let existingSuffix = url.indexOf(suffix.substring(0, suffix.length - 1));
|
||||
|
||||
// * Logic for slash and existing suffix (example)
|
||||
// No slash, no suffix: Add suffix (mozilla)
|
||||
// No slash, yes suffix: Add slash (mozilla.com)
|
||||
// Yes slash, no suffix: Insert suffix (mozilla/stuff)
|
||||
// Yes slash, suffix before slash: Do nothing (mozilla.com/stuff)
|
||||
// Yes slash, suffix after slash: Insert suffix (mozilla/?stuff=.com)
|
||||
|
||||
if (firstSlash >= 0) {
|
||||
if (existingSuffix == -1 || existingSuffix > firstSlash)
|
||||
url = url.substring(0, firstSlash) + suffix +
|
||||
url.substring(firstSlash + 1);
|
||||
} else
|
||||
url = url + (existingSuffix == -1 ? suffix : "/");
|
||||
url = url.substring(0, firstSlash) + suffix +
|
||||
url.substring(firstSlash + 1);
|
||||
} else {
|
||||
url = url + suffix;
|
||||
}
|
||||
|
||||
url = "http://www." + url;
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ browser.jar:
|
||||
content/browser/tabview.css (content/tabview/tabview.css)
|
||||
* content/browser/tabview.js (content/tabview/tabview.js)
|
||||
content/browser/tabview.html (content/tabview/tabview.html)
|
||||
content/browser/tabview-content.js (content/tabview/content.js)
|
||||
* content/browser/urlbarBindings.xml (content/urlbarBindings.xml)
|
||||
* content/browser/utilityOverlay.js (content/utilityOverlay.js)
|
||||
* content/browser/web-panels.js (content/web-panels.js)
|
||||
|
@ -53,7 +53,6 @@
|
||||
#if !defined(XP_OS2)
|
||||
#include "nsOperaProfileMigrator.h"
|
||||
#endif
|
||||
#include "nsSeamonkeyProfileMigrator.h"
|
||||
#if defined(XP_WIN) && !defined(__MINGW32__)
|
||||
#include "nsIEProfileMigrator.h"
|
||||
#elif defined(XP_MACOSX)
|
||||
@ -85,7 +84,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsOperaProfileMigrator)
|
||||
#endif
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsProfileMigrator)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSeamonkeyProfileMigrator)
|
||||
#if defined(XP_WIN) && !defined(__MINGW32__)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEProfileMigrator)
|
||||
#elif defined(XP_MACOSX)
|
||||
@ -114,7 +112,6 @@ NS_DEFINE_NAMED_CID(NS_SAFARIPROFILEMIGRATOR_CID);
|
||||
#if !defined(XP_OS2)
|
||||
NS_DEFINE_NAMED_CID(NS_OPERAPROFILEMIGRATOR_CID);
|
||||
#endif
|
||||
NS_DEFINE_NAMED_CID(NS_SEAMONKEYPROFILEMIGRATOR_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID);
|
||||
|
||||
static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
|
||||
@ -136,7 +133,6 @@ static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
|
||||
#if !defined(XP_OS2)
|
||||
{ &kNS_OPERAPROFILEMIGRATOR_CID, false, NULL, nsOperaProfileMigratorConstructor },
|
||||
#endif
|
||||
{ &kNS_SEAMONKEYPROFILEMIGRATOR_CID, false, NULL, nsSeamonkeyProfileMigratorConstructor },
|
||||
{ &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID, false, NULL, nsPrivateBrowsingServiceWrapperConstructor },
|
||||
{ NULL }
|
||||
};
|
||||
@ -173,7 +169,6 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
|
||||
#if !defined(XP_OS2)
|
||||
{ NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "opera", &kNS_OPERAPROFILEMIGRATOR_CID },
|
||||
#endif
|
||||
{ NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "seamonkey", &kNS_SEAMONKEYPROFILEMIGRATOR_CID },
|
||||
{ NS_PRIVATE_BROWSING_SERVICE_CONTRACTID, &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID },
|
||||
{ NULL }
|
||||
};
|
||||
|
@ -256,7 +256,8 @@ FeedWriter.prototype = {
|
||||
__contentSandbox: null,
|
||||
get _contentSandbox() {
|
||||
if (!this.__contentSandbox)
|
||||
this.__contentSandbox = new Cu.Sandbox(this._window);
|
||||
this.__contentSandbox = new Cu.Sandbox(this._window,
|
||||
{sandboxName: 'FeedWriter'});
|
||||
|
||||
return this.__contentSandbox;
|
||||
},
|
||||
|
@ -340,9 +340,6 @@ var MigrationWizard = {
|
||||
case "safari":
|
||||
source = "sourceNameSafari";
|
||||
break;
|
||||
case "seamonkey":
|
||||
source = "sourceNameSeamonkey";
|
||||
break;
|
||||
}
|
||||
|
||||
// semi-wallpaper for crash when multiple profiles exist, since we haven't initialized mSourceProfile in places
|
||||
|
@ -70,19 +70,14 @@
|
||||
browser/components/migration/src/nsProfileMigrator.cpp -->
|
||||
#ifdef XP_MACOSX
|
||||
<radio id="safari" label="&importFromSafari.label;" accesskey="&importFromSafari.accesskey;"/>
|
||||
<radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
|
||||
<radio id="opera" label="&importFromOpera.label;" accesskey="&importFromOpera.accesskey;"/>
|
||||
#elifdef XP_UNIX
|
||||
<radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
|
||||
<radio id="opera" label="&importFromOpera.label;" accesskey="&importFromOpera.accesskey;"/>
|
||||
#elifdef XP_WIN
|
||||
#ifndef NO_IE_MIGRATOR
|
||||
<radio id="ie" label="&importFromIE.label;" accesskey="&importFromIE.accesskey;"/>
|
||||
#endif
|
||||
<radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
|
||||
<radio id="opera" label="&importFromOpera.label;" accesskey="&importFromOpera.accesskey;"/>
|
||||
#else
|
||||
<radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
|
||||
#endif
|
||||
<radio id="fromfile" label="&importFromHTMLFile.label;" accesskey="&importFromHTMLFile.accesskey;" hidden="true"/>
|
||||
<radio id="nothing" label="&importFromNothing.label;" accesskey="&importFromNothing.accesskey;" hidden="true"/>
|
||||
|
@ -52,8 +52,6 @@ endif
|
||||
|
||||
CPPSRCS = nsProfileMigrator.cpp \
|
||||
nsBrowserProfileMigratorUtils.cpp \
|
||||
nsNetscapeProfileMigratorBase.cpp \
|
||||
nsSeamonkeyProfileMigrator.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifneq ($(OS_ARCH),OS2)
|
||||
|
@ -1,469 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; 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 The Browser Profile Migrator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Ben Goodger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Goodger <ben@bengoodger.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsBrowserProfileMigratorUtils.h"
|
||||
#include "nsICookieManager2.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsILineInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefLocalizedString.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "NSReg.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsNetscapeProfileMigratorBase.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "prtime.h"
|
||||
#include "prprf.h"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#define NEED_TO_FIX_4X_COOKIES 1
|
||||
#define SECONDS_BETWEEN_1900_AND_1970 2208988800UL
|
||||
#endif /* XP_MACOSX */
|
||||
|
||||
#define FILE_NAME_PREFS_5X NS_LITERAL_STRING("prefs.js")
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// nsNetscapeProfileMigratorBase
|
||||
nsNetscapeProfileMigratorBase::nsNetscapeProfileMigratorBase()
|
||||
{
|
||||
}
|
||||
|
||||
static nsresult
|
||||
regerr2nsresult(REGERR errCode)
|
||||
{
|
||||
switch (errCode) {
|
||||
case REGERR_PARAM:
|
||||
case REGERR_BADTYPE:
|
||||
case REGERR_BADNAME:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
case REGERR_MEMORY:
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::GetProfileDataFromRegistry(nsILocalFile* aRegistryFile,
|
||||
nsISupportsArray* aProfileNames,
|
||||
nsISupportsArray* aProfileLocations)
|
||||
{
|
||||
nsresult rv;
|
||||
REGERR errCode;
|
||||
|
||||
// Ensure aRegistryFile exists before open it
|
||||
PRBool regFileExists = PR_FALSE;
|
||||
rv = aRegistryFile->Exists(®FileExists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!regFileExists)
|
||||
return NS_ERROR_FILE_NOT_FOUND;
|
||||
|
||||
// Open It
|
||||
nsCAutoString regPath;
|
||||
rv = aRegistryFile->GetNativePath(regPath);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if ((errCode = NR_StartupRegistry()))
|
||||
return regerr2nsresult(errCode);
|
||||
|
||||
HREG reg;
|
||||
if ((errCode = NR_RegOpen(regPath.get(), ®))) {
|
||||
NR_ShutdownRegistry();
|
||||
|
||||
return regerr2nsresult(errCode);
|
||||
}
|
||||
|
||||
RKEY profilesTree;
|
||||
if ((errCode = NR_RegGetKey(reg, ROOTKEY_COMMON, "Profiles", &profilesTree))) {
|
||||
NR_RegClose(reg);
|
||||
NR_ShutdownRegistry();
|
||||
|
||||
return regerr2nsresult(errCode);
|
||||
}
|
||||
|
||||
char profileStr[MAXREGPATHLEN];
|
||||
REGENUM enumState = nsnull;
|
||||
|
||||
while (!NR_RegEnumSubkeys(reg, profilesTree, &enumState, profileStr,
|
||||
sizeof(profileStr), REGENUM_CHILDREN))
|
||||
{
|
||||
RKEY profileKey;
|
||||
if (NR_RegGetKey(reg, profilesTree, profileStr, &profileKey))
|
||||
continue;
|
||||
|
||||
// "migrated" is "yes" for all valid Seamonkey profiles. It is only "no"
|
||||
// for 4.x profiles.
|
||||
char migratedStr[3];
|
||||
errCode = NR_RegGetEntryString(reg, profileKey, (char *)"migrated",
|
||||
migratedStr, sizeof(migratedStr));
|
||||
if ((errCode != REGERR_OK && errCode != REGERR_BUFTOOSMALL) ||
|
||||
strcmp(migratedStr, "no") == 0)
|
||||
continue;
|
||||
|
||||
// Get the profile location and add it to the locations array
|
||||
REGINFO regInfo;
|
||||
regInfo.size = sizeof(REGINFO);
|
||||
|
||||
if (NR_RegGetEntryInfo(reg, profileKey, (char *)"directory", ®Info))
|
||||
continue;
|
||||
|
||||
nsCAutoString dirStr;
|
||||
dirStr.SetLength(regInfo.entryLength);
|
||||
|
||||
errCode = NR_RegGetEntryString(reg, profileKey, (char *)"directory",
|
||||
dirStr.BeginWriting(), regInfo.entryLength);
|
||||
// Remove trailing \0
|
||||
dirStr.SetLength(regInfo.entryLength-1);
|
||||
|
||||
nsCOMPtr<nsILocalFile> dir;
|
||||
#ifdef XP_MACOSX
|
||||
rv = NS_NewNativeLocalFile(EmptyCString(), PR_TRUE, getter_AddRefs(dir));
|
||||
if (NS_FAILED(rv)) break;
|
||||
dir->SetPersistentDescriptor(dirStr);
|
||||
#else
|
||||
rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(dirStr), PR_TRUE,
|
||||
getter_AddRefs(dir));
|
||||
if (NS_FAILED(rv)) break;
|
||||
#endif
|
||||
|
||||
PRBool exists;
|
||||
dir->Exists(&exists);
|
||||
|
||||
if (exists) {
|
||||
aProfileLocations->AppendElement(dir);
|
||||
|
||||
// Get the profile name and add it to the names array
|
||||
nsString profileName;
|
||||
CopyUTF8toUTF16(nsDependentCString(profileStr), profileName);
|
||||
|
||||
nsCOMPtr<nsISupportsString> profileNameString(
|
||||
do_CreateInstance("@mozilla.org/supports-string;1"));
|
||||
|
||||
profileNameString->SetData(profileName);
|
||||
aProfileNames->AppendElement(profileNameString);
|
||||
}
|
||||
}
|
||||
NR_RegClose(reg);
|
||||
NR_ShutdownRegistry();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define GETPREF(xform, method, value) \
|
||||
nsresult rv = aBranch->method(xform->sourcePrefName, value); \
|
||||
if (NS_SUCCEEDED(rv)) \
|
||||
xform->prefHasValue = PR_TRUE; \
|
||||
return rv;
|
||||
|
||||
#define SETPREF(xform, method, value) \
|
||||
if (xform->prefHasValue) { \
|
||||
return aBranch->method(xform->targetPrefName ? xform->targetPrefName : xform->sourcePrefName, value); \
|
||||
} \
|
||||
return NS_OK;
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::GetString(void* aTransform, nsIPrefBranch* aBranch)
|
||||
{
|
||||
PrefTransform* xform = (PrefTransform*)aTransform;
|
||||
GETPREF(xform, GetCharPref, &xform->stringValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::SetString(void* aTransform, nsIPrefBranch* aBranch)
|
||||
{
|
||||
PrefTransform* xform = (PrefTransform*)aTransform;
|
||||
SETPREF(xform, SetCharPref, xform->stringValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::GetWString(void* aTransform, nsIPrefBranch* aBranch)
|
||||
{
|
||||
PrefTransform* xform = (PrefTransform*)aTransform;
|
||||
nsCOMPtr<nsIPrefLocalizedString> prefValue;
|
||||
nsresult rv = aBranch->GetComplexValue(xform->sourcePrefName,
|
||||
NS_GET_IID(nsIPrefLocalizedString),
|
||||
getter_AddRefs(prefValue));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && prefValue) {
|
||||
nsString data;
|
||||
prefValue->ToString(getter_Copies(data));
|
||||
|
||||
xform->stringValue = ToNewCString(NS_ConvertUTF16toUTF8(data));
|
||||
xform->prefHasValue = PR_TRUE;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::SetWStringFromASCII(void* aTransform, nsIPrefBranch* aBranch)
|
||||
{
|
||||
PrefTransform* xform = (PrefTransform*)aTransform;
|
||||
if (xform->prefHasValue) {
|
||||
nsCOMPtr<nsIPrefLocalizedString> pls(do_CreateInstance("@mozilla.org/pref-localizedstring;1"));
|
||||
NS_ConvertUTF8toUTF16 data(xform->stringValue);
|
||||
pls->SetData(data.get());
|
||||
return aBranch->SetComplexValue(xform->targetPrefName ? xform->targetPrefName : xform->sourcePrefName, NS_GET_IID(nsIPrefLocalizedString), pls);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::SetWString(void* aTransform, nsIPrefBranch* aBranch)
|
||||
{
|
||||
PrefTransform* xform = (PrefTransform*)aTransform;
|
||||
if (xform->prefHasValue) {
|
||||
nsCOMPtr<nsIPrefLocalizedString> pls(do_CreateInstance("@mozilla.org/pref-localizedstring;1"));
|
||||
nsAutoString data = NS_ConvertUTF8toUTF16(xform->stringValue);
|
||||
pls->SetData(data.get());
|
||||
return aBranch->SetComplexValue(xform->targetPrefName ? xform->targetPrefName : xform->sourcePrefName, NS_GET_IID(nsIPrefLocalizedString), pls);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::GetBool(void* aTransform, nsIPrefBranch* aBranch)
|
||||
{
|
||||
PrefTransform* xform = (PrefTransform*)aTransform;
|
||||
GETPREF(xform, GetBoolPref, &xform->boolValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::SetBool(void* aTransform, nsIPrefBranch* aBranch)
|
||||
{
|
||||
PrefTransform* xform = (PrefTransform*)aTransform;
|
||||
SETPREF(xform, SetBoolPref, xform->boolValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::GetInt(void* aTransform, nsIPrefBranch* aBranch)
|
||||
{
|
||||
PrefTransform* xform = (PrefTransform*)aTransform;
|
||||
GETPREF(xform, GetIntPref, &xform->intValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::SetInt(void* aTransform, nsIPrefBranch* aBranch)
|
||||
{
|
||||
PrefTransform* xform = (PrefTransform*)aTransform;
|
||||
SETPREF(xform, SetIntPref, xform->intValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::CopyFile(const nsAString& aSourceFileName, const nsAString& aTargetFileName)
|
||||
{
|
||||
nsCOMPtr<nsIFile> sourceFile;
|
||||
mSourceProfile->Clone(getter_AddRefs(sourceFile));
|
||||
|
||||
sourceFile->Append(aSourceFileName);
|
||||
PRBool exists = PR_FALSE;
|
||||
sourceFile->Exists(&exists);
|
||||
if (!exists)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIFile> targetFile;
|
||||
mTargetProfile->Clone(getter_AddRefs(targetFile));
|
||||
|
||||
targetFile->Append(aTargetFileName);
|
||||
targetFile->Exists(&exists);
|
||||
if (exists)
|
||||
targetFile->Remove(PR_FALSE);
|
||||
|
||||
return sourceFile->CopyTo(mTargetProfile, aTargetFileName);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::ImportNetscapeBookmarks(const nsAString& aBookmarksFileName,
|
||||
const PRUnichar* aImportSourceNameKey)
|
||||
{
|
||||
nsCOMPtr<nsIFile> bookmarksFile;
|
||||
mSourceProfile->Clone(getter_AddRefs(bookmarksFile));
|
||||
bookmarksFile->Append(aBookmarksFileName);
|
||||
|
||||
return ImportBookmarksHTML(bookmarksFile, PR_FALSE, PR_FALSE, aImportSourceNameKey);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::ImportNetscapeCookies(nsIFile* aCookiesFile)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIInputStream> cookiesStream;
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(cookiesStream), aCookiesFile);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsILineInputStream> lineInputStream(do_QueryInterface(cookiesStream));
|
||||
|
||||
// This code is copied from mozilla/netwerk/cookie/src/nsCookieManager.cpp
|
||||
static NS_NAMED_LITERAL_CSTRING(kTrue, "TRUE");
|
||||
|
||||
nsCAutoString buffer;
|
||||
PRBool isMore = PR_TRUE;
|
||||
PRInt32 hostIndex = 0, isDomainIndex, pathIndex, secureIndex, expiresIndex, nameIndex, cookieIndex;
|
||||
PRInt32 numInts;
|
||||
PRInt64 expires;
|
||||
PRBool isDomain;
|
||||
PRInt64 currentTime = PR_Now() / PR_USEC_PER_SEC;
|
||||
|
||||
nsCOMPtr<nsICookieManager2> cookieManager(do_GetService(NS_COOKIEMANAGER_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
/* file format is:
|
||||
*
|
||||
* host \t isDomain \t path \t secure \t expires \t name \t cookie
|
||||
*
|
||||
* if this format isn't respected we move onto the next line in the file.
|
||||
* isDomain is "TRUE" or "FALSE" (default to "FALSE")
|
||||
* isSecure is "TRUE" or "FALSE" (default to "TRUE")
|
||||
* expires is a PRInt64 integer
|
||||
* note 1: cookie can contain tabs.
|
||||
* note 2: cookies are written in order of lastAccessed time:
|
||||
* most-recently used come first; least-recently-used come last.
|
||||
*/
|
||||
|
||||
while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore))) {
|
||||
if (buffer.IsEmpty() || buffer.First() == '#')
|
||||
continue;
|
||||
|
||||
// this is a cheap, cheesy way of parsing a tab-delimited line into
|
||||
// string indexes, which can be lopped off into substrings. just for
|
||||
// purposes of obfuscation, it also checks that each token was found.
|
||||
// todo: use iterators?
|
||||
if ((isDomainIndex = buffer.FindChar('\t', hostIndex) + 1) == 0 ||
|
||||
(pathIndex = buffer.FindChar('\t', isDomainIndex) + 1) == 0 ||
|
||||
(secureIndex = buffer.FindChar('\t', pathIndex) + 1) == 0 ||
|
||||
(expiresIndex = buffer.FindChar('\t', secureIndex) + 1) == 0 ||
|
||||
(nameIndex = buffer.FindChar('\t', expiresIndex) + 1) == 0 ||
|
||||
(cookieIndex = buffer.FindChar('\t', nameIndex) + 1) == 0)
|
||||
continue;
|
||||
|
||||
// check the expirytime first - if it's expired, ignore
|
||||
// nullstomp the trailing tab, to avoid copying the string
|
||||
char *iter = buffer.BeginWriting();
|
||||
*(iter += nameIndex - 1) = char(0);
|
||||
numInts = PR_sscanf(buffer.get() + expiresIndex, "%lld", &expires);
|
||||
if (numInts != 1 || expires < currentTime)
|
||||
continue;
|
||||
|
||||
isDomain = Substring(buffer, isDomainIndex, pathIndex - isDomainIndex - 1).Equals(kTrue);
|
||||
const nsDependentCSubstring host =
|
||||
Substring(buffer, hostIndex, isDomainIndex - hostIndex - 1);
|
||||
// check for bad legacy cookies (domain not starting with a dot, or containing a port),
|
||||
// and discard
|
||||
if (isDomain && !host.IsEmpty() && host.First() != '.' ||
|
||||
host.FindChar(':') != -1)
|
||||
continue;
|
||||
|
||||
// create a new nsCookie and assign the data.
|
||||
rv = cookieManager->Add(host,
|
||||
Substring(buffer, pathIndex, secureIndex - pathIndex - 1),
|
||||
Substring(buffer, nameIndex, cookieIndex - nameIndex - 1),
|
||||
Substring(buffer, cookieIndex, buffer.Length() - cookieIndex),
|
||||
Substring(buffer, secureIndex, expiresIndex - secureIndex - 1).Equals(kTrue),
|
||||
PR_FALSE, // isHttpOnly
|
||||
PR_FALSE, // isSession
|
||||
expires);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::GetSignonFileName(PRBool aReplace, char** aFileName)
|
||||
{
|
||||
nsresult rv;
|
||||
if (aReplace) {
|
||||
// Find out what the signons file was called, this is stored in a pref
|
||||
// in Seamonkey.
|
||||
nsCOMPtr<nsIPrefService> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
psvc->ResetPrefs();
|
||||
|
||||
nsCOMPtr<nsIFile> sourcePrefsName;
|
||||
mSourceProfile->Clone(getter_AddRefs(sourcePrefsName));
|
||||
sourcePrefsName->Append(FILE_NAME_PREFS_5X);
|
||||
psvc->ReadUserPrefs(sourcePrefsName);
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(psvc));
|
||||
rv = branch->GetCharPref("signon.SignonFileName", aFileName);
|
||||
}
|
||||
else
|
||||
rv = LocateSignonsFile(aFileName);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNetscapeProfileMigratorBase::LocateSignonsFile(char** aResult)
|
||||
{
|
||||
nsCOMPtr<nsISimpleEnumerator> entries;
|
||||
nsresult rv = mSourceProfile->GetDirectoryEntries(getter_AddRefs(entries));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCAutoString fileName;
|
||||
do {
|
||||
PRBool hasMore = PR_FALSE;
|
||||
rv = entries->HasMoreElements(&hasMore);
|
||||
if (NS_FAILED(rv) || !hasMore) break;
|
||||
|
||||
nsCOMPtr<nsISupports> supp;
|
||||
rv = entries->GetNext(getter_AddRefs(supp));
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
nsCOMPtr<nsIFile> currFile(do_QueryInterface(supp));
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewFileURI(getter_AddRefs(uri), currFile);
|
||||
if (NS_FAILED(rv)) break;
|
||||
nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
|
||||
|
||||
nsCAutoString extn;
|
||||
url->GetFileExtension(extn);
|
||||
|
||||
if (extn.Equals("s", CaseInsensitiveCompare)) {
|
||||
url->GetFileName(fileName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
|
||||
*aResult = ToNewCString(fileName);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1,101 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; 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 The Browser Profile Migrator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Ben Goodger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Goodger <ben@bengoodger.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
#ifndef netscapeprofilemigratorbase___h___
|
||||
#define netscapeprofilemigratorbase___h___
|
||||
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsStringAPI.h"
|
||||
|
||||
class nsIFile;
|
||||
class nsIPrefBranch;
|
||||
|
||||
class nsNetscapeProfileMigratorBase
|
||||
{
|
||||
public:
|
||||
nsNetscapeProfileMigratorBase();
|
||||
virtual ~nsNetscapeProfileMigratorBase() { }
|
||||
|
||||
public:
|
||||
typedef nsresult(*prefConverter)(void*, nsIPrefBranch*);
|
||||
|
||||
struct PrefTransform {
|
||||
const char* sourcePrefName;
|
||||
const char* targetPrefName;
|
||||
prefConverter prefGetterFunc;
|
||||
prefConverter prefSetterFunc;
|
||||
PRBool prefHasValue;
|
||||
union {
|
||||
PRInt32 intValue;
|
||||
PRBool boolValue;
|
||||
char* stringValue;
|
||||
};
|
||||
};
|
||||
|
||||
static nsresult GetString(void* aTransform, nsIPrefBranch* aBranch);
|
||||
static nsresult SetString(void* aTransform, nsIPrefBranch* aBranch);
|
||||
static nsresult GetWString(void* aTransform, nsIPrefBranch* aBranch);
|
||||
static nsresult SetWString(void* aTransform, nsIPrefBranch* aBranch);
|
||||
static nsresult SetWStringFromASCII(void* aTransform, nsIPrefBranch* aBranch);
|
||||
static nsresult GetBool(void* aTransform, nsIPrefBranch* aBranch);
|
||||
static nsresult SetBool(void* aTransform, nsIPrefBranch* aBranch);
|
||||
static nsresult GetInt(void* aTransform, nsIPrefBranch* aBranch);
|
||||
static nsresult SetInt(void* aTransform, nsIPrefBranch* aBranch);
|
||||
|
||||
protected:
|
||||
nsresult GetProfileDataFromRegistry(nsILocalFile* aRegistryFile,
|
||||
nsISupportsArray* aProfileNames,
|
||||
nsISupportsArray* aProfileLocations);
|
||||
|
||||
nsresult CopyFile(const nsAString& aSourceFileName, const nsAString& aTargetFileName);
|
||||
|
||||
nsresult ImportNetscapeBookmarks(const nsAString& aBookmarksFileName,
|
||||
const PRUnichar* aImportSourceNameKey);
|
||||
|
||||
nsresult ImportNetscapeCookies(nsIFile* aCookiesFile);
|
||||
|
||||
nsresult GetSignonFileName(PRBool aReplace, char** aFileName);
|
||||
nsresult LocateSignonsFile(char** aResult);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsILocalFile> mSourceProfile;
|
||||
nsCOMPtr<nsIFile> mTargetProfile;
|
||||
};
|
||||
|
||||
#endif
|
@ -162,7 +162,6 @@ NS_IMPL_ISUPPORTS1(nsProfileMigrator, nsIProfileMigrator)
|
||||
|
||||
#define INTERNAL_NAME_IEXPLORE "iexplore"
|
||||
#define INTERNAL_NAME_MOZILLA_SUITE "apprunner"
|
||||
#define INTERNAL_NAME_SEAMONKEY "seamonkey"
|
||||
#define INTERNAL_NAME_OPERA "opera"
|
||||
#endif
|
||||
|
||||
@ -243,12 +242,7 @@ nsProfileMigrator::GetDefaultBrowserMigratorKey(nsACString& aKey,
|
||||
aKey = "ie";
|
||||
return NS_OK;
|
||||
}
|
||||
if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_MOZILLA_SUITE) ||
|
||||
internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_SEAMONKEY)) {
|
||||
aKey = "seamonkey";
|
||||
return NS_OK;
|
||||
}
|
||||
if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_OPERA)) {
|
||||
else if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_OPERA)) {
|
||||
aKey = "opera";
|
||||
return NS_OK;
|
||||
}
|
||||
@ -267,7 +261,6 @@ nsProfileMigrator::GetDefaultBrowserMigratorKey(nsACString& aKey,
|
||||
#if defined(XP_MACOSX)
|
||||
CHECK_MIGRATOR("safari");
|
||||
#endif
|
||||
CHECK_MIGRATOR("seamonkey");
|
||||
CHECK_MIGRATOR("opera");
|
||||
|
||||
#undef CHECK_MIGRATOR
|
||||
|
@ -1,721 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; 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 The Browser Profile Migrator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Ben Goodger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Goodger <ben@bengoodger.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
#include "nsBrowserProfileMigratorUtils.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsILoginInfo.h"
|
||||
#include "nsILoginManager.h"
|
||||
#include "nsILoginManagerStorage.h"
|
||||
#include "nsIPrefLocalizedString.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsSeamonkeyProfileMigrator.h"
|
||||
#include "nsIProfileMigrator.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// nsSeamonkeyProfileMigrator
|
||||
|
||||
#define FILE_NAME_BOOKMARKS NS_LITERAL_STRING("bookmarks.html")
|
||||
#define FILE_NAME_COOKIES NS_LITERAL_STRING("cookies.txt")
|
||||
#define FILE_NAME_SITEPERM_OLD NS_LITERAL_STRING("cookperm.txt")
|
||||
#define FILE_NAME_SITEPERM_NEW NS_LITERAL_STRING("hostperm.1")
|
||||
#define FILE_NAME_CERT8DB NS_LITERAL_STRING("cert8.db")
|
||||
#define FILE_NAME_KEY3DB NS_LITERAL_STRING("key3.db")
|
||||
#define FILE_NAME_SECMODDB NS_LITERAL_STRING("secmod.db")
|
||||
#define FILE_NAME_MIMETYPES NS_LITERAL_STRING("mimeTypes.rdf")
|
||||
#define FILE_NAME_DOWNLOADS NS_LITERAL_STRING("downloads.rdf")
|
||||
#define FILE_NAME_PREFS NS_LITERAL_STRING("prefs.js")
|
||||
#define FILE_NAME_USER_PREFS NS_LITERAL_STRING("user.js")
|
||||
#define FILE_NAME_USERCONTENT NS_LITERAL_STRING("userContent.css")
|
||||
#define DIR_NAME_CHROME NS_LITERAL_STRING("chrome")
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsSeamonkeyProfileMigrator, nsIBrowserProfileMigrator)
|
||||
|
||||
nsSeamonkeyProfileMigrator::nsSeamonkeyProfileMigrator()
|
||||
{
|
||||
mObserverService = do_GetService("@mozilla.org/observer-service;1");
|
||||
}
|
||||
|
||||
nsSeamonkeyProfileMigrator::~nsSeamonkeyProfileMigrator()
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// nsIBrowserProfileMigrator
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSeamonkeyProfileMigrator::Migrate(PRUint16 aItems, nsIProfileStartup* aStartup, const PRUnichar* aProfile)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
PRBool aReplace = aStartup ? PR_TRUE : PR_FALSE;
|
||||
|
||||
if (!mTargetProfile) {
|
||||
GetProfilePath(aStartup, mTargetProfile);
|
||||
if (!mTargetProfile) return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!mSourceProfile)
|
||||
GetSourceProfile(aProfile);
|
||||
|
||||
NOTIFY_OBSERVERS(MIGRATION_STARTED, nsnull);
|
||||
|
||||
COPY_DATA(CopyPreferences, aReplace, nsIBrowserProfileMigrator::SETTINGS);
|
||||
COPY_DATA(CopyCookies, aReplace, nsIBrowserProfileMigrator::COOKIES);
|
||||
COPY_DATA(CopyPasswords, aReplace, nsIBrowserProfileMigrator::PASSWORDS);
|
||||
COPY_DATA(CopyOtherData, aReplace, nsIBrowserProfileMigrator::OTHERDATA);
|
||||
|
||||
// Need to do startup before trying to copy bookmarks, since bookmarks
|
||||
// import requires a profile. Can't do it earlier because services might
|
||||
// end up creating the files we try to copy above.
|
||||
if (aStartup) {
|
||||
rv = aStartup->DoStartup();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
COPY_DATA(CopyBookmarks, aReplace, nsIBrowserProfileMigrator::BOOKMARKS);
|
||||
|
||||
if (aReplace &&
|
||||
(aItems & nsIBrowserProfileMigrator::SETTINGS ||
|
||||
aItems & nsIBrowserProfileMigrator::COOKIES ||
|
||||
aItems & nsIBrowserProfileMigrator::PASSWORDS ||
|
||||
!aItems)) {
|
||||
// Permissions (Images, Cookies, Popups)
|
||||
rv |= CopyFile(FILE_NAME_SITEPERM_NEW, FILE_NAME_SITEPERM_NEW);
|
||||
rv |= CopyFile(FILE_NAME_SITEPERM_OLD, FILE_NAME_SITEPERM_OLD);
|
||||
}
|
||||
|
||||
NOTIFY_OBSERVERS(MIGRATION_ENDED, nsnull);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSeamonkeyProfileMigrator::GetMigrateData(const PRUnichar* aProfile,
|
||||
PRBool aReplace,
|
||||
PRUint16* aResult)
|
||||
{
|
||||
*aResult = 0;
|
||||
|
||||
if (!mSourceProfile) {
|
||||
GetSourceProfile(aProfile);
|
||||
if (!mSourceProfile)
|
||||
return NS_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
MigrationData data[] = { { ToNewUnicode(FILE_NAME_PREFS),
|
||||
nsIBrowserProfileMigrator::SETTINGS,
|
||||
PR_TRUE },
|
||||
{ ToNewUnicode(FILE_NAME_USER_PREFS),
|
||||
nsIBrowserProfileMigrator::SETTINGS,
|
||||
PR_TRUE },
|
||||
{ ToNewUnicode(FILE_NAME_COOKIES),
|
||||
nsIBrowserProfileMigrator::COOKIES,
|
||||
PR_FALSE },
|
||||
{ ToNewUnicode(FILE_NAME_BOOKMARKS),
|
||||
nsIBrowserProfileMigrator::BOOKMARKS,
|
||||
PR_FALSE },
|
||||
{ ToNewUnicode(FILE_NAME_DOWNLOADS),
|
||||
nsIBrowserProfileMigrator::OTHERDATA,
|
||||
PR_TRUE },
|
||||
{ ToNewUnicode(FILE_NAME_MIMETYPES),
|
||||
nsIBrowserProfileMigrator::OTHERDATA,
|
||||
PR_TRUE } };
|
||||
|
||||
// Frees file name strings allocated above.
|
||||
GetMigrateDataFromArray(data, sizeof(data)/sizeof(MigrationData),
|
||||
aReplace, mSourceProfile, aResult);
|
||||
|
||||
// Now locate passwords
|
||||
nsCString signonsFileName;
|
||||
GetSignonFileName(aReplace, getter_Copies(signonsFileName));
|
||||
|
||||
if (!signonsFileName.IsEmpty()) {
|
||||
NS_ConvertASCIItoUTF16 fileName(signonsFileName);
|
||||
nsCOMPtr<nsIFile> sourcePasswordsFile;
|
||||
mSourceProfile->Clone(getter_AddRefs(sourcePasswordsFile));
|
||||
sourcePasswordsFile->Append(fileName);
|
||||
|
||||
PRBool exists;
|
||||
sourcePasswordsFile->Exists(&exists);
|
||||
if (exists)
|
||||
*aResult |= nsIBrowserProfileMigrator::PASSWORDS;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSeamonkeyProfileMigrator::GetSourceExists(PRBool* aResult)
|
||||
{
|
||||
nsCOMPtr<nsISupportsArray> profiles;
|
||||
GetSourceProfiles(getter_AddRefs(profiles));
|
||||
|
||||
if (profiles) {
|
||||
PRUint32 count;
|
||||
profiles->Count(&count);
|
||||
*aResult = count > 0;
|
||||
}
|
||||
else
|
||||
*aResult = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSeamonkeyProfileMigrator::GetSourceHasMultipleProfiles(PRBool* aResult)
|
||||
{
|
||||
nsCOMPtr<nsISupportsArray> profiles;
|
||||
GetSourceProfiles(getter_AddRefs(profiles));
|
||||
|
||||
if (profiles) {
|
||||
PRUint32 count;
|
||||
profiles->Count(&count);
|
||||
*aResult = count > 1;
|
||||
}
|
||||
else
|
||||
*aResult = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSeamonkeyProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
|
||||
{
|
||||
if (!mProfileNames && !mProfileLocations) {
|
||||
mProfileNames = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
|
||||
mProfileLocations = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
|
||||
NS_ENSURE_TRUE(mProfileNames && mProfileLocations, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// Fills mProfileNames and mProfileLocations
|
||||
FillProfileDataFromSeamonkeyRegistry();
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*aResult = mProfileNames);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSeamonkeyProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
|
||||
{
|
||||
// Load the source pref file
|
||||
nsCOMPtr<nsIPrefService> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
psvc->ResetPrefs();
|
||||
|
||||
nsCOMPtr<nsIFile> sourcePrefsFile;
|
||||
|
||||
mSourceProfile->Clone(getter_AddRefs(sourcePrefsFile));
|
||||
sourcePrefsFile->Append(FILE_NAME_PREFS);
|
||||
|
||||
psvc->ReadUserPrefs(sourcePrefsFile);
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(psvc));
|
||||
|
||||
PRBool hasUserValue;
|
||||
nsCOMPtr<nsIPrefLocalizedString> prefValue;
|
||||
nsresult rv = branch->PrefHasUserValue("browser.startup.homepage", &hasUserValue);
|
||||
if (NS_SUCCEEDED(rv) && hasUserValue) {
|
||||
rv = branch->GetComplexValue("browser.startup.homepage",
|
||||
NS_GET_IID(nsIPrefLocalizedString),
|
||||
getter_AddRefs(prefValue));
|
||||
if (NS_SUCCEEDED(rv) && prefValue) {
|
||||
nsString data;
|
||||
prefValue->ToString(getter_Copies(data));
|
||||
|
||||
nsCAutoString val;
|
||||
val = ToNewCString(NS_ConvertUTF16toUTF8(data));
|
||||
|
||||
aResult.Assign(val);
|
||||
}
|
||||
}
|
||||
|
||||
psvc->ResetPrefs();
|
||||
psvc->ReadUserPrefs(nsnull);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// nsSeamonkeyProfileMigrator
|
||||
|
||||
nsresult
|
||||
nsSeamonkeyProfileMigrator::GetSourceProfile(const PRUnichar* aProfile)
|
||||
{
|
||||
PRUint32 count;
|
||||
mProfileNames->Count(&count);
|
||||
for (PRUint32 i = 0; i < count; ++i) {
|
||||
nsCOMPtr<nsISupportsString> str;
|
||||
mProfileNames->QueryElementAt(i, NS_GET_IID(nsISupportsString),
|
||||
getter_AddRefs(str));
|
||||
nsString profileName;
|
||||
str->GetData(profileName);
|
||||
if (profileName.Equals(aProfile)) {
|
||||
mProfileLocations->QueryElementAt(i, NS_GET_IID(nsILocalFile),
|
||||
getter_AddRefs(mSourceProfile));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSeamonkeyProfileMigrator::FillProfileDataFromSeamonkeyRegistry()
|
||||
{
|
||||
// Find the Seamonkey Registry
|
||||
nsCOMPtr<nsIProperties> fileLocator(do_GetService("@mozilla.org/file/directory_service;1"));
|
||||
nsCOMPtr<nsILocalFile> seamonkeyRegistry;
|
||||
#ifdef XP_WIN
|
||||
fileLocator->Get(NS_WIN_APPDATA_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(seamonkeyRegistry));
|
||||
|
||||
seamonkeyRegistry->Append(NS_LITERAL_STRING("Mozilla"));
|
||||
seamonkeyRegistry->Append(NS_LITERAL_STRING("registry.dat"));
|
||||
#elif defined(XP_MACOSX)
|
||||
fileLocator->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(seamonkeyRegistry));
|
||||
|
||||
seamonkeyRegistry->Append(NS_LITERAL_STRING("Mozilla"));
|
||||
seamonkeyRegistry->Append(NS_LITERAL_STRING("Application Registry"));
|
||||
#elif defined(XP_UNIX)
|
||||
fileLocator->Get(NS_UNIX_HOME_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(seamonkeyRegistry));
|
||||
|
||||
seamonkeyRegistry->Append(NS_LITERAL_STRING(".mozilla"));
|
||||
seamonkeyRegistry->Append(NS_LITERAL_STRING("appreg"));
|
||||
#elif defined(XP_OS2)
|
||||
fileLocator->Get(NS_OS2_HOME_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(seamonkeyRegistry));
|
||||
|
||||
seamonkeyRegistry->Append(NS_LITERAL_STRING("Mozilla"));
|
||||
seamonkeyRegistry->Append(NS_LITERAL_STRING("registry.dat"));
|
||||
#endif
|
||||
|
||||
return GetProfileDataFromRegistry(seamonkeyRegistry, mProfileNames, mProfileLocations);
|
||||
}
|
||||
|
||||
#define F(a) nsSeamonkeyProfileMigrator::a
|
||||
|
||||
#define MAKEPREFTRANSFORM(pref, newpref, getmethod, setmethod) \
|
||||
{ pref, newpref, F(Get##getmethod), F(Set##setmethod), PR_FALSE, { -1 } }
|
||||
|
||||
#define MAKESAMETYPEPREFTRANSFORM(pref, method) \
|
||||
{ pref, 0, F(Get##method), F(Set##method), PR_FALSE, { -1 } }
|
||||
|
||||
|
||||
static
|
||||
nsSeamonkeyProfileMigrator::PrefTransform gTransforms[] = {
|
||||
MAKESAMETYPEPREFTRANSFORM("signon.SignonFileName", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("browser.tabs.autoHide", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("browser.tabs.loadInBackground", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("browser.enable_automatic_image_resizing", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.cookie.warnAboutCookies", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.cookie.lifetime.enabled", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.cookie.lifetime.behavior", Int),
|
||||
MAKESAMETYPEPREFTRANSFORM("dom.disable_open_during_load", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("signon.rememberSignons", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("security.enable_ssl3", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("security.enable_tls", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("security.warn_entering_secure", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("security.warn_entering_weak", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("security.warn_leaving_secure", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("security.warn_submit_insecure", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("security.warn_viewing_mixed", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("security.default_personal_cert", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("security.OSCP.enabled", Int),
|
||||
MAKESAMETYPEPREFTRANSFORM("security.OSCP.signingCA", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("security.OSCP.URL", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("javascript.enabled", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("dom.disable_window_move_resize", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("dom.disable_window_flip", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("dom.disable_window_open_feature.status", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("dom.disable_window_status_change", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("dom.disable_image_src_set", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("accessibility.typeaheadfind.autostart", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("accessibility.typeaheadfind.linksonly", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.proxy.type", Int),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.proxy.http", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.proxy.http_port", Int),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.proxy.ftp", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.proxy.ftp_port", Int),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.proxy.ssl", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.proxy.ssl_port", Int),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.proxy.socks", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.proxy.socks_port", Int),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.proxy.no_proxies_on", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("network.proxy.autoconfig_url", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("browser.display.foreground_color", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("browser.display.background_color", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("browser.anchor_color", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("browser.visited_color", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("browser.underline_anchors", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("browser.display.use_system_colors", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("browser.display.use_document_colors", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("browser.display.use_document_fonts", Bool),
|
||||
MAKESAMETYPEPREFTRANSFORM("intl.charset.default", String),
|
||||
MAKESAMETYPEPREFTRANSFORM("intl.accept_languages", String),
|
||||
|
||||
MAKEPREFTRANSFORM("network.image.imageBehavior", 0, Int, Image),
|
||||
MAKEPREFTRANSFORM("network.cookie.cookieBehavior", 0, Int, Cookie),
|
||||
MAKEPREFTRANSFORM("browser.downloadmanager.behavior", 0, Int, DownloadManager),
|
||||
|
||||
MAKEPREFTRANSFORM("wallet.captureForms", "formfill.enabled", Bool, Bool)
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsSeamonkeyProfileMigrator::SetImage(void* aTransform, nsIPrefBranch* aBranch)
|
||||
{
|
||||
PrefTransform* xform = (PrefTransform*)aTransform;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (xform->prefHasValue)
|
||||
rv = aBranch->SetIntPref("network.image.imageBehavior", xform->intValue == 1 ? 0 : xform->intValue);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSeamonkeyProfileMigrator::SetCookie(void* aTransform, nsIPrefBranch* aBranch)
|
||||
{
|
||||
PrefTransform* xform = (PrefTransform*)aTransform;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (xform->prefHasValue)
|
||||
rv = aBranch->SetIntPref("network.cookie.cookieBehavior", xform->intValue == 3 ? 0 : xform->intValue);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSeamonkeyProfileMigrator::SetDownloadManager(void* aTransform, nsIPrefBranch* aBranch)
|
||||
{
|
||||
PrefTransform* xform = (PrefTransform*)aTransform;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (xform->prefHasValue) {
|
||||
// Seamonkey's download manager uses a single pref to control behavior:
|
||||
// 0 - show download manager window
|
||||
// 1 - show individual progress dialogs
|
||||
// 2 - show nothing
|
||||
//
|
||||
// Firefox has only a download manager window, but it can behave like a progress dialog, thus:
|
||||
// 0 || 1 -> show downloads window when a download starts
|
||||
// 2 -> don't show anything when a download starts
|
||||
// 1 -> close the downloads window as if it were a progress window when downloads complete.
|
||||
//
|
||||
rv |= aBranch->SetBoolPref("browser.download.manager.showWhenStarting", xform->intValue != 2);
|
||||
rv |= aBranch->SetBoolPref("browser.download.manager.closeWhenDone", xform->intValue == 1);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSeamonkeyProfileMigrator::TransformPreferences(const nsAString& aSourcePrefFileName,
|
||||
const nsAString& aTargetPrefFileName)
|
||||
{
|
||||
PrefTransform* transform;
|
||||
PrefTransform* end = gTransforms + sizeof(gTransforms)/sizeof(PrefTransform);
|
||||
|
||||
// Load the source pref file
|
||||
nsCOMPtr<nsIPrefService> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
psvc->ResetPrefs();
|
||||
|
||||
nsCOMPtr<nsIFile> sourcePrefsFile;
|
||||
mSourceProfile->Clone(getter_AddRefs(sourcePrefsFile));
|
||||
sourcePrefsFile->Append(aSourcePrefFileName);
|
||||
psvc->ReadUserPrefs(sourcePrefsFile);
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(psvc));
|
||||
for (transform = gTransforms; transform < end; ++transform)
|
||||
transform->prefGetterFunc(transform, branch);
|
||||
|
||||
nsTArray<FontPref> fontPrefs;
|
||||
ReadFontsBranch(psvc, &fontPrefs);
|
||||
|
||||
// Now that we have all the pref data in memory, load the target pref file,
|
||||
// and write it back out
|
||||
psvc->ResetPrefs();
|
||||
for (transform = gTransforms; transform < end; ++transform)
|
||||
transform->prefSetterFunc(transform, branch);
|
||||
|
||||
WriteFontsBranch(psvc, &fontPrefs);
|
||||
|
||||
nsCOMPtr<nsIFile> targetPrefsFile;
|
||||
mTargetProfile->Clone(getter_AddRefs(targetPrefsFile));
|
||||
targetPrefsFile->Append(aTargetPrefFileName);
|
||||
psvc->SavePrefFile(targetPrefsFile);
|
||||
|
||||
psvc->ResetPrefs();
|
||||
psvc->ReadUserPrefs(nsnull);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsSeamonkeyProfileMigrator::ReadFontsBranch(nsIPrefService* aPrefService,
|
||||
nsTArray<FontPref>* aPrefs)
|
||||
{
|
||||
// Enumerate the branch
|
||||
nsCOMPtr<nsIPrefBranch> branch;
|
||||
aPrefService->GetBranch("font.", getter_AddRefs(branch));
|
||||
|
||||
PRUint32 count;
|
||||
char** prefs = nsnull;
|
||||
nsresult rv = branch->GetChildList("", &count, &prefs);
|
||||
if (NS_FAILED(rv)) return;
|
||||
|
||||
for (PRUint32 i = 0; i < count; ++i) {
|
||||
// Save each pref's value into an array
|
||||
char* currPref = prefs[i];
|
||||
PRInt32 type;
|
||||
branch->GetPrefType(currPref, &type);
|
||||
FontPref* pref = aPrefs->AppendElement();
|
||||
pref->prefName = currPref;
|
||||
pref->type = type;
|
||||
switch (type) {
|
||||
case nsIPrefBranch::PREF_STRING:
|
||||
rv = branch->GetCharPref(currPref, &pref->stringValue);
|
||||
break;
|
||||
case nsIPrefBranch::PREF_BOOL:
|
||||
rv = branch->GetBoolPref(currPref, &pref->boolValue);
|
||||
break;
|
||||
case nsIPrefBranch::PREF_INT:
|
||||
rv = branch->GetIntPref(currPref, &pref->intValue);
|
||||
break;
|
||||
case nsIPrefBranch::PREF_INVALID:
|
||||
{
|
||||
nsCOMPtr<nsIPrefLocalizedString> str;
|
||||
rv = branch->GetComplexValue(currPref,
|
||||
NS_GET_IID(nsIPrefLocalizedString),
|
||||
getter_AddRefs(str));
|
||||
if (NS_SUCCEEDED(rv) && str)
|
||||
str->ToString(&pref->wstringValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
aPrefs->RemoveElementAt(aPrefs->Length()-1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSeamonkeyProfileMigrator::WriteFontsBranch(nsIPrefService* aPrefService,
|
||||
nsTArray<FontPref>* aPrefs)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Enumerate the branch
|
||||
nsCOMPtr<nsIPrefBranch> branch;
|
||||
aPrefService->GetBranch("font.", getter_AddRefs(branch));
|
||||
|
||||
PRUint32 count = aPrefs->Length();
|
||||
for (PRUint32 i = 0; i < count; ++i) {
|
||||
FontPref &pref = aPrefs->ElementAt(i);
|
||||
switch (pref.type) {
|
||||
case nsIPrefBranch::PREF_STRING:
|
||||
rv = branch->SetCharPref(pref.prefName, pref.stringValue);
|
||||
NS_Free(pref.stringValue);
|
||||
pref.stringValue = nsnull;
|
||||
break;
|
||||
case nsIPrefBranch::PREF_BOOL:
|
||||
rv = branch->SetBoolPref(pref.prefName, pref.boolValue);
|
||||
break;
|
||||
case nsIPrefBranch::PREF_INT:
|
||||
rv = branch->SetIntPref(pref.prefName, pref.intValue);
|
||||
break;
|
||||
case nsIPrefBranch::PREF_INVALID:
|
||||
nsCOMPtr<nsIPrefLocalizedString> pls(do_CreateInstance("@mozilla.org/pref-localizedstring;1"));
|
||||
pls->SetData(pref.wstringValue);
|
||||
rv = branch->SetComplexValue(pref.prefName,
|
||||
NS_GET_IID(nsIPrefLocalizedString),
|
||||
pls);
|
||||
NS_Free(pref.wstringValue);
|
||||
pref.wstringValue = nsnull;
|
||||
break;
|
||||
}
|
||||
NS_Free(pref.prefName);
|
||||
}
|
||||
aPrefs->Clear();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSeamonkeyProfileMigrator::CopyPreferences(PRBool aReplace)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (!aReplace)
|
||||
return rv;
|
||||
|
||||
rv |= TransformPreferences(FILE_NAME_PREFS, FILE_NAME_PREFS);
|
||||
rv |= CopyFile(FILE_NAME_USER_PREFS, FILE_NAME_USER_PREFS);
|
||||
|
||||
// Security Stuff
|
||||
rv |= CopyFile(FILE_NAME_CERT8DB, FILE_NAME_CERT8DB);
|
||||
rv |= CopyFile(FILE_NAME_KEY3DB, FILE_NAME_KEY3DB);
|
||||
rv |= CopyFile(FILE_NAME_SECMODDB, FILE_NAME_SECMODDB);
|
||||
|
||||
// User MIME Type overrides
|
||||
rv |= CopyFile(FILE_NAME_MIMETYPES, FILE_NAME_MIMETYPES);
|
||||
|
||||
rv |= CopyUserContentSheet();
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSeamonkeyProfileMigrator::CopyUserContentSheet()
|
||||
{
|
||||
nsCOMPtr<nsIFile> sourceUserContent;
|
||||
mSourceProfile->Clone(getter_AddRefs(sourceUserContent));
|
||||
sourceUserContent->Append(DIR_NAME_CHROME);
|
||||
sourceUserContent->Append(FILE_NAME_USERCONTENT);
|
||||
|
||||
PRBool exists = PR_FALSE;
|
||||
sourceUserContent->Exists(&exists);
|
||||
if (!exists)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIFile> targetUserContent;
|
||||
mTargetProfile->Clone(getter_AddRefs(targetUserContent));
|
||||
targetUserContent->Append(DIR_NAME_CHROME);
|
||||
nsCOMPtr<nsIFile> targetChromeDir;
|
||||
targetUserContent->Clone(getter_AddRefs(targetChromeDir));
|
||||
targetUserContent->Append(FILE_NAME_USERCONTENT);
|
||||
|
||||
targetUserContent->Exists(&exists);
|
||||
if (exists)
|
||||
targetUserContent->Remove(PR_FALSE);
|
||||
|
||||
return sourceUserContent->CopyTo(targetChromeDir, FILE_NAME_USERCONTENT);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSeamonkeyProfileMigrator::CopyCookies(PRBool aReplace)
|
||||
{
|
||||
nsresult rv;
|
||||
if (aReplace)
|
||||
rv = CopyFile(FILE_NAME_COOKIES, FILE_NAME_COOKIES);
|
||||
else {
|
||||
nsCOMPtr<nsIFile> seamonkeyCookiesFile;
|
||||
mSourceProfile->Clone(getter_AddRefs(seamonkeyCookiesFile));
|
||||
seamonkeyCookiesFile->Append(FILE_NAME_COOKIES);
|
||||
|
||||
rv = ImportNetscapeCookies(seamonkeyCookiesFile);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSeamonkeyProfileMigrator::CopyPasswords(PRBool aReplace)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCString signonsFileName;
|
||||
GetSignonFileName(aReplace, getter_Copies(signonsFileName));
|
||||
|
||||
if (signonsFileName.IsEmpty())
|
||||
return NS_ERROR_FILE_NOT_FOUND;
|
||||
|
||||
NS_ConvertASCIItoUTF16 fileName(signonsFileName);
|
||||
if (aReplace)
|
||||
rv = CopyFile(fileName, fileName);
|
||||
else {
|
||||
// Get the password manager, which is the destination for the passwords
|
||||
// being migrated. Also create a new instance of the legacy password
|
||||
// storage component, which we'll use to slurp in the signons from
|
||||
// Seamonkey's signons.txt.
|
||||
nsCOMPtr<nsILoginManager> pwmgr(
|
||||
do_GetService("@mozilla.org/login-manager;1"));
|
||||
nsCOMPtr<nsILoginManagerStorage> importer(
|
||||
do_CreateInstance("@mozilla.org/login-manager/storage/legacy;1"));
|
||||
|
||||
nsCOMPtr<nsIFile> signonsFile;
|
||||
mSourceProfile->Clone(getter_AddRefs(signonsFile));
|
||||
signonsFile->Append(fileName);
|
||||
|
||||
importer->InitWithFile(signonsFile, nsnull);
|
||||
|
||||
PRUint32 count;
|
||||
nsILoginInfo **logins;
|
||||
|
||||
rv = importer->GetAllLogins(&count, &logins);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
for (PRUint32 i = 0; i < count; i++) {
|
||||
pwmgr->AddLogin(logins[i]);
|
||||
}
|
||||
NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
|
||||
|
||||
PRUnichar **hostnames;
|
||||
rv = importer->GetAllDisabledHosts(&count, &hostnames);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
for (PRUint32 i = 0; i < count; i++) {
|
||||
pwmgr->SetLoginSavingEnabled(nsDependentString(hostnames[i]),
|
||||
PR_FALSE);
|
||||
}
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, hostnames);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSeamonkeyProfileMigrator::CopyBookmarks(PRBool aReplace)
|
||||
{
|
||||
nsresult rv;
|
||||
if (aReplace) {
|
||||
// Initialize the default bookmarks
|
||||
rv = InitializeBookmarks(mTargetProfile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Merge in the bookmarks from the source profile
|
||||
nsCOMPtr<nsIFile> sourceFile;
|
||||
mSourceProfile->Clone(getter_AddRefs(sourceFile));
|
||||
sourceFile->Append(FILE_NAME_BOOKMARKS);
|
||||
rv = ImportBookmarksHTML(sourceFile, PR_TRUE, PR_FALSE, EmptyString().get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
rv = ImportNetscapeBookmarks(FILE_NAME_BOOKMARKS,
|
||||
NS_LITERAL_STRING("sourceNameSeamonkey").get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSeamonkeyProfileMigrator::CopyOtherData(PRBool aReplace)
|
||||
{
|
||||
return aReplace ? CopyFile(FILE_NAME_DOWNLOADS, FILE_NAME_DOWNLOADS) : NS_OK;
|
||||
}
|
||||
|
@ -1,105 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; 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 The Browser Profile Migrator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Ben Goodger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Goodger <ben@bengoodger.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
#ifndef seamonkeyprofilemigrator___h___
|
||||
#define seamonkeyprofilemigrator___h___
|
||||
|
||||
#include "nsIBrowserProfileMigrator.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsNetscapeProfileMigratorBase.h"
|
||||
#include "nsStringAPI.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIFile;
|
||||
class nsIPrefBranch;
|
||||
class nsIPrefService;
|
||||
|
||||
struct FontPref {
|
||||
char* prefName;
|
||||
PRInt32 type;
|
||||
union {
|
||||
char* stringValue;
|
||||
PRInt32 intValue;
|
||||
PRBool boolValue;
|
||||
PRUnichar* wstringValue;
|
||||
};
|
||||
};
|
||||
|
||||
class nsSeamonkeyProfileMigrator : public nsNetscapeProfileMigratorBase,
|
||||
public nsIBrowserProfileMigrator
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIBROWSERPROFILEMIGRATOR
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsSeamonkeyProfileMigrator();
|
||||
virtual ~nsSeamonkeyProfileMigrator();
|
||||
|
||||
public:
|
||||
static nsresult SetImage(void* aTransform, nsIPrefBranch* aBranch);
|
||||
static nsresult SetCookie(void* aTransform, nsIPrefBranch* aBranch);
|
||||
static nsresult SetDownloadManager(void* aTransform, nsIPrefBranch* aBranch);
|
||||
|
||||
protected:
|
||||
nsresult FillProfileDataFromSeamonkeyRegistry();
|
||||
nsresult GetSourceProfile(const PRUnichar* aProfile);
|
||||
|
||||
nsresult CopyPreferences(PRBool aReplace);
|
||||
nsresult TransformPreferences(const nsAString& aSourcePrefFileName,
|
||||
const nsAString& aTargetPrefFileName);
|
||||
void ReadFontsBranch(nsIPrefService* aPrefService,
|
||||
nsTArray<FontPref>* aPrefs);
|
||||
void WriteFontsBranch(nsIPrefService* aPrefService,
|
||||
nsTArray<FontPref>* aPrefs);
|
||||
|
||||
nsresult CopyUserContentSheet();
|
||||
|
||||
nsresult CopyCookies(PRBool aReplace);
|
||||
nsresult CopyPasswords(PRBool aReplace);
|
||||
nsresult LocateSignonsFile(char** aResult);
|
||||
nsresult CopyBookmarks(PRBool aReplace);
|
||||
nsresult CopyOtherData(PRBool aReplace);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsISupportsArray> mProfileNames;
|
||||
nsCOMPtr<nsISupportsArray> mProfileLocations;
|
||||
nsCOMPtr<nsIObserverService> mObserverService;
|
||||
};
|
||||
|
||||
#endif
|
@ -277,17 +277,30 @@ var PlacesOrganizer = {
|
||||
* the node to set up scope from
|
||||
*/
|
||||
_setSearchScopeForNode: function PO__setScopeForNode(aNode) {
|
||||
var itemId = aNode.itemId;
|
||||
let itemId = aNode.itemId;
|
||||
|
||||
// Set default buttons status.
|
||||
let bookmarksButton = document.getElementById("scopeBarAll");
|
||||
bookmarksButton.hidden = false;
|
||||
let downloadsButton = document.getElementById("scopeBarDownloads");
|
||||
downloadsButton.hidden = true;
|
||||
|
||||
if (PlacesUtils.nodeIsHistoryContainer(aNode) ||
|
||||
itemId == PlacesUIUtils.leftPaneQueries["History"]) {
|
||||
PlacesQueryBuilder.setScope("history");
|
||||
}
|
||||
// Default to All Bookmarks for all other nodes, per bug 469437.
|
||||
else
|
||||
else if (itemId == PlacesUIUtils.leftPaneQueries["Downloads"]) {
|
||||
downloadsButton.hidden = false;
|
||||
bookmarksButton.hidden = true;
|
||||
PlacesQueryBuilder.setScope("downloads");
|
||||
}
|
||||
else {
|
||||
// Default to All Bookmarks for all other nodes, per bug 469437.
|
||||
PlacesQueryBuilder.setScope("bookmarks");
|
||||
}
|
||||
|
||||
// Enable or disable the folder scope button.
|
||||
var folderButton = document.getElementById("scopeBarFolder");
|
||||
let folderButton = document.getElementById("scopeBarFolder");
|
||||
folderButton.hidden = !PlacesUtils.nodeIsFolder(aNode) ||
|
||||
itemId == PlacesUIUtils.allBookmarksFolderId;
|
||||
},
|
||||
@ -901,9 +914,21 @@ var PlacesSearchBox = {
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
|
||||
content.load([query], options);
|
||||
}
|
||||
else
|
||||
else {
|
||||
content.applyFilter(filterString);
|
||||
}
|
||||
break;
|
||||
case "downloads": {
|
||||
let query = PlacesUtils.history.getNewQuery();
|
||||
query.searchTerms = filterString;
|
||||
query.setTransitions([Ci.nsINavHistoryService.TRANSITION_DOWNLOAD], 1);
|
||||
let options = currentOptions.clone();
|
||||
// Make sure we're getting uri results.
|
||||
options.resultType = currentOptions.RESULT_TYPE_URI;
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
|
||||
content.load([query], options);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw "Invalid filterCollection on search";
|
||||
break;
|
||||
@ -933,17 +958,28 @@ var PlacesSearchBox = {
|
||||
|
||||
/**
|
||||
* Updates the display with the title of the current collection.
|
||||
* @param title
|
||||
* @param aTitle
|
||||
* The title of the current collection.
|
||||
*/
|
||||
updateCollectionTitle: function PSB_updateCollectionTitle(title) {
|
||||
if (title)
|
||||
this.searchFilter.placeholder =
|
||||
PlacesUIUtils.getFormattedString("searchCurrentDefault", [title]);
|
||||
else
|
||||
this.searchFilter.placeholder = this.filterCollection == "history" ?
|
||||
PlacesUIUtils.getString("searchHistory") :
|
||||
PlacesUIUtils.getString("searchBookmarks");
|
||||
updateCollectionTitle: function PSB_updateCollectionTitle(aTitle) {
|
||||
let title = "";
|
||||
if (aTitle) {
|
||||
title = PlacesUIUtils.getFormattedString("searchCurrentDefault",
|
||||
[aTitle]);
|
||||
}
|
||||
else {
|
||||
switch(this.filterCollection) {
|
||||
case "history":
|
||||
title = PlacesUIUtils.getString("searchHistory");
|
||||
break;
|
||||
case "downloads":
|
||||
title = PlacesUIUtils.getString("searchDownloads");
|
||||
break;
|
||||
default:
|
||||
title = PlacesUIUtils.getString("searchBookmarks");
|
||||
}
|
||||
}
|
||||
this.searchFilter.placeholder = title;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1025,6 +1061,9 @@ var PlacesQueryBuilder = {
|
||||
case "scopeBarFolder":
|
||||
this.setScope("collection");
|
||||
break;
|
||||
case "scopeBarDownloads":
|
||||
this.setScope("downloads");
|
||||
break;
|
||||
case "scopeBarAll":
|
||||
this.setScope("bookmarks");
|
||||
break;
|
||||
@ -1040,7 +1079,8 @@ var PlacesQueryBuilder = {
|
||||
* PSB_search()). If there is an active search, it's performed again to
|
||||
* update the content tree.
|
||||
* @param aScope
|
||||
* the search scope, "bookmarks", "collection", or "history"
|
||||
* The search scope: "bookmarks", "collection", "downloads" or
|
||||
* "history".
|
||||
*/
|
||||
setScope: function PQB_setScope(aScope) {
|
||||
// Determine filterCollection, folders, and scopeButtonId based on aScope.
|
||||
@ -1072,6 +1112,10 @@ var PlacesQueryBuilder = {
|
||||
PlacesUtils.toolbarFolderId,
|
||||
PlacesUtils.unfiledBookmarksFolderId);
|
||||
break;
|
||||
case "downloads":
|
||||
filterCollection = "downloads";
|
||||
scopeButtonId = "scopeBarDownloads";
|
||||
break;
|
||||
default:
|
||||
throw "Invalid search scope";
|
||||
break;
|
||||
|
@ -412,18 +412,16 @@
|
||||
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
|
||||
label="&search.scopeBookmarks.label;"
|
||||
accesskey="&search.scopeBookmarks.accesskey;"/>
|
||||
<!--
|
||||
<toolbarbutton id="scopeBarDownloads" class="small-margin"
|
||||
type="radio" group="scopeBar"
|
||||
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
|
||||
label="&search.scopeDownloads.label;"
|
||||
accesskey="&search.scopeDownloads.accesskey;"/>
|
||||
-->
|
||||
<toolbarbutton id="scopeBarHistory" class="small-margin"
|
||||
type="radio" group="scopeBar"
|
||||
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
|
||||
label="&search.scopeHistory.label;"
|
||||
accesskey="&search.scopeHistory.accesskey;"/>
|
||||
<toolbarbutton id="scopeBarDownloads" class="small-margin"
|
||||
type="radio" group="scopeBar"
|
||||
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
|
||||
label="&search.scopeDownloads.label;"
|
||||
accesskey="&search.scopeDownloads.accesskey;"/>
|
||||
<toolbarbutton id="scopeBarFolder" class="small-margin"
|
||||
type="radio" group="scopeBar"
|
||||
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
|
||||
|
@ -139,18 +139,3 @@ let tests = {
|
||||
is(unsortedNode.uri, MOZURISPEC, "node uri's are the same");
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears history invoking callback when done.
|
||||
*/
|
||||
function waitForClearHistory(aCallback) {
|
||||
const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
|
||||
aCallback();
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
}
|
||||
|
@ -37,25 +37,6 @@
|
||||
|
||||
// This test makes sure that the Forget This Site command is hidden for multiple
|
||||
// selections.
|
||||
|
||||
/**
|
||||
* Clears history invoking callback when done.
|
||||
*/
|
||||
function waitForClearHistory(aCallback) {
|
||||
const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
|
||||
aCallback();
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
|
||||
|
||||
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
|
||||
}
|
||||
|
||||
function test() {
|
||||
// initialization
|
||||
waitForExplicitFinish();
|
||||
|
@ -48,20 +48,6 @@ function uri(spec) {
|
||||
return ios.newURI(spec, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears history invoking callback when done.
|
||||
*/
|
||||
function waitForClearHistory(aCallback) {
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
|
||||
aCallback(aSubject, aTopic, aData);
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(observer, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
}
|
||||
|
||||
var sidebar = document.getElementById("sidebar");
|
||||
|
||||
function add_visit(aURI, aDate) {
|
||||
|
@ -83,14 +83,3 @@ function test() {
|
||||
|
||||
openLibrary(onLibraryReady);
|
||||
}
|
||||
|
||||
function waitForClearHistory(aCallback) {
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
|
||||
aCallback(aSubject, aTopic, aData);
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(observer, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
}
|
||||
|
@ -61,67 +61,74 @@
|
||||
*/
|
||||
|
||||
const TEST_URL = "http://dummy.mozilla.org/";
|
||||
const TEST_DOWNLOAD_URL = "http://dummy.mozilla.org/dummy.pdf";
|
||||
|
||||
// Add your tests here. Each is a function that's called by testHelper().
|
||||
var testCases = [
|
||||
let gLibrary;
|
||||
|
||||
// All Bookmarks
|
||||
function () {
|
||||
var defScope = getDefaultScope(PlacesUIUtils.allBookmarksFolderId);
|
||||
let testCases = [
|
||||
function allBookmarksScope() {
|
||||
let defScope = getDefaultScope(PlacesUIUtils.allBookmarksFolderId);
|
||||
search(PlacesUIUtils.allBookmarksFolderId, "dummy", defScope);
|
||||
is(selectScope("scopeBarFolder"), false,
|
||||
ok(!selectScope("scopeBarFolder"),
|
||||
"Folder scope should be disabled for All Bookmarks");
|
||||
resetSearch(defScope);
|
||||
ok(selectScope("scopeBarAll"),
|
||||
"Bookmarks scope should be enabled for All Bookmarks");
|
||||
resetSearch("scopeBarAll");
|
||||
},
|
||||
|
||||
// History
|
||||
function () {
|
||||
var defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["History"]);
|
||||
function historyScope() {
|
||||
let defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["History"]);
|
||||
search(PlacesUIUtils.leftPaneQueries["History"], "dummy", defScope);
|
||||
is(selectScope("scopeBarFolder"), false,
|
||||
ok(!selectScope("scopeBarFolder"),
|
||||
"Folder scope should be disabled for History");
|
||||
ok(selectScope("scopeBarAll"),
|
||||
"Bookmarks scope should be enabled for History");
|
||||
resetSearch("scopeBarAll");
|
||||
},
|
||||
|
||||
function downloadsScope() {
|
||||
let defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["Downloads"]);
|
||||
search(PlacesUIUtils.leftPaneQueries["Downloads"], "dummy", defScope);
|
||||
ok(!selectScope("scopeBarFolder"),
|
||||
"Folder scope should be disabled for Downloads");
|
||||
ok(!selectScope("scopeBarAll"),
|
||||
"Bookmarks scope should be disabled for Downloads");
|
||||
resetSearch(defScope);
|
||||
},
|
||||
|
||||
// Toolbar folder
|
||||
function () {
|
||||
var defScope = getDefaultScope(bmsvc.toolbarFolder);
|
||||
search(bmsvc.toolbarFolder, "dummy", defScope);
|
||||
is(selectScope("scopeBarFolder"), true,
|
||||
function toolbarFolderScope() {
|
||||
let defScope = getDefaultScope(PlacesUtils.toolbarFolderId);
|
||||
search(PlacesUtils.toolbarFolderId, "dummy", defScope);
|
||||
ok(selectScope("scopeBarAll"),
|
||||
"Bookmarks scope should be enabled for toolbar folder");
|
||||
ok(selectScope("scopeBarFolder"),
|
||||
"Folder scope should be enabled for toolbar folder");
|
||||
// Ensure that folder scope is still selected after resetting and searching
|
||||
// again.
|
||||
resetSearch("scopeBarFolder");
|
||||
search(bmsvc.toolbarFolder, "dummy", "scopeBarFolder");
|
||||
search(PlacesUtils.toolbarFolderId, "dummy", "scopeBarFolder");
|
||||
},
|
||||
|
||||
// A regular non-root subfolder
|
||||
function () {
|
||||
var folderId = bmsvc.createFolder(bmsvc.toolbarFolder,
|
||||
"dummy folder",
|
||||
bmsvc.DEFAULT_INDEX);
|
||||
var defScope = getDefaultScope(folderId);
|
||||
function subFolderScope() {
|
||||
let folderId = PlacesUtils.bookmarks.createFolder(PlacesUtils.toolbarFolderId,
|
||||
"dummy folder",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
let defScope = getDefaultScope(folderId);
|
||||
search(folderId, "dummy", defScope);
|
||||
is(selectScope("scopeBarFolder"), true,
|
||||
ok(selectScope("scopeBarAll"),
|
||||
"Bookmarks scope should be enabled for regularfolder");
|
||||
ok(selectScope("scopeBarFolder"),
|
||||
"Folder scope should be enabled for regular subfolder");
|
||||
// Ensure that folder scope is still selected after resetting and searching
|
||||
// again.
|
||||
resetSearch("scopeBarFolder");
|
||||
search(folderId, "dummy", "scopeBarFolder");
|
||||
bmsvc.removeItem(folderId);
|
||||
PlacesUtils.bookmarks.removeItem(folderId);
|
||||
},
|
||||
];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
var libraryWin;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Returns the default search scope for a given folder.
|
||||
*
|
||||
@ -130,9 +137,14 @@ var libraryWin;
|
||||
* @return the default scope when the folder is newly selected
|
||||
*/
|
||||
function getDefaultScope(aFolderId) {
|
||||
return aFolderId === PlacesUIUtils.leftPaneQueries["History"] ?
|
||||
"scopeBarHistory" :
|
||||
"scopeBarAll";
|
||||
switch (aFolderId) {
|
||||
case PlacesUIUtils.leftPaneQueries["History"]:
|
||||
return "scopeBarHistory"
|
||||
case PlacesUIUtils.leftPaneQueries["Downloads"]:
|
||||
return "scopeBarDownloads";
|
||||
default:
|
||||
return "scopeBarAll";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,8 +153,8 @@ function getDefaultScope(aFolderId) {
|
||||
* @return the ID of the selected scope folder button
|
||||
*/
|
||||
function getSelectedScopeButtonId() {
|
||||
var doc = libraryWin.document;
|
||||
var scopeButtons = doc.getElementById("organizerScopeBar").childNodes;
|
||||
let doc = gLibrary.document;
|
||||
let scopeButtons = doc.getElementById("organizerScopeBar").childNodes;
|
||||
for (let i = 0; i < scopeButtons.length; i++) {
|
||||
if (scopeButtons[i].checked)
|
||||
return scopeButtons[i].id;
|
||||
@ -158,8 +170,8 @@ function getSelectedScopeButtonId() {
|
||||
* @return an nsINavHistoryQuery object
|
||||
*/
|
||||
function queryStringToQuery(aPlaceURI) {
|
||||
var queries = {};
|
||||
histsvc.queryStringToQueries(aPlaceURI, queries, {}, {});
|
||||
let queries = {};
|
||||
PlacesUtils.history.queryStringToQueries(aPlaceURI, queries, {}, {});
|
||||
return queries.value[0];
|
||||
}
|
||||
|
||||
@ -188,9 +200,9 @@ function resetSearch(aExpectedScopeButtonId) {
|
||||
* after searching the selected scope button should be this
|
||||
*/
|
||||
function search(aFolderId, aSearchStr, aExpectedScopeButtonId) {
|
||||
var doc = libraryWin.document;
|
||||
var folderTree = doc.getElementById("placesList");
|
||||
var contentTree = doc.getElementById("placeContent");
|
||||
let doc = gLibrary.document;
|
||||
let folderTree = doc.getElementById("placesList");
|
||||
let contentTree = doc.getElementById("placeContent");
|
||||
|
||||
// First, ensure that selecting the folder in the left pane updates the
|
||||
// content tree properly.
|
||||
@ -201,10 +213,11 @@ function search(aFolderId, aSearchStr, aExpectedScopeButtonId) {
|
||||
|
||||
// getFolders() on a History query returns an empty array, so no use
|
||||
// comparing against aFolderId in that case.
|
||||
if (aFolderId !== PlacesUIUtils.leftPaneQueries["History"]) {
|
||||
if (aFolderId !== PlacesUIUtils.leftPaneQueries["History"] &&
|
||||
aFolderId !== PlacesUIUtils.leftPaneQueries["Downloads"]) {
|
||||
// contentTree.place should be equal to contentTree.result.root.uri,
|
||||
// but it's not until bug 476952 is fixed.
|
||||
var query = queryStringToQuery(contentTree.result.root.uri);
|
||||
let query = queryStringToQuery(contentTree.result.root.uri);
|
||||
is(query.getFolders()[0], aFolderId,
|
||||
"Content tree's folder should be what was selected in the left pane");
|
||||
}
|
||||
@ -212,27 +225,41 @@ function search(aFolderId, aSearchStr, aExpectedScopeButtonId) {
|
||||
|
||||
// Second, ensure that searching updates the content tree and search UI
|
||||
// properly.
|
||||
var searchBox = doc.getElementById("searchFilter");
|
||||
let searchBox = doc.getElementById("searchFilter");
|
||||
searchBox.value = aSearchStr;
|
||||
libraryWin.PlacesSearchBox.search(searchBox.value);
|
||||
query = queryStringToQuery(contentTree.result.root.uri);
|
||||
gLibrary.PlacesSearchBox.search(searchBox.value);
|
||||
let query = queryStringToQuery(contentTree.result.root.uri);
|
||||
if (aSearchStr) {
|
||||
is(query.searchTerms, aSearchStr,
|
||||
"Content tree's searchTerms should be text in search box");
|
||||
is(doc.getElementById("searchModifiers").hidden, false,
|
||||
"Scope bar should not be hidden after searching");
|
||||
if (getSelectedScopeButtonId() == "scopeBarHistory" ||
|
||||
getSelectedScopeButtonId() == "scopeBarAll" ||
|
||||
aFolderId == PlacesUtils.bookmarks.unfiledBookmarksFolder) {
|
||||
|
||||
let scopeButtonId = getSelectedScopeButtonId();
|
||||
if (scopeButtonId == "scopeBarDownloads" ||
|
||||
scopeButtonId == "scopeBarHistory" ||
|
||||
scopeButtonId == "scopeBarAll" ||
|
||||
aFolderId == PlacesUtils.unfiledBookmarksFolderId) {
|
||||
// Check that the target node exists in the tree's search results.
|
||||
var node = null;
|
||||
for (var i = 0; i < contentTree.view.rowCount; i++) {
|
||||
let url, count;
|
||||
if (scopeButtonId == "scopeBarDownloads") {
|
||||
url = TEST_DOWNLOAD_URL;
|
||||
count = 1;
|
||||
}
|
||||
else {
|
||||
url = TEST_URL;
|
||||
count = scopeButtonId == "scopeBarHistory" ? 2 : 1;
|
||||
}
|
||||
is(contentTree.view.rowCount, count, "Found correct number of results");
|
||||
|
||||
let node = null;
|
||||
for (let i = 0; i < contentTree.view.rowCount; i++) {
|
||||
node = contentTree.view.nodeForTreeIndex(i);
|
||||
if (node.uri === TEST_URL)
|
||||
if (node.uri === url)
|
||||
break;
|
||||
}
|
||||
isnot(node, null, "At least the target node should be in the tree");
|
||||
is(node.uri, TEST_URL, "URI of node should match target URL");
|
||||
is(node.uri, url, "URI of node should match target URL");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -253,10 +280,10 @@ function search(aFolderId, aSearchStr, aExpectedScopeButtonId) {
|
||||
* @return true if the button is enabled, false otherwise
|
||||
*/
|
||||
function selectScope(aScopeButtonId) {
|
||||
var doc = libraryWin.document;
|
||||
var button = doc.getElementById(aScopeButtonId);
|
||||
let doc = gLibrary.document;
|
||||
let button = doc.getElementById(aScopeButtonId);
|
||||
isnot(button, null,
|
||||
"Sanity check: scope button with ID " + aScopeButtonId + "should exist");
|
||||
"Sanity check: scope button with ID " + aScopeButtonId + " should exist");
|
||||
// Bug 469436 may hide an inappropriate scope button instead of disabling it.
|
||||
if (button.disabled || button.hidden)
|
||||
return false;
|
||||
@ -267,21 +294,17 @@ function selectScope(aScopeButtonId) {
|
||||
/**
|
||||
* test() contains window-launching boilerplate that calls this to really kick
|
||||
* things off. Add functions to the testCases array, and this will call them.
|
||||
*
|
||||
* @param aLibraryWin
|
||||
* the Places Library window
|
||||
*/
|
||||
function testHelper(aLibraryWin) {
|
||||
libraryWin = aLibraryWin;
|
||||
function onLibraryAvailable() {
|
||||
testCases.forEach(function (aTest) aTest());
|
||||
aLibraryWin.close();
|
||||
|
||||
gLibrary.close();
|
||||
gLibrary = null;
|
||||
|
||||
// Cleanup.
|
||||
PlacesUtils.tagging.untagURI(PlacesUtils._uri(TEST_URL), ["dummyTag"]);
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.bookmarks.unfiledBookmarksFolder);
|
||||
PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
|
||||
|
||||
finish();
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
|
||||
waitForClearHistory(finish);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -291,15 +314,19 @@ function test() {
|
||||
|
||||
// Sanity:
|
||||
ok(PlacesUtils, "PlacesUtils in context");
|
||||
// Add a visit, a bookmark and a tag.
|
||||
|
||||
// Add visits, a bookmark and a tag.
|
||||
PlacesUtils.history.addVisit(PlacesUtils._uri(TEST_URL),
|
||||
Date.now() * 1000, null,
|
||||
PlacesUtils.history.TRANSITION_TYPED, false, 0);
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarks.unfiledBookmarksFolder,
|
||||
PlacesUtils.history.addVisit(PlacesUtils._uri(TEST_DOWNLOAD_URL),
|
||||
Date.now() * 1000, null,
|
||||
PlacesUtils.history.TRANSITION_DOWNLOAD, false, 0);
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
PlacesUtils._uri(TEST_URL),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"dummy");
|
||||
PlacesUtils.tagging.tagURI(PlacesUtils._uri(TEST_URL), ["dummyTag"]);
|
||||
|
||||
openLibrary(testHelper);
|
||||
gLibrary = openLibrary(onLibraryAvailable);
|
||||
}
|
||||
|
@ -173,14 +173,6 @@ function test() {
|
||||
sidebar.contentDocument.documentElement.style.direction = aDirection;
|
||||
}
|
||||
|
||||
function waitForClearHistory(aCallback) {
|
||||
Services.obs.addObserver(function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(arguments.callee, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
|
||||
aCallback(aSubject, aTopic, aData);
|
||||
}, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
// Remove eventual tabs created by previous sub-tests.
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
|
@ -59,7 +59,7 @@ window.onload = function() {
|
||||
gStateObject = JSON.parse(sessionData.value);
|
||||
}
|
||||
catch (exJSON) {
|
||||
var s = new Cu.Sandbox("about:blank");
|
||||
var s = new Cu.Sandbox("about:blank", {sandboxName: 'aboutSessionRestore'});
|
||||
gStateObject = Cu.evalInSandbox("(" + sessionData.value + ")", s);
|
||||
// If we couldn't parse the string with JSON.parse originally, make sure
|
||||
// that the value in the textbox will be parsable.
|
||||
|
@ -135,7 +135,7 @@ SessionStartup.prototype = {
|
||||
this._initialState = JSON.parse(iniString);
|
||||
}
|
||||
catch (exJSON) {
|
||||
var s = new Cu.Sandbox("about:blank");
|
||||
var s = new Cu.Sandbox("about:blank", {sandboxName: 'nsSessionStartup'});
|
||||
this._initialState = Cu.evalInSandbox("(" + iniString + ")", s);
|
||||
}
|
||||
|
||||
|
@ -4014,7 +4014,7 @@ SessionStoreService.prototype = {
|
||||
this._restoreCount = -1;
|
||||
},
|
||||
|
||||
/**
|
||||
/**
|
||||
* Set the given window's busy state
|
||||
* @param aWindow the window
|
||||
* @param aValue the window's busy state
|
||||
|
@ -178,7 +178,8 @@ var Scratchpad = {
|
||||
this._previousLocation != this.gBrowser.contentWindow.location.href) {
|
||||
let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
|
||||
this._contentSandbox = new Cu.Sandbox(contentWindow,
|
||||
{ sandboxPrototype: contentWindow, wantXrays: false });
|
||||
{ sandboxPrototype: contentWindow, wantXrays: false,
|
||||
sandboxName: 'scratchpad-content'});
|
||||
|
||||
this._previousBrowserWindow = this.browserWindow;
|
||||
this._previousBrowser = this.gBrowser.selectedBrowser;
|
||||
@ -211,7 +212,8 @@ var Scratchpad = {
|
||||
if (!this._chromeSandbox ||
|
||||
this.browserWindow != this._previousBrowserWindow) {
|
||||
this._chromeSandbox = new Cu.Sandbox(this.browserWindow,
|
||||
{ sandboxPrototype: this.browserWindow, wantXrays: false });
|
||||
{ sandboxPrototype: this.browserWindow, wantXrays: false,
|
||||
sandboxName: 'scratchpad-chrome'});
|
||||
|
||||
this._previousBrowserWindow = this.browserWindow;
|
||||
}
|
||||
|
@ -48,4 +48,4 @@ _BROWSER_TEST_FILES = \
|
||||
browser_sourceeditor_initialization.js \
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
# $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
|
@ -19,21 +19,15 @@ function test()
|
||||
" title='test for bug 660784' width='600' height='500'><hbox flex='1'/></window>";
|
||||
const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onTabLoad() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onTabLoad, true);
|
||||
|
||||
testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
|
||||
testWin.addEventListener("load", initEditor, false);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,<p>bug 660784 - test the SourceEditor";
|
||||
|
||||
testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
|
||||
testWin.addEventListener("load", function onWindowLoad() {
|
||||
testWin.removeEventListener("load", onWindowLoad, false);
|
||||
waitForFocus(initEditor, testWin);
|
||||
}, false);
|
||||
}
|
||||
|
||||
function initEditor()
|
||||
{
|
||||
testWin.removeEventListener("load", initEditor, false);
|
||||
testDoc = testWin.document;
|
||||
|
||||
let hbox = testDoc.querySelector("hbox");
|
||||
@ -327,10 +321,7 @@ function editorLoaded()
|
||||
|
||||
testWin = testDoc = editor = null;
|
||||
|
||||
waitForFocus(function() {
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}, content);
|
||||
waitForFocus(finish, window);
|
||||
}
|
||||
|
||||
function testBackspaceKey()
|
||||
|
@ -2708,6 +2708,12 @@ HUD_SERVICE.prototype =
|
||||
|
||||
let _browser = gBrowser.
|
||||
getBrowserForDocument(aContentWindow.top.document);
|
||||
|
||||
// ignore newly created documents that don't belong to a tab's browser
|
||||
if (!_browser) {
|
||||
return;
|
||||
}
|
||||
|
||||
let nBox = gBrowser.getNotificationBox(_browser);
|
||||
let nBoxId = nBox.getAttribute("id");
|
||||
let hudId = "hud_" + nBoxId;
|
||||
|
@ -144,6 +144,7 @@ _BROWSER_TEST_FILES = \
|
||||
browser_webconsole_bug_651501_document_body_autocomplete.js \
|
||||
browser_webconsole_bug_653531_highlighter_console_helper.js \
|
||||
browser_webconsole_bug_659907_console_dir.js \
|
||||
browser_webconsole_bug_678816.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
@ -212,6 +213,7 @@ _BROWSER_TEST_PAGES = \
|
||||
test-bug-644419-log-limits.html \
|
||||
test-bug-632275-getters.html \
|
||||
test-bug-646025-console-file-location.html \
|
||||
test-bug-678816-content.js \
|
||||
test-file-location.js \
|
||||
$(NULL)
|
||||
|
||||
|
@ -0,0 +1,62 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/browser/test-console.html";
|
||||
const FRAME_SCRIPT_URI ="chrome://mochitests/content/browser/browser/devtools/webconsole/test/browser/test-bug-678816-content.js";
|
||||
|
||||
let HUD;
|
||||
let outputItem;
|
||||
|
||||
function tabLoad1(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, arguments.callee, true);
|
||||
|
||||
openConsole();
|
||||
HUD = HUDService.getHudByWindow(content);
|
||||
|
||||
browser.addEventListener("load", tabLoad2, true);
|
||||
|
||||
// Reload so we get some output in the console.
|
||||
browser.contentWindow.location.reload();
|
||||
}
|
||||
|
||||
function tabLoad2(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, tabLoad2, true);
|
||||
|
||||
outputItem = HUD.outputNode.querySelector(".hud-networkinfo .hud-clickable");
|
||||
ok(outputItem, "found a network message");
|
||||
document.addEventListener("popupshown", networkPanelShown, false);
|
||||
|
||||
// Click the network message to open the network panel.
|
||||
EventUtils.synthesizeMouseAtCenter(outputItem, {});
|
||||
}
|
||||
|
||||
function networkPanelShown(aEvent) {
|
||||
document.removeEventListener(aEvent.type, networkPanelShown, false);
|
||||
|
||||
executeSoon(function() {
|
||||
aEvent.target.addEventListener("popuphidden", networkPanelHidden, false);
|
||||
aEvent.target.hidePopup();
|
||||
});
|
||||
}
|
||||
|
||||
function networkPanelHidden(aEvent) {
|
||||
this.removeEventListener(aEvent.type, networkPanelHidden, false);
|
||||
|
||||
is(HUD.contentWindow, browser.contentWindow,
|
||||
"console has not been re-attached to the wrong window");
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
||||
function test() {
|
||||
messageManager.loadFrameScript(FRAME_SCRIPT_URI, true);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
// There's no way to unload a frameScript so send a kill signal to
|
||||
// unregister the frame script's webProgressListener
|
||||
messageManager.sendAsyncMessage("bug-678816-kill-webProgressListener");
|
||||
});
|
||||
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", tabLoad1, true);
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
(function () {
|
||||
let ifaceReq = docShell.QueryInterface(Ci.nsIInterfaceRequestor);
|
||||
let webProgress = ifaceReq.getInterface(Ci.nsIWebProgress);
|
||||
|
||||
let WebProgressListener = {
|
||||
onStateChange: function WebProgressListener_onStateChange(
|
||||
webProgress, request, flag, status) {
|
||||
|
||||
if (flag & Ci.nsIWebProgressListener.STATE_START &&
|
||||
flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
|
||||
// ensure the dom window is the top one
|
||||
return (webProgress.DOMWindow.parent == webProgress.DOMWindow);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Implements progress listener interface.
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference])
|
||||
};
|
||||
|
||||
// add web progress listener
|
||||
webProgress.addProgressListener(WebProgressListener, Ci.nsIWebProgress.NOTIFY_STATE_ALL);
|
||||
|
||||
addMessageListener("bug-678816-kill-webProgressListener", function () {
|
||||
webProgress.removeProgressListener(WebProgressListener);
|
||||
});
|
||||
})();
|
@ -42,6 +42,7 @@ view.sortBy.tags.accesskey=T
|
||||
|
||||
searchBookmarks=Search Bookmarks
|
||||
searchHistory=Search History
|
||||
searchDownloads=Search Downloads
|
||||
searchCurrentDefault=Search in '%S'
|
||||
findInPrefix=Find in '%S'…
|
||||
|
||||
|
@ -375,3 +375,26 @@ code {
|
||||
.nodeBox.highlighted > .nodeLabel {
|
||||
border-color: #3875d7 !important;
|
||||
}
|
||||
|
||||
.editingAttributeValue {
|
||||
background-color: #492;
|
||||
}
|
||||
|
||||
#attribute-editor {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
z-index: 5000;
|
||||
background-color: #fff;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
#attribute-editor.editing {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#attribute-editor-input {
|
||||
border: none;
|
||||
padding: 2px 5px;
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
@ -363,3 +363,26 @@ code {
|
||||
.nodeBox.highlighted > .nodeLabel {
|
||||
border-color: #3875d7 !important;
|
||||
}
|
||||
|
||||
.editingAttributeValue {
|
||||
background-color: #492;
|
||||
}
|
||||
|
||||
#attribute-editor {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
z-index: 5000;
|
||||
background-color: #fff;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
#attribute-editor.editing {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#attribute-editor-input {
|
||||
border: none;
|
||||
padding: 2px 5px;
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
@ -348,3 +348,25 @@ code {
|
||||
background-image: url("chrome://global/skin/tree/twisty-open.png") !important;
|
||||
}
|
||||
|
||||
.editingAttributeValue {
|
||||
background-color: #492;
|
||||
}
|
||||
|
||||
#attribute-editor {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
z-index: 5000;
|
||||
background-color: #fff;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
#attribute-editor.editing {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#attribute-editor-input {
|
||||
border: none;
|
||||
padding: 2px 5px;
|
||||
font-family: Menlo, Andale Mono, monospace;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
@ -5,12 +5,17 @@ import os
|
||||
|
||||
class DeviceManagerADB(DeviceManager):
|
||||
|
||||
def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = "org.mozilla.fennec_unofficial"):
|
||||
def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = None):
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.retrylimit = retrylimit
|
||||
self.retries = 0
|
||||
self._sock = None
|
||||
if packageName == None:
|
||||
if os.getenv('USER'):
|
||||
packageName = 'org.mozilla.fennec_' + os.getenv('USER')
|
||||
else:
|
||||
packageName = 'org.mozilla.fennec_'
|
||||
self.Init(packageName)
|
||||
|
||||
def Init(self, packageName):
|
||||
@ -27,7 +32,11 @@ class DeviceManagerADB(DeviceManager):
|
||||
self.tmpDir = None
|
||||
try:
|
||||
# a test to see if we have root privs
|
||||
self.checkCmd(["shell", "ls", "/sbin"])
|
||||
files = self.listFiles("/data/data")
|
||||
if (len(files) == 1):
|
||||
if (files[0].find("Permission denied") != -1):
|
||||
print "NOT running as root"
|
||||
raise Exception("not running as root")
|
||||
except:
|
||||
try:
|
||||
self.checkCmd(["root"])
|
||||
@ -98,7 +107,7 @@ class DeviceManagerADB(DeviceManager):
|
||||
try:
|
||||
if (not self.dirExists(remoteDir)):
|
||||
self.mkDirs(remoteDir+"/x")
|
||||
for root, dirs, files in os.walk(localDir):
|
||||
for root, dirs, files in os.walk(localDir, followlinks='true'):
|
||||
relRoot = os.path.relpath(root, localDir)
|
||||
for file in files:
|
||||
localFile = os.path.join(root, file)
|
||||
@ -134,8 +143,12 @@ class DeviceManagerADB(DeviceManager):
|
||||
# success: True
|
||||
# failure: False
|
||||
def fileExists(self, filepath):
|
||||
self.checkCmd(["shell", "ls", filepath])
|
||||
return True
|
||||
p = self.runCmd(["shell", "ls", "-a", filepath])
|
||||
data = p.stdout.readlines()
|
||||
if (len(data) == 1):
|
||||
if (data[0].rstrip() == filepath):
|
||||
return True
|
||||
return False
|
||||
|
||||
def removeFile(self, filename):
|
||||
return self.runCmd(["shell", "rm", filename]).stdout.read()
|
||||
@ -381,18 +394,11 @@ class DeviceManagerADB(DeviceManager):
|
||||
return devroot + '/fennec'
|
||||
elif (self.dirExists(devroot + '/firefox')):
|
||||
return devroot + '/firefox'
|
||||
elif (self.dirExists('/data/data/org.mozilla.fennec')):
|
||||
return '/data/data/org.mozilla.fennec'
|
||||
elif (self.dirExists('/data/data/org.mozilla.firefox')):
|
||||
return '/data/data/org.mozilla.firefox'
|
||||
elif (self.dirExists('/data/data/org.mozilla.fennec_unofficial')):
|
||||
return '/data/data/org.mozilla.fennec_unofficial'
|
||||
elif (self.dirExists('/data/data/org.mozilla.fennec_aurora')):
|
||||
return '/data/data/org.mozilla.fennec_aurora'
|
||||
elif (self.dirExists('/data/data/org.mozilla.firefox_beta')):
|
||||
return '/data/data/org.mozilla.firefox_beta'
|
||||
elif (self.packageName and self.dirExists('/data/data/' + self.packageName)):
|
||||
return '/data/data/' + self.packageName
|
||||
|
||||
# Failure (either not installed or not a recognized platform)
|
||||
print "devicemanagerADB: getAppRoot failed"
|
||||
return None
|
||||
|
||||
# Gets the directory location on the device for a specific test type
|
||||
|
@ -107,7 +107,6 @@ public class WatcherService extends Service
|
||||
|
||||
|
||||
private IWatcherService.Stub stub = new IWatcherService.Stub() {
|
||||
@Override
|
||||
public int UpdateApplication(String sAppName, String sFileName, String sOutFile, int bReboot) throws RemoteException
|
||||
{
|
||||
return UpdtApp(sAppName, sFileName, sOutFile, bReboot);
|
||||
@ -874,7 +873,6 @@ public class WatcherService extends Service
|
||||
runner.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
bInstalling = true;
|
||||
UpdtApp(msPkgName, msPkgFileName, msOutFile, mbReboot);
|
||||
|
@ -1737,7 +1737,8 @@ nsScriptSecurityManager::CheckFunctionAccess(JSContext *aCx, void *aFunObj,
|
||||
{
|
||||
#ifdef DEBUG
|
||||
{
|
||||
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, (JSObject *)aFunObj);
|
||||
JS_ASSERT(JS_ObjectIsFunction(aCx, (JSObject *)aFunObj));
|
||||
JSFunction *fun = (JSFunction *)JS_GetPrivate(aCx, (JSObject *)aFunObj);
|
||||
JSScript *script = JS_GetFunctionScript(aCx, fun);
|
||||
|
||||
NS_ASSERTION(!script, "Null principal for non-native function!");
|
||||
@ -2218,7 +2219,7 @@ nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx,
|
||||
return result;
|
||||
}
|
||||
|
||||
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
|
||||
JSFunction *fun = (JSFunction *)JS_GetPrivate(cx, obj);
|
||||
JSScript *script = JS_GetFunctionScript(cx, fun);
|
||||
|
||||
if (!script)
|
||||
@ -2284,7 +2285,7 @@ nsScriptSecurityManager::GetFramePrincipal(JSContext *cx,
|
||||
#ifdef DEBUG
|
||||
if (NS_SUCCEEDED(*rv) && !result)
|
||||
{
|
||||
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
|
||||
JSFunction *fun = (JSFunction *)JS_GetPrivate(cx, obj);
|
||||
JSScript *script = JS_GetFunctionScript(cx, fun);
|
||||
|
||||
NS_ASSERTION(!script, "Null principal for non-native function!");
|
||||
|
@ -212,6 +212,7 @@ profiledbuild::
|
||||
$(MAKE) -f $(TOPSRCDIR)/client.mk realbuild MOZ_PROFILE_GENERATE=1
|
||||
$(MAKE) -C $(PGO_OBJDIR) package
|
||||
OBJDIR=${PGO_OBJDIR} JARLOG_DIR=${PGO_OBJDIR}/jarlog/en-US $(PROFILE_GEN_SCRIPT)
|
||||
$(MAKE) -f $(TOPSRCDIR)/client.mk maybe_clobber_profiledbuild
|
||||
$(MAKE) -f $(TOPSRCDIR)/client.mk realbuild MOZ_PROFILE_USE=1
|
||||
|
||||
#####################################################
|
||||
@ -253,7 +254,7 @@ endif
|
||||
# loop through them.
|
||||
|
||||
ifeq (,$(MOZ_CURRENT_PROJECT)$(if $(MOZ_BUILD_PROJECTS),,1))
|
||||
configure depend realbuild install export libs clean realclean distclean alldep preflight postflight upload sdk::
|
||||
configure depend realbuild install export libs clean realclean distclean alldep preflight postflight maybe_clobber_profiledbuild upload sdk::
|
||||
set -e; \
|
||||
for app in $(MOZ_BUILD_PROJECTS); do \
|
||||
$(MAKE) -f $(TOPSRCDIR)/client.mk $@ MOZ_CURRENT_PROJECT=$$app; \
|
||||
@ -353,7 +354,7 @@ realbuild:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
|
||||
# Other targets
|
||||
|
||||
# Pass these target onto the real build system
|
||||
install export libs clean realclean distclean alldep upload sdk:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
|
||||
install export libs clean realclean distclean alldep maybe_clobber_profiledbuild upload sdk:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
|
||||
$(MOZ_MAKE) $@
|
||||
|
||||
####################################
|
||||
@ -412,4 +413,4 @@ echo-variable-%:
|
||||
# in parallel.
|
||||
.NOTPARALLEL:
|
||||
|
||||
.PHONY: checkout real_checkout depend realbuild build profiledbuild export libs alldep install clean realclean distclean cleansrcdir pull_all build_all clobber clobber_all pull_and_build_all everything configure preflight_all preflight postflight postflight_all upload sdk
|
||||
.PHONY: checkout real_checkout depend realbuild build profiledbuild maybe_clobber_profiledbuild export libs alldep install clean realclean distclean cleansrcdir pull_all build_all clobber clobber_all pull_and_build_all everything configure preflight_all preflight postflight postflight_all upload sdk
|
||||
|
@ -223,7 +223,6 @@ MOZ_XUL = @MOZ_XUL@
|
||||
MOZ_RDF = @MOZ_RDF@
|
||||
|
||||
NECKO_PROTOCOLS = @NECKO_PROTOCOLS@
|
||||
NECKO_DISK_CACHE = @NECKO_DISK_CACHE@
|
||||
NECKO_COOKIES = @NECKO_COOKIES@
|
||||
NECKO_WIFI = @NECKO_WIFI@
|
||||
MOZ_AUTH_EXTENSION = @MOZ_AUTH_EXTENSION@
|
||||
|
2809
config/gtscc.c
2809
config/gtscc.c
File diff suppressed because it is too large
Load Diff
@ -153,6 +153,20 @@ xpcshell-tests:
|
||||
$(LIBXUL_DIST)/bin/xpcshell \
|
||||
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
|
||||
|
||||
xpcshell-tests-remote: DM_TRANS?=adb
|
||||
xpcshell-tests-remote:
|
||||
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
|
||||
-I$(topsrcdir)/build \
|
||||
-I$(topsrcdir)/build/mobile \
|
||||
$(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
|
||||
--symbols-path=$(DIST)/crashreporter-symbols \
|
||||
--build-info-json=$(DEPTH)/mozinfo.json \
|
||||
$(EXTRA_TEST_ARGS) \
|
||||
--dm_trans=$(DM_TRANS) \
|
||||
--deviceIP=${TEST_DEVICE} \
|
||||
--objdir=$(DEPTH) \
|
||||
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
|
||||
|
||||
# Execute a single test, specified in $(SOLO_FILE), but don't automatically
|
||||
# start the test. Instead, present the xpcshell prompt so the user can
|
||||
# attach a debugger and then start the test.
|
||||
@ -182,6 +196,23 @@ check-one:
|
||||
$(LIBXUL_DIST)/bin/xpcshell \
|
||||
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
|
||||
|
||||
check-one-remote: DM_TRANS?=adb
|
||||
check-one-remote:
|
||||
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
|
||||
-I$(topsrcdir)/build \
|
||||
-I$(topsrcdir)/build/mobile \
|
||||
$(testxpcsrcdir)/remotexpcshelltests.py \
|
||||
--symbols-path=$(DIST)/crashreporter-symbols \
|
||||
--build-info-json=$(DEPTH)/mozinfo.json \
|
||||
--test-path=$(SOLO_FILE) \
|
||||
--profile-name=$(MOZ_APP_NAME) \
|
||||
--verbose \
|
||||
$(EXTRA_TEST_ARGS) \
|
||||
--dm_trans=$(DM_TRANS) \
|
||||
--deviceIP=${TEST_DEVICE} \
|
||||
--objdir=$(DEPTH) \
|
||||
--noSetup \
|
||||
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
|
||||
endif # XPCSHELL_TESTS
|
||||
|
||||
ifdef CPP_UNIT_TESTS
|
||||
@ -898,9 +929,6 @@ ifdef SHARED_LIBRARY
|
||||
$(SHARED_LIBRARY_NAME) $(DIST)/$(MOZ_APP_NAME)
|
||||
endif
|
||||
endif # SHARED_LIBRARY || PROGRAM
|
||||
else # ! WINNT_
|
||||
# Force rebuilding all objects on the second pass
|
||||
$(OBJS): FORCE
|
||||
endif # WINNT_
|
||||
endif # MOZ_PROFILE_USE
|
||||
ifdef MOZ_PROFILE_GENERATE
|
||||
|
79
configure.in
79
configure.in
@ -970,6 +970,7 @@ if test -n "$_WIN32_MSVC"; then
|
||||
AC_DEFINE(HAVE_IO_H)
|
||||
AC_DEFINE(HAVE_SETBUF)
|
||||
AC_DEFINE(HAVE_ISATTY)
|
||||
AC_DEFINE(HAVE_STDCALL)
|
||||
fi
|
||||
|
||||
fi # COMPILE_ENVIRONMENT
|
||||
@ -2107,6 +2108,8 @@ case "$target" in
|
||||
# logging code in nsObjCExceptions.h. Currently we only use that in debug
|
||||
# builds.
|
||||
MOZ_DEBUG_LDFLAGS="$MOZ_DEBUG_LDFLAGS -framework ExceptionHandling"
|
||||
# Debug builds should always have frame pointers
|
||||
MOZ_DEBUG_FLAGS="-g -fno-omit-frame-pointer"
|
||||
|
||||
if test "x$lto_is_enabled" = "xyes"; then
|
||||
echo "Skipping -dead_strip because lto is enabled."
|
||||
@ -2253,6 +2256,8 @@ ia64*-hpux*)
|
||||
else
|
||||
MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fno-omit-frame-pointer"
|
||||
fi
|
||||
# Debug builds should always have frame pointers
|
||||
MOZ_DEBUG_FLAGS="-g -fno-omit-frame-pointer"
|
||||
;;
|
||||
|
||||
*-*linux*)
|
||||
@ -2278,7 +2283,8 @@ ia64*-hpux*)
|
||||
fi
|
||||
MOZ_PGO_OPTIMIZE_FLAGS="-O3 $MOZ_FRAMEPTR_FLAGS"
|
||||
MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks $MOZ_OPTIMIZE_SIZE_TWEAK $MOZ_FRAMEPTR_FLAGS"
|
||||
MOZ_DEBUG_FLAGS="-g"
|
||||
# Debug builds should always have frame pointers
|
||||
MOZ_DEBUG_FLAGS="-g -fno-omit-frame-pointer"
|
||||
fi
|
||||
|
||||
TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"'
|
||||
@ -2371,7 +2377,8 @@ ia64*-hpux*)
|
||||
CFLAGS="$CFLAGS -we4553"
|
||||
CXXFLAGS="$CXXFLAGS -we4553"
|
||||
LIBS="$LIBS kernel32.lib user32.lib gdi32.lib winmm.lib wsock32.lib advapi32.lib"
|
||||
MOZ_DEBUG_FLAGS='-Zi'
|
||||
# Debug builds should always have frame pointers
|
||||
MOZ_DEBUG_FLAGS='-Zi -Oy-'
|
||||
MOZ_DEBUG_LDFLAGS='-DEBUG -DEBUGTYPE:CV'
|
||||
WARNINGS_AS_ERRORS='-WX'
|
||||
# If we're building with --enable-profiling, we need -Oy-, which forces a frame pointer.
|
||||
@ -3588,53 +3595,6 @@ then
|
||||
LDFLAGS="${_PTHREAD_LDFLAGS} ${LDFLAGS}"
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl See if mmap sees writes
|
||||
dnl For cross compiling, just define it as no, which is a safe default
|
||||
dnl ========================================================
|
||||
AC_MSG_CHECKING(whether mmap() sees write()s)
|
||||
|
||||
changequote(,)
|
||||
mmap_test_prog='
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
char fname[] = "conftest.file";
|
||||
char zbuff[1024]; /* Fractional page is probably worst case */
|
||||
|
||||
int main() {
|
||||
char *map;
|
||||
int fd;
|
||||
int i;
|
||||
unlink(fname);
|
||||
fd = open(fname, O_RDWR | O_CREAT, 0660);
|
||||
if(fd<0) return 1;
|
||||
unlink(fname);
|
||||
write(fd, zbuff, sizeof(zbuff));
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
map = (char*)mmap(0, sizeof(zbuff), PROT_READ, MAP_SHARED, fd, 0);
|
||||
if(map==(char*)-1) return 2;
|
||||
for(i=0; fname[i]; i++) {
|
||||
int rc = write(fd, &fname[i], 1);
|
||||
if(map[i]!=fname[i]) return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
'
|
||||
changequote([,])
|
||||
|
||||
AC_TRY_RUN($mmap_test_prog , result="yes", result="no", result="yes")
|
||||
|
||||
AC_MSG_RESULT("$result")
|
||||
|
||||
if test "$result" = "no"; then
|
||||
AC_DEFINE(MMAP_MISSES_WRITES)
|
||||
fi
|
||||
|
||||
|
||||
dnl Checks for library functions.
|
||||
dnl ========================================================
|
||||
@ -4778,7 +4738,6 @@ MOZ_DISABLE_DOMCRYPTO=
|
||||
NSS_DISABLE_DBM=
|
||||
NECKO_WIFI=1
|
||||
NECKO_COOKIES=1
|
||||
NECKO_DISK_CACHE=1
|
||||
NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg"
|
||||
USE_ARM_KUSER=
|
||||
BUILD_CTYPES=1
|
||||
@ -5194,7 +5153,7 @@ incorrect])
|
||||
fi
|
||||
|
||||
MOZ_ENABLE_QTMOBILITY=
|
||||
PKG_CHECK_MODULES(_QTMOBILITY, QtSensors QtFeedback,
|
||||
PKG_CHECK_MODULES(_QTMOBILITY, QtSensors QtFeedback QtLocation,
|
||||
MOZ_ENABLE_QTMOBILITY=1,
|
||||
MOZ_ENABLE_QTMOBILITY=)
|
||||
if test "$MOZ_ENABLE_QTMOBILITY"; then
|
||||
@ -5202,12 +5161,13 @@ incorrect])
|
||||
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS $_QTMOBILITY_CFLAGS"
|
||||
MOZ_QT_LIBS="$MOZ_QT_LIBS $_QTMOBILITY_LIBS"
|
||||
else
|
||||
AC_CHECK_LIB(QtSensors QtFeedback, main, [
|
||||
AC_CHECK_LIB(QtSensors QtFeedback QtLocation, main, [
|
||||
MOZ_ENABLE_QTMOBILITY=1
|
||||
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtMobility"
|
||||
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtSensors"
|
||||
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtFeedback"
|
||||
MOZ_QT_LIBS="$MOZ_QT_LIBS -lQtSensors -lQtFeedback"
|
||||
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtLocation"
|
||||
MOZ_QT_LIBS="$MOZ_QT_LIBS -lQtSensors -lQtFeedback -lQtLocation"
|
||||
])
|
||||
fi
|
||||
if test "$MOZ_ENABLE_QTMOBILITY"; then
|
||||
@ -8764,19 +8724,6 @@ for p in $NECKO_PROTOCOLS; do
|
||||
AC_DEFINE_UNQUOTED(NECKO_PROTOCOL_$p)
|
||||
done
|
||||
|
||||
dnl
|
||||
dnl option to disable necko's disk cache
|
||||
dnl
|
||||
MOZ_ARG_DISABLE_BOOL(necko-disk-cache,
|
||||
[ --disable-necko-disk-cache
|
||||
Disable necko disk cache],
|
||||
NECKO_DISK_CACHE=,
|
||||
NECKO_DISK_CACHE=1)
|
||||
AC_SUBST(NECKO_DISK_CACHE)
|
||||
if test "$NECKO_DISK_CACHE"; then
|
||||
AC_DEFINE(NECKO_DISK_CACHE)
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl option to disable necko's wifi scanner
|
||||
dnl
|
||||
|
@ -118,8 +118,15 @@ interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager
|
||||
[notxpcom] nsIContent getOwnerContent();
|
||||
};
|
||||
|
||||
[scriptable, uuid(ed6522fd-ffb6-4920-b50d-cf629309616b)]
|
||||
interface nsIChromeFrameMessageManager : nsIFrameMessageManager
|
||||
[scriptable, uuid(6331bbca-2c9f-4766-b3c7-ae75554bf1ec)]
|
||||
interface nsITreeItemFrameMessageManager : nsIFrameMessageManager
|
||||
{
|
||||
readonly attribute unsigned long childCount;
|
||||
nsITreeItemFrameMessageManager getChildAt(in unsigned long aIndex);
|
||||
};
|
||||
|
||||
[scriptable, uuid(23e6ef7b-8cc5-4e8b-9391-453440a3b858)]
|
||||
interface nsIChromeFrameMessageManager : nsITreeItemFrameMessageManager
|
||||
{
|
||||
/*
|
||||
* Load a script in the (remote) frame. aURL must be the absolute URL.
|
||||
|
@ -95,6 +95,7 @@ CPPSRCS = \
|
||||
nsDOMAttribute.cpp \
|
||||
nsDOMAttributeMap.cpp \
|
||||
nsDOMBlobBuilder.cpp \
|
||||
nsDOMCaretPosition.cpp \
|
||||
nsDOMDocumentType.cpp \
|
||||
nsDOMEventTargetWrapperCache.cpp \
|
||||
nsDOMFile.cpp \
|
||||
|
77
content/base/src/nsDOMCaretPosition.cpp
Normal file
77
content/base/src/nsDOMCaretPosition.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
/* ***** 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.org.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brad Lassey <blassey@mozilla.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
#include "nsDOMCaretPosition.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsIDOMClassInfo.h"
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCaretPosition)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMCaretPosition)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMCaretPosition)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CaretPosition)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_1(nsDOMCaretPosition, mNode)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCaretPosition)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMCaretPosition)
|
||||
|
||||
DOMCI_DATA(CaretPosition, nsDOMCaretPosition)
|
||||
|
||||
|
||||
nsDOMCaretPosition::nsDOMCaretPosition(nsIDOMNode* aNode, PRUint32 aOffset)
|
||||
: mNode(aNode), mOffset(aOffset)
|
||||
{
|
||||
}
|
||||
|
||||
nsDOMCaretPosition::~nsDOMCaretPosition()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDOMCaretPosition::GetOffsetNode(nsIDOMNode** aOffsetNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node = mNode;
|
||||
node.forget(aOffsetNode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDOMCaretPosition::GetOffset(PRUint32* aOffset)
|
||||
{
|
||||
*aOffset = mOffset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
59
content/base/src/nsDOMCaretPosition.h
Normal file
59
content/base/src/nsDOMCaretPosition.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* ***** 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.org.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brad Lassey <blassey@mozilla.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
#ifndef nsDOMCaretPosition_h
|
||||
#define nsDOMCaretPosition_h
|
||||
|
||||
#include "nsIDOMCaretPosition.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsDOMCaretPosition : public nsIDOMCaretPosition
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMCaretPosition)
|
||||
NS_DECL_NSIDOMCARETPOSITION
|
||||
|
||||
nsDOMCaretPosition(nsIDOMNode* aNode, PRUint32 aOffset);
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMCaretPosition();
|
||||
PRUint32 mOffset;
|
||||
nsCOMPtr<nsIDOMNode> mNode;
|
||||
};
|
||||
#endif
|
@ -202,9 +202,13 @@
|
||||
#include "nsDOMTouchEvent.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsFrame.h"
|
||||
|
||||
#include "imgILoader.h"
|
||||
|
||||
#include "nsDOMCaretPosition.h"
|
||||
#include "nsIDOMHTMLTextAreaElement.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
@ -8394,6 +8398,58 @@ nsDocument::CreateTouchList(nsIVariant* aPoints,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::CaretPositionFromPoint(float aX, float aY, nsIDOMCaretPosition** aCaretPos)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCaretPos);
|
||||
*aCaretPos = nsnull;
|
||||
|
||||
nscoord x = nsPresContext::CSSPixelsToAppUnits(aX);
|
||||
nscoord y = nsPresContext::CSSPixelsToAppUnits(aY);
|
||||
nsPoint pt(x, y);
|
||||
|
||||
nsIPresShell *ps = GetShell();
|
||||
if (!ps) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIFrame *rootFrame = ps->GetRootFrame();
|
||||
|
||||
// XUL docs, unlike HTML, have no frame tree until everything's done loading
|
||||
if (!rootFrame) {
|
||||
return NS_OK; // return null to premature XUL callers as a reminder to wait
|
||||
}
|
||||
|
||||
nsIFrame *ptFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, pt, PR_TRUE,
|
||||
PR_FALSE);
|
||||
if (!ptFrame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsFrame::ContentOffsets offsets = ptFrame->GetContentOffsetsFromPoint(pt);
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(offsets.content);
|
||||
nsIContent* ptContent = offsets.content;
|
||||
PRInt32 offset = offsets.offset;
|
||||
if (ptContent && ptContent->IsInNativeAnonymousSubtree()) {
|
||||
nsIContent* nonanon = ptContent->FindFirstNonNativeAnonymous();
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(nonanon);
|
||||
nsCOMPtr<nsIDOMHTMLTextAreaElement> textArea = do_QueryInterface(nonanon);
|
||||
PRBool isText;
|
||||
if (textArea || (input &&
|
||||
NS_SUCCEEDED(input->MozIsTextField(PR_FALSE, &isText)) &&
|
||||
isText)) {
|
||||
node = do_QueryInterface(nonanon);
|
||||
} else {
|
||||
node = nsnull;
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*aCaretPos = new nsDOMCaretPosition(node, offset);
|
||||
NS_ADDREF(*aCaretPos);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt64
|
||||
nsIDocument::SizeOf() const
|
||||
{
|
||||
|
@ -1791,7 +1791,7 @@ nsFrameLoader::TryRemoteBrowser()
|
||||
return false;
|
||||
}
|
||||
|
||||
ContentParent* parent = ContentParent::GetSingleton();
|
||||
ContentParent* parent = ContentParent::GetNewOrUsed();
|
||||
NS_ASSERTION(parent->IsAlive(), "Process parent should be alive; something is very wrong!");
|
||||
mRemoteBrowser = parent->CreateTab(chromeFlags);
|
||||
if (mRemoteBrowser) {
|
||||
|
@ -98,6 +98,8 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameMessageManager)
|
||||
!mChrome && !mIsProcessManager)
|
||||
/* Message managers in child process support nsISyncMessageSender. */
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISyncMessageSender, !mChrome)
|
||||
/* Message managers in chrome process support nsITreeItemFrameMessageManager. */
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITreeItemFrameMessageManager, mChrome)
|
||||
/* Process message manager doesn't support nsIChromeFrameMessageManager. */
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIChromeFrameMessageManager,
|
||||
mChrome && !mIsProcessManager)
|
||||
@ -323,6 +325,24 @@ nsFrameMessageManager::GetDocShell(nsIDocShell** aDocShell)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameMessageManager::GetChildCount(PRUint32* aChildCount)
|
||||
{
|
||||
*aChildCount = static_cast<PRUint32>(mChildManagers.Count());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameMessageManager::GetChildAt(PRUint32 aIndex,
|
||||
nsITreeItemFrameMessageManager** aMM)
|
||||
{
|
||||
*aMM = nsnull;
|
||||
nsCOMPtr<nsITreeItemFrameMessageManager> mm =
|
||||
do_QueryInterface(mChildManagers.SafeObjectAt(static_cast<PRUint32>(aIndex)));
|
||||
mm.swap(*aMM);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameMessageManager::Btoa(const nsAString& aBinaryData,
|
||||
nsAString& aAsciiBase64String)
|
||||
@ -823,7 +843,7 @@ bool SendAsyncMessageToChildProcess(void* aCallbackData,
|
||||
const nsAString& aJSON)
|
||||
{
|
||||
mozilla::dom::ContentParent* cp =
|
||||
mozilla::dom::ContentParent::GetSingleton(PR_FALSE);
|
||||
static_cast<mozilla::dom::ContentParent*>(aCallbackData);
|
||||
NS_WARN_IF_FALSE(cp, "No child process!");
|
||||
if (cp) {
|
||||
return cp->SendAsyncMessage(nsString(aMessage), nsString(aJSON));
|
||||
@ -857,6 +877,7 @@ bool SendAsyncMessageToParentProcess(void* aCallbackData,
|
||||
return true;
|
||||
}
|
||||
|
||||
// This creates the global parent process message manager.
|
||||
nsresult
|
||||
NS_NewParentProcessMessageManager(nsIFrameMessageManager** aResult)
|
||||
{
|
||||
@ -865,9 +886,9 @@ NS_NewParentProcessMessageManager(nsIFrameMessageManager** aResult)
|
||||
NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE);
|
||||
nsFrameMessageManager* mm = new nsFrameMessageManager(PR_TRUE,
|
||||
nsnull,
|
||||
SendAsyncMessageToChildProcess,
|
||||
nsnull,
|
||||
&nsFrameMessageManager::sParentProcessManager,
|
||||
nsnull,
|
||||
nsnull,
|
||||
nsnull,
|
||||
nsnull,
|
||||
PR_FALSE,
|
||||
@ -877,6 +898,25 @@ NS_NewParentProcessMessageManager(nsIFrameMessageManager** aResult)
|
||||
return CallQueryInterface(mm, aResult);
|
||||
}
|
||||
|
||||
nsFrameMessageManager*
|
||||
nsFrameMessageManager::NewProcessMessageManager(mozilla::dom::ContentParent* aProcess)
|
||||
{
|
||||
if (!nsFrameMessageManager::sParentProcessManager) {
|
||||
nsCOMPtr<nsIFrameMessageManager> dummy;
|
||||
NS_NewParentProcessMessageManager(getter_AddRefs(dummy));
|
||||
}
|
||||
|
||||
nsFrameMessageManager* mm = new nsFrameMessageManager(PR_TRUE,
|
||||
nsnull,
|
||||
SendAsyncMessageToChildProcess,
|
||||
nsnull,
|
||||
aProcess,
|
||||
nsFrameMessageManager::sParentProcessManager,
|
||||
nsnull,
|
||||
PR_FALSE,
|
||||
PR_TRUE);
|
||||
return mm;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
|
||||
|
@ -52,6 +52,12 @@
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
}
|
||||
}
|
||||
|
||||
class nsAXPCNativeCallContext;
|
||||
struct JSContext;
|
||||
struct JSObject;
|
||||
@ -125,6 +131,10 @@ public:
|
||||
NS_DECL_NSISYNCMESSAGESENDER
|
||||
NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
|
||||
NS_DECL_NSICHROMEFRAMEMESSAGEMANAGER
|
||||
NS_DECL_NSITREEITEMFRAMEMESSAGEMANAGER
|
||||
|
||||
static nsFrameMessageManager*
|
||||
NewProcessMessageManager(mozilla::dom::ContentParent* aProcess);
|
||||
|
||||
nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
|
||||
PRBool aSync, const nsAString& aJSON,
|
||||
|
@ -1059,8 +1059,9 @@ nsINode::AddEventListener(const nsAString& aType,
|
||||
|
||||
nsEventListenerManager* listener_manager = GetListenerManager(PR_TRUE);
|
||||
NS_ENSURE_STATE(listener_manager);
|
||||
return listener_manager->AddEventListener(aType, aListener, aUseCapture,
|
||||
aWantsUntrusted);
|
||||
listener_manager->AddEventListener(aType, aListener, aUseCapture,
|
||||
aWantsUntrusted);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -70,6 +70,7 @@ GK_ATOM(mozeditorbogusnode, "_moz_editor_bogus_node")
|
||||
GK_ATOM(mozgeneratedcontentbefore, "_moz_generated_content_before")
|
||||
GK_ATOM(mozgeneratedcontentafter, "_moz_generated_content_after")
|
||||
GK_ATOM(mozgeneratedcontentimage, "_moz_generated_content_image")
|
||||
GK_ATOM(_moz_original_size, "_moz_original_size")
|
||||
GK_ATOM(_moz_target, "_moz_target")
|
||||
GK_ATOM(_moz_type, "_moz-type")
|
||||
GK_ATOM(menuactive, "_moz-menuactive")
|
||||
@ -1873,6 +1874,7 @@ GK_ATOM(images_in_menus, "images-in-menus")
|
||||
GK_ATOM(images_in_buttons, "images-in-buttons")
|
||||
GK_ATOM(windows_default_theme, "windows-default-theme")
|
||||
GK_ATOM(mac_graphite_theme, "mac-graphite-theme")
|
||||
GK_ATOM(mac_lion_theme, "mac-lion-theme")
|
||||
GK_ATOM(windows_compositor, "windows-compositor")
|
||||
GK_ATOM(touch_enabled, "touch-enabled")
|
||||
GK_ATOM(maemo_classic, "maemo-classic")
|
||||
@ -1898,6 +1900,7 @@ GK_ATOM(_moz_images_in_menus, "-moz-images-in-menus")
|
||||
GK_ATOM(_moz_images_in_buttons, "-moz-images-in-buttons")
|
||||
GK_ATOM(_moz_windows_default_theme, "-moz-windows-default-theme")
|
||||
GK_ATOM(_moz_mac_graphite_theme, "-moz-mac-graphite-theme")
|
||||
GK_ATOM(_moz_mac_lion_theme, "-moz-mac-lion-theme")
|
||||
GK_ATOM(_moz_windows_compositor, "-moz-windows-compositor")
|
||||
GK_ATOM(_moz_windows_classic, "-moz-windows-classic")
|
||||
GK_ATOM(_moz_windows_theme, "-moz-windows-theme")
|
||||
|
@ -503,6 +503,7 @@ _TEST_FILES2 = \
|
||||
test_bug666604.html \
|
||||
test_bug675121.html \
|
||||
file_bug675121.sjs \
|
||||
test_bug654352.html \
|
||||
$(NULL)
|
||||
|
||||
_CHROME_FILES = \
|
||||
|
50
content/base/test/test_bug654352.html
Normal file
50
content/base/test/test_bug654352.html
Normal file
@ -0,0 +1,50 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=654352
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 654352</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=654352">Mozilla Bug 654352</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 654352 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
function afterLoad() {
|
||||
var testpre = document.getElementById("testpre");
|
||||
var rect1 = testpre.getBoundingClientRect();
|
||||
dump(rect1 + "\n");
|
||||
var caret1 = document.caretPositionFromPoint(rect1.right - 5, rect1.top + 10);
|
||||
ok(caret1.offsetNode == testpre.firstChild, "node in CaretPosition not correct (" + caret1.offsetNode + " == " + testpre.firstChild + ")")
|
||||
ok(caret1.offset == 9, "offset in CaretPosition not correct (" + caret1.offset + "== 9)")
|
||||
|
||||
var testinput = document.getElementById("testinput");
|
||||
var rect2 = testinput.getBoundingClientRect();
|
||||
dump(rect2.top +", " + rect2.left + "\n");
|
||||
var caret2 = document.caretPositionFromPoint( rect2.right - 5, rect2.top + 10);
|
||||
ok(caret2.offsetNode == testinput, "node in CaretPosition not correct (" + caret2.offsetNode + " == " + testinput + ")")
|
||||
ok(caret2.offset == 9, "offset in CaretPosition not correct (" + caret2.offset + "== 9)")
|
||||
SimpleTest.finish();
|
||||
};
|
||||
addLoadEvent(afterLoad);
|
||||
</script>
|
||||
</pre>
|
||||
<span id="testdiv">
|
||||
<pre id="testpre">test text</pre>
|
||||
</span>
|
||||
<br>
|
||||
<br>
|
||||
</div>
|
||||
<input id="testinput" type="text" value="test text"></input>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -53,8 +53,8 @@ function testCopyPaste () {
|
||||
|
||||
function copySelectionToClipboard() {
|
||||
documentViewer.copySelection();
|
||||
is(clipboard.hasDataMatchingFlavors(["text/unicode"], 1,1), true);
|
||||
is(clipboard.hasDataMatchingFlavors(["text/html"], 1,1), true);
|
||||
ok(clipboard.hasDataMatchingFlavors(["text/unicode"], 1,1), "check text/unicode");
|
||||
ok(clipboard.hasDataMatchingFlavors(["text/html"], 1,1), "check text/html");
|
||||
}
|
||||
function copyToClipboard(node) {
|
||||
textarea.blur();
|
||||
|
@ -126,7 +126,8 @@ nsDOMEventTargetHelper::AddEventListener(const nsAString& aType,
|
||||
|
||||
nsEventListenerManager* elm = GetListenerManager(PR_TRUE);
|
||||
NS_ENSURE_STATE(elm);
|
||||
return elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
|
||||
elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -103,9 +103,11 @@ nsDOMMessageEvent::UnrootData()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMMessageEvent::GetData(jsval* aData)
|
||||
nsDOMMessageEvent::GetData(JSContext* aCx, jsval* aData)
|
||||
{
|
||||
*aData = mData;
|
||||
if (!JS_WrapValue(aCx, aData))
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -209,14 +209,17 @@ nsEventListenerManager::GetInnerWindowForTarget()
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener,
|
||||
PRUint32 aType,
|
||||
nsIAtom* aTypeAtom,
|
||||
PRInt32 aFlags)
|
||||
{
|
||||
NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(aType, NS_ERROR_FAILURE);
|
||||
NS_ABORT_IF_FALSE(aType && aTypeAtom, "Missing type");
|
||||
|
||||
if (!aListener) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<nsIDOMEventListener> kungFuDeathGrip = aListener;
|
||||
|
||||
@ -226,7 +229,7 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener,
|
||||
ls = &mListeners.ElementAt(i);
|
||||
if (ls->mListener == aListener && ls->mFlags == aFlags &&
|
||||
EVENT_TYPE_EQUALS(ls, aType, aTypeAtom)) {
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,8 +294,6 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener,
|
||||
if (window)
|
||||
window->SetHasTouchEventListeners();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
@ -334,14 +335,14 @@ ListenerCanHandle(nsListenerStruct* aLs, nsEvent* aEvent)
|
||||
(aLs->mEventType == aEvent->message);
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsEventListenerManager::AddEventListenerByType(nsIDOMEventListener *aListener,
|
||||
const nsAString& aType,
|
||||
PRInt32 aFlags)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aType);
|
||||
PRUint32 type = nsContentUtils::GetEventId(atom);
|
||||
return AddEventListener(aListener, type, atom, aFlags);
|
||||
AddEventListener(aListener, type, atom, aFlags);
|
||||
}
|
||||
|
||||
void
|
||||
@ -943,8 +944,7 @@ nsEventListenerManager::Disconnect()
|
||||
RemoveAllListeners();
|
||||
}
|
||||
|
||||
// nsIDOMEventTarget interface
|
||||
nsresult
|
||||
void
|
||||
nsEventListenerManager::AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture,
|
||||
|
@ -84,10 +84,10 @@ public:
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsEventListenerManager)
|
||||
|
||||
nsresult AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture,
|
||||
PRBool aWantsUntrusted);
|
||||
void AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture,
|
||||
PRBool aWantsUntrusted);
|
||||
void RemoveEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture);
|
||||
@ -96,9 +96,9 @@ public:
|
||||
* Sets events listeners of all types.
|
||||
* @param an event listener
|
||||
*/
|
||||
nsresult AddEventListenerByType(nsIDOMEventListener *aListener,
|
||||
const nsAString& type,
|
||||
PRInt32 aFlags);
|
||||
void AddEventListenerByType(nsIDOMEventListener *aListener,
|
||||
const nsAString& type,
|
||||
PRInt32 aFlags);
|
||||
void RemoveEventListenerByType(nsIDOMEventListener *aListener,
|
||||
const nsAString& type,
|
||||
PRInt32 aFlags);
|
||||
@ -210,10 +210,10 @@ protected:
|
||||
void *aScopeGlobal,
|
||||
nsIAtom* aName, PRBool aIsString,
|
||||
PRBool aPermitUntrustedEvents);
|
||||
nsresult AddEventListener(nsIDOMEventListener *aListener,
|
||||
PRUint32 aType,
|
||||
nsIAtom* aTypeAtom,
|
||||
PRInt32 aFlags);
|
||||
void AddEventListener(nsIDOMEventListener *aListener,
|
||||
PRUint32 aType,
|
||||
nsIAtom* aTypeAtom,
|
||||
PRInt32 aFlags);
|
||||
void RemoveEventListener(nsIDOMEventListener *aListener,
|
||||
PRUint32 aType,
|
||||
nsIAtom* aUserType,
|
||||
|
@ -280,7 +280,8 @@ nsEventListenerService::AddSystemEventListener(nsIDOMEventTarget *aTarget,
|
||||
NS_EVENT_FLAG_SYSTEM_EVENT :
|
||||
NS_EVENT_FLAG_BUBBLE |
|
||||
NS_EVENT_FLAG_SYSTEM_EVENT;
|
||||
return manager->AddEventListenerByType(aListener, aType, flags);
|
||||
manager->AddEventListenerByType(aListener, aType, flags);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -107,6 +107,8 @@ _TEST_FILES = \
|
||||
test_bug662678.html \
|
||||
test_bug667919-1.html \
|
||||
test_bug667919-2.html \
|
||||
test_bug667612.html \
|
||||
empty.js \
|
||||
$(NULL)
|
||||
|
||||
#bug 585630
|
||||
@ -135,6 +137,8 @@ _CHROME_FILES = \
|
||||
test_bug602962.xul \
|
||||
test_bug617528.xul \
|
||||
window_bug617528.xul \
|
||||
test_bug679494.xul \
|
||||
file_bug679494.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
0
content/events/test/empty.js
Normal file
0
content/events/test/empty.js
Normal file
8
content/events/test/file_bug679494.html
Normal file
8
content/events/test/file_bug679494.html
Normal file
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Bug 679494</title>
|
||||
</head>
|
||||
<body>
|
||||
There and back again.
|
||||
</body>
|
||||
</html>
|
39
content/events/test/test_bug667612.html
Normal file
39
content/events/test/test_bug667612.html
Normal file
@ -0,0 +1,39 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=667612
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 667612</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=667612">Mozilla Bug 667612</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
xhr = new XMLHttpRequest;
|
||||
w = new Worker("empty.js");
|
||||
window.addEventListener("load", null, false);
|
||||
document.addEventListener("load", null, false);
|
||||
document.body.addEventListener("load", null, false);
|
||||
xhr.addEventListener("load", null, false);
|
||||
w.addEventListener("load", null, false);
|
||||
window.addEventListener("load", undefined, false);
|
||||
document.addEventListener("load", undefined, false);
|
||||
document.body.addEventListener("load", undefined, false);
|
||||
xhr.addEventListener("load", undefined, false);
|
||||
w.addEventListener("load", undefined, false);
|
||||
|
||||
ok(true, "didn't throw");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
37
content/events/test/test_bug679494.xul
Normal file
37
content/events/test/test_bug679494.xul
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=67949
|
||||
-->
|
||||
<window title="Mozilla Bug 67949" onload="doTest();"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<title>Test for Bug 67949</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=67949">Mozilla Bug 67949</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<iframe id="contentframe" src="http://mochi.test:8888/tests/content/event/test/file_679494.html"></iframe>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script class="testbody" type="application/javascript;version=1.8"><![CDATA[
|
||||
|
||||
/* Test for bug 679494 */
|
||||
function doTest() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var w = document.getElementById("contentframe").contentWindow;
|
||||
w.addEventListener("message", function(e) {
|
||||
is("test", e.data, "We got the data without a compartment mismatch assertion!");
|
||||
SimpleTest.finish();
|
||||
}, false);
|
||||
w.postMessage("test", "*");
|
||||
}
|
||||
|
||||
]]></script>
|
||||
|
||||
</window>
|
@ -36,6 +36,7 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "nsIDOMHTMLTableCellElement.h"
|
||||
#include "nsIDOMHTMLTableRowElement.h"
|
||||
#include "nsHTMLTableElement.h"
|
||||
#include "nsIDOMHTMLCollection.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsMappedAttributes.h"
|
||||
@ -44,6 +45,7 @@
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsRuleData.h"
|
||||
#include "nsRuleWalker.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "celldata.h"
|
||||
|
||||
@ -203,19 +205,15 @@ nsHTMLTableCellElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
|
||||
nsresult rv = nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Add style information from the mapped attributes of the table
|
||||
// element. This depends on the strange behavior of the
|
||||
// |MapAttributesIntoRule| in nsHTMLTableElement.cpp, which is
|
||||
// technically incorrect since it's violating the nsIStyleRule
|
||||
// contract. However, things are OK (except for the incorrect
|
||||
// dependence on display type rather than tag) since tables and cells
|
||||
// match different, less specific, rules.
|
||||
nsIContent* table = GetTable();
|
||||
if (table) {
|
||||
rv = table->WalkContentStyleRules(aRuleWalker);
|
||||
nsIContent* node = GetTable();
|
||||
if (node && node->IsHTML() && node->NodeInfo()->Equals(nsGkAtoms::table)) {
|
||||
nsHTMLTableElement* table = static_cast<nsHTMLTableElement*>(node);
|
||||
nsMappedAttributes* tableInheritedAttributes =
|
||||
table->GetAttributesMappedForCell();
|
||||
if (tableInheritedAttributes)
|
||||
aRuleWalker->Forward(tableInheritedAttributes);
|
||||
}
|
||||
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user