diff --git a/third_party/firefox_sendtophone/chrome/content/ff-overlay.js b/third_party/firefox_sendtophone/chrome/content/ff-overlay.js
index bf288fe..2d2b9c1 100644
--- a/third_party/firefox_sendtophone/chrome/content/ff-overlay.js
+++ b/third_party/firefox_sendtophone/chrome/content/ff-overlay.js
@@ -102,8 +102,11 @@ sendtophone.checkDrag = function(event)
{
//event.dataTransfer.dropEffect = "copy";
var types = event.dataTransfer.types;
- if (types.contains("text/plain") || types.contains("text/uri-list") || types.contains("text/x-moz-url") || types.contains("application/x-moz-file"))
+ if (types.contains("text/plain") || types.contains("text/uri-list") || types.contains("text/x-moz-url"))
event.preventDefault();
+
+ if (this.prefs.getCharPref( "fileServerUrl" ) && types.contains("application/x-moz-file") )
+ event.preventDefault();
}
sendtophone.doDrop = function(event)
@@ -154,8 +157,10 @@ sendtophone.pickFile = function(folder)
if (folder)
fp.init(window, this.strings.getString("SendFolderToPhone"), Ci.nsIFilePicker.modeGetFolder);
else
+ {
fp.init(window, this.strings.getString("SendFileToPhone"), Ci.nsIFilePicker.modeOpenMultiple);
- fp.appendFilters(Ci.nsIFilePicker.filterAll | Ci.nsIFilePicker.filterImages);
+ fp.appendFilters(Ci.nsIFilePicker.filterAll | Ci.nsIFilePicker.filterImages);
+ }
var rv = fp.show();
diff --git a/third_party/firefox_sendtophone/chrome/content/ff-overlay.xul b/third_party/firefox_sendtophone/chrome/content/ff-overlay.xul
index 3260fc5..3c3d95c 100644
--- a/third_party/firefox_sendtophone/chrome/content/ff-overlay.xul
+++ b/third_party/firefox_sendtophone/chrome/content/ff-overlay.xul
@@ -10,10 +10,10 @@
-
+
-
+
-
- %downloadDTD;
+
+ %downloadManagerDTD;
+
+ %uploadDTD;
]>
-
-
diff --git a/third_party/firefox_sendtophone/chrome/content/uploads.js b/third_party/firefox_sendtophone/chrome/content/uploads.js
index 1e0a7b7..56f9efd 100644
--- a/third_party/firefox_sendtophone/chrome/content/uploads.js
+++ b/third_party/firefox_sendtophone/chrome/content/uploads.js
@@ -65,8 +65,8 @@ let gUploadListener = {
gUploadsView.removeChild(item);
// If no more pending uploads, close the tab.
- // Use a 100ms timeout to avoid flicker while compress -> upload a folder
- window.setTimeout( checkPendingUploads, 100);
+ // Use a 0 ms timeout to avoid flicker while compress -> upload a folder
+ window.setTimeout( checkPendingUploads, 0);
}
};
diff --git a/third_party/firefox_sendtophone/chrome/content/uploads.xul b/third_party/firefox_sendtophone/chrome/content/uploads.xul
index bbd27ad..367bc68 100644
--- a/third_party/firefox_sendtophone/chrome/content/uploads.xul
+++ b/third_party/firefox_sendtophone/chrome/content/uploads.xul
@@ -10,19 +10,6 @@
onload="Startup();" onunload="Shutdown();"
onclose="return closeWindow(false);">
-
-
diff --git a/third_party/firefox_sendtophone/chrome/locale/en/overlay.properties b/third_party/firefox_sendtophone/chrome/locale/en/overlay.properties
index c6ec434..08120a0 100644
--- a/third_party/firefox_sendtophone/chrome/locale/en/overlay.properties
+++ b/third_party/firefox_sendtophone/chrome/locale/en/overlay.properties
@@ -17,3 +17,5 @@ InvalidFile=Not a valid file
SendFileToPhone=Send files to your phone.
SendFolderToPhone=Send a folder to your phone.
qrTitle=QR Image Link
+FileUploadsDisabled=It's not possible to upload files to the phone.
+FileTooBig=The file is too big.
diff --git a/third_party/firefox_sendtophone/chrome/locale/en/uploads.dtd b/third_party/firefox_sendtophone/chrome/locale/en/uploads.dtd
index 4c92f20..4bc5eab 100644
--- a/third_party/firefox_sendtophone/chrome/locale/en/uploads.dtd
+++ b/third_party/firefox_sendtophone/chrome/locale/en/uploads.dtd
@@ -1,3 +1 @@
-
-
diff --git a/third_party/firefox_sendtophone/chrome/locale/es/overlay.properties b/third_party/firefox_sendtophone/chrome/locale/es/overlay.properties
index 8d835d0..b67efa4 100644
--- a/third_party/firefox_sendtophone/chrome/locale/es/overlay.properties
+++ b/third_party/firefox_sendtophone/chrome/locale/es/overlay.properties
@@ -17,3 +17,5 @@ InvalidFile=No es un fichero válido.
SendFileToPhone=Envía ficheros al teléfono.
SendFolderToPhone=Envía una carpeta al teléfono.
qrTitle=Imagen QR
+FileUploadsDisabled=No se pueden enviar ficheros al teléfono.
+FileTooBig=El fichero que quiere enviar es demasiado grande.
diff --git a/third_party/firefox_sendtophone/chrome/locale/es/uploads.dtd b/third_party/firefox_sendtophone/chrome/locale/es/uploads.dtd
index 0a6f0a9..66aae1c 100644
--- a/third_party/firefox_sendtophone/chrome/locale/es/uploads.dtd
+++ b/third_party/firefox_sendtophone/chrome/locale/es/uploads.dtd
@@ -1,3 +1 @@
-
-
diff --git a/third_party/firefox_sendtophone/defaults/preferences/prefs.js b/third_party/firefox_sendtophone/defaults/preferences/prefs.js
index fca6c0d..68b98fd 100644
--- a/third_party/firefox_sendtophone/defaults/preferences/prefs.js
+++ b/third_party/firefox_sendtophone/defaults/preferences/prefs.js
@@ -3,6 +3,7 @@ pref("extensions.sendtophone.appUrl", "https://chrometophone.appspot.com");
pref("extensions.sendtophone.proxyUrl", "http://smallroomstudios.net/s2p.php?ml=");
pref("extensions.sendtophone.fileServerUrl", "http://martinezdelizarrondo.com/sendtophone.php");
+pref("extensions.sendtophone.fileUploadMaxKb", 50000);
pref("extensions.sendtophone.protocols.market", true);
pref("extensions.sendtophone.protocols.sms", true);
diff --git a/third_party/firefox_sendtophone/modules/sendtophone.js b/third_party/firefox_sendtophone/modules/sendtophone.js
index 836d804..2d93e9b 100644
--- a/third_party/firefox_sendtophone/modules/sendtophone.js
+++ b/third_party/firefox_sendtophone/modules/sendtophone.js
@@ -43,7 +43,7 @@ var sendtophoneCore = {
this.sendUrl = baseUrl + '/send?ver=' + this.apiVersion;
this.logInUrl = baseUrl + '/signin?ver=' + this.apiVersion + '&extret=' + encodeURIComponent(this.loggedInUrl);
this.logOutUrl = baseUrl + '/signout?ver=' + this.apiVersion + '&extret=' + encodeURIComponent(this.loggedOutUrl);
- },
+ },
getString: function(name)
{
@@ -53,10 +53,10 @@ var sendtophoneCore = {
// Shows a message in a modal alert
alert: function(text)
{
- var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"]
- .getService(Ci.nsIPromptService);
- promptService.alert(null, this.getString("SendToPhoneTitle"),
- text);
+ var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"]
+ .getService(Ci.nsIPromptService);
+ promptService.alert(null, this.getString("SendToPhoneTitle"),
+ text);
},
// Shows a message in a growl-like notification
@@ -96,7 +96,7 @@ var sendtophoneCore = {
processXHR: function(url, method, data, callback)
{
- var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
+ var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
req.open(method, url, true);
@@ -137,16 +137,16 @@ var sendtophoneCore = {
};
// To send correctly cookies.
- // Force the request to include cookies even though this chrome code
- // is seen as a third-party, so the server knows the user for which we are
- // requesting favorites (or anything else user-specific in the future).
- // This only works in Firefox 3.6; in Firefox 3.5 the request will instead
- // fail to send cookies if the user has disabled third-party cookies.
- try {
- req.channel.QueryInterface(Ci.nsIHttpChannelInternal).
- forceAllowThirdPartyCookie = true;
- }
- catch(ex) { /* user is using Firefox 3.5 */ }
+ // Force the request to include cookies even though this chrome code
+ // is seen as a third-party, so the server knows the user for which we are
+ // requesting favorites (or anything else user-specific in the future).
+ // This only works in Firefox 3.6; in Firefox 3.5 the request will instead
+ // fail to send cookies if the user has disabled third-party cookies.
+ try {
+ req.channel.QueryInterface(Ci.nsIHttpChannelInternal).
+ forceAllowThirdPartyCookie = true;
+ }
+ catch(ex) { /* user is using Firefox 3.5 */ }
req.send( data );
},
@@ -182,12 +182,12 @@ var sendtophoneCore = {
selection = selection.substring(0, max_length);
// Send the protocols that aren't currently whitelisted through a proxy server
- if (!(/^(https?):/i).test( url ))
- {
- // Rewrite the URI so it's send first to the proxy
- var proxyUrl = this.prefs.getCharPref( "proxyUrl" ) ;
+ if (!(/^(https?):/i).test( url ))
+ {
+ // Rewrite the URI so it's send first to the proxy
+ var proxyUrl = this.prefs.getCharPref( "proxyUrl" );
if (proxyUrl)
- url = proxyUrl + encodeURIComponent( url);
+ url = proxyUrl + encodeURIComponent( url);
}
var data = 'title=' + encodeURIComponent(title) +
@@ -230,6 +230,9 @@ var sendtophoneCore = {
logout: function()
{
+ if (!this.prefs)
+ this.init();
+
// Open Google logout page, and close tab when finished
this.openTab(this.logOutUrl, this.loggedOutUrl, function() {sendtophoneCore.logoutSuccessful();} );
@@ -263,7 +266,7 @@ var sendtophoneCore = {
callback();
// Close tab
- gBrowser.removeTab(c2pTab);
+ gBrowser.removeTab(tab);
// ReFocus on tab being sent
gBrowser.selectedTab = gBrowser.tabContainer.childNodes[lastTabIndex];
}
@@ -297,6 +300,13 @@ var sendtophoneCore = {
{
if (!this.prefs)
this.init();
+
+ let uri = this.prefs.getCharPref( "fileServerUrl" );
+ if (!uri)
+ {
+ this.alert( this.getString("FileUploadsDisabled") );
+ return;
+ }
if (typeof sendtophoneUploadsManager == "undefined")
Components.utils.import("resource://sendtophone/uploadsManager.js");
@@ -304,7 +314,7 @@ var sendtophoneCore = {
if (nsFile.isDirectory())
{
// There's no progress notification while compressing, only on end.
- var progressId = sendtophoneUploadsManager.addZip(nsFile);
+ let progressId = sendtophoneUploadsManager.addZip(nsFile);
// Compress the contents to a zip file
zipFolder(nsFile, function(nsZip)
{
@@ -322,8 +332,16 @@ var sendtophoneCore = {
this.alert(this.getString("InvalidFile"));
return;
}
-
- var uploadName = nsFile.leafName;
+
+ let size = Math.round(nsFile.fileSize / 1024);
+ let maxSize = this.prefs.getIntPref( "fileUploadMaxKb" );
+ if (maxSize>0 && size>maxSize)
+ {
+ this.alert( this.getString("FileTooBig") );
+ return;
+ }
+
+ let uploadName = nsFile.leafName;
// Try to determine the MIME type of the file
var mimeType = "text/plain";
try {
@@ -340,23 +358,24 @@ var sendtophoneCore = {
var bufInStream = Cc["@mozilla.org/network/buffered-input-stream;1"]
.createInstance(Ci.nsIBufferedInputStream);
bufInStream.init(inStream, 4096);
-
- //Setup the boundary start stream
+
+ //Setup the boundary start stream
var boundary = "--SendToPhone-------------" + Math.random();
var startBoundryStream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
startBoundryStream.setData("\r\n--"+boundary+"\r\n",-1);
-
- // Setup the boundary end stream
- var endBoundryStream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
+
+ // Setup the boundary end stream
+ var endBoundryStream = Cc["@mozilla.org/io/string-input-stream;1"]
+ .createInstance(Ci.nsIStringInputStream);
endBoundryStream.setData("\r\n--"+boundary+"--",-1);
-
- // Setup the mime-stream - the 'part' of a multi-part mime type
- var mimeStream = Cc["@mozilla.org/network/mime-input-stream;1"].createInstance(Ci.nsIMIMEInputStream);
- mimeStream.addContentLength = false;
- mimeStream.addHeader("Content-disposition","form-data; charset: utf-8; name=\"upload\"; filename=\"" + this.toUTF8(uploadName) + "\"");
- mimeStream.addHeader("Content-type", mimeType);
- mimeStream.setData(bufInStream);
+
+ // Setup the mime-stream - the 'part' of a multi-part mime type
+ var mimeStream = Cc["@mozilla.org/network/mime-input-stream;1"].createInstance(Ci.nsIMIMEInputStream);
+ mimeStream.addContentLength = false;
+ mimeStream.addHeader("Content-disposition","form-data; charset: utf-8; name=\"upload\"; filename=\"" + this.toUTF8(uploadName) + "\"");
+ mimeStream.addHeader("Content-type", mimeType);
+ mimeStream.setData(bufInStream);
// Setup a multiplex stream
var multiStream = Cc["@mozilla.org/io/multiplex-input-stream;1"]
@@ -364,9 +383,6 @@ var sendtophoneCore = {
multiStream.appendStream(startBoundryStream);
multiStream.appendStream(mimeStream);
multiStream.appendStream(endBoundryStream);
- var size = Math.round(nsFile.fileSize / 1024);
-
- var uri = this.prefs.getCharPref( "fileServerUrl" );
var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
@@ -399,25 +415,29 @@ var sendtophoneCore = {
// Handle errors or aborted uploads
req.addEventListener("error", function(evt)
{
+ sendtophoneCore.alert("Error while sending the file to the server:\r\n" + uri);
+
// If there's a callback (to delete temporary files) we call it now
if (callback)
callback();
}, false);
req.addEventListener("abort", function(evt)
{
+ // Silent.
+
// If there's a callback (to delete temporary files) we call it now
if (callback)
callback();
}, false);
- /*
- if required for cookies... don't think so.
+ /*
+ if required for cookies... don't think so.
try {
req.channel.QueryInterface(Ci.nsIHttpChannelInternal).
forceAllowThirdPartyCookie = true;
}
catch(ex) {}
- */
+ */
req.send(multiStream);
}
diff --git a/third_party/firefox_sendtophone/modules/uploadsManager.js b/third_party/firefox_sendtophone/modules/uploadsManager.js
index fda28a6..e239499 100644
--- a/third_party/firefox_sendtophone/modules/uploadsManager.js
+++ b/third_party/firefox_sendtophone/modules/uploadsManager.js
@@ -36,7 +36,7 @@ var sendtophoneUploadsManager = {
addUpload: function(nsFile, req)
{
let id = this._addToUploads( {file:nsFile, req:req, state:0, percent:0,
- startTime: Date.now(), currBytes: 0, maxBytes: nsFile.fileSize} );
+ startTime: Date.now() - 100, currBytes: 0, maxBytes: nsFile.fileSize} );
req.upload.addEventListener("progress", function(evt)
{
@@ -79,7 +79,7 @@ var sendtophoneUploadsManager = {
_addToUploads: function( obj )
{
- this.init();
+ initShowTest();
// Creates a counter to automatically assign new ids to each upload
let id = this._counter++;
@@ -92,7 +92,7 @@ var sendtophoneUploadsManager = {
return id;
},
- init: function()
+ showWindow: function()
{
// Open the tab
openAndReuseOneTabPerURL("chrome://sendtophone/content/uploads.xul");
@@ -101,6 +101,23 @@ var sendtophoneUploadsManager = {
updateProgress: function(id, loaded, total)
{
let upload = this.uploads[id];
+
+ // The progress events are fired when the data is sent,
+ // but that leads to wrong speed because we don't know how long
+ // it has really taken to process the packet
+ // As long as the upload progress the speed converges to a more correct value
+ // But here we will try to adjust it (fake it) sooner
+ if (!upload.firstPacket)
+ upload.firstPacket = Date.now();
+ else
+ if (!upload.adjusted)
+ {
+ upload.adjusted = true;
+// let elapsed = Date.now() - upload.firstPacket; // time to send a packet to the server and get back
+ let elapsed = Date.now() - upload.startTime; //
+ upload.startTime = upload.startTime - elapsed;
+ }
+
upload.currBytes = loaded;
upload.maxBytes = total;
@@ -114,6 +131,14 @@ var sendtophoneUploadsManager = {
let upload = this.uploads[id];
delete this.uploads[id];
+ // Review if there are pending files to cancel the show timer
+ let count = 0;
+ for(let id in this.uploads)
+ count++;
+ if (count == 0)
+ cancelShowTimer();
+
+ // Notify the listeners
this._listeners.forEach( function( listener ) {
listener.fileFinished( upload );
});
@@ -124,9 +149,90 @@ var sendtophoneUploadsManager = {
let upload = this.uploads[id];
upload.req.abort();
+ },
+
+ // For use while debugging
+ toConsole: function(text)
+ {
+ var aConsoleService = Cc["@mozilla.org/consoleservice;1"]
+ .getService(Ci.nsIConsoleService);
+
+ aConsoleService.logStringMessage( text );
+ },
+
+ // Check if we might need to show the window.
+ // Either some folder is being compressed,
+ // or there's some file that might take longer than 2 seconds.
+ // If there's some file that we still don't know the speed
+ // then consider it also as needed.
+ isWindowNeeded: function()
+ {
+ for (let id in this.uploads)
+ {
+ let upload = this.uploads[id] ;
+
+ // zipping folder: if takes so long to compress it, it will also take some time to upload it
+ if (upload.state==1)
+ return true;
+
+ // If it still hasn't uploaded anything then something might be wrong
+ if (upload.currBytes==0)
+ return true;
+
+ let elapsedTime = (Date.now() - upload.startTime) / 1000;
+ let speed = upload.currBytes/elapsedTime;
+ let remainingSecs = (upload.maxBytes - upload.currBytes) / speed;
+// this.toConsole(elapsedTime + " " + speed + " " + remainingSecs);
+
+ if (remainingSecs > 2)
+ return true;
+
+// if (remainingSecs > 1 && elapsedTime> 2)
+// return true;
+ }
}
}
+/**
+* Internal function
+* Instead of poping up the uploads window inmediately wait a little
+* trying to avoid flicker for small files
+*/
+let showTimer = null;
+
+// we need a nsITimerCallback compatible...
+// ... interface for the callbacks.
+var showTimerEvent =
+{
+ notify: function(timer)
+ {
+ if (sendtophoneUploadsManager.isWindowNeeded())
+ {
+ cancelShowTimer();
+ sendtophoneUploadsManager.showWindow();
+ }
+ }
+}
+
+function initShowTest()
+{
+ if (showTimer)
+ return;
+
+ // Now it is time to create the timer...
+ showTimer = Components.classes["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ showTimer.initWithCallback(showTimerEvent, 400, Ci.nsITimer.TYPE_REPEATING_SLACK);
+}
+
+function cancelShowTimer()
+{
+ if (!showTimer)
+ return;
+
+ showTimer.cancel();
+ showTimer = null
+}
+
// https://developer.mozilla.org/en/Code_snippets/Tabbed_browser#Reusing_tabs
function openAndReuseOneTabPerURL(url) {
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]