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 | 1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
6 | 2 | 2 | ||
7 | 3 | """ | ||
8 | 4 | Returns the remote host name if the terminal is an ssh session, otherwise it | ||
9 | 5 | returns given app_name (in this case 'Gnome-terminal') | ||
10 | 6 | """ | ||
11 | 7 | |||
12 | 3 | import sys | 8 | import sys |
13 | 4 | import os | 9 | import os |
14 | 5 | app_name = raw_input("") | 10 | app_name = raw_input("") |
15 | 6 | 11 | ||
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 | 1 | #!/usr/bin/env python | ||
22 | 2 | |||
23 | 3 | # Copyright (c) 2010 Joseph Lisee <jlisee@gmail.com> | ||
24 | 4 | # | ||
25 | 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy | ||
26 | 6 | # of this software and associated documentation files (the "Software"), to deal | ||
27 | 7 | # in the Software without restriction, including without limitation the rights | ||
28 | 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
29 | 9 | # copies of the Software, and to permit persons to whom the Software is | ||
30 | 10 | # furnished to do so, subject to the following conditions: | ||
31 | 11 | # | ||
32 | 12 | # The above copyright notice and this permission notice shall be included in | ||
33 | 13 | # all copies or substantial portions of the Software. | ||
34 | 14 | # | ||
35 | 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
36 | 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
37 | 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
38 | 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
39 | 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
40 | 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
41 | 21 | # THE SOFTWARE. | ||
42 | 22 | |||
43 | 23 | # White list checking and URL parsing our borrowed from the firefox extension | ||
44 | 24 | # in the future the code should be merged somehow | ||
45 | 25 | |||
46 | 26 | |||
47 | 27 | import os | ||
48 | 28 | import subprocess | ||
49 | 29 | from urlparse import urlparse | ||
50 | 30 | from os.path import expanduser, join, exists | ||
51 | 31 | |||
52 | 32 | """ | ||
53 | 33 | Extracts the current google chrome URL local HTML storage of the extension and | ||
54 | 34 | prints it to stdout. It is intelligent about searching out and finding the | ||
55 | 35 | write google extension local storage database, and cashes the result for use. | ||
56 | 36 | """ | ||
57 | 37 | |||
58 | 38 | # Overall settings and paths | ||
59 | 39 | preferenceDir = join(expanduser('~'), '.rescuetime') | ||
60 | 40 | whitelist_file = join(preferenceDir, 'domainwhitelist.txt') | ||
61 | 41 | extensionID_file = join(preferenceDir, 'google-chrome_extension-id.txt') | ||
62 | 42 | localStorageDir = join(os.getenv("HOME"), ".config", "google-chrome", | ||
63 | 43 | "Default", "Local Storage") | ||
64 | 44 | |||
65 | 45 | # Load whitelist | ||
66 | 46 | allowed_domains = [] | ||
67 | 47 | |||
68 | 48 | if exists(whitelist_file): | ||
69 | 49 | have_whitelist = True | ||
70 | 50 | for line in open(whitelist_file): | ||
71 | 51 | # strip comments and whitespace | ||
72 | 52 | line = line.split('#', 1)[0].strip() | ||
73 | 53 | if line: | ||
74 | 54 | allowed_domains.append(line) | ||
75 | 55 | else: | ||
76 | 56 | have_whitelist = False | ||
77 | 57 | |||
78 | 58 | def findExtensionID(): | ||
79 | 59 | dirs = os.listdir(localStorageDir) | ||
80 | 60 | extensionDirs = [d for d in dirs if d.startswith('chrome-extension_')] | ||
81 | 61 | |||
82 | 62 | for extensionDir in extensionDirs: | ||
83 | 63 | extID = extensionDir.split('_')[1] | ||
84 | 64 | url = retrieveURL(extID) | ||
85 | 65 | |||
86 | 66 | if len(url) > 0: | ||
87 | 67 | return extID | ||
88 | 68 | |||
89 | 69 | def findAndStoreExtensionID(): | ||
90 | 70 | extID = findExtensionID() | ||
91 | 71 | f = open(extensionID_file, 'w') | ||
92 | 72 | f.write(extID) | ||
93 | 73 | f.close() | ||
94 | 74 | return extID | ||
95 | 75 | |||
96 | 76 | def retrieveURL(extID): | ||
97 | 77 | # Build the complete path to the database inside goolge chrome directory | ||
98 | 78 | databaseName = "chrome-extension_%s_0.localstorage" % extID | ||
99 | 79 | databasePath = join(localStorageDir, databaseName) | ||
100 | 80 | |||
101 | 81 | currentURL = '' | ||
102 | 82 | |||
103 | 83 | if exists(databasePath): | ||
104 | 84 | # Form the SQLlite3 command to extract the data | ||
105 | 85 | sql = "SELECT value FROM ItemTable WHERE key = 'RescueTimeLinuxUrl';" | ||
106 | 86 | command = "sqlite3 \"%s\" \"%s\"" % (databasePath, sql) | ||
107 | 87 | |||
108 | 88 | runner = subprocess.Popen(command, shell=True, | ||
109 | 89 | stdin=subprocess.PIPE, stdout=subprocess.PIPE) | ||
110 | 90 | currentURL = runner.communicate()[0][:-1] | ||
111 | 91 | |||
112 | 92 | return currentURL | ||
113 | 93 | |||
114 | 94 | |||
115 | 95 | def check_whitelist(urlparse_tuple): | ||
116 | 96 | """urlparse_tuple is a tuple returned by urlparse | ||
117 | 97 | Return True if domain is allowed, False if not. | ||
118 | 98 | """ | ||
119 | 99 | if not have_whitelist: | ||
120 | 100 | # let everything through | ||
121 | 101 | return True | ||
122 | 102 | name = urlparse_tuple[1] | ||
123 | 103 | for domain in allowed_domains: | ||
124 | 104 | if name.find(domain) != -1: | ||
125 | 105 | return True | ||
126 | 106 | return False | ||
127 | 107 | |||
128 | 108 | # Find and verify our extenionID | ||
129 | 109 | extensionID = '' | ||
130 | 110 | |||
131 | 111 | if exists(extensionID_file): | ||
132 | 112 | f = open(extensionID_file) | ||
133 | 113 | extensionID = f.read() | ||
134 | 114 | f.close() | ||
135 | 115 | else: | ||
136 | 116 | extensionID = findAndStoreExtensionID() | ||
137 | 117 | |||
138 | 118 | # Attempt to get URL | ||
139 | 119 | url = retrieveURL(extensionID) | ||
140 | 120 | |||
141 | 121 | if len(url) == 0: | ||
142 | 122 | # Extension ID must have changed | ||
143 | 123 | extensionID = findAndStoreExtensionID() | ||
144 | 124 | url = retrieveURL(extensionID) | ||
145 | 125 | |||
146 | 126 | # Break it up into its parts | ||
147 | 127 | info = urlparse(url) | ||
148 | 128 | |||
149 | 129 | # Check white list and log just the needed parts of the URL | ||
150 | 130 | allowed = check_whitelist(info) | ||
151 | 131 | if not allowed: | ||
152 | 132 | print 'unlisted' | ||
153 | 133 | elif "google" in info[1].lower(): | ||
154 | 134 | print info[0] + "://" + info[1] + info[2] | ||
155 | 135 | else: | ||
156 | 136 | print info[0] + "://" + info[1] | ||
157 | 0 | 137 | ||
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 | 23 | socket.setdefaulttimeout(15) | 23 | socket.setdefaulttimeout(15) |
163 | 24 | import urllib | 24 | import urllib |
164 | 25 | import urllib2 | 25 | import urllib2 |
165 | 26 | import threading | ||
166 | 26 | 27 | ||
167 | 27 | import RescueTimeUploader.options | 28 | import RescueTimeUploader.options |
168 | 28 | import RescueTimeUploader.dirstructure | 29 | import RescueTimeUploader.dirstructure |
169 | @@ -178,12 +179,12 @@ | |||
170 | 178 | if idle_time > (self.options.max_idle_minutes * 60): | 179 | if idle_time > (self.options.max_idle_minutes * 60): |
171 | 179 | return None | 180 | return None |
172 | 180 | try: | 181 | try: |
174 | 181 | 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'""" | 182 | 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 | 182 | runner = subprocess.Popen(exec_cmd, shell=True, | 183 | runner = subprocess.Popen(exec_cmd, shell=True, |
176 | 183 | stdin=subprocess.PIPE, stdout=subprocess.PIPE) | 184 | stdin=subprocess.PIPE, stdout=subprocess.PIPE) |
177 | 184 | runner_res = runner.communicate()[0][:-1] | 185 | runner_res = runner.communicate()[0][:-1] |
180 | 185 | if not runner_res.isalnum(): | 186 | if len(runner_res) == 0: |
181 | 186 | 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'""" | 187 | 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 | 187 | runner = subprocess.Popen(exec_cmd, shell=True, | 188 | runner = subprocess.Popen(exec_cmd, shell=True, |
183 | 188 | stdin=subprocess.PIPE, stdout=subprocess.PIPE) | 189 | stdin=subprocess.PIPE, stdout=subprocess.PIPE) |
184 | 189 | runner_res = runner.communicate()[0][:-1] | 190 | runner_res = runner.communicate()[0][:-1] |
185 | @@ -259,7 +260,7 @@ | |||
186 | 259 | 260 | ||
187 | 260 | encoded_title_re = re.compile("(0x[0-9abcdefABCDEF]*,* *)+$") | 261 | encoded_title_re = re.compile("(0x[0-9abcdefABCDEF]*,* *)+$") |
188 | 261 | def _get_raw_window_title(self): | 262 | def _get_raw_window_title(self): |
190 | 262 | 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'""" | 263 | 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 | 263 | try: | 264 | try: |
192 | 264 | runner = subprocess.Popen(exec_cmd, shell=True, | 265 | runner = subprocess.Popen(exec_cmd, shell=True, |
193 | 265 | stdin=subprocess.PIPE, stdout=subprocess.PIPE) | 266 | stdin=subprocess.PIPE, stdout=subprocess.PIPE) |
194 | @@ -333,6 +334,7 @@ | |||
195 | 333 | ##out.flush() | 334 | ##out.flush() |
196 | 334 | self.dir_structure = RescueTimeUploader.dirstructure.DirStructure() | 335 | self.dir_structure = RescueTimeUploader.dirstructure.DirStructure() |
197 | 335 | self.options = RescueTimeUploader.options.Options(self.dir_structure) | 336 | self.options = RescueTimeUploader.options.Options(self.dir_structure) |
198 | 337 | self.time_objs_lock = threading.RLock() | ||
199 | 336 | 338 | ||
200 | 337 | signal.signal(signal.SIGTERM, handle_signal) | 339 | signal.signal(signal.SIGTERM, handle_signal) |
201 | 338 | signal.signal(signal.SIGHUP, handle_signal) | 340 | signal.signal(signal.SIGHUP, handle_signal) |
202 | @@ -365,6 +367,8 @@ | |||
203 | 365 | 367 | ||
204 | 366 | 368 | ||
205 | 367 | def get_latest_time_obj(self): | 369 | def get_latest_time_obj(self): |
206 | 370 | self.time_objs_lock.acquire() | ||
207 | 371 | |||
208 | 368 | f = file(os.path.join(self.dir_structure.tmp_dir, "notifier.debuglog"), "a") | 372 | f = file(os.path.join(self.dir_structure.tmp_dir, "notifier.debuglog"), "a") |
209 | 369 | f.write("---- STARTING CHECK ----\n") | 373 | f.write("---- STARTING CHECK ----\n") |
210 | 370 | f.write("archived_time_objs: %s\n" % self.archived_time_objs) | 374 | f.write("archived_time_objs: %s\n" % self.archived_time_objs) |
211 | @@ -398,6 +402,8 @@ | |||
212 | 398 | latest_time_obj = timeobj | 402 | latest_time_obj = timeobj |
213 | 399 | f.write("Returning %s\n" % latest_time_obj) | 403 | f.write("Returning %s\n" % latest_time_obj) |
214 | 400 | f.close() | 404 | f.close() |
215 | 405 | |||
216 | 406 | self.time_objs_lock.release() | ||
217 | 401 | return latest_time_obj | 407 | return latest_time_obj |
218 | 402 | 408 | ||
219 | 403 | def retrieve_credentials(self): | 409 | def retrieve_credentials(self): |
220 | @@ -435,8 +441,10 @@ | |||
221 | 435 | print "Failed to save preferences on shutdown." | 441 | print "Failed to save preferences on shutdown." |
222 | 436 | ##out.flush() | 442 | ##out.flush() |
223 | 437 | try: | 443 | try: |
224 | 444 | self.time_objs_lock.acquire() | ||
225 | 438 | self.time_objs[-1].close() | 445 | self.time_objs[-1].close() |
226 | 439 | self.prepare_data(self.time_objs) | 446 | self.prepare_data(self.time_objs) |
227 | 447 | self.time_objs_lock.release() | ||
228 | 440 | except: | 448 | except: |
229 | 441 | print "Failed to prepare data on shutdown." | 449 | print "Failed to prepare data on shutdown." |
230 | 442 | ##out.flush() | 450 | ##out.flush() |
231 | @@ -494,6 +502,8 @@ | |||
232 | 494 | 502 | ||
233 | 495 | try: | 503 | try: |
234 | 496 | while True: | 504 | while True: |
235 | 505 | self.time_objs_lock.acquire() | ||
236 | 506 | |||
237 | 497 | # If the focused window has changed | 507 | # If the focused window has changed |
238 | 498 | if not self.time_objs[len(self.time_objs) - 1].still_active(): | 508 | if not self.time_objs[len(self.time_objs) - 1].still_active(): |
239 | 499 | self.time_objs[len(self.time_objs) - 1].close() | 509 | self.time_objs[len(self.time_objs) - 1].close() |
240 | @@ -507,6 +517,8 @@ | |||
241 | 507 | next_upload_time = datetime.datetime.today() + self.options.upload_interval | 517 | next_upload_time = datetime.datetime.today() + self.options.upload_interval |
242 | 508 | # Sleep for a few seconds | 518 | # Sleep for a few seconds |
243 | 509 | time.sleep(self.options.scan_interval_seconds) | 519 | time.sleep(self.options.scan_interval_seconds) |
244 | 520 | |||
245 | 521 | self.time_objs_lock.release() | ||
246 | 510 | # Aborted by keyboard | 522 | # Aborted by keyboard |
247 | 511 | except KeyboardInterrupt: | 523 | except KeyboardInterrupt: |
248 | 512 | self.time_objs[-1].close() | 524 | self.time_objs[-1].close() |
249 | 513 | 525 | ||
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 | 1 | <!-- | ||
256 | 2 | Copyright (c) 2010 Joseph Lisee <jlisee@gmail.com> | ||
257 | 3 | |||
258 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
259 | 5 | of this software and associated documentation files (the "Software"), to deal | ||
260 | 6 | in the Software without restriction, including without limitation the rights | ||
261 | 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
262 | 8 | copies of the Software, and to permit persons to whom the Software is | ||
263 | 9 | furnished to do so, subject to the following conditions: | ||
264 | 10 | |||
265 | 11 | The above copyright notice and this permission notice shall be included in | ||
266 | 12 | all copies or substantial portions of the Software. | ||
267 | 13 | |||
268 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
269 | 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
270 | 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
271 | 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
272 | 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
273 | 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
274 | 20 | THE SOFTWARE. | ||
275 | 21 | --> | ||
276 | 22 | |||
277 | 23 | <html> | ||
278 | 24 | <script> | ||
279 | 25 | // Logs the tab into local storage for reading later | ||
280 | 26 | function logTab(tab) { | ||
281 | 27 | // Grab the URL and chop to 1024 charaters | ||
282 | 28 | extended_info = tab.url; | ||
283 | 29 | if (extended_info.length > 1024) | ||
284 | 30 | extended_info = extended_info.substring(0, 1023); | ||
285 | 31 | |||
286 | 32 | // Store in our local storage for later retrieval | ||
287 | 33 | localStorage['RescueTimeLinuxUrl'] = extended_info | ||
288 | 34 | |||
289 | 35 | // Log to console (for debugging only) | ||
290 | 36 | //console.log(localStorage['RescueTimeLinuxUrl']); | ||
291 | 37 | } | ||
292 | 38 | |||
293 | 39 | // Wrapper to grab tabId then call logTab | ||
294 | 40 | function logTabById(tabId) { | ||
295 | 41 | chrome.tabs.get(tabId, logTab); | ||
296 | 42 | } | ||
297 | 43 | |||
298 | 44 | // Subscribe to the tab change event | ||
299 | 45 | chrome.tabs.onSelectionChanged.addListener(function(tabId, selectionInfo) { | ||
300 | 46 | logTabById(tabId); | ||
301 | 47 | }); | ||
302 | 48 | |||
303 | 49 | // Subscribe to the new tab creation event | ||
304 | 50 | chrome.tabs.onCreated.addListener(logTab); | ||
305 | 51 | |||
306 | 52 | // Subscribe to when the current tab is changed | ||
307 | 53 | chrome.tabs.onUpdated.addListener(logTabById); | ||
308 | 54 | </script> | ||
309 | 55 | </html> | ||
310 | 0 | 56 | ||
311 | === added file 'chrome_extension/icon128.png' | |||
312 | 1 | 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 | 57 | 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 | 2 | 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 | 58 | 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 | 1 | { | ||
320 | 2 | "name": "RescueTime Linux", | ||
321 | 3 | "version": "1.0", | ||
322 | 4 | "description": "Logs current URL data for use by RescueTime Linux Uploader.", | ||
323 | 5 | "browser_action": { | ||
324 | 6 | "default_icon": "toolbar-button.png" | ||
325 | 7 | }, | ||
326 | 8 | "icons": { | ||
327 | 9 | "128": "icon128.png", | ||
328 | 10 | "48": "icon48.png" | ||
329 | 11 | }, | ||
330 | 12 | "permissions": ["tabs"], | ||
331 | 13 | "background_page" : "background.html" | ||
332 | 14 | } | ||
333 | 0 | 15 | ||
334 | === added file 'chrome_extension/toolbar-button.png' | |||
335 | 1 | 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 | 16 | 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?