Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / common / extensions / docs / server2 / appengine_url_fetcher.py
index a4c359b..8ed0494 100644 (file)
@@ -3,14 +3,20 @@
 # found in the LICENSE file.
 
 import base64
+import logging
 import posixpath
+import time
 
 from appengine_wrappers import urlfetch
 from environment import GetAppVersion
 from future import Future
 
 
-def _MakeHeaders(username, password):
+_MAX_RETRIES = 5
+_RETRY_DELAY_SECONDS = 30
+
+
+def _MakeHeaders(username, password, access_token):
   headers = {
     'User-Agent': 'Chromium docserver %s' % GetAppVersion(),
     'Cache-Control': 'max-age=0',
@@ -18,6 +24,8 @@ def _MakeHeaders(username, password):
   if username is not None and password is not None:
     headers['Authorization'] = 'Basic %s' % base64.b64encode(
         '%s:%s' % (username, password))
+  if access_token is not None:
+    headers['Authorization'] = 'OAuth %s' % access_token
   return headers
 
 
@@ -28,21 +36,39 @@ class AppEngineUrlFetcher(object):
   def __init__(self, base_path=None):
     assert base_path is None or not base_path.endswith('/'), base_path
     self._base_path = base_path
+    self._retries_left = _MAX_RETRIES
 
-  def Fetch(self, url, username=None, password=None):
+  def Fetch(self, url, username=None, password=None, access_token=None):
     """Fetches a file synchronously.
     """
     return urlfetch.fetch(self._FromBasePath(url),
-                          headers=_MakeHeaders(username, password))
+                          deadline=20,
+                          headers=_MakeHeaders(username,
+                                               password,
+                                               access_token))
 
-  def FetchAsync(self, url, username=None, password=None):
+  def FetchAsync(self, url, username=None, password=None, access_token=None):
     """Fetches a file asynchronously, and returns a Future with the result.
     """
-    rpc = urlfetch.create_rpc()
+    def process_result(result):
+      if result.status_code == 429:
+        if self._retries_left == 0:
+          logging.error('Still throttled. Giving up.')
+          return result
+        self._retries_left -= 1
+        logging.info('Throttled. Trying again in %s seconds.' %
+                     _RETRY_DELAY_SECONDS)
+        time.sleep(_RETRY_DELAY_SECONDS)
+        return self.FetchAsync(url, username, password, access_token).Get()
+      return result
+
+    rpc = urlfetch.create_rpc(deadline=20)
     urlfetch.make_fetch_call(rpc,
                              self._FromBasePath(url),
-                             headers=_MakeHeaders(username, password))
-    return Future(callback=lambda: rpc.get_result())
+                             headers=_MakeHeaders(username,
+                                                  password,
+                                                  access_token))
+    return Future(callback=lambda: process_result(rpc.get_result()))
 
   def _FromBasePath(self, url):
     assert not url.startswith('/'), url