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 g_auth_code = None |
| 30 g_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 g_auth_code |
| 52 if g_auth_code: |
| 53 return g_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 g_auth_code = httpd.code |
| 67 return g_auth_code |
60 | 68 |
61 def GetOauthToken(code, client_secret): | 69 def GetOauthToken(code, client_secret): |
| 70 global g_oauth_token |
| 71 if g_oauth_token: |
| 72 return g_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 g_oauth_token = json.loads(content) |
| 86 return g_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 |
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 |