Browse Source

fix sync logic

Gerald 9 years ago
parent
commit
bfee3efe25
3 changed files with 74 additions and 29 deletions
  1. 45 11
      src/background/requests.js
  2. 8 8
      src/background/sync/dropbox.js
  3. 21 10
      src/background/sync/index.js

+ 45 - 11
src/background/requests.js

@@ -7,6 +7,7 @@ var requests = function () {
     'origin',
     'host',
   ];
+  var tasks = {};
 
   function getRequestId() {
     var id = _.getUniqId();
@@ -123,36 +124,69 @@ var requests = function () {
   // Modifications on headers
   chrome.webRequest.onBeforeSendHeaders.addListener(function (details) {
     var headers = details.requestHeaders;
-    var new_headers = [];
-    var vm_headers = {};
+    var newHeaders = [];
+    var vmHeaders = {};
     headers.forEach(function (header) {
-      if (header.name.substr(0, 3) == 'VM-')
-        vm_headers[header.name.slice(3)] = header.value;
+      if (header.name === 'VM-Task')
+        tasks[details.requestId] = header.value;
+      else if (header.name.slice(0, 3) === 'VM-')
+        vmHeaders[header.name.slice(3)] = header.value;
       else
-        new_headers.push(header);
+        newHeaders.push(header);
     });
-    var reqId = vm_headers['Verify'];
+    var reqId = vmHeaders['Verify'];
     if (reqId) {
       var req = requests[reqId];
       if (req) {
-        delete vm_headers['Verify'];
+        delete vmHeaders['Verify'];
         verify[details.requestId] = reqId;
         req.coreId = details.requestId;
-        for (var i in vm_headers)
+        for (var i in vmHeaders)
           if (~special_headers.indexOf(i.toLowerCase()))
-            new_headers.push({name: i, value: vm_headers[i]});
+            newHeaders.push({name: i, value: vmHeaders[i]});
       }
     }
-    return {requestHeaders: new_headers};
+    return {requestHeaders: newHeaders};
   }, {
     urls: ['<all_urls>'],
     types: ['xmlhttprequest'],
   }, ['blocking', 'requestHeaders']);
 
+  // Stop redirects
+  chrome.webRequest.onHeadersReceived.addListener(function (details) {
+    var task = tasks[details.requestId];
+    if (task) {
+      delete tasks[details.requestId];
+      if (task === 'Get-Location' && _.includes([301, 302, 303], details.statusCode)) {
+        var locationHeader = _.find(details.responseHeaders, function (header) {
+          return header.name.toLowerCase() === 'location';
+        });
+        return {
+          redirectUrl: 'data:text/plain;charset=utf-8,' + (locationHeader && locationHeader.value || ''),
+        };
+      }
+    }
+  }, {
+    urls: ['<all_urls>'],
+    types: ['xmlhttprequest'],
+  }, ['blocking', 'responseHeaders']);
+  chrome.webRequest.onCompleted.addListener(function (details) {
+    delete tasks[details.requestId];
+  }, {
+    urls: ['<all_urls>'],
+    types: ['xmlhttprequest'],
+  });
+  chrome.webRequest.onErrorOccurred.addListener(function (details) {
+    delete tasks[details.requestId];
+  }, {
+    urls: ['<all_urls>'],
+    types: ['xmlhttprequest'],
+  });
+
   chrome.webRequest.onBeforeRequest.addListener(function (req) {
     // onBeforeRequest is fired for local files too
     if (/\.user\.js([\?#]|$)/.test(req.url)) {
-      var noredirect = {redirectUrl: 'javascript:history.back()'};
+      var noredirect = {cancel: true};
       var x = new XMLHttpRequest();
       x.open('GET', req.url, false);
       try {

+ 8 - 8
src/background/sync/dropbox.js

@@ -4,13 +4,6 @@ setTimeout(function () {
     redirect_uri: 'https://violentmonkey.github.io/auth_dropbox.html',
   };
 
-  function checkAuthenticate(url) {
-    var redirect_uri = config.redirect_uri + '#';
-    if (url.slice(0, redirect_uri.length) === redirect_uri) {
-      authorized(url.slice(redirect_uri.length));
-      return true;
-    }
-  }
   function authenticate() {
     var params = {
       response_type: 'token',
@@ -22,6 +15,13 @@ setTimeout(function () {
     url += '?' + qs;
     chrome.tabs.create({url: url});
   }
+  function checkAuthenticate(url) {
+    var redirect_uri = config.redirect_uri + '#';
+    if (url.slice(0, redirect_uri.length) === redirect_uri) {
+      authorized(url.slice(redirect_uri.length));
+      return true;
+    }
+  }
   function authorized(raw) {
     var data = searchParams.load(raw);
     if (data.access_token) {
@@ -29,7 +29,7 @@ setTimeout(function () {
         uid: data.uid,
         token: data.access_token,
       });
-      this.prepare();
+      dropbox.prepare();
     }
   }
   function normalize(item) {

+ 21 - 10
src/background/sync/index.js

@@ -7,6 +7,8 @@ var sync = function () {
   var inited;
   var debouncedSync = _.debounce(function () {
     console.log('Start to sync');
+    queue = nextQueue;
+    nextQueue = [];
     process();
     autoSync();
   }, 10 * 1000);
@@ -122,9 +124,7 @@ var sync = function () {
   }
   function start() {
     if (syncing) return;
-    queue = nextQueue;
-    nextQueue = [];
-    if (queue.length) {
+    if (nextQueue.length) {
       console.log('Ready to sync');
       debouncedSync();
       return true;
@@ -172,6 +172,14 @@ var sync = function () {
   var BaseService = serviceFactory({
     name: 'base',
     displayName: 'BaseService',
+    delayTime: 1000,
+    urlPrefix: '',
+    delay: function (time) {
+      if (time == null) time = this.delayTime;
+      return new Promise(function (resolve, reject) {
+        setTimeout(resolve, time);
+      });
+    },
     initialize: function (name) {
       var _this = this;
       if (name) _this.name = name;
@@ -239,16 +247,19 @@ var sync = function () {
     },
     request: function (options) {
       var _this = this;
-      var lastFetch = _this.lastFetch;
-      _this.lastFetch = lastFetch.then(function () {
-        return new Promise(function (resolve, reject) {
-          setTimeout(resolve, 1000);
+      var lastFetch;
+      if (options.noDelay) {
+        lastFetch = Promise.resolve();
+      } else {
+        lastFetch = _this.lastFetch;
+        _this.lastFetch = lastFetch.then(function () {
+          return _this.delay();
         });
-      });
+      }
       return lastFetch.then(function () {
         return new Promise(function (resolve, reject) {
           var xhr = new XMLHttpRequest;
-          xhr.open(options.method || 'GET', options.url, true);
+          xhr.open(options.method || 'GET', _this.urlPrefix + options.url, true);
           var headers = _.assign({}, _this.headers, options.headers);
           if (options.body && typeof options.body === 'object') {
             headers['Content-Type'] = 'application/json';
@@ -276,7 +287,7 @@ var sync = function () {
 
           function requestError(reason) {
             reject({
-              url: xhr.url,
+              url: options.url,
               status: xhr.status,
               reason: reason || xhr.responseText,
             });