Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 | 2 |
| 3 # Copyright 2014 The Chromium Authors. All rights reserved. | 3 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 '''A set of utilities to interface with the Chrome Webstore API.''' | 7 '''A set of utilities to interface with the Chrome Webstore API.''' |
| 8 | 8 |
| 9 import SimpleHTTPServer | 9 import SimpleHTTPServer |
| 10 import SocketServer | 10 import SocketServer |
| 11 import httplib | 11 import httplib |
| 12 import json | 12 import json |
| 13 import os | 13 import os |
| 14 import re | 14 import re |
| 15 import sys | 15 import sys |
| 16 import thread | 16 import thread |
| 17 import urllib | 17 import urllib |
| 18 import webbrowser | 18 import webbrowser |
| 19 | 19 |
| 20 PROJECT_ARGS = { | 20 PROJECT_ARGS = { |
| 21 'client_id': ('937534751394-gbj5334v9144c57qjqghl7d283plj5r4' | 21 'client_id': ('937534751394-gbj5334v9144c57qjqghl7d283plj5r4' |
| 22 '.apps.googleusercontent.com'), | 22 '.apps.googleusercontent.com'), |
| 23 'grant_type': 'authorization_code', | 23 'grant_type': 'authorization_code', |
| 24 'redirect_uri': 'http://localhost:8000' | 24 'redirect_uri': 'http://localhost:8000' |
| 25 } | 25 } |
| 26 | 26 |
| 27 # Globals. | |
| 27 PORT = 8000 | 28 PORT = 8000 |
| 29 auth_code = None | |
|
dmazzoni
2015/02/20 23:03:01
No strong preference, but maybe g_auth_code? I'm n
David Tseng
2015/02/20 23:34:52
Done.
| |
| 30 oauth_token = None | |
| 28 | 31 |
| 29 APP_ID = 'kgejglhpjiefppelpmljglcjbhoiplfn' | 32 APP_ID = 'kgejglhpjiefppelpmljglcjbhoiplfn' |
| 30 OAUTH_DOMAIN = 'accounts.google.com' | 33 OAUTH_DOMAIN = 'accounts.google.com' |
| 31 OAUTH_AUTH_COMMAND = '/o/oauth2/auth' | 34 OAUTH_AUTH_COMMAND = '/o/oauth2/auth' |
| 32 OAUTH_TOKEN_COMMAND = '/o/oauth2/token' | 35 OAUTH_TOKEN_COMMAND = '/o/oauth2/token' |
| 33 WEBSTORE_API_SCOPE = 'https://www.googleapis.com/auth/chromewebstore' | 36 WEBSTORE_API_SCOPE = 'https://www.googleapis.com/auth/chromewebstore' |
| 34 | 37 |
| 35 API_ENDPOINT_DOMAIN = 'www.googleapis.com' | 38 API_ENDPOINT_DOMAIN = 'www.googleapis.com' |
| 36 COMMAND_GET_UPLOAD_STATUS = ( | 39 COMMAND_GET_UPLOAD_STATUS = ( |
| 37 '/chromewebstore/v1.1/items/%s?projection=draft' % APP_ID) | 40 '/chromewebstore/v1.1/items/%s?projection=draft' % APP_ID) |
| 38 COMMAND_POST_PUBLISH = '/chromewebstore/v1.1/items/%s/publish' % APP_ID | 41 COMMAND_POST_PUBLISH = '/chromewebstore/v1.1/items/%s/publish' % APP_ID |
| 39 COMMAND_POST_UPLOAD = '/upload/chromewebstore/v1.1/items/%s' % APP_ID | 42 COMMAND_POST_UPLOAD = '/upload/chromewebstore/v1.1/items/%s' % APP_ID |
| 40 | 43 |
| 41 class CodeRequestHandler(SocketServer.StreamRequestHandler): | 44 class CodeRequestHandler(SocketServer.StreamRequestHandler): |
| 42 def handle(self): | 45 def handle(self): |
| 43 content = self.rfile.readline() | 46 content = self.rfile.readline() |
| 44 self.server.code = re.search('code=(.*) ', content).groups()[0] | 47 self.server.code = re.search('code=(.*) ', content).groups()[0] |
| 45 self.rfile.close() | 48 self.rfile.close() |
| 46 | 49 |
| 47 def GetAuthCode(): | 50 def GetAuthCode(): |
| 51 global auth_code | |
| 52 if auth_code: | |
| 53 return auth_code | |
| 54 | |
| 48 Handler = CodeRequestHandler | 55 Handler = CodeRequestHandler |
| 49 httpd = SocketServer.TCPServer(("", PORT), Handler) | 56 httpd = SocketServer.TCPServer(("", PORT), Handler) |
| 50 query = '&'.join(['response_type=code', | 57 query = '&'.join(['response_type=code', |
| 51 'scope=%s' % WEBSTORE_API_SCOPE, | 58 'scope=%s' % WEBSTORE_API_SCOPE, |
| 52 'client_id=%(client_id)s' % PROJECT_ARGS, | 59 'client_id=%(client_id)s' % PROJECT_ARGS, |
| 53 'redirect_uri=%(redirect_uri)s' % PROJECT_ARGS]) | 60 'redirect_uri=%(redirect_uri)s' % PROJECT_ARGS]) |
| 54 auth_url = 'https://%s%s?%s' % (OAUTH_DOMAIN, OAUTH_AUTH_COMMAND, query) | 61 auth_url = 'https://%s%s?%s' % (OAUTH_DOMAIN, OAUTH_AUTH_COMMAND, query) |
| 55 print 'Navigating to %s' % auth_url | 62 print 'Navigating to %s' % auth_url |
| 56 webbrowser.open(auth_url) | 63 webbrowser.open(auth_url) |
| 57 httpd.handle_request() | 64 httpd.handle_request() |
| 58 httpd.server_close() | 65 httpd.server_close() |
| 59 return httpd.code | 66 auth_code = httpd.code |
| 67 return auth_code | |
| 60 | 68 |
| 61 def GetOauthToken(code, client_secret): | 69 def GetOauthToken(code, client_secret): |
| 70 global oauth_token | |
| 71 if oauth_token: | |
| 72 return oauth_token | |
| 73 | |
| 62 PROJECT_ARGS['code'] = code | 74 PROJECT_ARGS['code'] = code |
| 63 PROJECT_ARGS['client_secret'] = client_secret | 75 PROJECT_ARGS['client_secret'] = client_secret |
| 64 body = urllib.urlencode(PROJECT_ARGS) | 76 body = urllib.urlencode(PROJECT_ARGS) |
| 65 conn = httplib.HTTPSConnection(OAUTH_DOMAIN) | 77 conn = httplib.HTTPSConnection(OAUTH_DOMAIN) |
| 66 conn.putrequest('POST', OAUTH_TOKEN_COMMAND) | 78 conn.putrequest('POST', OAUTH_TOKEN_COMMAND) |
| 67 conn.putheader('content-type', 'application/x-www-form-urlencoded') | 79 conn.putheader('content-type', 'application/x-www-form-urlencoded') |
| 68 conn.putheader('content-length', len(body)) | 80 conn.putheader('content-length', len(body)) |
| 69 conn.endheaders() | 81 conn.endheaders() |
| 70 conn.send(body) | 82 conn.send(body) |
| 71 content = conn.getresponse().read() | 83 content = conn.getresponse().read() |
| 72 return json.loads(content) | 84 conn.close() |
| 85 oauth_token = json.loads(content) | |
| 86 return oauth_token | |
| 73 | 87 |
| 74 def GetPopulatedHeader(client_secret): | 88 def GetPopulatedHeader(client_secret): |
| 75 code = GetAuthCode() | 89 code = GetAuthCode() |
| 76 access_token = GetOauthToken(code, client_secret) | 90 access_token = GetOauthToken(code, client_secret) |
| 91 print "a!"+str(access_token) | |
|
dmazzoni
2015/02/20 23:03:01
debugging?
David Tseng
2015/02/20 23:34:52
Oops; removed.
| |
| 77 url = 'www.googleapis.com' | 92 url = 'www.googleapis.com' |
| 78 | 93 |
| 79 return {'Authorization': 'Bearer %(access_token)s' % access_token, | 94 return {'Authorization': 'Bearer %(access_token)s' % access_token, |
| 80 'x-goog-api-version': 2, | 95 'x-goog-api-version': 2, |
| 81 'Content-Length': 0 | 96 'Content-Length': 0 |
| 82 } | 97 } |
| 83 | 98 |
| 84 def SendGetCommand(command, client_secret): | 99 def SendGetCommand(command, client_secret): |
| 85 headers = GetPopulatedHeader(client_secret) | 100 headers = GetPopulatedHeader(client_secret) |
| 86 conn = httplib.HTTPSConnection(API_ENDPOINT_DOMAIN) | 101 conn = httplib.HTTPSConnection(API_ENDPOINT_DOMAIN) |
| 87 conn.request('GET', command, '', headers) | 102 conn.request('GET', command, '', headers) |
| 88 return conn.getresponse() | 103 r = conn.getresponse() |
| 104 conn.close() | |
| 105 return r | |
| 89 | 106 |
| 90 def SendPostCommand(command, client_secret, header_additions = {}, body=None): | 107 def SendPostCommand(command, client_secret, header_additions = {}, body=None): |
| 91 headers = GetPopulatedHeader(client_secret) | 108 headers = GetPopulatedHeader(client_secret) |
| 92 headers = dict(headers.items() + header_additions.items()) | 109 headers = dict(headers.items() + header_additions.items()) |
| 93 conn = httplib.HTTPSConnection(API_ENDPOINT_DOMAIN) | 110 conn = httplib.HTTPSConnection(API_ENDPOINT_DOMAIN) |
| 94 conn.request('POST', command, body, headers) | 111 conn.request('POST', command, body, headers) |
| 95 return conn.getresponse() | 112 r = conn.getresponse() |
| 113 conn.close() | |
| 114 return r | |
| 96 | 115 |
| 97 def GetUploadStatus(client_secret): | 116 def GetUploadStatus(client_secret): |
| 98 '''Gets the status of a previous upload. | 117 '''Gets the status of a previous upload. |
| 99 Args: | 118 Args: |
| 100 client_secret ChromeVox's client secret creds. | 119 client_secret ChromeVox's client secret creds. |
| 101 ''' | 120 ''' |
| 102 return SendGetCommand(COMMAND_GET_UPLOAD_STATUS, client_secret) | 121 return SendGetCommand(COMMAND_GET_UPLOAD_STATUS, client_secret) |
| 103 | 122 |
| 104 # httplib fails to persist the connection during upload; use curl instead. | 123 # httplib fails to persist the connection during upload; use curl instead. |
| 105 def PostUpload(file, client_secret): | 124 def PostUpload(file, client_secret): |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 130 return SendPostCommand(COMMAND_POST_PUBLISH, | 149 return SendPostCommand(COMMAND_POST_PUBLISH, |
| 131 client_secret, | 150 client_secret, |
| 132 { 'publishTarget': 'trustedTesters'}) | 151 { 'publishTarget': 'trustedTesters'}) |
| 133 | 152 |
| 134 def PostPublish(client_secret): | 153 def PostPublish(client_secret): |
| 135 '''Publishes a previously uploaded ChromeVox extension publically. | 154 '''Publishes a previously uploaded ChromeVox extension publically. |
| 136 Args: | 155 Args: |
| 137 client_secret ChromeVox's client secret creds. | 156 client_secret ChromeVox's client secret creds. |
| 138 ''' | 157 ''' |
| 139 return SendPostCommand(COMMAND_POST_PUBLISH, client_secret) | 158 return SendPostCommand(COMMAND_POST_PUBLISH, client_secret) |
| OLD | NEW |