forked from EFForg/https-everywhere
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshim.py
More file actions
187 lines (149 loc) · 6.92 KB
/
shim.py
File metadata and controls
187 lines (149 loc) · 6.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import os
from contextlib import contextmanager
from collections import namedtuple
import subprocess
import time
import shutil
from selenium import webdriver
from selenium.webdriver import DesiredCapabilities
from selenium.webdriver.chrome.options import Options
firefox_info = {'extension_id': 'https-everywhere-eff@eff.org', 'uuid': 'd56a5b99-51b6-4e83-ab23-796216679614'}
chrome_info = {'extension_id': 'kofalhllfompobhklifpbealgeckijek'}
BROWSER_TYPES = ['chrome', 'firefox']
BROWSER_NAMES = ['google-chrome', 'google-chrome-stable', 'google-chrome-beta', 'firefox']
Specifics = namedtuple('Specifics', ['manager', 'background_url', 'info'])
parse_stdout = lambda res: res.strip().decode('utf-8')
run_shell_command = lambda command: parse_stdout(subprocess.check_output(command))
get_git_root = lambda: run_shell_command(['git', 'rev-parse', '--show-toplevel'])
def unix_which(command, silent=False):
try:
return run_shell_command(['which', command])
except subprocess.CalledProcessError as e:
if silent:
return None
raise e
def get_browser_type(string):
for t in BROWSER_TYPES:
if t in string:
return t
raise ValueError("couldn't get browser type from {}".format(string))
def get_browser_name(string):
if ('/' in string) or ('\\' in string): # its a path
return os.path.basename(string)
else: # its a browser type
for bn in BROWSER_NAMES:
if string in bn and unix_which(bn, silent=True):
return os.path.basename(unix_which(bn))
raise ValueError('Could not get browser name from {}'.format(string))
def build_crx():
'''Builds the .crx file for Chrome and returns the path to it'''
cmd = [os.path.join(get_git_root(), 'make.sh'), '--remove-update-channels']
run_shell_command(cmd)
# Since this is an unpacked extension we're loading, the extension ID is
# determined by the below `crx_dir` path alone. Don't alter it without
# changing the corresponding ID at the top of this file.
crx_dir = os.path.join(os.sep, 'tmp','https-everywhere-test')
shutil.rmtree(crx_dir, True)
shutil.copytree(os.path.join(get_git_root(), 'pkg', 'crx-cws'), crx_dir)
return crx_dir
def build_xpi():
cmd = [os.path.join(get_git_root(), 'make.sh'), '--remove-update-channels']
return os.path.join(get_git_root(), run_shell_command(cmd).split()[-5])
def install_ext_on_ff(driver, extension_path):
'''
Use Selenium's internal API's to manually send a message to geckodriver
to install the extension. We should remove this once the functionality is
included in Selenium. See https://github.com/SeleniumHQ/selenium/issues/4215
'''
command = 'addonInstall'
driver.install_addon(extension_path, temporary = True)
time.sleep(2)
class Shim:
_browser_msg = '''BROWSER should be one of:
* /path/to/a/browser
* a browser executable name so we can find the browser with "which $BROWSER"
* something from BROWSER_TYPES
'''
__doc__ = 'Chooses the correct driver and extension_url based on the BROWSER environment\nvariable. ' + _browser_msg
def __init__(self, chrome_info, firefox_info):
print('Configuring the test run')
self.chrome_info, self.firefox_info = chrome_info, firefox_info
self._specifics = None
browser = os.environ.get('BROWSER')
# get browser_path and broser_type first
if browser is None:
raise ValueError("The BROWSER environment variable is not set. " + self._browser_msg)
elif ("/" in browser) or ("\\" in browser): # path to a browser binary
self.browser_path = browser
self.browser_type = get_browser_type(self.browser_path)
elif unix_which(browser, silent=True): # executable browser name like 'google-chrome-stable'
self.browser_path = unix_which(browser)
self.browser_type = get_browser_type(browser)
elif get_browser_type(browser): # browser type like 'firefox' or 'chrome'
bname = get_browser_name(browser)
self.browser_path = unix_which(bname)
self.browser_type = browser
else:
raise ValueError("could not infer BROWSER from {}".format(browser))
self.extension_path = self.get_ext_path()
self._set_specifics()
print('\nUsing browser path: {} \nwith browser type: {} \nand extension path: {}'.format(self.browser_path, self.browser_type, self.extension_path))
self._set_urls(self.base_url)
def _set_specifics(self):
self._specifics = self._specifics or {
'chrome': Specifics(self.chrome_manager,
'chrome-extension://{}/'.format(self.chrome_info['extension_id']),
self.chrome_info),
'firefox': Specifics(self.firefox_manager,
'moz-extension://{}/'.format(self.firefox_info['uuid']),
self.firefox_info)}
self.manager, self.base_url, self.info = self._specifics[self.browser_type]
def _set_urls(self, base_url):
self.base_url = base_url
self.bg_url = base_url + "_generated_background_page.html"
self.popup_url = base_url + "pages/popup/index.html"
self.options_url = base_url + "pages/options/index.html"
def get_ext_path(self):
if self.browser_type == 'chrome':
return build_crx()
elif self.browser_type == 'firefox':
return build_xpi()
else:
raise ValueError("bad browser getting extension path")
@property
def wants_xvfb(self):
if self.on_travis or bool(int(os.environ.get('ENABLE_XVFB', 0))):
return True
return False
@property
def on_travis(self):
if "TRAVIS" in os.environ:
return True
return False
@contextmanager
def chrome_manager(self):
opts = Options()
if self.on_travis: # github.com/travis-ci/travis-ci/issues/938
opts.add_argument("--no-sandbox")
opts.add_argument("--load-extension=" + self.extension_path)
opts.binary_location = self.browser_path
opts.add_experimental_option("prefs", {"profile.block_third_party_cookies": False})
caps = DesiredCapabilities.CHROME.copy()
driver = webdriver.Chrome(options=opts, desired_capabilities=caps)
try:
yield driver
finally:
driver.quit()
@contextmanager
def firefox_manager(self):
ffp = webdriver.FirefoxProfile()
# make extension id constant across runs
ffp.set_preference('extensions.webextensions.uuids', '{{"{}": "{}"}}'.format(self.info['extension_id'], self.info['uuid']))
driver = webdriver.Firefox(firefox_profile=ffp, firefox_binary=self.browser_path)
install_ext_on_ff(driver, self.extension_path)
try:
yield driver
finally:
time.sleep(2)
driver.quit()
time.sleep(2)