Bug 568691 - component registration changes for mobile-browser, r=mfinkle
|
@ -474,3 +474,8 @@ pref("font.default.x-western", "SwissA");
|
|||
// See bug 545869 for details on why these are set the way they are
|
||||
pref("network.buffer.cache.count", 24);
|
||||
pref("network.buffer.cache.size", 16384);
|
||||
|
||||
// sync service
|
||||
pref("services.sync.client.type", "mobile");
|
||||
pref("services.sync.registerEngines", "Tab,Bookmarks,Form,History,Password");
|
||||
pref("services.sync.autoconnectDelay", 5);
|
||||
|
|
|
@ -481,8 +481,6 @@ BrowserView.prototype = {
|
|||
this.updateScrolledArea(aMessage);
|
||||
break;
|
||||
}
|
||||
|
||||
return {};
|
||||
},
|
||||
|
||||
updateDirtyTiles: function updateDirtyTiles(aMessage) {
|
||||
|
|
|
@ -138,7 +138,6 @@ function InputHandler(browserViewContainer) {
|
|||
browserViewContainer.addEventListener("keydown", this, false);
|
||||
browserViewContainer.addEventListener("DOMMouseScroll", this, true);
|
||||
browserViewContainer.addEventListener("MozMousePixelScroll", this, true);
|
||||
browserViewContainer.addEventListener("contextmenu", this, true);
|
||||
|
||||
this.addModule(new MouseModule(this, browserViewContainer));
|
||||
this.addModule(new KeyModule(this, browserViewContainer));
|
||||
|
@ -355,13 +354,15 @@ function MouseModule(owner, browserViewContainer) {
|
|||
var self = this;
|
||||
this._kinetic = new KineticController(Util.bind(this._dragBy, this),
|
||||
Util.bind(this._kineticStop, this));
|
||||
|
||||
messageManager.addMessageListener("Browser:ContextMenu", this);
|
||||
}
|
||||
|
||||
|
||||
MouseModule.prototype = {
|
||||
handleEvent: function handleEvent(evInfo) {
|
||||
let evt = evInfo.event;
|
||||
if (evt.button !== 0 && evt.type != "contextmenu")
|
||||
if (evt.button !== 0)
|
||||
return;
|
||||
|
||||
switch (evt.type) {
|
||||
|
@ -374,17 +375,6 @@ MouseModule.prototype = {
|
|||
case "mouseup":
|
||||
this._onMouseUp(evInfo);
|
||||
break;
|
||||
case "contextmenu":
|
||||
// TODO: Make "contextmenu" a first class part of InputHandler
|
||||
// Bug 554639
|
||||
if (ContextHelper.popupNode) {
|
||||
if (this._clicker)
|
||||
this._clicker.panBegin();
|
||||
if (this._dragger)
|
||||
this._dragger.dragStop(0, 0, this._targetScrollInterface);
|
||||
this.cancelPending();
|
||||
}
|
||||
break;
|
||||
case "MozMagnifyGestureStart":
|
||||
case "MozMagnifyGesture":
|
||||
// disallow kinetic panning after gesture
|
||||
|
@ -394,6 +384,19 @@ MouseModule.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
receiveMessage: function receiveMessage(aMessage) {
|
||||
// TODO: Make "contextmenu" a first class part of InputHandler
|
||||
// Bug 554639
|
||||
if (aMessage.name != "Browser:ContextMenu" || !ContextHelper.popupState)
|
||||
return;
|
||||
|
||||
if (this._clicker)
|
||||
this._clicker.panBegin();
|
||||
if (this._dragger)
|
||||
this._dragger.dragStop(0, 0, this._targetScrollInterface);
|
||||
this.cancelPending();
|
||||
},
|
||||
|
||||
/**
|
||||
* This gets invoked by the input handler if another module grabs. We should
|
||||
* reset our state or something here. This is probably doing the wrong thing
|
||||
|
|
|
@ -114,9 +114,9 @@ let Util = {
|
|||
|
||||
let link = null;
|
||||
while (target) {
|
||||
if (target instanceof HTMLAnchorElement ||
|
||||
target instanceof HTMLAreaElement ||
|
||||
target instanceof HTMLLinkElement) {
|
||||
if (target instanceof Ci.nsIDOMHTMLAnchorElement ||
|
||||
target instanceof Ci.nsIDOMHTMLAreaElement ||
|
||||
target instanceof Ci.nsIDOMHTMLLinkElement) {
|
||||
if (target.hasAttribute("href"))
|
||||
link = target;
|
||||
}
|
||||
|
@ -129,9 +129,13 @@ let Util = {
|
|||
return null;
|
||||
},
|
||||
|
||||
makeURI: function makeURI(aURL, aOriginCharset, aBaseURI) {
|
||||
return gIOService.newURI(aURL, aOriginCharset, aBaseURI);
|
||||
},
|
||||
|
||||
makeURLAbsolute: function makeURLAbsolute(base, url) {
|
||||
// Note: makeURI() will throw if url is not a valid URI
|
||||
return makeURI(url, null, makeURI(base)).spec;
|
||||
return this.makeURI(url, null, this.makeURI(base)).spec;
|
||||
},
|
||||
|
||||
clamp: function(num, min, max) {
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
||||
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" [
|
||||
<!ENTITY % remoteTabsDTD SYSTEM "chrome://browser/locale/aboutTabs.dtd" >
|
||||
%remoteTabsDTD;
|
||||
]>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&remoteTabs.title;</title>
|
||||
<link rel="icon" type="image/png" href="chrome://branding/content/favicon32.png" />
|
||||
<link rel="stylesheet" href="chrome://browser/skin/aboutTabs.css" type="text/css"/>
|
||||
</head>
|
||||
<body onload="RemoteTabViewer.show();">
|
||||
<div id="tabList">
|
||||
</div>
|
||||
|
||||
<script type="application/javascript;version=1.8"><![CDATA[
|
||||
// Make sure this is the only instance of the page
|
||||
Components.utils.import("resource://services-sync/service.js");
|
||||
Weave.Utils.ensureOneOpen(window);
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
let RemoteTabViewer = {
|
||||
get chromeWin() {
|
||||
let chromeWin = window.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShellTreeItem).
|
||||
rootTreeItem.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindow).QueryInterface(Ci.nsIDOMChromeWindow);
|
||||
|
||||
delete this.chromeWin;
|
||||
return this.chromeWin = chromeWin;
|
||||
},
|
||||
|
||||
show: function RemoteTabViewer_show() {
|
||||
// Don't do anything if the tabs engine isn't ready
|
||||
if (!Weave.Engines.get("tabs"))
|
||||
return;
|
||||
|
||||
this._maybeNotify();
|
||||
this._populateTabs();
|
||||
this._refetchTabs();
|
||||
},
|
||||
|
||||
_maybeNotify: function _maybeNotify() {
|
||||
// Don't notify if the tab engine has new tabs or the user dismissed it
|
||||
let prefs = Weave.Svc.Prefs;
|
||||
if (prefs.get("notifyTabState") == 0)
|
||||
return;
|
||||
|
||||
// No need to reshow the notification if it's still open
|
||||
let notifyBox = this.chromeWin.getNotificationBox(window);
|
||||
if (notifyBox.getNotificationWithValue("remote-tabs") != null)
|
||||
return;
|
||||
|
||||
let message = Weave.Str.sync.get("remote.notification.label");
|
||||
let notification = notifyBox.appendNotification(message, "remote-tabs", "",
|
||||
notifyBox.PRIORITY_INFO_LOW);
|
||||
|
||||
// Wrap the close function to find out if the user clicks the X
|
||||
let close = notification.close;
|
||||
notification.close = function() {
|
||||
// Once the user dismisses the dialog, remember that and don't show again
|
||||
prefs.set("notifyTabState", 0);
|
||||
close.apply(notification, arguments);
|
||||
};
|
||||
},
|
||||
|
||||
_refetchTabs: function _refetchTabs() {
|
||||
// Don't bother refetching tabs if we already did so recently
|
||||
let lastFetch = Weave.Svc.Prefs.get("lastTabFetch", 0);
|
||||
let now = Math.floor(Date.now() / 1000);
|
||||
if (now - lastFetch < 30)
|
||||
return;
|
||||
|
||||
// Asynchronously fetch the tabs
|
||||
setTimeout(function() {
|
||||
let engine = Weave.Engines.get("tabs");
|
||||
let lastSync = engine.lastSync;
|
||||
|
||||
// Force a sync only for the tabs engine
|
||||
engine.lastModified = null;
|
||||
engine.sync();
|
||||
Weave.Svc.Prefs.set("lastTabFetch", now);
|
||||
|
||||
// Only reload the page if something synced
|
||||
if (engine.lastSync != lastSync)
|
||||
location.reload();
|
||||
}, 0);
|
||||
},
|
||||
|
||||
_populateTabs: function _populateTabs() {
|
||||
// Clear out all child elements from holder first, so we don't
|
||||
// end up adding duplicate rows.
|
||||
let engine = Weave.Engines.get("tabs");
|
||||
let holder = document.getElementById("tabList");
|
||||
if (holder.hasChildNodes()) {
|
||||
while (holder.childNodes.length >= 1)
|
||||
holder.removeChild(holder.firstChild);
|
||||
}
|
||||
|
||||
// Generate the list of tabs
|
||||
let haveTabs = false;
|
||||
for (let [guid, client] in Iterator(engine.getAllClients())) {
|
||||
haveTabs = true;
|
||||
|
||||
// Create the client node, but don't add it in-case we don't show any tabs
|
||||
let appendClient = true;
|
||||
let nameNode = document.createElement("h2");
|
||||
nameNode.textContent = client.clientName;
|
||||
|
||||
client.tabs.forEach(function({title, urlHistory, icon}) {
|
||||
let pageUrl = urlHistory[0];
|
||||
|
||||
// Skip tabs that are already open
|
||||
if (engine.locallyOpenTabMatchesURL(pageUrl))
|
||||
return;
|
||||
|
||||
if (title == "")
|
||||
title = pageUrl;
|
||||
|
||||
let item = document.createElement("div");
|
||||
item.addEventListener("click", function() {
|
||||
item.setAttribute("selected", true);
|
||||
RemoteTabViewer.chromeWin.BrowserUI.newTab(pageUrl);
|
||||
}, false)
|
||||
item.setAttribute("class", "tab");
|
||||
|
||||
let img = document.createElement("img");
|
||||
img.setAttribute("class", "icon");
|
||||
img.src = Weave.Utils.getIcon(icon, "chrome://browser/skin/images/tab.png");
|
||||
|
||||
let tabDiv = document.createElement("div");
|
||||
tabDiv.setAttribute("class", "info");
|
||||
let titleNode = document.createElement("div");
|
||||
titleNode.setAttribute("class", "title");
|
||||
titleNode.textContent = title;
|
||||
let urlNode = document.createElement("div");
|
||||
urlNode.setAttribute("class", "url");
|
||||
urlNode.textContent = pageUrl;
|
||||
tabDiv.appendChild(titleNode);
|
||||
tabDiv.appendChild(urlNode);
|
||||
|
||||
item.appendChild(img);
|
||||
item.appendChild(tabDiv);
|
||||
|
||||
// Append the client name if we haven't yet
|
||||
if (appendClient) {
|
||||
appendClient = false;
|
||||
holder.appendChild(nameNode);
|
||||
}
|
||||
|
||||
holder.appendChild(item);
|
||||
});
|
||||
}
|
||||
|
||||
if (holder.childNodes.length == 0) {
|
||||
// Assume we're pending, but we might already have tabs or have synced
|
||||
let text = Weave.Str.sync.get("remote.pending.label");
|
||||
if (haveTabs)
|
||||
text = Weave.Str.sync.get("remote.opened.label");
|
||||
else if (engine.lastSync != 0)
|
||||
text = Weave.Str.sync.get("remote.missing.label");
|
||||
|
||||
let item = document.createElement("h1");
|
||||
item.textContent = text;
|
||||
document.getElementsByTagName('body')[0].appendChild(item);
|
||||
}
|
||||
}
|
||||
};
|
||||
]]></script>
|
||||
</body>
|
||||
</html>
|
|
@ -255,7 +255,7 @@
|
|||
let title = controller.getCommentAt(i);
|
||||
let tags = '';
|
||||
|
||||
if (type == "tag")
|
||||
if (title && type == "tag")
|
||||
[, title, tags] = title.match(/^(.+) \u2013 (.+)$/);
|
||||
item.setAttribute("tags", tags);
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@
|
|||
let link = aMessage.json;
|
||||
// ignore results from subdocuments
|
||||
if (link.windowId != this.contentWindowId)
|
||||
return {};
|
||||
return;
|
||||
|
||||
let linkType = this._getLinkType(link);
|
||||
switch(linkType) {
|
||||
|
@ -135,8 +135,6 @@
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return {};
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
|
@ -274,8 +272,6 @@
|
|||
args);
|
||||
break;
|
||||
}
|
||||
|
||||
return {};
|
||||
},
|
||||
|
||||
_notify: function(aFlags, aName, aArguments) {
|
||||
|
@ -406,6 +402,27 @@
|
|||
|
||||
<field name="_webNavigation"><![CDATA[
|
||||
({
|
||||
LOAD_FLAGS_MASK: 65535,
|
||||
LOAD_FLAGS_NONE: 0,
|
||||
LOAD_FLAGS_IS_REFRESH: 16,
|
||||
LOAD_FLAGS_IS_LINK: 32,
|
||||
LOAD_FLAGS_BYPASS_HISTORY: 64,
|
||||
LOAD_FLAGS_REPLACE_HISTORY: 128,
|
||||
LOAD_FLAGS_BYPASS_CACHE: 256,
|
||||
LOAD_FLAGS_BYPASS_PROXY: 512,
|
||||
LOAD_FLAGS_CHARSET_CHANGE: 1024,
|
||||
LOAD_FLAGS_STOP_CONTENT: 2048,
|
||||
LOAD_FLAGS_FROM_EXTERNAL: 4096,
|
||||
LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP: 8192,
|
||||
LOAD_FLAGS_FIRST_LOAD: 16384,
|
||||
LOAD_FLAGS_ALLOW_POPUPS: 32768,
|
||||
LOAD_FLAGS_BYPASS_CLASSIFIER: 65536,
|
||||
LOAD_FLAGS_FORCE_ALLOW_COOKIES: 131072,
|
||||
|
||||
STOP_NETWORK: 1,
|
||||
STOP_CONTENT: 2,
|
||||
STOP_ALL: 3,
|
||||
|
||||
canGoBack: false,
|
||||
canGoForward: false,
|
||||
goBack: function() { this._sendMessage("WebNavigation:GoBack", {}); },
|
||||
|
@ -438,6 +455,12 @@
|
|||
catch (e) {
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: function(aIID) {
|
||||
if (aIID.equals(Components.interfaces.nsIWebNavigation) || aIID.equals(Components.interfaces.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
}
|
||||
})
|
||||
]]></field>
|
||||
|
@ -565,8 +588,6 @@
|
|||
args);
|
||||
break;
|
||||
}
|
||||
|
||||
return {};
|
||||
},
|
||||
|
||||
_notify: function(aFlags, aName, aArguments) {
|
||||
|
|
|
@ -119,8 +119,6 @@ var BrowserUI = {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return { };
|
||||
},
|
||||
|
||||
_titleChanged : function(aBrowser) {
|
||||
|
@ -150,8 +148,6 @@ var BrowserUI = {
|
|||
return { preventDefault: true };
|
||||
}
|
||||
}
|
||||
|
||||
return { };
|
||||
},
|
||||
|
||||
_updateButtons : function(aBrowser) {
|
||||
|
@ -388,9 +384,10 @@ var BrowserUI = {
|
|||
messageManager.addMessageListener("DOMWillOpenModalDialog", this);
|
||||
messageManager.addMessageListener("DOMWindowClose", this);
|
||||
|
||||
// listen returns messages from content
|
||||
messageManager.addMessageListener("Browser:SaveAs:Return", this);
|
||||
messageManager.addMessageListener("Browser:Highlight", this);
|
||||
messageManager.addMessageListener("Browser:OpenURI", this);
|
||||
messageManager.addMessageListener("Browser:ContextMenu", ContextHelper);
|
||||
messageManager.addMessageListener("Browser:SaveAs:Return", this);
|
||||
|
||||
// listening mousedown for automatically dismiss some popups (e.g. larry)
|
||||
window.addEventListener("mousedown", this, true);
|
||||
|
@ -415,6 +412,9 @@ var BrowserUI = {
|
|||
DownloadsView.init();
|
||||
PreferencesView.init();
|
||||
ConsoleView.init();
|
||||
|
||||
// Init the sync system
|
||||
WeaveGlue.init();
|
||||
});
|
||||
|
||||
FormMessageReceiver.start();
|
||||
|
@ -815,9 +815,10 @@ var BrowserUI = {
|
|||
}
|
||||
TapHighlightHelper.show(rects);
|
||||
break;
|
||||
}
|
||||
|
||||
return {};
|
||||
case "Browser:OpenURI":
|
||||
Browser.addTab(json.uri, false, Browser.selectedTab);
|
||||
}
|
||||
},
|
||||
|
||||
supportsCommand : function(cmd) {
|
||||
|
@ -2003,135 +2004,40 @@ var SelectHelper = {
|
|||
const kXLinkNamespace = "http://www.w3.org/1999/xlink";
|
||||
|
||||
var ContextHelper = {
|
||||
popupNode: null,
|
||||
onLink: false,
|
||||
onSaveableLink: false,
|
||||
onVoiceLink: false,
|
||||
onImage: false,
|
||||
onLoadedImage: false,
|
||||
linkURL: "",
|
||||
linkProtocol: null,
|
||||
mediaURL: "",
|
||||
popupState: null,
|
||||
|
||||
_clearState: function ch_clearState() {
|
||||
this.popupNode = null;
|
||||
this.onLink = false;
|
||||
this.onSaveableLink = false;
|
||||
this.onVoiceLink = false;
|
||||
this.onImage = false;
|
||||
this.onLoadedImage = false;
|
||||
this.linkURL = "";
|
||||
this.linkProtocol = null;
|
||||
this.mediaURL = "";
|
||||
},
|
||||
receiveMessage: function ch_receiveMessage(aMessage) {
|
||||
this.popupState = aMessage.json;
|
||||
this.popupState.browser = aMessage.target;
|
||||
|
||||
_getLinkURL: function ch_getLinkURL(aLink) {
|
||||
let href = aLink.href;
|
||||
if (href)
|
||||
return href;
|
||||
|
||||
href = aLink.getAttributeNS(kXLinkNamespace, "href");
|
||||
if (!href || !href.match(/\S/)) {
|
||||
// Without this we try to save as the current doc,
|
||||
// for example, HTML case also throws if empty
|
||||
throw "Empty href";
|
||||
}
|
||||
|
||||
return Util.makeURLAbsolute(aLink.baseURI, href);
|
||||
},
|
||||
|
||||
_getURI: function ch_getURI(aURL) {
|
||||
try {
|
||||
return makeURI(aURL);
|
||||
} catch (ex) { }
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
_getProtocol: function ch_getProtocol(aURI) {
|
||||
if (aURI)
|
||||
return aURI.scheme;
|
||||
return null;
|
||||
},
|
||||
|
||||
_isSaveable: function ch_isSaveable(aProtocol) {
|
||||
// We don't do the Right Thing for news/snews yet, so turn them off until we do
|
||||
return aProtocol && !(aProtocol == "mailto" || aProtocol == "javascript" || aProtocol == "news" || aProtocol == "snews");
|
||||
},
|
||||
|
||||
_isVoice: function ch_isVoice(aProtocol) {
|
||||
// Collection of protocols related to voice or data links
|
||||
return aProtocol && (aProtocol == "tel" || aProtocol == "callto" || aProtocol == "sip" || aProtocol == "voipto");
|
||||
},
|
||||
|
||||
handleEvent: function ch_handleEvent(aEvent) {
|
||||
this._clearState();
|
||||
|
||||
let [elementX, elementY] = Browser.transformClientToBrowser(aEvent.clientX, aEvent.clientY);
|
||||
this.popupNode = Browser.elementFromPoint(elementX, elementY);
|
||||
|
||||
// Do checks for nodes that never have children.
|
||||
if (this.popupNode.nodeType == Node.ELEMENT_NODE) {
|
||||
// See if the user clicked on an image.
|
||||
if (this.popupNode instanceof Ci.nsIImageLoadingContent && this.popupNode.currentURI) {
|
||||
this.onImage = true;
|
||||
this.mediaURL = this.popupNode.currentURI.spec;
|
||||
|
||||
let request = this.popupNode.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
|
||||
if (request && (request.imageStatus & request.STATUS_SIZE_AVAILABLE))
|
||||
this.onLoadedImage = true;
|
||||
}
|
||||
}
|
||||
|
||||
let elem = this.popupNode;
|
||||
while (elem) {
|
||||
if (elem.nodeType == Node.ELEMENT_NODE) {
|
||||
// Link?
|
||||
if (!this.onLink &&
|
||||
((elem instanceof HTMLAnchorElement && elem.href) ||
|
||||
(elem instanceof HTMLAreaElement && elem.href) ||
|
||||
elem instanceof HTMLLinkElement ||
|
||||
elem.getAttributeNS(kXLinkNamespace, "type") == "simple")) {
|
||||
|
||||
// Target is a link or a descendant of a link.
|
||||
this.linkURL = this._getLinkURL(elem);
|
||||
this.linkProtocol = this._getProtocol(this._getURI(this.linkURL));
|
||||
this.onLink = true;
|
||||
this.onSaveableLink = this._isSaveable(this.linkProtocol);
|
||||
this.onVoiceLink = this._isVoice(this.linkProtocol);
|
||||
}
|
||||
}
|
||||
|
||||
elem = elem.parentNode;
|
||||
}
|
||||
|
||||
let first = last = null;
|
||||
let first = null;
|
||||
let last = null;
|
||||
let commands = document.getElementById("context-commands");
|
||||
for (let i=0; i<commands.childElementCount; i++) {
|
||||
let command = commands.children[i];
|
||||
let types = command.getAttribute("type").split(/\s+/);
|
||||
command.removeAttribute("selector");
|
||||
if (types.indexOf("image") != -1 && this.onImage) {
|
||||
if (types.indexOf("image") != -1 && this.popupState.onImage) {
|
||||
first = (first ? first : command);
|
||||
last = command;
|
||||
command.hidden = false;
|
||||
continue;
|
||||
} else if (types.indexOf("image-loaded") != -1 && this.onLoadedImage) {
|
||||
} else if (types.indexOf("image-loaded") != -1 && this.popupState.onLoadedImage) {
|
||||
first = (first ? first : command);
|
||||
last = command;
|
||||
command.hidden = false;
|
||||
continue;
|
||||
} else if (types.indexOf("link") != -1 && this.onSaveableLink) {
|
||||
} else if (types.indexOf("link") != -1 && this.popupState.onSaveableLink) {
|
||||
first = (first ? first : command);
|
||||
last = command;
|
||||
command.hidden = false;
|
||||
continue;
|
||||
} else if (types.indexOf("callto") != -1 && this.onVoiceLink) {
|
||||
} else if (types.indexOf("callto") != -1 && this.popupState.onVoiceLink) {
|
||||
first = (first ? first : command);
|
||||
last = command;
|
||||
command.hidden = false;
|
||||
continue;
|
||||
} else if (types.indexOf("mailto") != -1 && this.onLink && this.linkProtocol == "mailto") {
|
||||
} else if (types.indexOf("mailto") != -1 && this.popupState.onLink && this.popupState.linkProtocol == "mailto") {
|
||||
first = (first ? first : command);
|
||||
last = command;
|
||||
command.hidden = false;
|
||||
|
@ -2141,7 +2047,7 @@ var ContextHelper = {
|
|||
}
|
||||
|
||||
if (!first) {
|
||||
this._clearState();
|
||||
this.popupState = null;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2149,10 +2055,10 @@ var ContextHelper = {
|
|||
last.setAttribute("selector", "last-child");
|
||||
|
||||
let label = document.getElementById("context-hint");
|
||||
if (this.onImage)
|
||||
label.value = this.mediaURL;
|
||||
if (this.onLink)
|
||||
label.value = this.linkURL;
|
||||
if (this.popupState.onImage)
|
||||
label.value = this.popupState.mediaURL;
|
||||
if (this.popupState.onLink)
|
||||
label.value = this.popupState.linkURL;
|
||||
|
||||
let container = document.getElementById("context-popup");
|
||||
container.hidden = false;
|
||||
|
@ -2176,7 +2082,7 @@ var ContextHelper = {
|
|||
},
|
||||
|
||||
hide: function ch_hide() {
|
||||
this._clearState();
|
||||
this.popupState = null;
|
||||
|
||||
let container = document.getElementById("context-popup");
|
||||
container.hidden = true;
|
||||
|
@ -2187,12 +2093,12 @@ var ContextHelper = {
|
|||
|
||||
var ContextCommands = {
|
||||
openInNewTab: function cc_openInNewTab(aEvent) {
|
||||
Browser.addTab(ContextHelper.linkURL, false, Browser.selectedTab);
|
||||
Browser.addTab(ContextHelper.popupState.linkURL, false, Browser.selectedTab);
|
||||
},
|
||||
|
||||
saveImage: function cc_saveImage(aEvent) {
|
||||
let doc = ContextHelper.popupNode.ownerDocument;
|
||||
saveImageURL(ContextHelper.mediaURL, null, "SaveImageTitle", false, false, doc.documentURIObject);
|
||||
let browser = ContextHelper.popupState.browser;
|
||||
saveImageURL(ContextHelper.popupState.mediaURL, null, "SaveImageTitle", false, false, browser.documentURI);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -476,14 +476,11 @@ var Browser = {
|
|||
notifications.addEventListener("AlertActive", notificationHandler, false);
|
||||
notifications.addEventListener("AlertClose", notificationHandler, false);
|
||||
|
||||
// Add context helper to the content area only
|
||||
container.addEventListener("contextmenu", ContextHelper, false);
|
||||
BrowserUI.init();
|
||||
|
||||
// initialize input handling
|
||||
ih = new InputHandler(container);
|
||||
|
||||
BrowserUI.init();
|
||||
|
||||
window.controllers.appendController(this);
|
||||
window.controllers.appendController(BrowserUI);
|
||||
|
||||
|
@ -691,7 +688,8 @@ var Browser = {
|
|||
if (aScrollY != 0)
|
||||
Browser.hideTitlebar();
|
||||
|
||||
Browser.contentScrollboxScroller.scrollTo(aScrollX, aScrollY);
|
||||
let zoomLevel = this._browserView.getZoomLevel();
|
||||
Browser.contentScrollboxScroller.scrollTo(aScrollX*zoomLevel, aScrollY*zoomLevel);
|
||||
this._browserView.onAfterVisibleMove();
|
||||
},
|
||||
|
||||
|
@ -1277,7 +1275,10 @@ var Browser = {
|
|||
switch (aMessage.name) {
|
||||
case "Browser:ViewportMetadata":
|
||||
let tab = Browser.getTabForBrowser(aMessage.target);
|
||||
tab.updateViewportMetadata(json);
|
||||
// Some browser such as iframes loaded dynamically into the chrome UI
|
||||
// does not have any assigned tab
|
||||
if (tab)
|
||||
tab.updateViewportMetadata(json);
|
||||
break;
|
||||
|
||||
case "Browser:FormSubmit":
|
||||
|
@ -1304,14 +1305,8 @@ Browser.MainDragger.prototype = {
|
|||
isDraggable: function isDraggable(target, scroller) { return true; },
|
||||
|
||||
dragStart: function dragStart(clientX, clientY, target, scroller) {
|
||||
// Make sure pausing occurs before any early returns.
|
||||
this.bv.pauseRendering();
|
||||
|
||||
// XXX shouldn't know about observer
|
||||
// adding pause in pauseRendering isn't so great, because tiles will hardly ever prefetch while
|
||||
// loading state is going (and already, the idle timer is bigger during loading so it doesn't fit
|
||||
// into the aggressive flag).
|
||||
this.bv._idleServiceObserver.pause();
|
||||
this._nextRender = Date.now() + 500;
|
||||
this._dragMoved = false;
|
||||
},
|
||||
|
||||
dragStop: function dragStop(dx, dy, scroller) {
|
||||
|
@ -1320,15 +1315,17 @@ Browser.MainDragger.prototype = {
|
|||
|
||||
Browser.tryUnfloatToolbar();
|
||||
|
||||
this.bv.resumeRendering();
|
||||
|
||||
// XXX shouldn't know about observer
|
||||
this.bv._idleServiceObserver.resume();
|
||||
if (this._dragMoved)
|
||||
this.bv.resumeRendering();
|
||||
},
|
||||
|
||||
dragMove: function dragMove(dx, dy, scroller) {
|
||||
let doffset = new Point(dx, dy);
|
||||
let render = false;
|
||||
|
||||
if (!this._dragMoved) {
|
||||
this._dragMoved = true;
|
||||
this.bv.pauseRendering();
|
||||
}
|
||||
|
||||
// First calculate any panning to take sidebars out of view
|
||||
let panOffset = this._panControlsAwayOffset(doffset);
|
||||
|
@ -1345,8 +1342,10 @@ Browser.MainDragger.prototype = {
|
|||
|
||||
this.bv.onAfterVisibleMove();
|
||||
|
||||
if (render)
|
||||
if (Date.now() >= this._nextRender) {
|
||||
this.bv.renderNow();
|
||||
this._nextRender = Date.now() + 500;
|
||||
}
|
||||
|
||||
return !doffset.equals(dx, dy);
|
||||
},
|
||||
|
@ -1555,10 +1554,13 @@ function ContentCustomClicker(browserView) {
|
|||
}
|
||||
|
||||
ContentCustomClicker.prototype = {
|
||||
_dispatchMouseEvent: function _dispatchMouseEvent(aName, aX, aY) {
|
||||
_dispatchMouseEvent: function _dispatchMouseEvent(aName, aX, aY, aModifiers) {
|
||||
let aX = aX || 0;
|
||||
let aY = aY || 0;
|
||||
let aModifiers = aModifiers || null;
|
||||
let browser = this._browserView.getBrowser();
|
||||
let [x, y] = Browser.transformClientToBrowser(aX, aY);
|
||||
browser.messageManager.sendAsyncMessage(aName, { x: x, y: y });
|
||||
browser.messageManager.sendAsyncMessage(aName, { x: x, y: y, modifiers: aModifiers });
|
||||
},
|
||||
|
||||
mouseDown: function mouseDown(aX, aY) {
|
||||
|
@ -1576,33 +1578,30 @@ ContentCustomClicker.prototype = {
|
|||
|
||||
panBegin: function panBegin() {
|
||||
TapHighlightHelper.hide();
|
||||
let browser = this._browserView.getBrowser();
|
||||
browser.messageManager.sendAsyncMessage("Browser:MouseCancel", {});
|
||||
|
||||
this._dispatchMouseEvent("Browser:MouseCancel");
|
||||
},
|
||||
|
||||
singleClick: function singleClick(aX, aY, aModifiers) {
|
||||
TapHighlightHelper.hide();
|
||||
this._dispatchMouseEvent("Browser:MouseUp", aX, aY);
|
||||
// TODO e10s: handle modifiers for clicks
|
||||
//
|
||||
// if (modifiers == Ci.nsIDOMNSEvent.CONTROL_MASK) {
|
||||
// let uri = Util.getHrefForElement(element);
|
||||
// if (uri)
|
||||
// Browser.addTab(uri, false);
|
||||
// }
|
||||
|
||||
// Cancel the mouse click if we are showing a context menu
|
||||
if (!ContextHelper.popupState)
|
||||
this._dispatchMouseEvent("Browser:MouseUp", aX, aY, aModifiers);
|
||||
this._dispatchMouseEvent("Browser:MouseCancel");
|
||||
},
|
||||
|
||||
doubleClick: function doubleClick(aX1, aY1, aX2, aY2) {
|
||||
TapHighlightHelper.hide();
|
||||
let browser = this._browserView.getBrowser();
|
||||
browser.messageManager.sendAsyncMessage("Browser:MouseCancel", {});
|
||||
|
||||
this._dispatchMouseEvent("Browser:MouseCancel");
|
||||
|
||||
const kDoubleClickRadius = 32;
|
||||
|
||||
let maxRadius = kDoubleClickRadius * Browser._browserView.getZoomLevel();
|
||||
let isClickInRadius = (Math.abs(aX1 - aX2) < maxRadius && Math.abs(aY1 - aY2) < maxRadius);
|
||||
if (isClickInRadius)
|
||||
browser.messageManager.sendAsyncMessage("Browser:ZoomToPoint", { x: aX1, y: aY1 });
|
||||
this._dispatchMouseEvent("Browser:ZoomToPoint", aX1, aY1);
|
||||
},
|
||||
|
||||
toString: function toString() {
|
||||
|
|
|
@ -86,6 +86,7 @@
|
|||
<script type="application/javascript" src="chrome://browser/content/TileManager.js"/>
|
||||
<script type="application/javascript" src="chrome://browser/content/BrowserView.js"/>
|
||||
<script type="application/javascript" src="chrome://browser/content/AnimatedZoom.js"/>
|
||||
<script type="application/javascript" src="chrome://browser/content/sync.js"/>
|
||||
|
||||
<stringbundleset id="stringbundleset">
|
||||
<stringbundle id="bundle_browser" src="chrome://browser/locale/browser.properties"/>
|
||||
|
@ -113,6 +114,7 @@
|
|||
<!-- tabs -->
|
||||
<command id="cmd_newTab" label="&newtab.label;" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
<command id="cmd_closeTab" label="&closetab.label;" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
<command id="cmd_remoteTabs" oncommand="WeaveGlue.openRemoteTabs();"/>
|
||||
|
||||
<!-- bookmarking -->
|
||||
<command id="cmd_star" label="&star.label;" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
|
@ -202,6 +204,7 @@
|
|||
<vbox id="tabs" onselect="BrowserUI.selectTab(this);" onclosetab="BrowserUI.closeTab(this)" flex="1"/>
|
||||
<hbox id="tabs-controls">
|
||||
<toolbarbutton id="newtab-button" class="button-image" command="cmd_newTab"/>
|
||||
<toolbarbutton id="remotetabs-button" class="button-image" disabled="true" command="cmd_remoteTabs"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
@ -257,7 +260,7 @@
|
|||
<stack id="tile-stack" class="window-width" flex="1">
|
||||
<scrollbox id="content-scrollbox" style="overflow: hidden;" class="window-width" flex="1">
|
||||
<!-- Content viewport -->
|
||||
<html:div id="tile-container" style="overflow: hidden;">
|
||||
<html:div id="tile-container" style="overflow: hidden;" tabindex="-1">
|
||||
<html:canvas id="content-overlay" style="display: none; position: absolute; z-index: 1000; left: 0; top: 0;">
|
||||
</html:canvas>
|
||||
</html:div>
|
||||
|
@ -431,6 +434,21 @@
|
|||
<button id="prefs-clear-data" label="&clearPrivateData.button;" command="cmd_sanitize"/>
|
||||
</setting>
|
||||
</settings>
|
||||
<settings id="prefs-sync" label="&sync.title;">
|
||||
<setting id="sync-user" type="string" title="&sync.username;" />
|
||||
<setting id="sync-pass" type="string" inputtype="password" title="&sync.password;" />
|
||||
<setting id="sync-secret" type="string" inputtype="password" title="&sync.secretPhrase;" />
|
||||
<setting id="sync-device" type="string" title="&sync.deviceName;" onchange="WeaveGlue.changeName(this)" collapsed="true"/>
|
||||
<setting id="sync-connect" type="control">
|
||||
<button label="&sync.connect;" oncommand="WeaveGlue.connect();" />
|
||||
</setting>
|
||||
<setting id="sync-disconnect" type="control" collapsed="true">
|
||||
<button label="&sync.disconnect;" oncommand="WeaveGlue.disconnect();" />
|
||||
</setting>
|
||||
<setting id="sync-sync" type="control" collapsed="true">
|
||||
<button id="sync-syncButton" label="&sync.syncNow;" oncommand="WeaveGlue.sync();" />
|
||||
</setting>
|
||||
</settings>
|
||||
</richlistbox>
|
||||
</notificationbox>
|
||||
</vbox>
|
||||
|
|
|
@ -12,6 +12,8 @@ let gPrefService = Cc["@mozilla.org/preferences-service;1"]
|
|||
.getService(Ci.nsIPrefBranch2);
|
||||
let gObserverService = Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(Ci.nsIObserverService);
|
||||
let gIOService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
|
||||
let XULDocument = Ci.nsIDOMXULDocument;
|
||||
let HTMLHtmlElement = Ci.nsIDOMHTMLHtmlElement;
|
||||
|
@ -443,6 +445,7 @@ Content.prototype = {
|
|||
let json = aMessage.json;
|
||||
let x = json.x;
|
||||
let y = json.y;
|
||||
let modifiers = json.modifiers;
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "Browser:Blur":
|
||||
|
@ -459,25 +462,38 @@ Content.prototype = {
|
|||
if (this._overlayTimeout)
|
||||
return;
|
||||
|
||||
this._overlayTimeout = content.setTimeout(function() {
|
||||
let element = elementFromPoint(x, y);
|
||||
if (!element || !element.mozMatchesSelector("*:link,*:visited,*:link *,*:visited *,*[role=button],button,input,option,select,textarea,label"))
|
||||
return;
|
||||
let element = elementFromPoint(x, y);
|
||||
if (!element)
|
||||
return;
|
||||
|
||||
let rects = getContentClientRects(element);
|
||||
sendAsyncMessage("Browser:Highlight", { rects: rects });
|
||||
}, kTapOverlayTimeout);
|
||||
this._sendMouseEvent("mousedown", element, x, y);
|
||||
|
||||
// If we don't release the implicit capture, we'll get dragging problems
|
||||
// when a contextmenu is displayed
|
||||
element.ownerDocument.releaseCapture();
|
||||
|
||||
if (element.mozMatchesSelector("*:link,*:visited,*:link *,*:visited *,*[role=button],button,input,option,select,textarea,label")) {
|
||||
this._overlayTimeout = content.setTimeout(function() {
|
||||
let rects = getContentClientRects(element);
|
||||
sendSyncMessage("Browser:Highlight", { rects: rects });
|
||||
}, kTapOverlayTimeout);
|
||||
}
|
||||
break;
|
||||
|
||||
case "Browser:MouseUp": {
|
||||
let element = elementFromPoint(x, y);
|
||||
if (!this._formAssistant.open(element)) {
|
||||
this._sendMouseEvent("mousedown", element, x, y);
|
||||
if (modifiers == Ci.nsIDOMNSEvent.CONTROL_MASK) {
|
||||
let uri = Util.getHrefForElement(element);
|
||||
if (uri)
|
||||
sendAsyncMessage("Browser:OpenURI", { uri: uri });
|
||||
} else if (!this._formAssistant.open(element)) {
|
||||
this._sendMouseEvent("mouseup", element, x, y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "Browser:MouseCancel":
|
||||
this._cancelMouseEvent();
|
||||
if (this._overlayTimeout) {
|
||||
content.clearTimeout(this._overlayTimeout);
|
||||
this._overlayTimeout = 0;
|
||||
|
@ -538,10 +554,6 @@ Content.prototype = {
|
|||
},
|
||||
|
||||
_sendMouseEvent: function _sendMouseEvent(aName, aElement, aX, aY) {
|
||||
let scrollOffset = Util.getScrollOffset(content);
|
||||
aX -= scrollOffset.x;
|
||||
aY -= scrollOffset.y;
|
||||
|
||||
// the element can be out of the aX/aY point because of the touch radius
|
||||
if (!(aElement instanceof HTMLHtmlElement)) {
|
||||
let isTouchClick = true;
|
||||
|
@ -563,8 +575,17 @@ Content.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
let scrollOffset = Util.getScrollOffset(content);
|
||||
let windowUtils = Util.getWindowUtils(content);
|
||||
windowUtils.sendMouseEvent(aName, aX, aY, 0, 1, 0, true);
|
||||
windowUtils.sendMouseEvent(aName, aX - scrollOffset.x, aY - scrollOffset.y, 0, 1, 0, true);
|
||||
},
|
||||
|
||||
_cancelMouseEvent: function _cancelMouseEvent() {
|
||||
// We use a mouseup with a clickcount=0 to cancel the contextmenu timer in
|
||||
// nsEventStateManager.cpp
|
||||
let scrollOffset = Util.getScrollOffset(content);
|
||||
let windowUtils = Util.getWindowUtils(content);
|
||||
windowUtils.sendMouseEvent("mouseup", scrollOffset.x, scrollOffset.y, 0, 0, 0, true);
|
||||
},
|
||||
|
||||
startLoading: function startLoading() {
|
||||
|
@ -690,6 +711,108 @@ let ViewportHandler = {
|
|||
ViewportHandler.init();
|
||||
|
||||
|
||||
const kXLinkNamespace = "http://www.w3.org/1999/xlink";
|
||||
|
||||
var ContextHandler = {
|
||||
_getLinkURL: function ch_getLinkURL(aLink) {
|
||||
let href = aLink.href;
|
||||
if (href)
|
||||
return href;
|
||||
|
||||
href = aLink.getAttributeNS(kXLinkNamespace, "href");
|
||||
if (!href || !href.match(/\S/)) {
|
||||
// Without this we try to save as the current doc,
|
||||
// for example, HTML case also throws if empty
|
||||
throw "Empty href";
|
||||
}
|
||||
|
||||
return Util.makeURLAbsolute(aLink.baseURI, href);
|
||||
},
|
||||
|
||||
_getURI: function ch_getURI(aURL) {
|
||||
try {
|
||||
return Util.makeURI(aURL);
|
||||
} catch (ex) { }
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
_getProtocol: function ch_getProtocol(aURI) {
|
||||
if (aURI)
|
||||
return aURI.scheme;
|
||||
return null;
|
||||
},
|
||||
|
||||
_isSaveable: function ch_isSaveable(aProtocol) {
|
||||
// We don't do the Right Thing for news/snews yet, so turn them off until we do
|
||||
return aProtocol && !(aProtocol == "mailto" || aProtocol == "javascript" || aProtocol == "news" || aProtocol == "snews");
|
||||
},
|
||||
|
||||
_isVoice: function ch_isVoice(aProtocol) {
|
||||
// Collection of protocols related to voice or data links
|
||||
return aProtocol && (aProtocol == "tel" || aProtocol == "callto" || aProtocol == "sip" || aProtocol == "voipto");
|
||||
},
|
||||
|
||||
init: function ch_init() {
|
||||
addEventListener("contextmenu", this, false);
|
||||
},
|
||||
|
||||
handleEvent: function ch_handleEvent(aEvent) {
|
||||
let state = {
|
||||
onLink: false,
|
||||
onSaveableLink: false,
|
||||
onVoiceLink: false,
|
||||
onImage: false,
|
||||
onLoadedImage: false,
|
||||
linkURL: "",
|
||||
linkProtocol: null,
|
||||
mediaURL: ""
|
||||
};
|
||||
|
||||
let popupNode = elementFromPoint(aEvent.clientX, aEvent.clientY);
|
||||
|
||||
// Do checks for nodes that never have children.
|
||||
if (popupNode.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) {
|
||||
// See if the user clicked on an image.
|
||||
if (popupNode instanceof Ci.nsIImageLoadingContent && popupNode.currentURI) {
|
||||
state.onImage = true;
|
||||
state.mediaURL = popupNode.currentURI.spec;
|
||||
|
||||
let request = popupNode.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
|
||||
if (request && (request.imageStatus & request.STATUS_SIZE_AVAILABLE))
|
||||
state.onLoadedImage = true;
|
||||
}
|
||||
}
|
||||
|
||||
let elem = popupNode;
|
||||
while (elem) {
|
||||
if (elem.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) {
|
||||
// Link?
|
||||
if (!this.onLink &&
|
||||
((elem instanceof Ci.nsIDOMHTMLAnchorElement && elem.href) ||
|
||||
(elem instanceof Ci.nsIDOMHTMLAreaElement && elem.href) ||
|
||||
elem instanceof Ci.nsIDOMHTMLLinkElement ||
|
||||
elem.getAttributeNS(kXLinkNamespace, "type") == "simple")) {
|
||||
|
||||
// Target is a link or a descendant of a link.
|
||||
state.linkURL = this._getLinkURL(elem);
|
||||
state.linkProtocol = this._getProtocol(this._getURI(state.linkURL));
|
||||
state.onLink = true;
|
||||
state.onSaveableLink = this._isSaveable(state.linkProtocol);
|
||||
state.onVoiceLink = this._isVoice(state.linkProtocol);
|
||||
}
|
||||
}
|
||||
|
||||
elem = elem.parentNode;
|
||||
}
|
||||
|
||||
sendAsyncMessage("Browser:ContextMenu", state);
|
||||
}
|
||||
};
|
||||
|
||||
ContextHandler.init();
|
||||
|
||||
|
||||
var FormSubmitObserver = {
|
||||
init: function init() {
|
||||
gObserverService.addObserver(this, "formsubmit", false);
|
||||
|
@ -709,4 +832,4 @@ var FormSubmitObserver = {
|
|||
}
|
||||
};
|
||||
|
||||
FormSubmitObserver.init();
|
||||
FormSubmitObserver.init();
|
||||
|
|
|
@ -181,7 +181,6 @@ FormAssistant.prototype = {
|
|||
break;
|
||||
|
||||
default:
|
||||
let target = aEvent.target;
|
||||
if (currentWrapper.canAutocomplete())
|
||||
sendAsyncMessage("FormAssist:AutoComplete", this.getJSON());
|
||||
break;
|
||||
|
@ -382,6 +381,10 @@ BasicWrapper.prototype = {
|
|||
|
||||
autocomplete: function(aValue) {
|
||||
this.element.value = aValue;
|
||||
|
||||
let event = this.element.ownerDocument.createEvent("Events");
|
||||
event.initEvent("DOMAutoComplete", true, true);
|
||||
this.element.dispatchEvent(event);
|
||||
},
|
||||
|
||||
/** Caret is used to input text for this element. */
|
||||
|
@ -571,7 +574,7 @@ SelectWrapper.prototype = {
|
|||
evt.initEvent("change", true, true, this._control.ownerDocument.defaultView, 0,
|
||||
false, false,
|
||||
false, false, null);
|
||||
content.document.defaultView.setTimeout(function() {
|
||||
content.setTimeout(function() {
|
||||
control.dispatchEvent(evt);
|
||||
}, 0);
|
||||
}
|
||||
|
@ -632,7 +635,7 @@ MenulistWrapper.prototype = {
|
|||
evt.initCommandEvent("command", true, true, window, 0,
|
||||
false, false,
|
||||
false, false, null);
|
||||
content.document.defaultView.setTimeout(function() {
|
||||
content.setTimeout(function() {
|
||||
control.dispatchEvent(evt);
|
||||
}, 0);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
/* ***** 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 Bookmarks sync code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jono DiCarlo <jdicarlo@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 ***** */
|
||||
|
||||
let WeaveGlue = {
|
||||
init: function init() {
|
||||
Components.utils.import("resource://services-sync/service.js");
|
||||
|
||||
this._addListeners();
|
||||
|
||||
// Initialize the UI now
|
||||
this._updateOptions();
|
||||
|
||||
// Generating keypairs is expensive on mobile, so disable it
|
||||
Weave.Service.keyGenEnabled = false;
|
||||
},
|
||||
|
||||
openRemoteTabs: function openRemoteTabs() {
|
||||
this._openTab("about:sync-tabs");
|
||||
},
|
||||
|
||||
connect: function connect() {
|
||||
Weave.Service.login(this._settings.user.value, this._settings.pass.value,
|
||||
this._settings.secret.value);
|
||||
Weave.Service.persistLogin();
|
||||
},
|
||||
|
||||
disconnect: function disconnect() {
|
||||
Weave.Service.logout();
|
||||
},
|
||||
|
||||
sync: function sync() {
|
||||
Weave.Service.sync();
|
||||
},
|
||||
|
||||
_addListeners: function _addListeners() {
|
||||
let topics = ["weave:service:sync:start", "weave:service:sync:finish",
|
||||
"weave:service:sync:error", "weave:service:login:start",
|
||||
"weave:service:login:finish", "weave:service:login:error",
|
||||
"weave:service:logout:finish"];
|
||||
|
||||
// For each topic, add or remove _updateOptions as the observer
|
||||
let addRem = function(add) topics.forEach(function(topic) Weave.Svc.
|
||||
Obs[add ? "add" : "remove"](topic, WeaveGlue._updateOptions, WeaveGlue));
|
||||
|
||||
// Add the listeners now, and remove them on unload
|
||||
addRem(true);
|
||||
addEventListener("unload", function() addRem(false), false);
|
||||
},
|
||||
|
||||
_openTab: function _openTab(url) {
|
||||
setTimeout(function() BrowserUI.newTab(url), 0);
|
||||
},
|
||||
|
||||
get _settings() {
|
||||
// Do a quick test to see if the options exist yet
|
||||
let syncButton = document.getElementById("sync-syncButton");
|
||||
if (syncButton == null)
|
||||
return;
|
||||
|
||||
// Get all the setting nodes from the add-ons display
|
||||
let settings = {};
|
||||
let ids = ["user", "pass", "secret", "device", "connect", "disconnect", "sync"];
|
||||
ids.forEach(function(id) {
|
||||
settings[id] = document.getElementById("sync-" + id);
|
||||
});
|
||||
|
||||
// Replace the getter with the collection of settings
|
||||
delete this._settings;
|
||||
return this._settings = settings;
|
||||
},
|
||||
|
||||
_updateOptions: function _updateOptions() {
|
||||
let loggedIn = Weave.Service.isLoggedIn;
|
||||
document.getElementById("remotetabs-button").disabled = !loggedIn;
|
||||
|
||||
// Make sure we're online when connecting/syncing
|
||||
Util.forceOnline();
|
||||
|
||||
// Can't do anything before settings are loaded
|
||||
if (this._settings == null)
|
||||
return;
|
||||
|
||||
// Make some aliases
|
||||
let user = this._settings.user;
|
||||
let pass = this._settings.pass;
|
||||
let secret = this._settings.secret;
|
||||
let connect = this._settings.connect;
|
||||
let device = this._settings.device;
|
||||
let disconnect = this._settings.disconnect;
|
||||
let sync = this._settings.sync;
|
||||
let syncStr = Weave.Str.sync;
|
||||
|
||||
// Make sure the options are in the right state
|
||||
user.collapsed = loggedIn;
|
||||
pass.collapsed = loggedIn;
|
||||
secret.collapsed = loggedIn;
|
||||
connect.collapsed = loggedIn;
|
||||
device.collapsed = !loggedIn;
|
||||
disconnect.collapsed = !loggedIn;
|
||||
sync.collapsed = !loggedIn;
|
||||
|
||||
// Check the lock on a timeout because it's set just after notifying
|
||||
setTimeout(Weave.Utils.bind2(this, function() {
|
||||
// Prevent certain actions when the service is locked
|
||||
if (Weave.Service.locked) {
|
||||
connect.firstChild.disabled = true;
|
||||
sync.firstChild.disabled = true;
|
||||
connect.setAttribute("title", syncStr.get("connecting.label"));
|
||||
sync.setAttribute("title", syncStr.get("lastSyncInProgress.label"));
|
||||
} else {
|
||||
connect.firstChild.disabled = false;
|
||||
sync.firstChild.disabled = false;
|
||||
connect.setAttribute("title", syncStr.get("disconnected.label"));
|
||||
}
|
||||
}), 0);
|
||||
|
||||
// Move the disconnect and sync settings out to make connect the last item
|
||||
let parent = connect.parentNode;
|
||||
if (!loggedIn)
|
||||
parent = parent.parentNode;
|
||||
parent.appendChild(disconnect);
|
||||
parent.appendChild(sync);
|
||||
|
||||
// Dynamically generate some strings
|
||||
let connectedStr = syncStr.get("connected.label", [Weave.Service.username]);
|
||||
disconnect.setAttribute("title", connectedStr);
|
||||
|
||||
// Show the day-of-week and time (HH:MM) of last sync
|
||||
let lastSync = Weave.Svc.Prefs.get("lastSync");
|
||||
if (lastSync != null) {
|
||||
let syncDate = new Date(lastSync).toLocaleFormat("%a %R");
|
||||
let dateStr = syncStr.get("lastSync.label", [syncDate]);
|
||||
sync.setAttribute("title", dateStr);
|
||||
}
|
||||
|
||||
// Show what went wrong with login if necessary
|
||||
let login = Weave.Status.login;
|
||||
if (login == Weave.LOGIN_SUCCEEDED)
|
||||
connect.removeAttribute("desc");
|
||||
else if (login != null)
|
||||
connect.setAttribute("desc", Weave.Str.errors.get(login));
|
||||
|
||||
// Load the values for the string inputs
|
||||
user.value = Weave.Service.username || "";
|
||||
pass.value = Weave.Service.password || "";
|
||||
secret.value = Weave.Service.passphrase || "";
|
||||
device.value = Weave.Clients.localName || "";
|
||||
},
|
||||
|
||||
changeName: function changeName(input) {
|
||||
// Make sure to update to a modified name, e.g., empty-string -> default
|
||||
Weave.Clients.localName = input.value;
|
||||
input.value = Weave.Clients.localName;
|
||||
}
|
||||
};
|
|
@ -16,6 +16,7 @@ chrome.jar:
|
|||
content/aboutCertError.xhtml (content/aboutCertError.xhtml)
|
||||
content/aboutCertError.css (content/aboutCertError.css)
|
||||
content/aboutHome.xhtml (content/aboutHome.xhtml)
|
||||
content/aboutTabs.xhtml (content/aboutTabs.xhtml)
|
||||
content/languages.properties (content/languages.properties)
|
||||
* content/browser.xul (content/browser.xul)
|
||||
* content/browser.js (content/browser.js)
|
||||
|
@ -58,5 +59,6 @@ chrome.jar:
|
|||
content/prompt/select.xul (content/prompt/select.xul)
|
||||
content/prompt/prompt.js (content/prompt/prompt.js)
|
||||
content/AnimatedZoom.js (content/AnimatedZoom.js)
|
||||
content/sync.js (content/sync.js)
|
||||
|
||||
% override chrome://global/content/config.xul chrome://browser/content/config.xul
|
||||
|
|
|
@ -52,9 +52,7 @@ function checkClick() {
|
|||
element = newTab.browser.contentDocument.documentElement;
|
||||
element.addEventListener("click", clickFired, true);
|
||||
|
||||
finish(); // XXX Browser.getBoundingContentRect not available.
|
||||
|
||||
let rect = Browser.getBoundingContentRect(element);
|
||||
let rect = getBoundingContentRect(element);
|
||||
EventUtils.synthesizeMouse(element, 1, rect.height + 10, {}, window);
|
||||
waitFor(checkPosition, function() { return isClickFired });
|
||||
}
|
||||
|
@ -62,7 +60,7 @@ function checkClick() {
|
|||
function checkPosition() {
|
||||
element.removeEventListener("click", clickFired, true);
|
||||
|
||||
let rect = Browser.getBoundingContentRect(element);
|
||||
let rect = getBoundingContentRect(element);
|
||||
is(clickPosition.x, 1, "X position is correct");
|
||||
is(clickPosition.y, rect.height + 10, "Y position is correct");
|
||||
|
||||
|
@ -73,11 +71,11 @@ function checkThickBorder() {
|
|||
let frame = newTab.browser.contentDocument.getElementById("iframe-2");
|
||||
let element = frame.contentDocument.getElementsByTagName("input")[0];
|
||||
|
||||
let frameRect = Browser.getBoundingContentRect(frame);
|
||||
let frameRect = getBoundingContentRect(frame);
|
||||
let frameLeftBorder = window.getComputedStyle(frame, "").borderLeftWidth;
|
||||
let frameTopBorder = window.getComputedStyle(frame, "").borderTopWidth;
|
||||
|
||||
let elementRect = Browser.getBoundingContentRect(element);
|
||||
let elementRect = getBoundingContentRect(element);
|
||||
ok((frameRect.left + parseInt(frameLeftBorder)) < elementRect.left, "X position of nested element ok");
|
||||
ok((frameRect.top + parseInt(frameTopBorder)) < elementRect.top, "Y position of nested element ok");
|
||||
|
||||
|
@ -91,3 +89,27 @@ function close() {
|
|||
// We must finialize the tests
|
||||
finish();
|
||||
}
|
||||
|
||||
// XXX copied from chrome/content/content.js
|
||||
function getBoundingContentRect(aElement) {
|
||||
if (!aElement)
|
||||
return new Rect(0, 0, 0, 0);
|
||||
|
||||
let document = aElement.ownerDocument;
|
||||
while(document.defaultView.frameElement)
|
||||
document = document.defaultView.frameElement.ownerDocument;
|
||||
|
||||
let offset = Util.getScrollOffset(content);
|
||||
let r = aElement.getBoundingClientRect();
|
||||
|
||||
// step out of iframes and frames, offsetting scroll values
|
||||
for (let frame = aElement.ownerDocument.defaultView; frame != content; frame = frame.parent) {
|
||||
// adjust client coordinates' origin to be top left of iframe viewport
|
||||
let rect = frame.frameElement.getBoundingClientRect();
|
||||
let left = frame.getComputedStyle(frame.frameElement, "").borderLeftWidth;
|
||||
let top = frame.getComputedStyle(frame.frameElement, "").borderTopWidth;
|
||||
offset.add(rect.left + parseInt(left), rect.top + parseInt(top));
|
||||
}
|
||||
|
||||
return new Rect(r.left + offset.x, r.top + offset.y, r.width, r.height);
|
||||
}
|
||||
|
|
|
@ -67,8 +67,8 @@ gTests.push({
|
|||
let controls = document.getElementById("controls-scrollbox");
|
||||
|
||||
// Assign offsets while panning
|
||||
initialDragOffset = document.getElementById("tabs-container").getBoundingClientRect().width;
|
||||
finalDragOffset = initialDragOffset + document.getElementById("browser-controls")
|
||||
initialDragOffset = document.getElementById("tabs-container").getBoundingClientRect().width;
|
||||
finalDragOffset = initialDragOffset + document.getElementById("browser-controls")
|
||||
.getBoundingClientRect().width;
|
||||
|
||||
gCurrentTest._contentScrollbox.getPosition(x,y);
|
||||
|
@ -91,12 +91,12 @@ gTests.push({
|
|||
is(prefsOpen.checked, false, "Preferences open button must not be depressed");
|
||||
|
||||
// check if preferences pane is invisble
|
||||
is(document.getElementById("panel-container").hidden,true, "Preferences panel is invisble");
|
||||
is(BrowserUI.isPanelVisible(), false, "Preferences panel is invisble");
|
||||
|
||||
// click on the prefs button to go the preferences pane
|
||||
var prefsClick = document.getElementById("tool-panel-open");
|
||||
prefsClick.click();
|
||||
waitFor(gCurrentTest.onPrefsView, function() { return document.getElementById("panel-container").hidden == false; });
|
||||
waitFor(gCurrentTest.onPrefsView, BrowserUI.isPanelVisible);
|
||||
},
|
||||
|
||||
onPrefsView: function(){
|
||||
|
@ -105,8 +105,7 @@ gTests.push({
|
|||
let h = prefsList.clientHeight;
|
||||
|
||||
//check whether the preferences panel is visible
|
||||
var prefsContainer = document.getElementById("panel-container");
|
||||
is(prefsContainer.hidden, false, "Preferences panel must now be visble");
|
||||
ok(BrowserUI.isPanelVisible(), "Preferences panel must now be visble");
|
||||
|
||||
// Check if preferences container is visible
|
||||
is(document.getElementById("panel-container").hidden, false, "Preferences panel should be visible");
|
||||
|
@ -133,9 +132,10 @@ gTests.push({
|
|||
// Move preferences pane upexpected "+ finalDragOffset +"
|
||||
dragElement(prefsList,w/2,h/2,w/2,h/4);
|
||||
|
||||
// Check whether it is moved up to the correct view, height should be 104
|
||||
// Check whether it is moved up to the correct view
|
||||
let distance = (h/2) - (h/4);
|
||||
gCurrentTest._prefsScrollbox.getPosition(x,y);
|
||||
ok((x.value==0 & y.value==104),"Preferences pane is panned up","Got "+x.value+" "+y.value+", expected 0,104");
|
||||
ok((x.value==0 & y.value==distance),"Preferences pane is panned up","Got "+x.value+" "+y.value+", expected 0," + distance);
|
||||
|
||||
// Move preferences pane down
|
||||
dragElement(prefsList,w/2,h/4,w/2,h/2);
|
||||
|
|
|
@ -67,6 +67,10 @@ let modules = {
|
|||
home: {
|
||||
uri: "chrome://browser/content/aboutHome.xhtml",
|
||||
privileged: true
|
||||
},
|
||||
"sync-tabs": {
|
||||
uri: "chrome://browser/content/aboutTabs.xhtml",
|
||||
privileged: true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,6 +145,12 @@ AboutHome.prototype = {
|
|||
classID: Components.ID("{b071364f-ab68-4669-a9db-33fca168271a}")
|
||||
}
|
||||
|
||||
function AboutSyncTabs() {}
|
||||
AboutSyncTabs.prototype = {
|
||||
__proto__: AboutGeneric.prototype,
|
||||
classID: Components.ID("{d503134a-f6f3-4824-bc3c-09c123177944}")
|
||||
}
|
||||
|
||||
const components = [AboutFirstrun, AboutFennec, AboutRights,
|
||||
AboutCertError, AboutFirefox, AboutHome];
|
||||
AboutCertError, AboutFirefox, AboutHome, AboutSyncTabs];
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|
||||
|
|
|
@ -40,50 +40,97 @@ const Ci = Components.interfaces;
|
|||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
|
||||
function openWindow(aParent, aURL, aTarget, aFeatures) {
|
||||
let wwatch = Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher);
|
||||
return wwatch.openWindow(aParent, aURL, aTarget, aFeatures, null);
|
||||
}
|
||||
|
||||
function resolveURIInternal(aCmdLine, aArgument) {
|
||||
let uri = aCmdLine.resolveURI(aArgument);
|
||||
|
||||
if (!(uri instanceof Ci.nsIFileURL))
|
||||
return uri;
|
||||
|
||||
try {
|
||||
if (uri.file.exists())
|
||||
return uri;
|
||||
}
|
||||
catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
||||
try {
|
||||
let urifixup = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup);
|
||||
uri = urifixup.createFixupURI(aArgument, 0);
|
||||
}
|
||||
catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
|
||||
function BrowserCLH() { }
|
||||
|
||||
BrowserCLH.prototype = {
|
||||
//
|
||||
// nsICommandLineHandler
|
||||
//
|
||||
handle: function fs_handle(cmdLine) {
|
||||
handle: function fs_handle(aCmdLine) {
|
||||
// Instantiate the search service so the search engine cache is created now
|
||||
// instead when the application is running. The install process will register
|
||||
// this component by using the -silent command line flag, thereby creating
|
||||
// the cache during install, not runtime.
|
||||
// NOTE: This code assumes this CLH is run before the nsDefaultCLH, which
|
||||
// consumes the "-silent" flag.
|
||||
if (cmdLine.findFlag("silent", false) > -1) {
|
||||
if (aCmdLine.findFlag("silent", false) > -1) {
|
||||
let searchService = Cc["@mozilla.org/browser/search-service;1"].
|
||||
getService(Ci.nsIBrowserSearchService);
|
||||
let autoComplete = Cc["@mozilla.org/autocomplete/search;1?name=history"].
|
||||
getService(Ci.nsIAutoCompleteSearch);
|
||||
}
|
||||
|
||||
// Handle chrome windows loaded via commandline
|
||||
let chromeParam = aCmdLine.handleFlagWithParam("chrome", false);
|
||||
if (chromeParam) {
|
||||
try {
|
||||
// only load URIs which do not inherit chrome privs
|
||||
let features = "chrome,dialog=no,all";
|
||||
let uri = resolveURIInternal(aCmdLine, chromeParam);
|
||||
let netutil = Cc["@mozilla.org/network/util;1"].getService(Ci.nsINetUtil);
|
||||
if (!netutil.URIChainHasFlags(uri, Ci.nsIHttpProtocolHandler.URI_INHERITS_SECURITY_CONTEXT)) {
|
||||
openWindow(null, uri.spec, "_blank", features);
|
||||
aCmdLine.preventDefault = true;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
let win;
|
||||
try {
|
||||
var windowMediator =
|
||||
Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
|
||||
|
||||
let windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
|
||||
win = windowMediator.getMostRecentWindow("navigator:browser");
|
||||
if (!win)
|
||||
return;
|
||||
|
||||
win.focus();
|
||||
cmdLine.preventDefault = true;
|
||||
aCmdLine.preventDefault = true;
|
||||
} catch (e) { }
|
||||
|
||||
// Assumption: All CLH arguments we've received have been sent remotely,
|
||||
// or we wouldn't already have a window. Therefore: open 'em all!
|
||||
for (let i = 0; i < cmdLine.length; i++) {
|
||||
let arg = cmdLine.getArgument(i);
|
||||
for (let i = 0; i < aCmdLine.length; i++) {
|
||||
let arg = aCmdLine.getArgument(i);
|
||||
if (!arg || arg[0] == '-')
|
||||
continue;
|
||||
|
||||
let uri = cmdLine.resolveURI(arg);
|
||||
let uri = resolveURIInternal(aCmdLine, arg);
|
||||
if (uri)
|
||||
win.browserDOMWindow.openURI(uri, null, Ci.nsIBrowserDOMWindow.OPEN_NEWTAB, null);
|
||||
}
|
||||
|
|
|
@ -68,8 +68,7 @@ EXTRA_COMPONENTS = \
|
|||
AddonUpdateService.js \
|
||||
$(NULL)
|
||||
|
||||
DIRS = protocols \
|
||||
phone \
|
||||
DIRS = phone \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -11,6 +11,8 @@ component {972efe64-8ac0-4e91-bdb0-22835d987815} AboutRedirector.js
|
|||
contract @mozilla.org/network/protocol/about;1?what=certerror {972efe64-8ac0-4e91-bdb0-22835d987815}
|
||||
component {b071364f-ab68-4669-a9db-33fca168271a} AboutRedirector.js
|
||||
contract @mozilla.org/network/protocol/about;1?what=home {b071364f-ab68-4669-a9db-33fca168271a}
|
||||
component {d503134a-f6f3-4824-bc3c-09c123177944} AboutRedirector.js
|
||||
contract @mozilla.org/network/protocol/about;1?what=sync-tabs {d503134a-f6f3-4824-bc3c-09c123177944}
|
||||
|
||||
# DirectoryProvider.js
|
||||
component {ef0f7a87-c1ee-45a8-8d67-26f586e46a4b} DirectoryProvider.js
|
||||
|
|
|
@ -1,54 +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 Mozilla.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# the Mozilla Foundation <http://www.mozilla.org/>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2008
|
||||
# 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 *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = protocols
|
||||
|
||||
EXTRA_COMPONENTS = nsTelProtocolHandler.manifest
|
||||
EXTRA_PP_COMPONENTS = nsTelProtocolHandler.js
|
||||
|
||||
ifdef WINCE
|
||||
DEFINES += -DWINCE=$(WINCE)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -1,151 +0,0 @@
|
|||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const kSCHEME = "tel";
|
||||
|
||||
// Mozilla defined
|
||||
const kSIMPLEURI_CONTRACTID = "@mozilla.org/network/simple-uri;1";
|
||||
const kIOSERVICE_CONTRACTID = "@mozilla.org/network/io-service;1";
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
|
||||
|
||||
function TelProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
TelProtocol.prototype =
|
||||
{
|
||||
|
||||
classID: Components.ID("d4bc06cc-fa9f-48ce-98e4-5326ca96ba28"),
|
||||
contractID: kPROTOCOL_CONTRACTID,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler]),
|
||||
|
||||
scheme: kSCHEME,
|
||||
defaultPort: -1,
|
||||
protocolFlags: Ci.nsIProtocolHandler.URI_NORELATIVE |
|
||||
Ci.nsIProtocolHandler.URI_NOAUTH,
|
||||
|
||||
allowPort: function(port, scheme)
|
||||
{
|
||||
return false;
|
||||
},
|
||||
|
||||
newURI: function(spec, charset, baseURI)
|
||||
{
|
||||
var uri = Components.classes[kSIMPLEURI_CONTRACTID].createInstance(Ci.nsIURI);
|
||||
uri.spec = spec;
|
||||
return uri;
|
||||
},
|
||||
|
||||
|
||||
newChannel: function(aURI)
|
||||
{
|
||||
// aURI is a nsIUri, so get a string from it using .spec
|
||||
let phoneNumber = aURI.spec;
|
||||
|
||||
// strip away the kSCHEME: part
|
||||
phoneNumber = phoneNumber.substring(phoneNumber.indexOf(":") + 1, phoneNumber.length);
|
||||
phoneNumber = encodeURI(phoneNumber);
|
||||
|
||||
#ifdef WINCE
|
||||
try {
|
||||
//try tel:
|
||||
let channel = new nsWinceTelChannel (aURI, phoneNumber);
|
||||
return channel;
|
||||
} catch(e){
|
||||
//tel not registered, try the next one
|
||||
}
|
||||
#endif
|
||||
|
||||
var ios = Components.classes[kIOSERVICE_CONTRACTID].getService(Ci.nsIIOService);
|
||||
|
||||
try {
|
||||
//try voipto:
|
||||
let channel = ios.newChannel("voipto:"+phoneNumber, null, null);
|
||||
return channel;
|
||||
} catch(e){
|
||||
//voipto not registered, try the next one
|
||||
}
|
||||
try {
|
||||
//try callto:
|
||||
let channel = ios.newChannel("callto:"+phoneNumber, null, null);
|
||||
return channel;
|
||||
} catch(e){
|
||||
//callto not registered, try the next one
|
||||
}
|
||||
//try wtai:
|
||||
//this is our last equivalent protocol, so if it fails pass the exception on
|
||||
let channel = ios.newChannel("wtai:"+phoneNumber, null, null);
|
||||
return channel;
|
||||
}
|
||||
};
|
||||
|
||||
var components = [TelProtocol];
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|
||||
|
||||
#ifdef WINCE
|
||||
function nsWinceTelChannel(URI, phoneNumber)
|
||||
{
|
||||
this.URI = URI;
|
||||
this.originalURI = URI;
|
||||
this.phoneNumber = phoneNumber
|
||||
}
|
||||
|
||||
nsWinceTelChannel.prototype.QueryInterface =
|
||||
function bc_QueryInterface(iid)
|
||||
{
|
||||
if (!iid.equals(Ci.nsIChannel) && !iid.equals(Ci.nsIRequest) &&
|
||||
!iid.equals(Ci.nsISupports))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
}
|
||||
|
||||
/* nsIChannel */
|
||||
nsWinceTelChannel.prototype.loadAttributes = null;
|
||||
nsWinceTelChannel.prototype.contentLength = 0;
|
||||
nsWinceTelChannel.prototype.owner = null;
|
||||
nsWinceTelChannel.prototype.loadGroup = null;
|
||||
nsWinceTelChannel.prototype.notificationCallbacks = null;
|
||||
nsWinceTelChannel.prototype.securityInfo = null;
|
||||
|
||||
nsWinceTelChannel.prototype.open =
|
||||
nsWinceTelChannel.prototype.asyncOpen =
|
||||
function bc_open(observer, ctxt)
|
||||
{
|
||||
var phoneInterface= Components.classes["@mozilla.org/phone/support;1"].createInstance(Ci.nsIPhoneSupport);
|
||||
phoneInterface.makeCall(this.phoneNumber,"",false);
|
||||
|
||||
// We don't throw this (a number, not a real 'resultcode') because it
|
||||
// upsets xpconnect if we do (error in the js console).
|
||||
Components.returnCode = NS_ERROR_NO_CONTENT;
|
||||
}
|
||||
|
||||
nsWinceTelChannel.prototype.asyncRead =
|
||||
function bc_asyncRead(listener, ctxt)
|
||||
{
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* nsIRequest */
|
||||
nsWinceTelChannel.prototype.isPending =
|
||||
function bc_isPending()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
nsWinceTelChannel.prototype.status = Components.results.NS_OK;
|
||||
|
||||
nsWinceTelChannel.prototype.cancel =
|
||||
function bc_cancel(status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
nsWinceTelChannel.prototype.suspend =
|
||||
nsWinceTelChannel.prototype.resume =
|
||||
function bc_suspres()
|
||||
{
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif
|
|
@ -1,2 +0,0 @@
|
|||
component {d4bc06cc-fa9f-48ce-98e4-5326ca96ba28} nsTelProtocolHandler.js
|
||||
contract @mozilla.org/network/protocol;1?name=tel {d4bc06cc-fa9f-48ce-98e4-5326ca96ba28}
|
|
@ -52,6 +52,7 @@ esac
|
|||
|
||||
MOZ_XUL_APP=1
|
||||
MOZ_ENABLE_LIBXUL=1
|
||||
MOZ_SERVICES_SYNC=1
|
||||
MOZ_NO_XPCOM_OBSOLETE=1
|
||||
if test "$LIBXUL_SDK"; then
|
||||
MOZ_XULRUNNER=1
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<!ENTITY remoteTabs.title "Tabs from my other computers">
|
|
@ -18,3 +18,11 @@
|
|||
<!ENTITY homepage.none "Blank Page">
|
||||
<!ENTITY homepage.default "&brandShortName; Start">
|
||||
<!ENTITY homepage.currentpage "Use Current Page">
|
||||
<!ENTITY sync.title "Sync">
|
||||
<!ENTITY sync.username "Username">
|
||||
<!ENTITY sync.password "Password">
|
||||
<!ENTITY sync.secretPhrase "Secret Phrase">
|
||||
<!ENTITY sync.deviceName "Device Name">
|
||||
<!ENTITY sync.connect "Connect">
|
||||
<!ENTITY sync.disconnect "Disconnect">
|
||||
<!ENTITY sync.syncNow "Sync Now">
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
locale/@AB_CD@/browser/about.dtd (%chrome/about.dtd)
|
||||
locale/@AB_CD@/browser/aboutCertError.dtd (%chrome/aboutCertError.dtd)
|
||||
locale/@AB_CD@/browser/aboutHome.dtd (%chrome/aboutHome.dtd)
|
||||
locale/@AB_CD@/browser/aboutTabs.dtd (%chrome/aboutTabs.dtd)
|
||||
locale/@AB_CD@/browser/browser.dtd (%chrome/browser.dtd)
|
||||
locale/@AB_CD@/browser/browser.properties (%chrome/browser.properties)
|
||||
locale/@AB_CD@/browser/config.dtd (%chrome/config.dtd)
|
||||
|
|
|
@ -47,13 +47,11 @@ mobile/chrome/Makefile
|
|||
mobile/chrome/tests/Makefile
|
||||
mobile/components/Makefile
|
||||
mobile/components/phone/Makefile
|
||||
mobile/components/protocols/Makefile
|
||||
mobile/installer/Makefile
|
||||
mobile/locales/Makefile
|
||||
mobile/Makefile
|
||||
mobile/themes/hildon/Makefile
|
||||
mobile/themes/Makefile
|
||||
mobile/themes/wince/Makefile"
|
||||
mobile/themes/core/Makefile"
|
||||
|
||||
if test -n "$MOZ_UPDATE_PACKAGING"; then
|
||||
add_makefiles "
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# ***** 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
|
||||
|
@ -46,15 +45,8 @@ include $(DEPTH)/config/autoconf.mk
|
|||
#
|
||||
# Theme Selection
|
||||
#
|
||||
# Maemo hildon
|
||||
# Windows Mobile wince
|
||||
#
|
||||
|
||||
ifdef WINCE
|
||||
DIRS = wince
|
||||
else
|
||||
# default to hildon for desktop builds too
|
||||
DIRS = hildon
|
||||
endif
|
||||
# Add the core theme files
|
||||
DIRS = core
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
body {
|
||||
color: black;
|
||||
font-family: "Nokia Sans", Tahoma, Arial, Helvetica, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
h2 {
|
||||
background-color: lightgray;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.tab {
|
||||
border-bottom: solid 1px rgb(207, 207, 207);
|
||||
min-height: 70px;
|
||||
padding-right: 32px;
|
||||
position: relative;
|
||||
}
|
||||
.tab[selected] {
|
||||
background-color: #8db8d8;
|
||||
}
|
||||
.icon {
|
||||
height: 32px;
|
||||
left: 16px;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
width: 32px;
|
||||
}
|
||||
.info {
|
||||
margin-left: 32px;
|
||||
overflow: hidden;
|
||||
padding-left: 32px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.title {
|
||||
font-size: 24px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.url {
|
||||
color: blue;
|
||||
font-size: 18px;
|
||||
margin-top: 4px;
|
||||
}
|
|
@ -799,6 +799,18 @@ box[type="documenttab"]:only-child .documenttab-close {
|
|||
list-style-image: url("images/newtab-active-64.png");
|
||||
}
|
||||
|
||||
#remotetabs-button {
|
||||
list-style-image: url("images/remotetabs-default-64.png");
|
||||
}
|
||||
|
||||
#remotetabs-button:not([disabled]):hover:active {
|
||||
list-style-image: url("images/remotetabs-active-64.png");
|
||||
}
|
||||
|
||||
#remotetabs-button[disabled] {
|
||||
list-style-image: url("images/remotetabs-disabled-64.png");
|
||||
}
|
||||
|
||||
/* bookmark editor ------------------------------------------------------- */
|
||||
#bookmark-container {
|
||||
padding: 8px; /* core spacing */
|
До Ширина: | Высота: | Размер: 31 KiB После Ширина: | Высота: | Размер: 31 KiB |
До Ширина: | Высота: | Размер: 2.6 KiB После Ширина: | Высота: | Размер: 2.6 KiB |
До Ширина: | Высота: | Размер: 3.0 KiB После Ширина: | Высота: | Размер: 3.0 KiB |
До Ширина: | Высота: | Размер: 2.7 KiB После Ширина: | Высота: | Размер: 2.7 KiB |
До Ширина: | Высота: | Размер: 15 KiB После Ширина: | Высота: | Размер: 15 KiB |
До Ширина: | Высота: | Размер: 416 B После Ширина: | Высота: | Размер: 416 B |
До Ширина: | Высота: | Размер: 416 B После Ширина: | Высота: | Размер: 416 B |
До Ширина: | Высота: | Размер: 246 B После Ширина: | Высота: | Размер: 246 B |
До Ширина: | Высота: | Размер: 286 B После Ширина: | Высота: | Размер: 286 B |
До Ширина: | Высота: | Размер: 280 B После Ширина: | Высота: | Размер: 280 B |
До Ширина: | Высота: | Размер: 210 B После Ширина: | Высота: | Размер: 210 B |
До Ширина: | Высота: | Размер: 235 B После Ширина: | Высота: | Размер: 235 B |
До Ширина: | Высота: | Размер: 206 B После Ширина: | Высота: | Размер: 206 B |
До Ширина: | Высота: | Размер: 242 B После Ширина: | Высота: | Размер: 242 B |
До Ширина: | Высота: | Размер: 301 B После Ширина: | Высота: | Размер: 301 B |
До Ширина: | Высота: | Размер: 3.0 KiB После Ширина: | Высота: | Размер: 3.0 KiB |
До Ширина: | Высота: | Размер: 3.2 KiB После Ширина: | Высота: | Размер: 3.2 KiB |
До Ширина: | Высота: | Размер: 3.3 KiB После Ширина: | Высота: | Размер: 3.3 KiB |
До Ширина: | Высота: | Размер: 3.1 KiB После Ширина: | Высота: | Размер: 3.1 KiB |
До Ширина: | Высота: | Размер: 2.8 KiB После Ширина: | Высота: | Размер: 2.8 KiB |
До Ширина: | Высота: | Размер: 3.4 KiB После Ширина: | Высота: | Размер: 3.4 KiB |
До Ширина: | Высота: | Размер: 3.1 KiB После Ширина: | Высота: | Размер: 3.1 KiB |
До Ширина: | Высота: | Размер: 1.1 KiB После Ширина: | Высота: | Размер: 1.1 KiB |
До Ширина: | Высота: | Размер: 570 B После Ширина: | Высота: | Размер: 570 B |
До Ширина: | Высота: | Размер: 388 B После Ширина: | Высота: | Размер: 388 B |
До Ширина: | Высота: | Размер: 782 B После Ширина: | Высота: | Размер: 782 B |
До Ширина: | Высота: | Размер: 635 B После Ширина: | Высота: | Размер: 635 B |
До Ширина: | Высота: | Размер: 447 B После Ширина: | Высота: | Размер: 447 B |
До Ширина: | Высота: | Размер: 839 B После Ширина: | Высота: | Размер: 839 B |
До Ширина: | Высота: | Размер: 675 B После Ширина: | Высота: | Размер: 675 B |
До Ширина: | Высота: | Размер: 1.9 KiB После Ширина: | Высота: | Размер: 1.9 KiB |
До Ширина: | Высота: | Размер: 2.0 KiB После Ширина: | Высота: | Размер: 2.0 KiB |
До Ширина: | Высота: | Размер: 3.2 KiB После Ширина: | Высота: | Размер: 3.2 KiB |
До Ширина: | Высота: | Размер: 2.7 KiB После Ширина: | Высота: | Размер: 2.7 KiB |
До Ширина: | Высота: | Размер: 2.5 KiB После Ширина: | Высота: | Размер: 2.5 KiB |
До Ширина: | Высота: | Размер: 2.0 KiB После Ширина: | Высота: | Размер: 2.0 KiB |
До Ширина: | Высота: | Размер: 427 B После Ширина: | Высота: | Размер: 427 B |
До Ширина: | Высота: | Размер: 430 B После Ширина: | Высота: | Размер: 430 B |
До Ширина: | Высота: | Размер: 345 B После Ширина: | Высота: | Размер: 345 B |
До Ширина: | Высота: | Размер: 457 B После Ширина: | Высота: | Размер: 457 B |
До Ширина: | Высота: | Размер: 3.0 KiB После Ширина: | Высота: | Размер: 3.0 KiB |
До Ширина: | Высота: | Размер: 3.2 KiB После Ширина: | Высота: | Размер: 3.2 KiB |
До Ширина: | Высота: | Размер: 3.3 KiB После Ширина: | Высота: | Размер: 3.3 KiB |
До Ширина: | Высота: | Размер: 960 B После Ширина: | Высота: | Размер: 960 B |
До Ширина: | Высота: | Размер: 699 B После Ширина: | Высота: | Размер: 699 B |
До Ширина: | Высота: | Размер: 3.5 KiB После Ширина: | Высота: | Размер: 3.5 KiB |
До Ширина: | Высота: | Размер: 5.4 KiB После Ширина: | Высота: | Размер: 5.4 KiB |
До Ширина: | Высота: | Размер: 5.3 KiB После Ширина: | Высота: | Размер: 5.3 KiB |
До Ширина: | Высота: | Размер: 1.4 KiB После Ширина: | Высота: | Размер: 1.4 KiB |
До Ширина: | Высота: | Размер: 854 B После Ширина: | Высота: | Размер: 854 B |
До Ширина: | Высота: | Размер: 2.9 KiB После Ширина: | Высота: | Размер: 2.9 KiB |
До Ширина: | Высота: | Размер: 2.8 KiB После Ширина: | Высота: | Размер: 2.8 KiB |
До Ширина: | Высота: | Размер: 3.0 KiB После Ширина: | Высота: | Размер: 3.0 KiB |
До Ширина: | Высота: | Размер: 2.7 KiB После Ширина: | Высота: | Размер: 2.7 KiB |
До Ширина: | Высота: | Размер: 876 B После Ширина: | Высота: | Размер: 876 B |
До Ширина: | Высота: | Размер: 4.8 KiB После Ширина: | Высота: | Размер: 4.8 KiB |
До Ширина: | Высота: | Размер: 573 B После Ширина: | Высота: | Размер: 573 B |
До Ширина: | Высота: | Размер: 1.9 KiB После Ширина: | Высота: | Размер: 1.9 KiB |
До Ширина: | Высота: | Размер: 1.7 KiB После Ширина: | Высота: | Размер: 1.7 KiB |
До Ширина: | Высота: | Размер: 123 B После Ширина: | Высота: | Размер: 123 B |
До Ширина: | Высота: | Размер: 2.8 KiB После Ширина: | Высота: | Размер: 2.8 KiB |