Merge lp:~jlisee/rescuetime-linux-uploader/experimental into lp:rescuetime-linux-uploader
- experimental
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 105 | ||||
Proposed branch: | lp:~jlisee/rescuetime-linux-uploader/experimental | ||||
Merge into: | lp:rescuetime-linux-uploader | ||||
Diff against target: |
335 lines (+226/-4) 5 files modified
RescueTimeUploader/extensions/Gnome-terminal/app_name (+5/-0) RescueTimeUploader/extensions/Google-chrome/extended_info (+136/-0) RescueTimeUploader/uploader.py (+16/-4) chrome_extension/background.html (+55/-0) chrome_extension/manifest.json (+14/-0) |
||||
To merge this branch: | bzr merge lp:~jlisee/rescuetime-linux-uploader/experimental | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Joseph Lisee (community) | Approve | ||
Dirk T | Needs Information | ||
Review via email: mp+119601@code.launchpad.net |
Commit message
Description of the change
Joseph Lisee (jlisee) wrote : | # |
> Joseph, not sure if you're still active in this project. Do you remember what
> made you create revision 105?
I am pretty sure I found a race condition between two threads. Even through threading isn't used explicitly with the way things are done the Uploader class runs in a different thread then whatever runs the gnome panel.
Joseph Lisee (jlisee) wrote : | # |
I approve of the merge. My only reservation is that I have not used the Chrome plugin in a while so I am not sure if it still works. Even if it doesn't I think it would only require minor updates to get it working again.
Dirk T (miriup) wrote : | # |
> I approve of the merge. My only reservation is that I have not used the Chrome
> plugin in a while so I am not sure if it still works.
I will know. I'm using as my primary browser. :)
Cheers,
Dirk.
Preview Diff
1 | === modified file 'RescueTimeUploader/extensions/Gnome-terminal/app_name' |
2 | --- RescueTimeUploader/extensions/Gnome-terminal/app_name 2008-02-03 16:54:21 +0000 |
3 | +++ RescueTimeUploader/extensions/Gnome-terminal/app_name 2012-08-14 18:23:19 +0000 |
4 | @@ -1,5 +1,10 @@ |
5 | #!/usr/bin/env python |
6 | |
7 | +""" |
8 | +Returns the remote host name if the terminal is an ssh session, otherwise it |
9 | +returns given app_name (in this case 'Gnome-terminal') |
10 | +""" |
11 | + |
12 | import sys |
13 | import os |
14 | app_name = raw_input("") |
15 | |
16 | === added directory 'RescueTimeUploader/extensions/Google-chrome' |
17 | === added file 'RescueTimeUploader/extensions/Google-chrome/extended_info' |
18 | --- RescueTimeUploader/extensions/Google-chrome/extended_info 1970-01-01 00:00:00 +0000 |
19 | +++ RescueTimeUploader/extensions/Google-chrome/extended_info 2012-08-14 18:23:19 +0000 |
20 | @@ -0,0 +1,136 @@ |
21 | +#!/usr/bin/env python |
22 | + |
23 | +# Copyright (c) 2010 Joseph Lisee <jlisee@gmail.com> |
24 | +# |
25 | +# Permission is hereby granted, free of charge, to any person obtaining a copy |
26 | +# of this software and associated documentation files (the "Software"), to deal |
27 | +# in the Software without restriction, including without limitation the rights |
28 | +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
29 | +# copies of the Software, and to permit persons to whom the Software is |
30 | +# furnished to do so, subject to the following conditions: |
31 | +# |
32 | +# The above copyright notice and this permission notice shall be included in |
33 | +# all copies or substantial portions of the Software. |
34 | +# |
35 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
36 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
37 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
38 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
39 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
40 | +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
41 | +# THE SOFTWARE. |
42 | + |
43 | +# White list checking and URL parsing our borrowed from the firefox extension |
44 | +# in the future the code should be merged somehow |
45 | + |
46 | + |
47 | +import os |
48 | +import subprocess |
49 | +from urlparse import urlparse |
50 | +from os.path import expanduser, join, exists |
51 | + |
52 | +""" |
53 | +Extracts the current google chrome URL local HTML storage of the extension and |
54 | +prints it to stdout. It is intelligent about searching out and finding the |
55 | +write google extension local storage database, and cashes the result for use. |
56 | +""" |
57 | + |
58 | +# Overall settings and paths |
59 | +preferenceDir = join(expanduser('~'), '.rescuetime') |
60 | +whitelist_file = join(preferenceDir, 'domainwhitelist.txt') |
61 | +extensionID_file = join(preferenceDir, 'google-chrome_extension-id.txt') |
62 | +localStorageDir = join(os.getenv("HOME"), ".config", "google-chrome", |
63 | + "Default", "Local Storage") |
64 | + |
65 | +# Load whitelist |
66 | +allowed_domains = [] |
67 | + |
68 | +if exists(whitelist_file): |
69 | + have_whitelist = True |
70 | + for line in open(whitelist_file): |
71 | + # strip comments and whitespace |
72 | + line = line.split('#', 1)[0].strip() |
73 | + if line: |
74 | + allowed_domains.append(line) |
75 | +else: |
76 | + have_whitelist = False |
77 | + |
78 | +def findExtensionID(): |
79 | + dirs = os.listdir(localStorageDir) |
80 | + extensionDirs = [d for d in dirs if d.startswith('chrome-extension_')] |
81 | + |
82 | + for extensionDir in extensionDirs: |
83 | + extID = extensionDir.split('_')[1] |
84 | + url = retrieveURL(extID) |
85 | + |
86 | + if len(url) > 0: |
87 | + return extID |
88 | + |
89 | +def findAndStoreExtensionID(): |
90 | + extID = findExtensionID() |
91 | + f = open(extensionID_file, 'w') |
92 | + f.write(extID) |
93 | + f.close() |
94 | + return extID |
95 | + |
96 | +def retrieveURL(extID): |
97 | + # Build the complete path to the database inside goolge chrome directory |
98 | + databaseName = "chrome-extension_%s_0.localstorage" % extID |
99 | + databasePath = join(localStorageDir, databaseName) |
100 | + |
101 | + currentURL = '' |
102 | + |
103 | + if exists(databasePath): |
104 | + # Form the SQLlite3 command to extract the data |
105 | + sql = "SELECT value FROM ItemTable WHERE key = 'RescueTimeLinuxUrl';" |
106 | + command = "sqlite3 \"%s\" \"%s\"" % (databasePath, sql) |
107 | + |
108 | + runner = subprocess.Popen(command, shell=True, |
109 | + stdin=subprocess.PIPE, stdout=subprocess.PIPE) |
110 | + currentURL = runner.communicate()[0][:-1] |
111 | + |
112 | + return currentURL |
113 | + |
114 | + |
115 | +def check_whitelist(urlparse_tuple): |
116 | + """urlparse_tuple is a tuple returned by urlparse |
117 | + Return True if domain is allowed, False if not. |
118 | + """ |
119 | + if not have_whitelist: |
120 | + # let everything through |
121 | + return True |
122 | + name = urlparse_tuple[1] |
123 | + for domain in allowed_domains: |
124 | + if name.find(domain) != -1: |
125 | + return True |
126 | + return False |
127 | + |
128 | +# Find and verify our extenionID |
129 | +extensionID = '' |
130 | + |
131 | +if exists(extensionID_file): |
132 | + f = open(extensionID_file) |
133 | + extensionID = f.read() |
134 | + f.close() |
135 | +else: |
136 | + extensionID = findAndStoreExtensionID() |
137 | + |
138 | +# Attempt to get URL |
139 | +url = retrieveURL(extensionID) |
140 | + |
141 | +if len(url) == 0: |
142 | + # Extension ID must have changed |
143 | + extensionID = findAndStoreExtensionID() |
144 | + url = retrieveURL(extensionID) |
145 | + |
146 | +# Break it up into its parts |
147 | +info = urlparse(url) |
148 | + |
149 | +# Check white list and log just the needed parts of the URL |
150 | +allowed = check_whitelist(info) |
151 | +if not allowed: |
152 | + print 'unlisted' |
153 | +elif "google" in info[1].lower(): |
154 | + print info[0] + "://" + info[1] + info[2] |
155 | +else: |
156 | + print info[0] + "://" + info[1] |
157 | |
158 | === modified file 'RescueTimeUploader/uploader.py' |
159 | --- RescueTimeUploader/uploader.py 2012-08-14 17:19:37 +0000 |
160 | +++ RescueTimeUploader/uploader.py 2012-08-14 18:23:19 +0000 |
161 | @@ -23,6 +23,7 @@ |
162 | socket.setdefaulttimeout(15) |
163 | import urllib |
164 | import urllib2 |
165 | +import threading |
166 | |
167 | import RescueTimeUploader.options |
168 | import RescueTimeUploader.dirstructure |
169 | @@ -178,12 +179,12 @@ |
170 | if idle_time > (self.options.max_idle_minutes * 60): |
171 | return None |
172 | try: |
173 | - exec_cmd = """xprop -id `xprop -root |awk '/_NET_ACTIVE_WINDOW/ {print $5; exit;}'` |awk -F = '/WM_CLASS/ {print $2; exit;}'| awk '{print $2}' | sed 's/^"//g' | sed 's/"$//g'""" |
174 | + exec_cmd = """xprop -id `xprop -root |awk '/^_NET_ACTIVE_WINDOW/ {print $5; exit;}'` |awk -F = '/WM_CLASS/ {print $2; exit;}'| awk '{print $2}' | sed 's/^"//g' | sed 's/"$//g'""" |
175 | runner = subprocess.Popen(exec_cmd, shell=True, |
176 | stdin=subprocess.PIPE, stdout=subprocess.PIPE) |
177 | runner_res = runner.communicate()[0][:-1] |
178 | - if not runner_res.isalnum(): |
179 | - exec_cmd = """xprop -id `xprop -root |awk '/_NET_ACTIVE_WINDOW/ {print $5; exit;}'` |awk -F = '/^WM_NAME/ {print $2; exit;}' | sed -e's/^ *"//g' | sed -e's/\"$//g'""" |
180 | + if len(runner_res) == 0: |
181 | + exec_cmd = """xprop -id `xprop -root |awk '/^_NET_ACTIVE_WINDOW/ {print $5; exit;}'` |awk -F = '/^WM_NAME/ {print $2; exit;}' | sed -e's/^ *"//g' | sed -e's/\"$//g'""" |
182 | runner = subprocess.Popen(exec_cmd, shell=True, |
183 | stdin=subprocess.PIPE, stdout=subprocess.PIPE) |
184 | runner_res = runner.communicate()[0][:-1] |
185 | @@ -259,7 +260,7 @@ |
186 | |
187 | encoded_title_re = re.compile("(0x[0-9abcdefABCDEF]*,* *)+$") |
188 | def _get_raw_window_title(self): |
189 | - exec_cmd = """xprop -id `xprop -root |awk '/_NET_ACTIVE_WINDOW/ {print $5; exit;}'` |awk -F = '/^WM_NAME/ {print $2; exit;}' | sed -e's/^ *"//g' | sed -e's/\\"$//g'""" |
190 | + exec_cmd = """xprop -id `xprop -root |awk '/^_NET_ACTIVE_WINDOW/ {print $5; exit;}'` |awk -F = '/^WM_NAME/ {print $2; exit;}' | sed -e's/^ *"//g' | sed -e's/\\"$//g'""" |
191 | try: |
192 | runner = subprocess.Popen(exec_cmd, shell=True, |
193 | stdin=subprocess.PIPE, stdout=subprocess.PIPE) |
194 | @@ -333,6 +334,7 @@ |
195 | ##out.flush() |
196 | self.dir_structure = RescueTimeUploader.dirstructure.DirStructure() |
197 | self.options = RescueTimeUploader.options.Options(self.dir_structure) |
198 | + self.time_objs_lock = threading.RLock() |
199 | |
200 | signal.signal(signal.SIGTERM, handle_signal) |
201 | signal.signal(signal.SIGHUP, handle_signal) |
202 | @@ -365,6 +367,8 @@ |
203 | |
204 | |
205 | def get_latest_time_obj(self): |
206 | + self.time_objs_lock.acquire() |
207 | + |
208 | f = file(os.path.join(self.dir_structure.tmp_dir, "notifier.debuglog"), "a") |
209 | f.write("---- STARTING CHECK ----\n") |
210 | f.write("archived_time_objs: %s\n" % self.archived_time_objs) |
211 | @@ -398,6 +402,8 @@ |
212 | latest_time_obj = timeobj |
213 | f.write("Returning %s\n" % latest_time_obj) |
214 | f.close() |
215 | + |
216 | + self.time_objs_lock.release() |
217 | return latest_time_obj |
218 | |
219 | def retrieve_credentials(self): |
220 | @@ -435,8 +441,10 @@ |
221 | print "Failed to save preferences on shutdown." |
222 | ##out.flush() |
223 | try: |
224 | + self.time_objs_lock.acquire() |
225 | self.time_objs[-1].close() |
226 | self.prepare_data(self.time_objs) |
227 | + self.time_objs_lock.release() |
228 | except: |
229 | print "Failed to prepare data on shutdown." |
230 | ##out.flush() |
231 | @@ -494,6 +502,8 @@ |
232 | |
233 | try: |
234 | while True: |
235 | + self.time_objs_lock.acquire() |
236 | + |
237 | # If the focused window has changed |
238 | if not self.time_objs[len(self.time_objs) - 1].still_active(): |
239 | self.time_objs[len(self.time_objs) - 1].close() |
240 | @@ -507,6 +517,8 @@ |
241 | next_upload_time = datetime.datetime.today() + self.options.upload_interval |
242 | # Sleep for a few seconds |
243 | time.sleep(self.options.scan_interval_seconds) |
244 | + |
245 | + self.time_objs_lock.release() |
246 | # Aborted by keyboard |
247 | except KeyboardInterrupt: |
248 | self.time_objs[-1].close() |
249 | |
250 | === added directory 'chrome_extension' |
251 | === added file 'chrome_extension/background.html' |
252 | --- chrome_extension/background.html 1970-01-01 00:00:00 +0000 |
253 | +++ chrome_extension/background.html 2012-08-14 18:23:19 +0000 |
254 | @@ -0,0 +1,55 @@ |
255 | +<!-- |
256 | +Copyright (c) 2010 Joseph Lisee <jlisee@gmail.com> |
257 | + |
258 | +Permission is hereby granted, free of charge, to any person obtaining a copy |
259 | +of this software and associated documentation files (the "Software"), to deal |
260 | +in the Software without restriction, including without limitation the rights |
261 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
262 | +copies of the Software, and to permit persons to whom the Software is |
263 | +furnished to do so, subject to the following conditions: |
264 | + |
265 | +The above copyright notice and this permission notice shall be included in |
266 | +all copies or substantial portions of the Software. |
267 | + |
268 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
269 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
270 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
271 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
272 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
273 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
274 | +THE SOFTWARE. |
275 | +--> |
276 | + |
277 | +<html> |
278 | + <script> |
279 | + // Logs the tab into local storage for reading later |
280 | + function logTab(tab) { |
281 | + // Grab the URL and chop to 1024 charaters |
282 | + extended_info = tab.url; |
283 | + if (extended_info.length > 1024) |
284 | + extended_info = extended_info.substring(0, 1023); |
285 | + |
286 | + // Store in our local storage for later retrieval |
287 | + localStorage['RescueTimeLinuxUrl'] = extended_info |
288 | + |
289 | + // Log to console (for debugging only) |
290 | + //console.log(localStorage['RescueTimeLinuxUrl']); |
291 | + } |
292 | + |
293 | + // Wrapper to grab tabId then call logTab |
294 | + function logTabById(tabId) { |
295 | + chrome.tabs.get(tabId, logTab); |
296 | + } |
297 | + |
298 | + // Subscribe to the tab change event |
299 | + chrome.tabs.onSelectionChanged.addListener(function(tabId, selectionInfo) { |
300 | + logTabById(tabId); |
301 | + }); |
302 | + |
303 | + // Subscribe to the new tab creation event |
304 | + chrome.tabs.onCreated.addListener(logTab); |
305 | + |
306 | + // Subscribe to when the current tab is changed |
307 | + chrome.tabs.onUpdated.addListener(logTabById); |
308 | + </script> |
309 | +</html> |
310 | |
311 | === added file 'chrome_extension/icon128.png' |
312 | Binary files chrome_extension/icon128.png 1970-01-01 00:00:00 +0000 and chrome_extension/icon128.png 2012-08-14 18:23:19 +0000 differ |
313 | === added file 'chrome_extension/icon48.png' |
314 | Binary files chrome_extension/icon48.png 1970-01-01 00:00:00 +0000 and chrome_extension/icon48.png 2012-08-14 18:23:19 +0000 differ |
315 | === added file 'chrome_extension/manifest.json' |
316 | --- chrome_extension/manifest.json 1970-01-01 00:00:00 +0000 |
317 | +++ chrome_extension/manifest.json 2012-08-14 18:23:19 +0000 |
318 | @@ -0,0 +1,14 @@ |
319 | +{ |
320 | + "name": "RescueTime Linux", |
321 | + "version": "1.0", |
322 | + "description": "Logs current URL data for use by RescueTime Linux Uploader.", |
323 | + "browser_action": { |
324 | + "default_icon": "toolbar-button.png" |
325 | + }, |
326 | + "icons": { |
327 | + "128": "icon128.png", |
328 | + "48": "icon48.png" |
329 | + }, |
330 | + "permissions": ["tabs"], |
331 | + "background_page" : "background.html" |
332 | +} |
333 | |
334 | === added file 'chrome_extension/toolbar-button.png' |
335 | Binary files chrome_extension/toolbar-button.png 1970-01-01 00:00:00 +0000 and chrome_extension/toolbar-button.png 2012-08-14 18:23:19 +0000 differ |
Joseph, not sure if you're still active in this project. Do you remember what made you create revision 105?