Skip to content

Commit

Permalink
Merge pull request #10 from jberkel/favicons
Browse files Browse the repository at this point in the history
Add favicons
  • Loading branch information
tupton committed Dec 5, 2015
2 parents cc544f7 + e6b2693 commit 09109c9
Showing 1 changed file with 53 additions and 13 deletions.
66 changes: 53 additions & 13 deletions chrome.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,28 @@
import os
import sys
import time
import datetime

HISTORY_CACHE_EXPIRY = 60
CACHE_EXPIRY = 60
HISTORY_DB = 'History'
HISTORY_CACHE = os.path.join(alfred.work(True), HISTORY_DB)
FAVICONS_DB = 'Favicons'
FAVICONS_CACHE = 'Favicons-Cache'
HISTORY_QUERY = u"""
SELECT id,title,url FROM urls WHERE (title LIKE ? OR url LIKE ?) ORDER BY visit_count DESC, typed_count DESC, last_visit_time DESC
SELECT urls.id, urls.title, urls.url, favicon_bitmaps.image_data, favicon_bitmaps.last_updated
FROM urls
LEFT OUTER JOIN icon_mapping ON icon_mapping.page_url = urls.url,
favicon_bitmaps ON favicon_bitmaps.id =
(SELECT id FROM favicon_bitmaps
WHERE favicon_bitmaps.icon_id = icon_mapping.icon_id
ORDER BY width DESC LIMIT 1)
WHERE (urls.title LIKE ? OR urls.url LIKE ?)
ORDER BY visit_count DESC, typed_count DESC, last_visit_time DESC
"""
UNIX_EPOCH = datetime.datetime.utcfromtimestamp(0)
WINDOWS_EPOCH = datetime.datetime(1601, 1, 1)
SECONDS_BETWEEN_UNIX_AND_WINDOWS_EPOCH = (UNIX_EPOCH - WINDOWS_EPOCH).total_seconds()
MICROSECS_PER_SEC = 10**-6


class ErrorItem(alfred.Item):
def __init__(self, error):
Expand All @@ -21,28 +36,53 @@ def __init__(self, error):
def alfred_error(error):
alfred.write(alfred.xml([ErrorItem(error)]))

def copy_history(profile):
if os.path.isfile(HISTORY_CACHE) and time.time() - os.path.getmtime(HISTORY_CACHE) < HISTORY_CACHE_EXPIRY:
return HISTORY_CACHE
def copy_db(name, profile):
cache = os.path.join(alfred.work(True), name)
if os.path.isfile(cache) and time.time() - os.path.getmtime(cache) < CACHE_EXPIRY:
return cache

history_file = os.path.join(os.path.expanduser(profile), HISTORY_DB)
db_file = os.path.join(os.path.expanduser(profile), name)
try:
shutil.copy(history_file, HISTORY_CACHE)
shutil.copy(db_file, cache)
except:
raise IOError(u'Unable to copy Google Chrome history database from {}'.format(history_file))
raise IOError(u'Unable to copy Google Chrome history database from {}'.format(db_file))

return cache

return HISTORY_CACHE

def history_db(profile):
history = copy_history(profile)
history = copy_db(HISTORY_DB, profile)
favicons = copy_db(FAVICONS_DB, profile)
db = sqlite3.connect(history)
db.cursor().execute('ATTACH DATABASE ? AS favicons', (favicons,)).close()
return db


def cache_favicon(image_data, uid, last_updated):
cache_dir = os.path.join(alfred.work(True), FAVICONS_CACHE)
if not os.path.isdir(cache_dir):
os.makedirs(cache_dir)
icon_file = os.path.join(cache_dir, str(uid))
if not os.path.isfile(icon_file) or last_updated > os.path.getmtime(icon_file):
with open(icon_file, 'w') as f:
f.write(image_data)
os.utime(icon_file, (time.time(), last_updated))

return (icon_file, {'type': 'png'})


# Chrome measures time in microseconds since the Windows epoch (1601/1/1)
# https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time.h
def convert_chrometime(chrometime):
return (chrometime * MICROSECS_PER_SEC) - SECONDS_BETWEEN_UNIX_AND_WINDOWS_EPOCH


def history_results(db, query):
q = u'%{}%'.format(query)
for row in db.execute(HISTORY_QUERY, (q, q,)):
(uid, title, url) = row
yield alfred.Item({u'uid': alfred.uid(uid), u'arg': url, u'autocomplete': url}, title or url, url)
(uid, title, url, image_data, image_last_updated) = row
icon = cache_favicon(image_data, uid, convert_chrometime(image_last_updated)) if image_data and image_last_updated else None
yield alfred.Item({u'uid': alfred.uid(uid), u'arg': url, u'autocomplete': url}, title or url, url, icon)

if __name__ == '__main__':
(profile, query) = alfred.args()
Expand Down

0 comments on commit 09109c9

Please sign in to comment.