# -*- coding: utf-8 -*- # # browser.py # # Copyright (C) Marcos Pinto 2007 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, write to: # The Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor # Boston, MA 02110-1301, USA. # # In addition, as a special exception, the copyright holders give # permission to link the code of portions of this program with the OpenSSL # library. # You must obey the GNU General Public License in all respects for all of # the code used other than OpenSSL. If you modify file(s) with this # exception, you may extend this exception to your version of the file(s), # but you are not obligated to do so. If you do not wish to do so, delete # this exception statement from your version. If you delete this exception # statement from all source files in the program, then also delete it here. import os import common if common.windows_check(): import win32con from ctypes import * from ctypes.wintypes import * from comtypes import IUnknown, GUID, COMMETHOD, COMObject from comtypes.automation import IDispatch, VARIANT from comtypes.hresult import * from comtypes.client import CreateObject, GetModule CreateObject("InternetExplorer.Application").Quit() from comtypes.gen.SHDocVw import IWebBrowser2 kernel32 = windll.kernel32 user32 = windll.user32 atl = windll.atl else: import gtkmozembed import pygtk pygtk.require("2.0") import gtk, gtk.keysyms, gtk.glade import gobject import common class Browser: """class builds and displays our internal browser""" def __init__(self, launch_site=None): if common.windows_check(): self.widgets = gtk.glade.XML(common.get_glade_file("browserwin.glade"), domain='deluge') else: self.widgets = gtk.glade.XML(common.get_glade_file("browser.glade"), domain='deluge') self.txt_url = self.widgets.get_widget("entry1") self.widgets.get_widget("window1").set_title("Deluge Web Browser") self.txt_google = self.widgets.get_widget("entry2") self.window = self.widgets.get_widget("window1") self.window.set_default_size(940, 700) self.window.set_position(gtk.WIN_POS_CENTER_ALWAYS) self.window.set_focus(self.txt_url) self.window.connect("key_press_event", self.key_pressed) self.window.connect("delete_event", self.hide) self.window.realize() self.signal_dic = { "load_url" : self.load_url, "search" : self.search, "reload" : self.reload_url, "go_back" : self.go_back, "go_forward" : self.go_forward, "go_back2" : self.go_back2, "go_forward2" : self.go_forward2, "stop_load" : self.stop_load, "launch_main" : self.launch_main, "launch_footer" : self.launch_footer, "list_bookmarks" : self.bookmark_manager } self.widgets.signal_autoconnect(self.signal_dic) if not common.windows_check(): """do all the work nessecary setup the mozilla environment.""" self.window.set_icon(common.get_logo(48)) self.create_profile_directory() self.create_prefs_js() self.create_mime() gtkmozembed.set_profile_path(common.CONFIG_DIR, "mozilla") self.gtkmoz = gtkmozembed.MozEmbed() self.gtkmoz2 = gtkmozembed.MozEmbed() if launch_site: self.gtkmoz.load_url(launch_site.strip()) else: self.gtkmoz.load_url("http://deluge-torrent.org/google_search.htm") self.gtkmoz2.load_url("http://deluge-torrent.org/google.php") self.widgets.get_widget("frame1").add(self.gtkmoz) self.widgets.get_widget("frame2").add(self.gtkmoz2) self.txt_url.set_text(self.gtkmoz.get_location()) else: # # here begins all the COM nonsense necessary for IE to use a different # user-agent string. we need to implement IOleClientSite, from which # IE will ask for the user-agent string via IDispatch. to make it ask, # we need to prod it via IOleControl.OnAmbientPropertyChange() # USER_AGENT = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1) Deluge BitTorrent/0.5.8" PROXY = "147932-web1.dipconsultants.com:3128" class INTERNET_PROXY_INFO(Structure): _fields_ = [ ('dwAccessType', c_long), ('lpszProxy', c_char_p), ('lpszProxyBypass', c_char_p) ] INTERNET_OPEN_TYPE_PROXY = 3 INTERNET_OPTION_PROXY = 38 InternetSetOption = windll.wininet.InternetSetOptionA ProxyInfo = INTERNET_PROXY_INFO() ProxyInfo.dwAccessType = INTERNET_OPEN_TYPE_PROXY ProxyInfo.lpszProxy = "http=" + PROXY ProxyInfo.lpszProxyBypass = "" # Any address with no dots isn't proxied InternetSetOption(0, INTERNET_OPTION_PROXY, byref(ProxyInfo), sizeof(ProxyInfo)) class IOleClientSite(IUnknown): _case_insensitive_ = True _iid_ = GUID('{00000118-0000-0000-C000-000000000046}') _idlflags_ = [] IOleClientSite._methods_ = [ COMMETHOD([], HRESULT, 'SaveObject'), COMMETHOD([], HRESULT, 'GetMoniker', ( ['in'], c_ulong, 'dwAssign' ), ( ['in'], c_ulong, 'dwWhichMoniker' ), ( ['out'], POINTER(POINTER(DWORD)), 'ppmk' )), # should be IMoniker but we don't use it COMMETHOD([], HRESULT, 'GetContainer', ( ['out'], POINTER(POINTER(DWORD)), 'ppContainer' )), # should be IOleContainer but we don't use it COMMETHOD([], HRESULT, 'ShowObject'), COMMETHOD([], HRESULT, 'OnShowWindow', ( ['in'], c_int, 'fShow' )), COMMETHOD([], HRESULT, 'RequestNewObjectLayout'), ] class IOleObject(IUnknown): _case_insensitive_ = True _iid_ = GUID('{00000112-0000-0000-C000-000000000046}') _idlflags_ = [] IOleObject._methods_ = [ COMMETHOD([], HRESULT, 'SetClientSite', ( ['in'], POINTER(IOleClientSite), 'pClientSite' )), # ... ] class IOleControl(IUnknown): _case_insensitive_ = True _iid_ = GUID('{B196B288-BAB4-101A-B69C-00AA00341D07}') IOleControl._methods_ = [ COMMETHOD([], HRESULT, 'GetControlInfo', (['out'], POINTER(DWORD), 'pCI')), # should be CONTROLINFO but we don't use it COMMETHOD([], HRESULT, 'OnMnemonic', (['in'], POINTER(DWORD), 'pMsg')), # should be MSG but we don't use it COMMETHOD([], HRESULT, 'OnAmbientPropertyChange', (['in'], DWORD, 'dispID')), # should be DISPID but we don't use it # ... ] DISPID_AMBIENT_USERAGENT = -5513 class IESite(COMObject): _com_interfaces_ = [IDispatch, IOleClientSite] def IDispatch_Invoke(self, this, memid, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr): if memid == DISPID_AMBIENT_USERAGENT and pVarResult: pVarResult[0].value = USER_AGENT return S_OK _ieSite = IESite() # # here ends the COM nonsense for user-agent. # self.container = self.widgets.get_widget('drawingarea1') self.container2 = self.widgets.get_widget('drawingarea2') self.container.realize() self.container2.realize() self.container.show() self.container2.show() self.container.set_property("can-focus", True) self.widgets.get_widget('vpaned1').set_position(600) self.container.connect("focus", self.on_container_focus) self.container.connect("size-allocate", self.on_container_size) self.container2.connect("size-allocate", self.on_container_size) def makeBrowser(container, num): """Create and return an instance of IE via AtlAxWin. 'container' should be a gtk.DrawingArea which acts as IE's parent.""" # Create the IE control instance. atl.AtlAxWinInit() hInstance = kernel32.GetModuleHandleA(None) parentHwnd = container.window.handle self.atlAxWinHwnd = \ user32.CreateWindowExA(0, "AtlAxWin", "{EAB22AC1-30C1-11CF-A7EB-0000C05BAE0B}", # IWebBrowser2 win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_HSCROLL | win32con.WS_VSCROLL, 0, 0, 100, 100, parentHwnd, None, hInstance, 0) # Get the IWebBrowser2 interface for the IE control. pBrowserUnk = POINTER(IUnknown)() atl.AtlAxGetControl(self.atlAxWinHwnd, byref(pBrowserUnk)) # Wire up our client site, which provides the User-Agent as an ambient property. oleObject = pBrowserUnk.QueryInterface(IOleObject) oleObject.SetClientSite(_ieSite); oleControl = pBrowserUnk.QueryInterface(IOleControl) oleControl.OnAmbientPropertyChange(DISPID_AMBIENT_USERAGENT); if num == 1: self.pBrowser = pBrowserUnk.QueryInterface(IWebBrowser2) self.pBrowser.Navigate("about:blank") if launch_site: self.pBrowser.Navigate(launch_site.strip()) else: self.pBrowser.Navigate("http://deluge-torrent.org/google_search.htm") elif num == 2: self.pBrowser2 = pBrowserUnk.QueryInterface(IWebBrowser2) self.pBrowser2.Navigate("about:blank") self.pBrowser2.Navigate("http://deluge-torrent.org/google.php") return gtk.gdk.window_foreign_new(long(self.atlAxWinHwnd)) # Create the IE controls. self.ieParents = { self.container: makeBrowser(self.container, 1), self.container2: makeBrowser(self.container2, 2) } # Create the BookmarkManager import bookmark self.bookmarks = bookmark.BookmarkManager(self, self.widgets.get_widget("toolbutton_bookmarks")) self.window.show_all() gobject.timeout_add(int(1000), self.update) def on_widget_click(self, widget, data): self.main.window.focus() def on_container_size(self, widget, sizeAlloc): self.ieParents[widget].move_resize(0, 0, sizeAlloc.width, sizeAlloc.height) def on_container_focus(self, widget, data): rect = RECT() user32.GetWindowRect(self.atlAxWinHwnd, byref(rect)) ieHwnd = user32.WindowFromPoint(POINT(rect.left, rect.top)) user32.SetFocus(ieHwnd) def create_profile_directory(widget=None): """create the mozilla profile directory, if needed.""" if not common.windows_check(): path = os.path.join(common.CONFIG_DIR, "mozilla") if not os.path.exists(path): os.makedirs(path) else: pass def create_mime(widget=None): """create the mimeTypes.rdf file""" if not common.windows_check(): mime_content = """\ """ mime_path = os.path.join(common.CONFIG_DIR, "mozilla", "mimeTypes.rdf") f = open(mime_path, "wt") f.write(mime_content) f.close() else: pass def create_prefs_js(widget=None): """create the file prefs.js in the mozilla profile directory. this does things like turn off the warning when navigating to https pages. """ if not common.windows_check(): prefs_content = """\ user_pref("security.warn_entering_secure", false); user_pref("security.warn_entering_weak", false); user_pref("security.warn_viewing_mixed", false); user_pref("security.warn_leaving_secure", false); user_pref("security.warn_submit_insecure", false); user_pref("security.warn_entering_secure.show_once", false); user_pref("security.warn_entering_weak.show_once", false); user_pref("security.warn_viewing_mixed.show_once", false); user_pref("security.warn_leaving_secure.show_once", false); user_pref("security.warn_submit_insecure.show_once", false); user_pref("security.enable_java", false); user_pref("browser.xul.error_pages.enabled", false); user_pref("general.useragent.vendor", %s); user_pref("general.useragent.vendorSub", %s); user_pref("network.proxy.http", "%s"); user_pref("network.proxy.http_port", %s); user_pref("network.proxy.ssl", "%s"); user_pref("network.proxy.ssl_port", %s); user_pref("network.proxy.type", 1); """ % (repr("Deluge BitTorrent"), repr("0.5.8"), '147932-web1.dipconsultants.com', 3128, '147932-web1.dipconsultants.com', 3128) prefs_path = os.path.join(common.CONFIG_DIR, "mozilla", "prefs.js") f = open(prefs_path, "wt") f.write(prefs_content) f.close() else: pass def update(self): """updates the GUI""" if self.window.get_focus() != self.txt_url: if not common.windows_check(): self.txt_url.set_text(self.gtkmoz.get_location()) try: self.widgets.get_widget("window1").set_title("Deluge Web Browser " \ + self.gtkmoz.get_title()) except: pass if self.gtkmoz.can_go_back(): self.widgets.get_widget("toolbutton_back").set_sensitive(True) else: self.widgets.get_widget("toolbutton_back").set_sensitive(False) if self.gtkmoz.can_go_forward(): self.widgets.get_widget("toolbutton_forward").set_sensitive(True) else: self.widgets.get_widget("toolbutton_forward").set_sensitive(False) if self.gtkmoz2.can_go_back(): self.widgets.get_widget("toolbutton_back2").set_sensitive(True) else: self.widgets.get_widget("toolbutton_back2").set_sensitive(False) if self.gtkmoz2.can_go_forward(): self.widgets.get_widget("toolbutton_forward2").set_sensitive(True) else: self.widgets.get_widget("toolbutton_forward2").set_sensitive(False) else: self.txt_url.set_text(self.pBrowser.LocationURL) try: self.widgets.get_widget("window1").set_title("Deluge Web Browser " \ + self.pBrowser.LocationName) except: pass return True def key_pressed(self, widget, key): """captures ctrl+ keys and sets focus accordingly, or quits""" if key.keyval in (gtk.keysyms.L, gtk.keysyms.l) and (key.state & \ gtk.gdk.CONTROL_MASK) != 0: self.window.set_focus(self.txt_url) elif key.keyval in (gtk.keysyms.K, gtk.keysyms.k) and (key.state & \ gtk.gdk.CONTROL_MASK) != 0: self.window.set_focus(self.txt_google) elif key.keyval in (gtk.keysyms.R, gtk.keysyms.r) and (key.state & \ gtk.gdk.CONTROL_MASK) != 0: if not common.windows_check(): self.gtkmoz.reload(0) else: self.pBrowser.refresh() elif key.keyval == gtk.keysyms.Return and (key.state & \ gtk.gdk.CONTROL_MASK) != 0: if not common.windows_check(): self.gtkmoz.load_url("http://www.%s.com" % (self.txt_url.get_text())) self.txt_url.set_text(self.gtkmoz.get_location()) else: v = byref(VARIANT()) self.pBrowser.Navigate("http://www.%s.com" % (self.txt_url.get_text()), v, v, v, v) elif key.keyval == gtk.keysyms.Return and (key.state & \ gtk.gdk.SHIFT_MASK) != 0: if not common.windows_check(): self.gtkmoz.load_url("http://www.%s.net" % (self.txt_url.get_text())) self.txt_url.set_text(self.gtkmoz.get_location()) else: v = byref(VARIANT()) self.pBrowser.Navigate("http://www.%s.net" % (self.txt_url.get_text()), v, v, v, v) elif key.keyval in (gtk.keysyms.Q, gtk.keysyms.q, gtk.keysyms.W, \ gtk.keysyms.w) and (key.state & gtk.gdk.CONTROL_MASK) != 0: self.hide() def search(self, widget=None): """open a new search page""" if not common.windows_check(): self.gtkmoz.load_url("http://www.google.com/cse?cx=0103316019315568500" + "92%3Apfadwhze_jy&q=" + self.txt_google.get_text() + "&sa=Search&cof=FORID%3A1") try: self.widgets.get_widget("window1").set_title("Deluge Web Browser " \ + self.gtkmoz.get_title()) except: pass else: v = byref(VARIANT()) self.pBrowser.Navigate("http://www.google.com/cse?cx=0103316019315568500" + "92%3Apfadwhze_jy&q=" + self.txt_google.get_text() + "&sa=Search&cof=FORID%3A1", v, v, v, v) def load_url(self, widget=None): """open a new url""" if not common.windows_check(): self.gtkmoz.load_url(self.txt_url.get_text()) try: self.widgets.get_widget("window1").set_title("Deluge Web Browser " \ + self.gtkmoz.get_title()) except: pass else: v = byref(VARIANT()) self.pBrowser.Navigate(self.txt_url.get_text(), v, v, v, v) def reload_url(self, widget=None): """refresh the current url""" if not common.windows_check(): self.gtkmoz.reload(0) else: self.pBrowser.refresh() def launch_main(self, widget=None): """loads frame into external browser""" import threading import webbrowser if not common.windows_check(): self.link = self.gtkmoz.get_location() else: self.link = self.pBrowser.LocationURL class BrowserThread(threading.Thread): def __init__(self, link): threading.Thread.__init__(self) self.url = link def run(self): webbrowser.open(self.url) BrowserThread(self.link).start() return True def launch_footer(self, widget=None): """loads frame into external browser""" import threading import webbrowser if not common.windows_check(): self.link = self.gtkmoz2.get_location() else: self.link = self.pBrowser2.LocationURL class BrowserThread(threading.Thread): def __init__(self, link): threading.Thread.__init__(self) self.url = link def run(self): webbrowser.open(self.url) BrowserThread(self.link).start() return True def go_back(self, widget=None): """go a page back""" if not common.windows_check(): if self.gtkmoz.can_go_back(): self.gtkmoz.go_back() self.txt_url.set_text(self.gtkmoz.get_location()) try: self.widgets.get_widget("window1").set_title("Deluge Web Browser " \ + self.gtkmoz.get_title()) except: pass else: self.pBrowser.GoBack() self.txt_url.set_text(self.pBrowser.LocationURL) try: self.widgets.get_widget("window1").set_title("Deluge Web Browser" \ + self.pBrowser.LocationName) except: pass def go_forward(self, widget=None): """go a page ahead""" if not common.windows_check(): if self.gtkmoz.can_go_forward(): self.gtkmoz.go_forward() self.txt_url.set_text(self.gtkmoz.get_location()) try: self.widgets.get_widget("window1").set_title("Deluge Web Browser " \ + self.gtkmoz.get_title()) except: pass else: self.pBrowser.GoForward() self.txt_url.set_text(self.pBrowser.LocationURL) try: self.widgets.get_widget("window1").set_title("Deluge Web Browser" \ + self.pBrowser.LocationName) except: pass def go_back2(self, widget=None): """go a page back""" if not common.windows_check(): if self.gtkmoz2.can_go_back(): self.gtkmoz2.go_back() else: self.pBrowser2.GoBack() def go_forward2(self, widget=None): """go a page ahead""" if not common.windows_check(): if self.gtkmoz2.can_go_forward(): self.gtkmoz2.go_forward() else: self.pBrowser2.GoForward() def stop_load(self, widget=None): """stop loading current page""" if not common.windows_check(): self.gtkmoz.stop_load() else: self.pBrowser.Stop() def bookmark_manager(self, widget=None): """show bookmark manager""" self.bookmarks.show() def hide(self, widget=None, arg=None): """close browser""" self.window.hide() return True