Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(225)

Side by Side Diff: third_party/mozprofile/mozprofile/permissions.py

Issue 108313011: Adding mozilla libraries required by Firefox interop test. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/mozprofile/mozprofile/cli.py ('k') | third_party/mozprofile/mozprofile/prefs.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 # You can obtain one at http://mozilla.org/MPL/2.0/.
4
5
6 """
7 add permissions to the profile
8 """
9
10 __all__ = ['MissingPrimaryLocationError', 'MultiplePrimaryLocationsError',
11 'DuplicateLocationError', 'BadPortLocationError',
12 'LocationsSyntaxError', 'Location', 'ServerLocations',
13 'Permissions']
14
15 import codecs
16 import itertools
17 import os
18 try:
19 import sqlite3
20 except ImportError:
21 from pysqlite2 import dbapi2 as sqlite3
22 import urlparse
23
24
25 class LocationError(Exception):
26 "Signifies an improperly formed location."
27
28 def __str__(self):
29 s = "Bad location"
30 if self.message:
31 s += ": %s" % self.message
32 return s
33
34
35 class MissingPrimaryLocationError(LocationError):
36 "No primary location defined in locations file."
37
38 def __init__(self):
39 LocationError.__init__(self, "missing primary location")
40
41
42 class MultiplePrimaryLocationsError(LocationError):
43 "More than one primary location defined."
44
45 def __init__(self):
46 LocationError.__init__(self, "multiple primary locations")
47
48
49 class DuplicateLocationError(LocationError):
50 "Same location defined twice."
51
52 def __init__(self, url):
53 LocationError.__init__(self, "duplicate location: %s" % url)
54
55
56 class BadPortLocationError(LocationError):
57 "Location has invalid port value."
58
59 def __init__(self, given_port):
60 LocationError.__init__(self, "bad value for port: %s" % given_port)
61
62
63 class LocationsSyntaxError(Exception):
64 "Signifies a syntax error on a particular line in server-locations.txt."
65
66 def __init__(self, lineno, err=None):
67 self.err = err
68 self.lineno = lineno
69
70 def __str__(self):
71 s = "Syntax error on line %s" % self.lineno
72 if self.err:
73 s += ": %s." % self.err
74 else:
75 s += "."
76 return s
77
78
79 class Location(object):
80 "Represents a location line in server-locations.txt."
81
82 attrs = ('scheme', 'host', 'port')
83
84 def __init__(self, scheme, host, port, options):
85 for attr in self.attrs:
86 setattr(self, attr, locals()[attr])
87 self.options = options
88 try:
89 int(self.port)
90 except ValueError:
91 raise BadPortLocationError(self.port)
92
93 def isEqual(self, location):
94 "compare scheme://host:port, but ignore options"
95 return len([i for i in self.attrs if getattr(self, i) == getattr(locatio n, i)]) == len(self.attrs)
96
97 __eq__ = isEqual
98
99 def url(self):
100 return '%s://%s:%s' % (self.scheme, self.host, self.port)
101
102 def __str__(self):
103 return '%s %s' % (self.url(), ','.join(self.options))
104
105
106 class ServerLocations(object):
107 """Iterable collection of locations.
108 Use provided functions to add new locations, rather that manipulating
109 _locations directly, in order to check for errors and to ensure the
110 callback is called, if given.
111 """
112
113 def __init__(self, filename=None, add_callback=None):
114 self.add_callback = add_callback
115 self._locations = []
116 self.hasPrimary = False
117 if filename:
118 self.read(filename)
119
120 def __iter__(self):
121 return self._locations.__iter__()
122
123 def __len__(self):
124 return len(self._locations)
125
126 def add(self, location, suppress_callback=False):
127 if "primary" in location.options:
128 if self.hasPrimary:
129 raise MultiplePrimaryLocationsError()
130 self.hasPrimary = True
131
132 self._locations.append(location)
133 if self.add_callback and not suppress_callback:
134 self.add_callback([location])
135
136 def add_host(self, host, port='80', scheme='http', options='privileged'):
137 if isinstance(options, basestring):
138 options = options.split(',')
139 self.add(Location(scheme, host, port, options))
140
141 def read(self, filename, check_for_primary=True):
142 """
143 Reads the file (in the format of server-locations.txt) and add all
144 valid locations to the self._locations array.
145
146 If check_for_primary is True, a MissingPrimaryLocationError
147 exception is raised if no primary is found.
148
149 This format:
150 http://mxr.mozilla.org/mozilla-central/source/build/pgo/server-locations .txt
151 The only exception is that the port, if not defined, defaults to 80 or 4 43.
152
153 FIXME: Shouldn't this default to the protocol-appropriate port? Is
154 there any reason to have defaults at all?
155 """
156
157 locationFile = codecs.open(filename, "r", "UTF-8")
158 lineno = 0
159 new_locations = []
160
161 for line in locationFile:
162 line = line.strip()
163 lineno += 1
164
165 # check for comments and blank lines
166 if line.startswith("#") or not line:
167 continue
168
169 # split the server from the options
170 try:
171 server, options = line.rsplit(None, 1)
172 options = options.split(',')
173 except ValueError:
174 server = line
175 options = []
176
177 # parse the server url
178 if '://' not in server:
179 server = 'http://' + server
180 scheme, netloc, path, query, fragment = urlparse.urlsplit(server)
181 # get the host and port
182 try:
183 host, port = netloc.rsplit(':', 1)
184 except ValueError:
185 host = netloc
186 default_ports = {'http': '80',
187 'https': '443',
188 'ws': '443',
189 'wss': '443'}
190 port = default_ports.get(scheme, '80')
191
192 try:
193 location = Location(scheme, host, port, options)
194 self.add(location, suppress_callback=True)
195 except LocationError, e:
196 raise LocationsSyntaxError(lineno, e)
197
198 new_locations.append(location)
199
200 # ensure that a primary is found
201 if check_for_primary and not self.hasPrimary:
202 raise LocationsSyntaxError(lineno + 1,
203 MissingPrimaryLocationError())
204
205 if self.add_callback:
206 self.add_callback(new_locations)
207
208
209 class Permissions(object):
210 _num_permissions = 0
211
212 def __init__(self, profileDir, locations=None):
213 self._profileDir = profileDir
214 self._locations = ServerLocations(add_callback=self.write_db)
215 if locations:
216 if isinstance(locations, ServerLocations):
217 self._locations = locations
218 self._locations.add_callback = self.write_db
219 self.write_db(self._locations._locations)
220 elif isinstance(locations, list):
221 for l in locations:
222 self._locations.add_host(**l)
223 elif isinstance(locations, dict):
224 self._locations.add_host(**locations)
225 elif os.path.exists(locations):
226 self._locations.read(locations)
227
228 def write_db(self, locations):
229 """write permissions to the sqlite database"""
230
231 # Open database and create table
232 permDB = sqlite3.connect(os.path.join(self._profileDir, "permissions.sql ite"))
233 cursor = permDB.cursor();
234 # SQL copied from
235 # http://mxr.mozilla.org/mozilla-central/source/extensions/cookie/nsPerm issionManager.cpp
236 cursor.execute("""CREATE TABLE IF NOT EXISTS moz_hosts (
237 id INTEGER PRIMARY KEY,
238 host TEXT,
239 type TEXT,
240 permission INTEGER,
241 expireType INTEGER,
242 expireTime INTEGER)""")
243
244 for location in locations:
245 # set the permissions
246 permissions = { 'allowXULXBL': 'noxul' not in location.options }
247 for perm, allow in permissions.iteritems():
248 self._num_permissions += 1
249 if allow:
250 permission_type = 1
251 else:
252 permission_type = 2
253 cursor.execute("INSERT INTO moz_hosts values(?, ?, ?, ?, 0, 0)",
254 (self._num_permissions, location.host, perm,
255 permission_type))
256
257 # Commit and close
258 permDB.commit()
259 cursor.close()
260
261 def network_prefs(self, proxy=False):
262 """
263 take known locations and generate preferences to handle permissions and proxy
264 returns a tuple of prefs, user_prefs
265 """
266
267 # Grant God-power to all the privileged servers on which tests run.
268 prefs = []
269 privileged = [i for i in self._locations if "privileged" in i.options]
270 for (i, l) in itertools.izip(itertools.count(1), privileged):
271 prefs.append(("capability.principal.codebase.p%s.granted" % i, "Univ ersalXPConnect"))
272
273 prefs.append(("capability.principal.codebase.p%s.id" % i, "%s://%s:% s" %
274 (l.scheme, l.host, l.port)))
275 prefs.append(("capability.principal.codebase.p%s.subjectName" % i, " "))
276
277 if proxy:
278 user_prefs = self.pac_prefs()
279 else:
280 user_prefs = []
281
282 return prefs, user_prefs
283
284 def pac_prefs(self):
285 """
286 return preferences for Proxy Auto Config. originally taken from
287 http://mxr.mozilla.org/mozilla-central/source/build/automation.py.in
288 """
289
290 prefs = []
291
292 # We need to proxy every server but the primary one.
293 origins = ["'%s'" % l.url()
294 for l in self._locations]
295
296 origins = ", ".join(origins)
297
298 for l in self._locations:
299 if "primary" in l.options:
300 webServer = l.host
301 port = l.port
302
303 # TODO: this should live in a template!
304 # TODO: So changing the 5th line of the regex below from (\\\\\\\\d+)
305 # to (\\\\d+) makes this code work. Not sure why there would be this
306 # difference between automation.py.in and this file.
307 pacURL = """data:text/plain,
308 function FindProxyForURL(url, host)
309 {
310 var origins = [%(origins)s];
311 var regex = new RegExp('^([a-z][-a-z0-9+.]*)' +
312 '://' +
313 '(?:[^/@]*@)?' +
314 '(.*?)' +
315 '(?::(\\\\d+))?/');
316 var matches = regex.exec(url);
317 if (!matches)
318 return 'DIRECT';
319 var isHttp = matches[1] == 'http';
320 var isHttps = matches[1] == 'https';
321 var isWebSocket = matches[1] == 'ws';
322 var isWebSocketSSL = matches[1] == 'wss';
323 if (!matches[3])
324 {
325 if (isHttp | isWebSocket) matches[3] = '80';
326 if (isHttps | isWebSocketSSL) matches[3] = '443';
327 }
328 if (isWebSocket)
329 matches[1] = 'http';
330 if (isWebSocketSSL)
331 matches[1] = 'https';
332
333 var origin = matches[1] + '://' + matches[2] + ':' + matches[3];
334 if (origins.indexOf(origin) < 0)
335 return 'DIRECT';
336 if (isHttp || isHttps || isWebSocket || isWebSocketSSL)
337 return 'PROXY %(remote)s:%(port)s';
338 return 'DIRECT';
339 }""" % { "origins": origins,
340 "remote": webServer,
341 "port": port }
342 pacURL = "".join(pacURL.splitlines())
343
344 prefs.append(("network.proxy.type", 2))
345 prefs.append(("network.proxy.autoconfig_url", pacURL))
346
347 return prefs
348
349 def clean_db(self):
350 """Removed permissions added by mozprofile."""
351
352 sqlite_file = os.path.join(self._profileDir, "permissions.sqlite")
353 if not os.path.exists(sqlite_file):
354 return
355
356 # Open database and create table
357 permDB = sqlite3.connect(sqlite_file)
358 cursor = permDB.cursor();
359
360 # TODO: only delete values that we add, this would require sending in th e full permissions object
361 cursor.execute("DROP TABLE IF EXISTS moz_hosts");
362
363 # Commit and close
364 permDB.commit()
365 cursor.close()
OLDNEW
« no previous file with comments | « third_party/mozprofile/mozprofile/cli.py ('k') | third_party/mozprofile/mozprofile/prefs.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698