Bug 767327 - Add box.com to file link services. r=mconley
This commit is contained in:
Родитель
8f66bd4ed2
Коммит
cdd3eb3be4
|
@ -5,3 +5,7 @@ category cloud-files YouSendIt @mozilla.org/mail/yousendit;1
|
|||
component {9a44742b-a7b1-4f44-919e-6f3b28902c1a} nsUbuntuOne.js
|
||||
contract @mozilla.org/mail/ubuntuone;1 {9a44742b-a7b1-4f44-919e-6f3b28902c1a}
|
||||
category cloud-files UbuntuOne @mozilla.org/mail/ubuntuone;1
|
||||
|
||||
component {c06a8707-7463-416c-8b39-e85044a4ff6e} nsBox.js
|
||||
contract @mozilla.org/mail/box;1 {c06a8707-7463-416c-8b39-e85044a4ff6e}
|
||||
category cloud-files Box @mozilla.org/mail/box;1
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Modeled on browserRequest used by the OAuth module */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
@ -9,11 +11,15 @@ const Cr = Components.results;
|
|||
|
||||
Cu.import("resource:///modules/http.jsm");
|
||||
Cu.import("resource:///modules/gloda/log4moz.js");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const wpl = Ci.nsIWebProgressListener;
|
||||
|
||||
const kApiKey = "exs8m0agj1fa5728lxvn288ymz01dnzn";
|
||||
const kServerUrl = "https://www.box.com/api/1.0/rest";
|
||||
const kAuthUrl = "https://www.box.com/api/1.0/auth/";
|
||||
|
||||
const log = Log4Moz.getConfiguredLogger("BoxAuth");
|
||||
|
||||
var reporterListener = {
|
||||
_isBusy: false,
|
||||
|
@ -22,13 +28,9 @@ var reporterListener = {
|
|||
return this.securityButton = document.getElementById("security-button");
|
||||
},
|
||||
|
||||
QueryInterface: function(aIID) {
|
||||
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
|
||||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
|
||||
aIID.equals(Components.interfaces.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference,
|
||||
Ci.nsISupports]),
|
||||
|
||||
onStateChange: function(/*in nsIWebProgress*/ aWebProgress,
|
||||
/*in nsIRequest*/ aRequest,
|
||||
|
@ -66,7 +68,7 @@ var reporterListener = {
|
|||
wpl.STATE_SECURE_MED |
|
||||
wpl.STATE_SECURE_LOW;
|
||||
let browser = document.getElementById("requestFrame");
|
||||
var level;
|
||||
let level;
|
||||
|
||||
switch (aState & wpl_security_bits) {
|
||||
case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_HIGH:
|
||||
|
@ -82,6 +84,7 @@ var reporterListener = {
|
|||
}
|
||||
if (level) {
|
||||
this.securityButton.setAttribute("level", level);
|
||||
this.securityButton.removeAttribute("loading");
|
||||
this.securityButton.hidden = false;
|
||||
} else {
|
||||
this.securityButton.hidden = true;
|
||||
|
@ -92,29 +95,46 @@ var reporterListener = {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The authorization process is:
|
||||
* - We load this window and immediately make a ticket request
|
||||
* - With the returned ticket, we make a url and load it into the browser
|
||||
* - The user logs in, and our opener listens for a redirect url
|
||||
* - The redirect url contains the ticket and the auth token
|
||||
* - The opener, when satisfied it has what it needs, closes this window
|
||||
* - If the ticket call produces an error, we try again
|
||||
*/
|
||||
|
||||
function onLoad()
|
||||
{
|
||||
document.getElementById("security-button").setAttribute("loading", "true");
|
||||
let request = window.arguments[0].wrappedJSObject;
|
||||
document.getElementById("headerMessage").textContent = request.promptText;
|
||||
//let account = request.account;
|
||||
|
||||
// headerImage does not exist in the XUL. I wonder if the original intention was security-button?
|
||||
// I wonder, should we set the url-bar-type url holder to have the service icon?
|
||||
//if (request.iconURI != "")
|
||||
// document.getElementById("headerImage").src = request.iconURI;
|
||||
|
||||
nsBoxAuth.getSessionTicket(function(aTicket) {
|
||||
var authUrl = "https://www.box.com/api/1.0/auth/" + aTicket;
|
||||
loadRequestedUrl(authUrl);
|
||||
},
|
||||
function (aReq) {
|
||||
alert("get_ticket failed - status = " + aReq.status);
|
||||
// XX TODO Handle this some way in the auth window
|
||||
// Any ideas?
|
||||
// OR
|
||||
// Just close the window and let the opener handle the failure
|
||||
// cancelRequest();
|
||||
});
|
||||
nsBoxAuth.numTries = 0;
|
||||
setupTicketRequest();
|
||||
}
|
||||
|
||||
function setupTicketRequest()
|
||||
{
|
||||
let successCallback = function (aTicket) {
|
||||
let authUrl = kAuthUrl + aTicket;
|
||||
loadRequestedUrl(authUrl);
|
||||
};
|
||||
let failureCallback = function (aReq) {
|
||||
// retry
|
||||
if (nsBoxAuth.numTries < 3) {
|
||||
log.error("get_ticket failed, trying again - status = " + aReq.status);
|
||||
setupTicketRequest();
|
||||
}
|
||||
else {
|
||||
// give up after 3 tries
|
||||
log.error("get_ticket failed, giving up - status = " + aReq.status);
|
||||
cancelRequest();
|
||||
}
|
||||
};
|
||||
|
||||
nsBoxAuth.getSessionTicket(successCallback, failureCallback);
|
||||
}
|
||||
|
||||
function cancelRequest()
|
||||
|
@ -132,14 +152,10 @@ function reportUserClosed()
|
|||
function loadRequestedUrl(aUrl)
|
||||
{
|
||||
let request = window.arguments[0].wrappedJSObject;
|
||||
/*document.getElementById("headerMessage").textContent = request.promptText;
|
||||
let account = request.account;
|
||||
if (request.iconURI != "")
|
||||
document.getElementById("headerImage").src = request.iconURI;*/
|
||||
|
||||
var browser = document.getElementById("requestFrame");
|
||||
let browser = document.getElementById("requestFrame");
|
||||
browser.addProgressListener(reporterListener,
|
||||
Components.interfaces.nsIWebProgress.NOTIFY_ALL);
|
||||
Ci.nsIWebProgress.NOTIFY_ALL);
|
||||
if (aUrl != "") {
|
||||
browser.setAttribute("src", aUrl);
|
||||
document.getElementById("headerMessage").textContent = aUrl;
|
||||
|
@ -149,47 +165,63 @@ function loadRequestedUrl(aUrl)
|
|||
|
||||
var nsBoxAuth = {
|
||||
|
||||
log : Log4Moz.getConfiguredLogger("BoxAuth"),
|
||||
numTries : 0,
|
||||
|
||||
/**
|
||||
* A function for retrieving a new ticket needed for other API calls.
|
||||
* The lifespan of a ticket is only a few minutes for authentication
|
||||
* A function for retrieving a new ticket to use in the url for logging in
|
||||
* The lifespan of a ticket is only a few minutes
|
||||
*
|
||||
* @param ...
|
||||
* @param successCallback a callback fired if retrieving the ticket
|
||||
* is successful.
|
||||
* @param failureCallback a callback fired if retrieving the ticket
|
||||
* fails.
|
||||
*/
|
||||
getSessionTicket: function(successCallback, failureCallback) {
|
||||
let args = "?action=get_ticket&api_key=" + kApiKey;
|
||||
let requestUrl = kServerUrl + args;
|
||||
let args = "?action=get_ticket&api_key=" + kApiKey;
|
||||
let requestUrl = kServerUrl + args;
|
||||
|
||||
// Request to get the ticket
|
||||
doXHRequest(requestUrl,
|
||||
null,
|
||||
null,
|
||||
function(aResponseText, aRequest) {
|
||||
this.log.info("get_ticket request response = " + aResponseText);
|
||||
let doc = aRequest.responseXML;
|
||||
let docResponse = doc.documentElement;
|
||||
if (docResponse && docResponse.nodeName == "response") {
|
||||
let docStatus = doc.getElementsByTagName("status")[0].firstChild.nodeValue;
|
||||
this.log.info("status = " + docStatus);
|
||||
if (docStatus != "get_ticket_ok") {
|
||||
failureCallback(null, aResponseText, aRequest);
|
||||
return;
|
||||
}
|
||||
var ticket = doc.getElementsByTagName("ticket")[0].firstChild.nodeValue;
|
||||
this.log.info("Auth ticket = " + ticket);
|
||||
successCallback(ticket);
|
||||
}
|
||||
else {
|
||||
failureCallback("", aResponseText, aRequest);
|
||||
}
|
||||
}.bind(this),
|
||||
function(aException, aResponseText, aRequest) {
|
||||
this.log.info("Failed to acquire a ticket:" + aResponseText);
|
||||
failureCallback(aException, aResponseText, aRequest);
|
||||
}.bind(this),
|
||||
let ticketSuccess = function(aResponseText, aRequest) {
|
||||
log.info("get_ticket request response = " + aResponseText);
|
||||
try {
|
||||
let doc = aRequest.responseXML;
|
||||
let docResponse = doc.documentElement;
|
||||
if (docResponse && docResponse.nodeName == "response") {
|
||||
let docStatus = doc.getElementsByTagName("status")[0].firstChild.nodeValue;
|
||||
log.info("status = " + docStatus);
|
||||
if (docStatus != "get_ticket_ok") {
|
||||
failureCallback(aRequest);
|
||||
return;
|
||||
}
|
||||
let ticket = doc.getElementsByTagName("ticket")[0].firstChild.nodeValue;
|
||||
log.info("Auth ticket = " + ticket);
|
||||
successCallback(ticket);
|
||||
}
|
||||
else {
|
||||
log.error("Failed to acquire a ticket: " + aResponseText);
|
||||
failureCallback(aRequest);
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
// most likely bad XML
|
||||
log.error("Failed to parse ticket response: " + e);
|
||||
log.error("Ticket response: " + aResponseText);
|
||||
failureCallback(aRequest);
|
||||
}
|
||||
}.bind(this);
|
||||
let ticketFailure = function(aException, aResponseText, aRequest) {
|
||||
log.error("Ticket acquisition error: " + aResponseText);
|
||||
failureCallback(aRequest);
|
||||
}.bind(this)
|
||||
|
||||
// Request to get the ticket
|
||||
doXHRequest(requestUrl,
|
||||
null,
|
||||
null,
|
||||
ticketSuccess,
|
||||
ticketFailure,
|
||||
this,
|
||||
"GET");
|
||||
this.numTries++;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<!-- Modeled on browserRequest used by the OAuth module -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/browserRequest.css" type="text/css"?>
|
||||
|
||||
|
@ -14,9 +16,7 @@
|
|||
buttons=","
|
||||
onload="onLoad()"
|
||||
onclose="reportUserClosed()"
|
||||
title="&auth.title;"
|
||||
width="850"
|
||||
height="500">
|
||||
title="&auth.title;">
|
||||
|
||||
<script type="application/javascript" src="chrome://messenger/content/cloudfile/Box/auth.js"/>
|
||||
|
||||
|
@ -27,15 +27,15 @@
|
|||
|
||||
<hbox id="header">
|
||||
<hbox id="addressbox" flex="1" disabled="true">
|
||||
<image id="security-button" src="chrome://messenger/skin/icons/mailicon32.png"/>
|
||||
<image id="security-button"/>
|
||||
<description id="headerMessage"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
|
||||
<browser type="content"
|
||||
disablehistory="true"
|
||||
src="chrome://messenger/content/cloudfile/Box/loader.gif"
|
||||
id="requestFrame"
|
||||
<browser type="content"
|
||||
disablehistory="true"
|
||||
src="about:blank"
|
||||
id="requestFrame"
|
||||
flex="1"/>
|
||||
|
||||
</window>
|
||||
|
|
Двоичные данные
mail/components/cloudfile/content/Box/loader.gif
Двоичные данные
mail/components/cloudfile/content/Box/loader.gif
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 2.5 KiB |
|
@ -12,7 +12,6 @@ messenger.jar:
|
|||
content/messenger/cloudfile/Box/management.js (content/Box/management.js)
|
||||
content/messenger/cloudfile/Box/auth.xul (content/Box/auth.xul)
|
||||
content/messenger/cloudfile/Box/auth.js (content/Box/auth.js)
|
||||
content/messenger/cloudfile/Box/loader.gif (content/Box/loader.gif)
|
||||
content/messenger/cloudfile/UbuntuOne/management.js (content/UbuntuOne/management.js)
|
||||
content/messenger/cloudfile/UbuntuOne/management.xhtml (content/UbuntuOne/management.xhtml)
|
||||
content/messenger/cloudfile/UbuntuOne/settings.js (content/UbuntuOne/settings.js)
|
||||
|
|
|
@ -17,6 +17,8 @@ Cu.import("resource:///modules/cloudFileAccounts.js");
|
|||
Cu.import("resource:///modules/http.jsm");
|
||||
|
||||
var gServerUrl = "https://www.box.com/api/1.0/rest";
|
||||
var gUploadUrl = "https://upload.box.net/api/1.0/upload/";
|
||||
var gSharingUrl = "https://www.box.com/shared/";
|
||||
|
||||
const kApiKey = "exs8m0agj1fa5728lxvn288ymz01dnzn";
|
||||
|
||||
|
@ -51,9 +53,6 @@ nsBox.prototype = {
|
|||
_loggedIn: false,
|
||||
_userInfo: null,
|
||||
_file : null,
|
||||
_requestDate: null,
|
||||
_successCallback: null,
|
||||
_request: null,
|
||||
_maxFileSize : -1,
|
||||
_fileSpaceUsed : -1,
|
||||
_totalStorage : -1,
|
||||
|
@ -88,29 +87,32 @@ nsBox.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Private function for retrieving or creating folder
|
||||
* on the Box website for uploading file.
|
||||
* Private function for assigning the folder id from a cached version
|
||||
* If the folder doesn't exist, set in motion the creation
|
||||
*
|
||||
* @param aCallback called if folder is ready.
|
||||
*/
|
||||
_initFolder: function nsBox__initFolder(aCallback) {
|
||||
this.log.info('_initFolder');
|
||||
|
||||
this.log.info('_initFolder, cached folder id = ' + this._cachedFolderId);
|
||||
|
||||
let saveFolderId = function(aFolderId) {
|
||||
this.log.info('saveFolderId');
|
||||
this._folderId = aFolderId;
|
||||
this.log.info('saveFolderId : ' + aFolderId);
|
||||
this._cachedFolderId = this._folderId = aFolderId;
|
||||
if (aCallback)
|
||||
aCallback();
|
||||
}.bind(this);
|
||||
|
||||
let createThunderbirdFolder = function(aParentFolderId) {
|
||||
this._createFolder("Thunderbird", aParentFolderId, saveFolderId);
|
||||
let createThunderbirdFolder = function() {
|
||||
this._createFolder("Thunderbird", saveFolderId);
|
||||
}.bind(this);
|
||||
|
||||
if (this._folderId == "")
|
||||
if (this._cachedFolderId == "")
|
||||
createThunderbirdFolder();
|
||||
else
|
||||
this.createThunderbirdFolder(saveFolderId);
|
||||
else {
|
||||
this._folderId = this._cachedFolderId;
|
||||
if (aCallback)
|
||||
aCallback();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -221,9 +223,9 @@ nsBox.prototype = {
|
|||
|
||||
if (!this._uploader) {
|
||||
this._uploader = new nsBoxFileUploader(this, aFile,
|
||||
this._uploaderCallback
|
||||
.bind(this),
|
||||
aCallback);
|
||||
this._uploaderCallback
|
||||
.bind(this),
|
||||
aCallback);
|
||||
this._uploads.unshift(this._uploader);
|
||||
}
|
||||
|
||||
|
@ -260,63 +262,74 @@ nsBox.prototype = {
|
|||
* fails.
|
||||
*/
|
||||
_getUserInfo: function nsBox__getUserInfo(successCallback, failureCallback) {
|
||||
let args = "?action=get_account_info&api_key=" + kApiKey
|
||||
let args = "?action=get_account_info&api_key=" + kApiKey
|
||||
+ "&auth_token=" + this._cachedAuthToken;
|
||||
let requestUrl = gServerUrl + args;
|
||||
this.log.info("requestUrl = " + requestUrl);
|
||||
this.log.info("get_account_info requestUrl = " + requestUrl);
|
||||
|
||||
if (!successCallback)
|
||||
successCallback = function() {
|
||||
this.requestObserver
|
||||
.onStopRequest(null, null,
|
||||
this._loggedIn ? Cr.NS_OK : Ci.nsIMsgCloudFileProvider.authErr);
|
||||
}.bind(this);
|
||||
}.bind(this);
|
||||
|
||||
if (!failureCallback)
|
||||
failureCallback = function () {
|
||||
this.requestObserver
|
||||
.onStopRequest(null, null, Ci.nsIMsgCloudFileProvider.authErr);
|
||||
}.bind(this);
|
||||
}.bind(this);
|
||||
|
||||
let accountInfoSuccess = function(aResponseText, aRequest) {
|
||||
this.log.info("get_account_info request response = " + aResponseText);
|
||||
|
||||
try {
|
||||
let doc = aRequest.responseXML;
|
||||
let docResponse = doc.documentElement;
|
||||
if (docResponse && docResponse.nodeName == "response") {
|
||||
let docStatus = doc.getElementsByTagName("status")[0].firstChild.nodeValue;
|
||||
this.log.info("get_account_info status = " + docStatus);
|
||||
if (docStatus != "get_account_info_ok") {
|
||||
this.failureCallback();
|
||||
return;
|
||||
}
|
||||
this._userInfo = aResponseText;
|
||||
|
||||
this._totalStorage = doc.getElementsByTagName("space_amount")[0].firstChild.nodeValue;
|
||||
this._fileSpaceUsed = doc.getElementsByTagName("space_used")[0].firstChild.nodeValue;
|
||||
this._maxFileSize = doc.getElementsByTagName("max_upload_size")[0].firstChild.nodeValue;
|
||||
this.log.info("storage total = " + this._totalStorage);
|
||||
this.log.info("storage used = " + this._fileSpaceUsed);
|
||||
this.log.info("max file size = " + this._maxFileSize);
|
||||
successCallback();
|
||||
}
|
||||
else {
|
||||
failureCallback();
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
// most likely bad XML
|
||||
this.log.error("Failed to parse account info response: " + e);
|
||||
this.log.error("Account info response: " + aResponseText);
|
||||
failureCallback();
|
||||
}
|
||||
}.bind(this);
|
||||
let accountInfoFailure = function(aException, aResponseText, aRequest) {
|
||||
this.log.info("Failed to acquire user info:" + aResponseText);
|
||||
this.log.error("user info failed, status = " + aRequest.status);
|
||||
this.log.error("response text = " + aResponseText);
|
||||
this.log.error("exception = " + aException);
|
||||
failureCallback();
|
||||
}.bind(this)
|
||||
|
||||
// Request to get user info
|
||||
doXHRequest(requestUrl,
|
||||
doXHRequest(requestUrl,
|
||||
null,
|
||||
null,
|
||||
function(aResponseText, aRequest) {
|
||||
this.log.info("get_account_info request response = " + aResponseText);
|
||||
|
||||
let doc = aRequest.responseXML;
|
||||
let docResponse = doc.documentElement;
|
||||
if (docResponse && docResponse.nodeName == "response") {
|
||||
let docStatus = doc.getElementsByTagName("status")[0].firstChild.nodeValue;
|
||||
this.log.info("get_account_info status = " + docStatus);
|
||||
if (docStatus != "get_account_info_ok") {
|
||||
this.failureCallback();
|
||||
return;
|
||||
}
|
||||
this._userInfo = aResponseText;
|
||||
|
||||
this._totalStorage = doc.getElementsByTagName("space_amount")[0].firstChild.nodeValue;
|
||||
this._fileSpaceUsed = doc.getElementsByTagName("space_used")[0].firstChild.nodeValue;
|
||||
this._maxFileSize = doc.getElementsByTagName("max_upload_size")[0].firstChild.nodeValue;
|
||||
this.log.info("storage total = " + this._totalStorage);
|
||||
this.log.info("storage used = " + this._fileSpaceUsed);
|
||||
this.log.info("max file size = " + this._maxFileSize);
|
||||
successCallback();
|
||||
}
|
||||
else {
|
||||
failureCallback();
|
||||
}
|
||||
}.bind(this),
|
||||
function(aException, aResponseText, aRequest) {
|
||||
this.log.info("Failed to acquire user info:" + aResponseText);
|
||||
this.log.error("user info failed, status = " + aRequest.status);
|
||||
this.log.error("response text = " + aResponseText);
|
||||
this.log.error("exception = " + aException);
|
||||
failureCallback();
|
||||
}.bind(this),
|
||||
this,
|
||||
"GET");
|
||||
accountInfoSuccess,
|
||||
accountInfoFailure,
|
||||
this,
|
||||
"GET");
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -392,50 +405,54 @@ nsBox.prototype = {
|
|||
*/
|
||||
_createFolder: function nsBox__createFolder(aName,
|
||||
aSuccessCallback) {
|
||||
this.log.info("Create folder: " + aName);
|
||||
this.log.info("Creating folder: " + aName);
|
||||
if (Services.io.offline)
|
||||
throw Ci.nsIMsgCloudFileProvider.offlineErr;
|
||||
|
||||
let args = "?action=create_folder&api_key=" + kApiKey
|
||||
+ "&auth_token=" + this._cachedAuthToken
|
||||
+ "&parent_id=0&name" + aName
|
||||
+ "&share=1";
|
||||
let requestUrl = gServerUrl + args;
|
||||
let args = "?action=create_folder&api_key=" + kApiKey
|
||||
+ "&auth_token=" + this._cachedAuthToken
|
||||
+ "&parent_id=0&name=" + aName
|
||||
+ "&share=1";
|
||||
let requestUrl = gServerUrl + args;
|
||||
this.log.info("create_folder requestUrl = " + requestUrl);
|
||||
|
||||
// Request to get the ticket
|
||||
doXHRequest(requestUrl,
|
||||
null,
|
||||
null,
|
||||
function(aResponseText, aRequest) {
|
||||
this.log.info("create_folder request response = " + aResponseText);
|
||||
let createSuccess = function(aResponseText, aRequest) {
|
||||
this.log.info("create_folder request response = " + aResponseText);
|
||||
|
||||
let doc = aRequest.responseXML;
|
||||
let docResponse = doc.documentElement;
|
||||
if (docResponse && docResponse.nodeName == "response") {
|
||||
let docStatus = doc.getElementsByTagName("status")[0].firstChild.nodeValue;
|
||||
this.log.info("create_folder status = " + docStatus);
|
||||
if (docStatus != "create_ok") {
|
||||
// This means the folder likely exists
|
||||
// How do we get the id?
|
||||
//failureCallback(null, aResponseText, aRequest);
|
||||
return;
|
||||
}
|
||||
let folderId = doc.getElementsByTagName("folder_id")[0].firstChild.nodeValue;
|
||||
this.log.info("new folder id = " + folderId);
|
||||
successCallback(folderId);
|
||||
}
|
||||
else {
|
||||
// This means the folder likely exists
|
||||
// How do we get the id?
|
||||
//failureCallback("", aResponseText, aRequest);
|
||||
}
|
||||
}.bind(this),
|
||||
function(aException, aResponseText, aRequest) {
|
||||
this.log.info("Failed to create a new folder:" + aResponseText);
|
||||
// This means the folder likely exists
|
||||
// How do we get the id?
|
||||
//failureCallback(aException, aResponseText, aRequest);
|
||||
}.bind(this),
|
||||
try {
|
||||
let doc = aRequest.responseXML;
|
||||
let docResponse = doc.documentElement;
|
||||
if (docResponse && docResponse.nodeName == "response") {
|
||||
let docStatus = doc.getElementsByTagName("status")[0].firstChild.nodeValue;
|
||||
if (docStatus != "create_ok" && docStatus != "s_folder_exists") {
|
||||
this._lastErrorText = "Create folder failure";
|
||||
this._lastErrorStatus = docStatus;
|
||||
return;
|
||||
}
|
||||
let folderId = doc.getElementsByTagName("folder_id")[0].firstChild.nodeValue;
|
||||
this.log.info("folder id = " + folderId);
|
||||
aSuccessCallback(folderId);
|
||||
}
|
||||
else {
|
||||
this._lastErrorText = "Create folder failure";
|
||||
this._lastErrorStatus = "";
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
// most likely bad XML
|
||||
this.log.error("Failed to create a new folder");
|
||||
}
|
||||
}.bind(this);
|
||||
let createFailure = function(aException, aResponseText, aRequest) {
|
||||
this.log.error("Failed to create a new folder: " + aRequest.status);
|
||||
}.bind(this);
|
||||
|
||||
// Request to create the folder
|
||||
doXHRequest(requestUrl,
|
||||
null,
|
||||
null,
|
||||
createSuccess,
|
||||
createFailure,
|
||||
this,
|
||||
"GET");
|
||||
},
|
||||
|
@ -468,7 +485,6 @@ nsBox.prototype = {
|
|||
* @param aError an error to get the URL for.
|
||||
*/
|
||||
providerUrlForError: function nsBox_providerUrlForError(aError) {
|
||||
// XX TODO Identify other errors we need to worry about, and the resulting error page
|
||||
if (aError == Ci.nsIMsgCloudFileProvider.uploadWouldExceedQuota)
|
||||
return "https://www.box.com/pricing/";
|
||||
return "";
|
||||
|
@ -509,41 +525,53 @@ nsBox.prototype = {
|
|||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
let args = "?action=delete&api_key=" + kApiKey
|
||||
+ "&auth_token=" + this._cachedAuthToken
|
||||
+ "&target=file&target_id" + uploadInfo.fileId;
|
||||
let requestUrl = gServerUrl + args;
|
||||
let args = "?action=delete&api_key=" + kApiKey
|
||||
+ "&auth_token=" + this._cachedAuthToken
|
||||
+ "&target=file&target_id=" + uploadInfo.fileId;
|
||||
let requestUrl = gServerUrl + args;
|
||||
this.log.info("delete requestUrl = " + requestUrl);
|
||||
|
||||
// Request to get the ticket
|
||||
doXHRequest(requestUrl,
|
||||
null,
|
||||
null,
|
||||
function(aResponseText, aRequest) {
|
||||
this.log.info("delete request response = " + aResponseText);
|
||||
let deleteSuccess = function(aResponseText, aRequest) {
|
||||
this.log.info("delete request response = " + aResponseText);
|
||||
|
||||
let doc = aRequest.responseXML;
|
||||
let docResponse = doc.documentElement;
|
||||
if (docResponse && docResponse.nodeName == "response") {
|
||||
let docStatus = doc.getElementsByTagName("status")[0].firstChild.nodeValue;
|
||||
this.log.info("status = " + docStatus);
|
||||
if (docStatus != "s_delete_node") {
|
||||
aCallback.onStopRequest(null, null, Cr.NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
this.log.info("Delete was successful!");
|
||||
// Success!
|
||||
aCallback.onStopRequest(null, null, Cr.NS_OK);
|
||||
}
|
||||
else {
|
||||
aCallback.onStopRequest(null, null, Cr.NS_ERROR_FAILURE);
|
||||
}
|
||||
}.bind(this),
|
||||
function(aException, aResponseText, aRequest) {
|
||||
this.log.info("Failed to delete file:" + aResponseText);
|
||||
aCallback.onStopRequest(null, null, Cr.NS_ERROR_FAILURE);
|
||||
}.bind(this),
|
||||
try {
|
||||
let doc = aRequest.responseXML;
|
||||
let docResponse = doc.documentElement;
|
||||
if (docResponse && docResponse.nodeName == "response") {
|
||||
let docStatus = doc.getElementsByTagName("status")[0].firstChild.nodeValue;
|
||||
this.log.info("delete status = " + docStatus);
|
||||
if (docStatus != "s_delete_node") {
|
||||
aCallback.onStopRequest(null, null, Cr.NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
this.log.info("Delete was successful!");
|
||||
// Success!
|
||||
aCallback.onStopRequest(null, null, Cr.NS_OK);
|
||||
}
|
||||
else {
|
||||
aCallback.onStopRequest(null, null, Cr.NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
// most likely bad XML
|
||||
this.log.error("Failed to parse delete response: " + e);
|
||||
this.log.error("Delete response: " + aResponseText);
|
||||
aCallback.onStopRequest(null, null, Cr.NS_ERROR_FAILURE);
|
||||
}
|
||||
}.bind(this);
|
||||
let deleteFailure = function(aException, aResponseText, aRequest) {
|
||||
this.log.error("Failed to delete file:" + aResponseText);
|
||||
aCallback.onStopRequest(null, null, Cr.NS_ERROR_FAILURE);
|
||||
}.bind(this);
|
||||
|
||||
// Request to delete a file
|
||||
doXHRequest(requestUrl,
|
||||
null,
|
||||
null,
|
||||
deleteSuccess,
|
||||
deleteFailure,
|
||||
this,
|
||||
"GET");
|
||||
"GET");
|
||||
},
|
||||
|
||||
_getUrlParameter: function nsBox_getAuthParameter(aUrl, aName)
|
||||
|
@ -582,75 +610,77 @@ nsBox.prototype = {
|
|||
failureCallback();
|
||||
return;
|
||||
}
|
||||
//let aSuccessCallback = successCallback
|
||||
|
||||
this._browserRequest = {
|
||||
promptText : "box auth prompt",
|
||||
account: this,
|
||||
_active: true,
|
||||
iconURI : this.iconClass,
|
||||
successCallback : successCallback,
|
||||
failureCallback : failureCallback,
|
||||
cancelled: function() {
|
||||
if (!this._active)
|
||||
return;
|
||||
this.account.log.info("auth cancelled");
|
||||
this._finishLogonRequest();
|
||||
this.failureCallback();
|
||||
//this.account.connectFailureCallback();
|
||||
// ### auth cancelled.
|
||||
},
|
||||
loaded: function(aWindow, aWebProgress) {
|
||||
if (!this._active)
|
||||
return;
|
||||
this._browserRequest = {
|
||||
promptText : "Box",
|
||||
account: this,
|
||||
_active: true,
|
||||
iconURI : this.iconClass,
|
||||
successCallback : successCallback,
|
||||
failureCallback : failureCallback,
|
||||
cancelled: function() {
|
||||
if (!this._active)
|
||||
return;
|
||||
this.account.log.info("auth cancelled");
|
||||
this.account._finishLogonRequest();
|
||||
this.failureCallback();
|
||||
},
|
||||
loaded: function(aWindow, aWebProgress) {
|
||||
if (!this._active)
|
||||
return;
|
||||
|
||||
this._listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
_cleanUp: function() {
|
||||
this.webProgress.removeProgressListener(this);
|
||||
this.window.close();
|
||||
delete this.window;
|
||||
},
|
||||
_checkForRedirect: function(aURL) {
|
||||
if (aURL.indexOf(this._parent.completionURI) != 0)
|
||||
return;
|
||||
this._listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
_cleanUp: function() {
|
||||
this.webProgress.removeProgressListener(this);
|
||||
this.window.close();
|
||||
delete this.window;
|
||||
},
|
||||
_checkForRedirect: function(aURL) {
|
||||
if (aURL.indexOf(this._parent.completionURI) != 0)
|
||||
return;
|
||||
|
||||
let ticket = this._parent._getUrlParameter(aURL, "ticket");
|
||||
this._parent._cachedAuthToken = this._parent._getUrlParameter(aURL, "auth_token");
|
||||
this._parent.log.info("Box auth redirect : " + aURL + "| ticket = " + ticket + " | Auth token = " + this._parent._cachedAuthToken);
|
||||
let ticket = this._parent._getUrlParameter(aURL, "ticket");
|
||||
this._parent._cachedAuthToken = this._parent._getUrlParameter(aURL, "auth_token");
|
||||
this._parent.log.info("Box auth redirect : "
|
||||
+ aURL
|
||||
+ "| ticket = "
|
||||
+ ticket
|
||||
+ " | Auth token = "
|
||||
+ this._parent._cachedAuthToken);
|
||||
|
||||
this._parent._loggedIn = true;
|
||||
this._loggedIn = true;
|
||||
this.successCallback();
|
||||
this._parent._finishLogonRequest();
|
||||
},
|
||||
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
const wpl = Ci.nsIWebProgressListener;
|
||||
if (aStateFlags & (wpl.STATE_START | wpl.STATE_IS_NETWORK))
|
||||
this._checkForRedirect(aRequest.name);
|
||||
},
|
||||
onLocationChange: function(aWebProgress, aRequest, aLocation) {
|
||||
this._checkForRedirect(aLocation.spec);
|
||||
},
|
||||
onProgressChange: function() {},
|
||||
onStatusChange: function() {},
|
||||
onSecurityChange: function() {},
|
||||
this._parent._loggedIn = true;
|
||||
this._loggedIn = true;
|
||||
this.successCallback();
|
||||
this._parent._finishLogonRequest();
|
||||
},
|
||||
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
const wpl = Ci.nsIWebProgressListener;
|
||||
if (aStateFlags & (wpl.STATE_START | wpl.STATE_IS_NETWORK))
|
||||
this._checkForRedirect(aRequest.name);
|
||||
},
|
||||
onLocationChange: function(aWebProgress, aRequest, aLocation) {
|
||||
this._checkForRedirect(aLocation.spec);
|
||||
},
|
||||
onProgressChange: function() {},
|
||||
onStatusChange: function() {},
|
||||
onSecurityChange: function() {},
|
||||
|
||||
window: aWindow,
|
||||
webProgress: aWebProgress,
|
||||
_parent: this.account,
|
||||
successCallback : this.successCallback
|
||||
};
|
||||
window: aWindow,
|
||||
webProgress: aWebProgress,
|
||||
_parent: this.account,
|
||||
successCallback : this.successCallback
|
||||
};
|
||||
aWebProgress.addProgressListener(this._listener,
|
||||
Ci.nsIWebProgress.NOTIFY_ALL);
|
||||
},
|
||||
},
|
||||
};
|
||||
this.wrappedJSObject = this._browserRequest;
|
||||
|
||||
Services.ww.openWindow(null,
|
||||
"chrome://messenger/content/cloudfile/Box/auth.xul",
|
||||
null, "chrome,centerscreen,width=980px,height=600px", this);
|
||||
"chrome://messenger/content/cloudfile/Box/auth.xul",
|
||||
null, "chrome,centerscreen,width=1100px,height=600px", this);
|
||||
},
|
||||
|
||||
get _cachedAuthToken() {
|
||||
|
@ -673,10 +703,11 @@ nsBox.prototype = {
|
|||
},
|
||||
|
||||
get _cachedFolderId() {
|
||||
let folderId = this._prefBranch.getCharPref("folderid");
|
||||
|
||||
if (!folderId)
|
||||
return "";
|
||||
let folderId = "";
|
||||
try {
|
||||
folderId = this._prefBranch.getCharPref("folderid");
|
||||
}
|
||||
catch(e) { } // pref does not exist
|
||||
|
||||
return folderId;
|
||||
},
|
||||
|
@ -703,32 +734,179 @@ nsBoxFileUploader.prototype = {
|
|||
box : null,
|
||||
file : null,
|
||||
callback : null,
|
||||
_request : null,
|
||||
request : null,
|
||||
|
||||
/**
|
||||
* Kicks off the upload request for the file associated with this Uploader.
|
||||
* Do the upload of the file to Box.
|
||||
*/
|
||||
uploadFile: function nsDFU_uploadFile() {
|
||||
return Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
uploadFile: function nsBox_uploadFile() {
|
||||
this.requestObserver.onStartRequest(null, null);
|
||||
let args = this.box._cachedAuthToken + "/" + this.box._folderId + "?new_copy=1&share=1";
|
||||
let requestUrl = gUploadUrl + args;
|
||||
this.box._uploadInfo[this.file.path] = {};
|
||||
this.box._uploadInfo[this.file.path].uploadUrl = requestUrl;
|
||||
|
||||
let req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
|
||||
let curDate = Date.now().toString();
|
||||
this.log.info("upload url = " + requestUrl);
|
||||
this.request = req;
|
||||
req.open("POST", requestUrl, true);
|
||||
req.onload = function() {
|
||||
this.cleanupTempFile();
|
||||
if (req.status >= 200 && req.status < 400) {
|
||||
try {
|
||||
this.log.info("upload response = " + req.responseText);
|
||||
let doc = req.responseXML;
|
||||
let uploadResponse = doc.documentElement;
|
||||
if (uploadResponse && uploadResponse.nodeName == "response") {
|
||||
let uploadStatus = doc.getElementsByTagName("status")[0].firstChild.nodeValue;
|
||||
this.log.info("upload status = " + uploadStatus);
|
||||
if (uploadStatus != "upload_ok") {
|
||||
this.callback(this.requestObserver,
|
||||
Ci.nsIMsgCloudFileProvider.uploadErr);
|
||||
this.box._cachedFolderId = ""; // flush the folder id for a new attempt
|
||||
return;
|
||||
}
|
||||
|
||||
let file = doc.getElementsByTagName("file")[0];
|
||||
let pn = file.getAttribute("public_name");
|
||||
this.log.info("public_name = " + pn);
|
||||
this.box._uploadInfo[this.file.path].fileId = file.getAttribute("id");
|
||||
this.box._urlsForFiles[this.file.path] = gSharingUrl + pn;
|
||||
this.callback(this.requestObserver, Cr.NS_OK);
|
||||
}
|
||||
else {
|
||||
this.callback(this.requestObserver,
|
||||
Ci.nsIMsgCloudFileProvider.uploadErr);
|
||||
}
|
||||
} catch (ex) {
|
||||
this.log.error(ex);
|
||||
this.callback(this.requestObserver,
|
||||
Ci.nsIMsgCloudFileProvider.uploadErr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.callback(this.requestObserver,
|
||||
Ci.nsIMsgCloudFileProvider.uploadErr);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
req.onerror = function () {
|
||||
this.cleanupTempFile();
|
||||
if (this.callback)
|
||||
this.callback(this.requestObserver,
|
||||
Ci.nsIMsgCloudFileProvider.uploadErr);
|
||||
}.bind(this);
|
||||
|
||||
req.setRequestHeader("Date", curDate);
|
||||
let boundary = "------" + curDate;
|
||||
let contentType = "multipart/form-data; boundary="+ boundary;
|
||||
req.setRequestHeader("Content-Type", contentType);
|
||||
|
||||
let fileName = encodeURIComponent(this.file.leafName);
|
||||
|
||||
let fileContents = "\r\n--" + boundary +
|
||||
"\r\nContent-Disposition: form-data; name=\"fname\"; filename=\"" +
|
||||
fileName + "\"\r\nContent-Type: application/octet-stream" +
|
||||
"\r\n\r\n";
|
||||
|
||||
// Since js doesn't like binary data in strings, we're going to create
|
||||
// a temp file consisting of the message preamble, the file contents, and
|
||||
// the post script, and pass a stream based on that file to
|
||||
// nsIXMLHttpRequest.send().
|
||||
|
||||
try {
|
||||
this._tempFile = this.getTempFile(this.file.leafName);
|
||||
let ostream = Cc["@mozilla.org/network/file-output-stream;1"]
|
||||
.createInstance(Ci.nsIFileOutputStream);
|
||||
ostream.init(this._tempFile, -1, -1, 0);
|
||||
ostream.write(fileContents, fileContents.length);
|
||||
|
||||
this._fstream = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
let sstream = Cc["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
this._fstream.init(this.file, -1, 0, 0);
|
||||
sstream.init(this._fstream);
|
||||
|
||||
// This blocks the UI which is less than ideal. But it's a local
|
||||
// file operations so probably not the end of the world.
|
||||
while (sstream.available() > 0) {
|
||||
let bytes = sstream.readBytes(sstream.available());
|
||||
ostream.write(bytes, bytes.length);
|
||||
}
|
||||
|
||||
fileContents = "\r\n--" + boundary + "--\r\n";
|
||||
ostream.write(fileContents, fileContents.length);
|
||||
|
||||
ostream.close();
|
||||
this._fstream.close();
|
||||
sstream.close();
|
||||
|
||||
// defeat fstat caching
|
||||
this._tempFile = this._tempFile.clone();
|
||||
this._fstream.init(this._tempFile, -1, 0, 0);
|
||||
this._fstream.close();
|
||||
// I don't trust re-using the old fstream.
|
||||
this._fstream = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
this._fstream.init(this._tempFile, -1, 0, 0);
|
||||
this._bufStream = Cc["@mozilla.org/network/buffered-input-stream;1"]
|
||||
.createInstance(Ci.nsIBufferedInputStream);
|
||||
this._bufStream.init(this._fstream, this._tempFile.fileSize);
|
||||
// nsIXMLHttpRequest's nsIVariant handling requires that we QI
|
||||
// to nsIInputStream.
|
||||
req.send(this._bufStream.QueryInterface(Ci.nsIInputStream));
|
||||
} catch (ex) {
|
||||
this.cleanupTempFile();
|
||||
this.log.error(ex);
|
||||
throw ex;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Cancels the upload request for the file associated with this Uploader.
|
||||
*/
|
||||
cancel: function nsDFU_cancel() {
|
||||
return Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
cancel: function nsBox_cancel() {
|
||||
this.log.info("in uploader cancel");
|
||||
this.callback(this.requestObserver, Ci.nsIMsgCloudFileProvider.uploadCanceled);
|
||||
delete this.callback;
|
||||
if (this.request) {
|
||||
this.log.info("cancelling upload request");
|
||||
let req = this.request;
|
||||
if (req.channel) {
|
||||
this.log.info("cancelling upload channel");
|
||||
req.channel.cancel(Cr.NS_BINDING_ABORTED);
|
||||
}
|
||||
this.request = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Private function that attempts to retrieve the sharing URL for the file
|
||||
* uploaded with this Uploader.
|
||||
*
|
||||
* @param aFile ...
|
||||
* @param aCallback an nsIRequestObserver for monitoring the starting and
|
||||
* ending states of the URL retrieval request.
|
||||
* Creates and returns a temporary file on the local file system.
|
||||
*/
|
||||
_getShareUrl: function nsDFU__getShareUrl(aFile, aCallback) {
|
||||
return Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
getTempFile: function nsBox_getTempFile(leafName) {
|
||||
let tempfile = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile);
|
||||
tempfile.append(leafName)
|
||||
tempfile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("0666", 8));
|
||||
// do whatever you need to the created file
|
||||
return tempfile.clone()
|
||||
},
|
||||
|
||||
/**
|
||||
* Cleans up any temporary files that this nsBoxFileUploader may have
|
||||
* created.
|
||||
*/
|
||||
cleanupTempFile: function nsBox_cleanupTempFile() {
|
||||
if (this._bufStream)
|
||||
this._bufStream.close();
|
||||
if (this._fstream)
|
||||
this._fstream.close();
|
||||
if (this._tempFile)
|
||||
this._tempFile.remove(false);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!-- Note to localizers, Box is a brand from box.com -->
|
||||
<!ENTITY auth.title "Box Authentication">
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!-- Note to localizers, Box is a brand from box.com -->
|
||||
<!ENTITY boxSettings.needAnAccount "Get a Box account…">
|
||||
|
|
|
@ -18,6 +18,12 @@
|
|||
background-image: url("chrome://messenger/skin/icons/insecure.png");
|
||||
}
|
||||
|
||||
#security-button[loading="true"] {
|
||||
margin-top: 5px;
|
||||
margin-left: 4px;
|
||||
background-image: url("chrome://global/skin/icons/loading_16.png");
|
||||
}
|
||||
|
||||
#header {
|
||||
border-bottom: 1px solid black;
|
||||
overflow: hidden;
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
#security-button[level="broken"] {
|
||||
background-image: url("chrome://messenger/skin/icons/insecure.png");
|
||||
}
|
||||
|
||||
#security-button[loading="true"] {
|
||||
margin-top: 3px;
|
||||
margin-left: 4px;
|
||||
background-image: url("chrome://global/skin/icons/loading_16.png");
|
||||
}
|
||||
/*
|
||||
#header {
|
||||
overflow: hidden;
|
||||
|
|
|
@ -17,6 +17,11 @@
|
|||
background-image: url("chrome://messenger/skin/icons/insecure.png");
|
||||
}
|
||||
|
||||
#security-button[loading="true"] {
|
||||
margin-left: 4px;
|
||||
background-image: url("chrome://global/skin/icons/loading_16.png");
|
||||
}
|
||||
|
||||
#header {
|
||||
overflow: hidden;
|
||||
border-bottom: 1px solid black;
|
||||
|
|
Загрузка…
Ссылка в новой задаче