| <!DOCTYPE html> |
| <html> |
| <head> |
| <script src="chrome://resources/js/cr.js"></script> |
| <script src="chrome://resources/js/cr/event_target.js"></script> |
| |
| <script src="js/picasa_client.js"></script> |
| </head> |
| |
| <body> |
| |
| <script> |
| |
| /** |
| * Uploader constructor. |
| * |
| * Uploader object is responsible for uploading a bunch of images to the same |
| * picasa album. It also manages the notification. |
| * |
| * @param {Array.<picasa.LocalFile>} files Files to upload. |
| * @param {picasa.Album} album Album to upload to. |
| * @param {picasa.Client} client Picasa client. |
| * @param {string} hash Hash value unique to this uploader (to differentiate |
| * multiple uploaders). |
| */ |
| function Uploader(files, album, client, hash) { |
| this.album_ = album; |
| this.client_ = client; |
| this.files_ = files; |
| |
| this.filesTotal_ = this.files_.length; |
| this.filesDone_ = 0; |
| this.hash = hash; |
| |
| this.request_ = null; |
| this.failed_ = false; |
| this.canceled_ = false; |
| this.finished_ = false; |
| |
| this.startDate_ = null; |
| this.timeRemaining_ = null; |
| } |
| |
| Uploader.prototype = { |
| /** |
| * Starts the upload process. |
| */ |
| start: function() { |
| this.startDate_ = new Date(); |
| this.failed_ = false; |
| this.createNotification_(); |
| var self = this; |
| self.uploadNextFile_(); |
| }, |
| |
| /** |
| * Creates a webkit notification. |
| */ |
| createNotification_: function() { |
| // We pass unique hash to the notification dom, so it will distinct this |
| // uploader object from others. |
| this.webkitNotification_ = |
| window.webkitNotifications.createHTMLNotification( |
| chrome.extension.getURL('notification.html' + this.hash)); |
| this.webkitNotification_.onclose = this.onNotificationClose_.bind(this); |
| this.webkitNotification_.show(); |
| }, |
| |
| /** |
| * Sets the notification object (see notification.html). |
| * This method is called from notification dom, so uploader can modify it. |
| * @param {Notification} notification The notification object. |
| */ |
| setNotification: function(notification) { |
| this.notification_ = notification; |
| if (this.finished_) { |
| this.showFinished_(); |
| } else { |
| this.updateNotification_(); |
| } |
| }, |
| |
| /** |
| * Updates information in notification. |
| */ |
| updateNotification_: function() { |
| this.notification_.update(this.filesDone_, this.filesTotal_, |
| this.timeRemaining_); |
| }, |
| |
| /** |
| * This method is called when uploading is finished (either successfully or |
| * not). |
| */ |
| done_: function() { |
| this.finished_ = true; |
| // If notification was closed by user, we should create a new one. |
| if (this.webkitNotification_) { |
| this.showFinished_(); |
| } else { |
| this.createNotification_(); |
| } |
| }, |
| |
| /** |
| * Shows final information in notification. |
| */ |
| showFinished_: function() { |
| if (this.failed_) { |
| this.notification_.showFailed(this.filesDone_, this.filesTotal_); |
| } else if (this.canceled_) { |
| this.notification_.showCanceled(this.filesDone_, this.filesTotal_); |
| } else { |
| this.notification_.showCompleted(this.filesDone_, this.album_.link); |
| } |
| }, |
| |
| /** |
| * Event handler for notification close. |
| */ |
| onNotificationClose_: function() { |
| if (this.finished_) { |
| // Inform background page that we are done. |
| bg.removeUploader(this.hash); |
| } else { |
| // User closed notification "in progress". We will create a new one |
| // to show final information. |
| this.webkitNotification_ = null; |
| } |
| }, |
| |
| /** |
| * Uploads the next file to picasa web albums. |
| */ |
| uploadNextFile_: function() { |
| if (this.files_.length == 0 || this.failed_ || this.canceled_) { |
| this.done_(); |
| return; |
| } |
| |
| var file = this.files_.shift(); |
| this.request_ = this.client_.uploadFile(this.album_, file, |
| this.uploadFileCallback_.bind(this)); |
| }, |
| |
| /** |
| * Event handler for file upload. |
| * @param {?string} response The response or null if failed. |
| */ |
| uploadFileCallback_: function(response) { |
| if (this.failed_ || this.canceled_) { |
| return; |
| } |
| |
| this.request_ = null; |
| if (response == null) { |
| this.failed_ = true; |
| } else { |
| this.filesDone_++; |
| var elapsed = (new Date()) - this.startDate_; |
| this.timeRemaining_ = elapsed * |
| (this.filesTotal_ - this.filesDone_) / this.filesDone_; |
| } |
| this.updateNotification_(); |
| this.uploadNextFile_(); |
| }, |
| |
| /** |
| * Cancels the upload process. |
| */ |
| cancel: function() { |
| this.canceled_ = true; |
| this.done_(); |
| if (this.request_) { |
| this.request_.abort(); |
| this.request_ = null; |
| } |
| } |
| }; |
| |
| |
| /** |
| * BackgroundPage constructor. |
| * |
| * BackgroundPage object opens the upload window and passes upload requests |
| * to Uploader objects. It also holds the global picasa client object. |
| */ |
| function BackgroundPage() { |
| this.client = new picasa.Client(); |
| this.newFiles_ = []; |
| this.uploadPageUrl_ = chrome.extension.getURL('upload.html'); |
| this.uploaders_ = {}; |
| this.lastUploaderHash_ = 0; |
| |
| var self = this; |
| chrome.fileBrowserHandler.onExecute.addListener( |
| function(id, file_entries) { |
| console.log('picasa: got task - ' + id); |
| if (id == 'upload') { |
| self.onFileUpload_(file_entries); |
| } |
| }); |
| } |
| |
| BackgroundPage.prototype = { |
| /** |
| * Returns a window with specified url. |
| * @param {string} url Url of a window to find. |
| * @return {DOMWindow} Window with specified url. |
| */ |
| findWindow_: function(url) { |
| var views = chrome.extension.getViews(); |
| for (var view, i = 0; view = views[i]; i++) { |
| if (view.location.href == url) { |
| return view; |
| } |
| } |
| return null; |
| }, |
| |
| /** |
| * Event handler called when user chooses "send to picasa" somewhere. |
| * @param {Array.<picasa.LocalFile>} files Files to upload. |
| */ |
| onSendImageRequest_: function(files) { |
| var win = this.findWindow_(this.uploadPageUrl_); |
| if (win) { |
| // If upload window already loaded, just add one more file. |
| win.uploadPage.addFiles(files); |
| } else { |
| // If upload window is not yet loaded, it will ask for new files via |
| // getNewFiles method. |
| this.newFiles_ = this.newFiles_.concat(files); |
| chrome.windows.create({url: this.uploadPageUrl_, width: 620, height: 465}); |
| } |
| }, |
| |
| /** |
| * "Send to picasa" event handler from filebrowser. |
| * @param {*} fileEntries Entry object array. |
| */ |
| onFileUpload_: function(fileEntries) { |
| if (!fileEntries) { |
| return; |
| } |
| |
| var self = this; |
| var files = []; |
| var remaining = fileEntries.length; |
| console.log('got files: ' + remaining); |
| for (var i = 0; i < fileEntries.length; i++) { |
| var entry = fileEntries[i]; |
| entry.file(function(file) { |
| files.push(new picasa.LocalFile(file)); |
| remaining--; |
| if (remaining == 0 && files.length > 0) { |
| self.onSendImageRequest_(files); |
| } |
| }); |
| } |
| |
| // If not all the entries were resolved, send request for resolved ones. |
| setTimeout(function() { |
| if (remaining > 0 && files.length > 0) { |
| self.onSendImageRequest_(files); |
| } |
| }, 1000); |
| }, |
| |
| /** |
| * Returns new files for upload. |
| * @return {Array.<picasa.LocalFile>} New files. |
| */ |
| getNewFiles: function() { |
| var result = this.newFiles_; |
| this.newFiles_ = []; |
| return result; |
| }, |
| |
| /** |
| * Starts the uploading process. |
| * @param {Array.<picasa.LocalFile>} files Files to upload. |
| * @param {picasa.Album} album Album to upload to. |
| */ |
| uploadFiles: function(files, album) { |
| var hash = '#' + this.lastUploaderHash_++; |
| var uploader = new Uploader(files, album, this.client, hash); |
| this.uploaders_[hash] = uploader; |
| uploader.start(); |
| }, |
| |
| /** |
| * Returns an Uploader object by hash. |
| * @param {string} hash Unique hash. |
| * @return {Uploader} Uploader object with given hash. |
| */ |
| getUploader: function(hash) { |
| return this.uploaders_[hash]; |
| }, |
| |
| /** |
| * Removes an Uploader object by hash. |
| * @param {string} hash Unique hash. |
| */ |
| removeUploader: function(hash) { |
| this.uploaders_[hash] = null; |
| } |
| }; |
| |
| /** |
| * Single BackgroundPage object. |
| * @type {BackgroundPage} |
| */ |
| var bg = new BackgroundPage(); |
| |
| </script> |
| </body> |
| </html> |