github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/clients/chrome/clip-it-good/background.html (about)

     1  <html>
     2  <head>
     3  <script type="text/javascript" src="base64.js"></script>
     4  <script type="text/javascript" src="jquery-1.4.2.min.js"></script>
     5  <script type="text/javascript" src="chrome_ex_oauthsimple.js"></script>
     6  <script type="text/javascript" src="chrome_ex_oauth.js"></script>
     7  <script type="text/javascript" src="Crypto.js"></script>
     8  <script type="text/javascript" src="SHA1.js"></script>
     9  
    10  <script type="text/javascript" charset="utf-8">
    11  
    12    var OAUTH = ChromeExOAuth.initBackgroundPage({
    13      'request_url' : 'https://www.google.com/accounts/OAuthGetRequestToken',
    14      'authorize_url' : 'https://www.google.com/accounts/OAuthAuthorizeToken',
    15      'access_url' : 'https://www.google.com/accounts/OAuthGetAccessToken',
    16      'consumer_key' : 'anonymous',
    17      'consumer_secret' : 'anonymous',
    18      'scope' : 'http://picasaweb.google.com/data/',
    19      'app_name' : 'Clip It Good: Chrome Extension'
    20    });
    21  
    22    // Constants for various album types.
    23    var PICASA = 'picasa';
    24    var CAMLISTORE = 'camlistore';
    25    var ALBUM_TYPE_STRING = {
    26      picasa: 'Picasa Web Albums',
    27      camlistore: 'Camlistore'
    28    };
    29  
    30    // Preferences
    31    var ALBUM_CONFIG = {};  // 'type' -> ('id' -> 'name')
    32    var ALBUM_OPTIONS = {};  // 'type' -> ('id' -> optionsDict)
    33  
    34    function loadAlbumConfig() {
    35      var newAlbumConfig = localStorage.getItem('config:albums');
    36      if (newAlbumConfig) {
    37        ALBUM_CONFIG = $.parseJSON(newAlbumConfig);
    38      }
    39  
    40      var newAlbumOptions = localStorage.getItem('config:albumOptions');
    41      if (newAlbumOptions) {
    42        ALBUM_OPTIONS = $.parseJSON(newAlbumOptions);
    43      }
    44    }
    45  
    46    function saveAlbumConfig() {
    47      localStorage.setItem('config:albums', JSON.stringify(ALBUM_CONFIG));
    48      localStorage.setItem('config:albumOptions', JSON.stringify(ALBUM_OPTIONS));
    49    }
    50  
    51    // Sort albums by name.
    52    function getSortedAlbums(albumIdNameDict) {
    53      var albumIdNameArray = [];
    54      $.each(albumIdNameDict, function(id, name) {
    55        albumIdNameArray.push({'id': id, 'name': name});
    56      });
    57      albumIdNameArray.sort(function(a, b) {
    58        if (a['name'] < b['name']) {
    59          return -1;
    60        } else if (a['name'] > b['name']) {
    61          return 1;
    62        } else {
    63          return 0;
    64        }
    65      });
    66      return albumIdNameArray;
    67    }
    68  
    69    function setupMenus() {
    70      loadAlbumConfig();
    71  
    72      chrome.contextMenus.removeAll(function() {
    73        $.each(ALBUM_CONFIG, function(albumType, albumIdNameDict) {
    74          chrome.contextMenus.create({
    75            title: ALBUM_TYPE_STRING[albumType],
    76            contexts: ['image']
    77          });
    78          chrome.contextMenus.create({
    79            type: 'separator',
    80            contexts: ['image']
    81          });
    82  
    83          $.each(getSortedAlbums(albumIdNameDict), function(index, albumDict) {
    84            chrome.contextMenus.create({
    85              title: albumDict.name,
    86              contexts: ['image'],
    87              onclick: function(data, tab) {
    88                return handleMenuClick(
    89                    albumType, albumDict.name, albumDict.id, data, tab);
    90              }
    91            });
    92          });
    93        });
    94      });
    95    }
    96  
    97    // Upload actions
    98    var ALBUM_TYPE_UPLOAD_FUNC = {
    99  
   100      picasa: function(albumId, albumName, dataSrcUrl, dataBuffer, uploadDone) {
   101        var builder = new BlobBuilder();
   102        builder.append(dataBuffer);
   103  
   104        function complete(resp, xhr) {
   105          if (!(xhr.status >= 200 && xhr.status <= 299)) {
   106            alert('Error: Response status = ' + xhr.status +
   107                  ', response body = "' + xhr.responseText + '"');
   108          } else {
   109            uploadDone();
   110          }
   111        }
   112  
   113        OAUTH.authorize(function() {
   114          OAUTH.sendSignedRequest(
   115            'http://picasaweb.google.com/data/feed/api/' +
   116            'user/default/albumid/' + albumId,
   117            complete,
   118            {
   119              method: 'POST',
   120              headers: {
   121                'Content-Type': 'image/png',
   122                'Slug': dataSrcUrl
   123              },
   124              parameters: {
   125                alt: 'json'
   126              },
   127              body: builder.getBlob('image/png')
   128            }
   129          );
   130        });
   131      },
   132  
   133      camlistore: function(albumId, albumName, dataSrcUrl,
   134                           dataBuffer, uploadDone) {
   135        var hash = Crypto.SHA1(new Uint8Array(dataBuffer, 0));
   136        var blobRef = 'sha1-' + hash;
   137        var options = ALBUM_OPTIONS[CAMLISTORE][albumId];
   138  
   139        function doUpload(uploadUrl) {
   140          // XXX Use real random boundary.
   141          var boundary = 'randomboundaryXYZ';
   142          var contentType = 'multipart/form-data; boundary=' + boundary;
   143  
   144          var header =
   145            '--' + boundary + '\r\n' +
   146            'Content-Type: application/octet-stream\r\n' +
   147            'Content-Disposition: form-data; name="' + blobRef +
   148                '"; filename="1"\r\n\r\n'
   149          var footer = '\r\n--' + boundary + '--\r\n';
   150  
   151          var builder = new BlobBuilder();
   152          builder.append(header);
   153          builder.append(dataBuffer);
   154          builder.append(footer);
   155          var payload = builder.getBlob(contentType);
   156  
   157          var uploadXhr = new XMLHttpRequest();
   158          uploadXhr.open('POST', uploadUrl, true,
   159                         options.username, options.password);
   160          uploadXhr.onreadystatechange = function() {
   161            if (uploadXhr.readyState == XMLHttpRequest.DONE &&
   162                uploadXhr.status == 200) {
   163              // XXX Check for bad response format (not JSON).
   164              var responseJson = $.parseJSON(uploadXhr.responseText)
   165  
   166              if (responseJson.received &&
   167                  responseJson.received.length == 1 &&
   168                  responseJson.received[0].blobRef == blobRef) {
   169                console.log('Successful upload: ' + blobRef);
   170                uploadDone();
   171                return;
   172              }
   173  
   174              alert('Camlistore upload response did not verify blob "' +
   175                    blobRef + '": ' + uploadXhr.responseText);
   176            }
   177            // XXX: Handle request errors
   178          }
   179          uploadXhr.setRequestHeader('Content-Type', contentType);
   180          uploadXhr.send(payload);
   181        }
   182  
   183        var statXhr = new XMLHttpRequest();
   184        statXhr.open('POST', albumId + '/camli/stat', true,
   185                          options.username, options.password);
   186        statXhr.onreadystatechange = function() {
   187          if (statXhr.readyState == XMLHttpRequest.DONE &&
   188              statXhr.status == 200) {
   189            // XXX Check for bad response format (not JSON).
   190            var responseJson = $.parseJSON(statXhr.responseText);
   191  
   192            if (responseJson.stat &&
   193                responseJson.stat.length == 1 &&
   194                responseJson.stat[0].blobRef == blobRef) {
   195              console.log('Blob already present: ' + blobRef);
   196              uploadDone();
   197              return;
   198            }
   199  
   200            var uploadUrl = responseJson.uploadUrl;
   201            if (!uploadUrl) {
   202              alert('Camlistore stat response missing "uploadUrl": ' +
   203                    statXhr.responseText);
   204              return;
   205            }
   206  
   207            doUpload(uploadUrl);
   208          }
   209          // XXX: Handle request errors
   210        }
   211        statXhr.setRequestHeader(
   212            'Content-Type', 'application/x-www-form-urlencoded');
   213        statXhr.send('camliversion=1&blob1=' + blobRef);
   214      }
   215  
   216    };
   217  
   218    function handleMenuClick(albumType, albumName, albumId, data, tab) {
   219      chrome.pageAction.setTitle({
   220        tabId: tab.id,
   221        title: 'Clip It Good: Uploading (' + data.srcUrl.substr(0, 100) + ')'
   222      });
   223      chrome.pageAction.show(tab.id);
   224  
   225      var img = document.createElement('img');
   226      img.onload = function() {
   227        var canvas = document.createElement('canvas');
   228        canvas.width = img.width;
   229        canvas.height = img.height;
   230        canvas.getContext('2d').drawImage(img, 0, 0);
   231  
   232        var dataUrl = canvas.toDataURL();
   233        var dataUrlAdjusted = dataUrl.replace('data:image/png;base64,', '');
   234  
   235        var arrayBuffer = Base64.decode(dataUrlAdjusted).buffer;
   236  
   237        function uploadDone() {
   238          chrome.pageAction.hide(tab.id);
   239        }
   240  
   241        var uploadFunc = ALBUM_TYPE_UPLOAD_FUNC[albumType];
   242        uploadFunc(albumId, albumName, data.srcUrl, arrayBuffer, uploadDone);
   243      }  // end onload
   244  
   245      img.src = data.srcUrl;
   246    }
   247  
   248    $(document).ready( function() {
   249      setupMenus();
   250    });
   251  </script>
   252  
   253  </head>
   254  <body>
   255  </body>
   256  </html>