[Sugar-devel] [PATCH 1/3] Added proxy network support

Manuel Quiñones manuq at laptop.org
Fri Jan 4 16:56:26 EST 2013


2013/1/3 Ariel Calzada <ariel.calzada at gmail.com>:
> ---
>  webactivity.py      |    5 +
>  webactivity.py.orig |  669

Seems that you added a file by mistake.

Can you explain the reasoning behind this patch?  There is no commit
message.  In particular, how this differs from:

http://wiki.sugarlabs.org/go/Features/Proxy_Settings

I would like to see that feature pushed.  Seems almost complete.



+++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 674 insertions(+)
>  create mode 100644 webactivity.py.orig
>
> diff --git a/webactivity.py b/webactivity.py
> index 3c0d337..c5f13c1 100644
> --- a/webactivity.py
> +++ b/webactivity.py
> @@ -159,6 +159,11 @@ class WebActivity(activity.Activity):
>          session.set_property('ssl-use-system-ca-file', True)
>          session.set_property('ssl-strict', False)
>
> +        # Honor the http_proxy variable
> +        if os.environ.get('http_proxy') is not None:
> +            proxy_uri = Soup.URI.new(os.environ['http_proxy'])
> +            session.set_property("proxy-uri",proxy_uri)
> +
>          # By default, cookies are not stored persistently, we have to
>          # add a cookie jar so that they get saved to disk.  We use one
>          # with a SQlite database:
> diff --git a/webactivity.py.orig b/webactivity.py.orig
> new file mode 100644
> index 0000000..3c0d337
> --- /dev/null
> +++ b/webactivity.py.orig
> @@ -0,0 +1,669 @@
> +# Copyright (C) 2006, Red Hat, Inc.
> +# Copyright (C) 2009 Martin Langhoff, Simon Schampijer, Daniel Drake,
> +#                    Tomeu Vizoso
> +#
> +# 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 of the License, 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 St, Fifth Floor, Boston, MA  02110-1301  USA
> +
> +import logging
> +from gettext import gettext as _
> +from gettext import ngettext
> +import os
> +
> +from gi.repository import GObject
> +GObject.threads_init()
> +
> +from gi.repository import Gtk
> +from gi.repository import Gdk
> +from gi.repository import GdkPixbuf
> +from gi.repository import WebKit
> +from gi.repository import Soup
> +from gi.repository import SoupGNOME
> +
> +import base64
> +import time
> +import shutil
> +import sqlite3
> +import json
> +from gi.repository import GConf
> +import locale
> +import cairo
> +import StringIO
> +from hashlib import sha1
> +
> +from sugar3.activity import activity
> +from sugar3.graphics import style
> +import telepathy
> +import telepathy.client
> +from sugar3.presence import presenceservice
> +from sugar3.graphics.tray import HTray
> +from sugar3 import profile
> +from sugar3.graphics.alert import Alert
> +from sugar3.graphics.icon import Icon
> +from sugar3 import mime
> +
> +from sugar3.graphics.toolbarbox import ToolbarButton
> +
> +PROFILE_VERSION = 2
> +
> +_profile_version = 0
> +_profile_path = os.path.join(activity.get_activity_root(), 'data/gecko')
> +_version_file = os.path.join(_profile_path, 'version')
> +_cookies_db_path = os.path.join(_profile_path, 'cookies.sqlite')
> +
> +if os.path.exists(_version_file):
> +    f = open(_version_file)
> +    _profile_version = int(f.read())
> +    f.close()
> +
> +if _profile_version < PROFILE_VERSION:
> +    if not os.path.exists(_profile_path):
> +        os.mkdir(_profile_path)
> +
> +    shutil.copy('cert8.db', _profile_path)
> +    os.chmod(os.path.join(_profile_path, 'cert8.db'), 0660)
> +
> +    f = open(_version_file, 'w')
> +    f.write(str(PROFILE_VERSION))
> +    f.close()
> +
> +
> +def _seed_xs_cookie(cookie_jar):
> +    """Create a HTTP Cookie to authenticate with the Schoolserver.
> +
> +    Do nothing if the laptop is not registered with Schoolserver, or
> +    if the cookie already exists.
> +
> +    """
> +    client = GConf.Client.get_default()
> +    backup_url = client.get_string('/desktop/sugar/backup_url')
> +    if backup_url == '':
> +        _logger.debug('seed_xs_cookie: Not registered with Schoolserver')
> +        return
> +
> +    jabber_server = client.get_string(
> +        '/desktop/sugar/collaboration/jabber_server')
> +
> +    soup_uri = Soup.URI()
> +    soup_uri.set_scheme('xmpp')
> +    soup_uri.set_host(jabber_server)
> +    soup_uri.set_path('/')
> +    xs_cookie = cookie_jar.get_cookies(soup_uri, for_http=False)
> +    if xs_cookie is not None:
> +        _logger.debug('seed_xs_cookie: Cookie exists already')
> +        return
> +
> +    pubkey = profile.get_profile().pubkey
> +    cookie_data = {'color': profile.get_color().to_string(),
> +                   'pkey_hash': sha1(pubkey).hexdigest()}
> +
> +    expire = int(time.time()) + 10 * 365 * 24 * 60 * 60
> +
> +    xs_cookie = Soup.Cookie()
> +    xs_cookie.set_name('xoid')
> +    xs_cookie.set_value(json.dumps(cookie_data))
> +    xs_cookie.set_domain(jabber_server)
> +    xs_cookie.set_path('/')
> +    xs_cookie.set_max_age(expire)
> +    cookie_jar.add_cookie(xs_cookie)
> +    _logger.debug('seed_xs_cookie: Updated cookie successfully')
> +
> +
> +def _set_char_preference(name, value):
> +    cls = components.classes["@mozilla.org/preferences-service;1"]
> +    prefService = cls.getService(components.interfaces.nsIPrefService)
> +    branch = prefService.getBranch('')
> +    branch.setCharPref(name, value)
> +
> +
> +from browser import TabbedView
> +from browser import ZOOM_ORIGINAL
> +from webtoolbar import PrimaryToolbar
> +from edittoolbar import EditToolbar
> +from viewtoolbar import ViewToolbar
> +import downloadmanager
> +
> +# TODO: make the registration clearer SL #3087
> +
> +from model import Model
> +from sugar3.presence.tubeconn import TubeConnection
> +from messenger import Messenger
> +from linkbutton import LinkButton
> +
> +SERVICE = "org.laptop.WebActivity"
> +IFACE = SERVICE
> +PATH = "/org/laptop/WebActivity"
> +
> +_logger = logging.getLogger('web-activity')
> +
> +
> +class WebActivity(activity.Activity):
> +    def __init__(self, handle):
> +        activity.Activity.__init__(self, handle)
> +
> +        _logger.debug('Starting the web activity')
> +
> +        session = WebKit.get_default_session()
> +        session.set_property('accept-language-auto', True)
> +        session.set_property('ssl-use-system-ca-file', True)
> +        session.set_property('ssl-strict', False)
> +
> +        # By default, cookies are not stored persistently, we have to
> +        # add a cookie jar so that they get saved to disk.  We use one
> +        # with a SQlite database:
> +        cookie_jar = SoupGNOME.CookieJarSqlite(filename=_cookies_db_path,
> +                                               read_only=False)
> +        session.add_feature(cookie_jar)
> +
> +        _seed_xs_cookie(cookie_jar)
> +
> +        # FIXME
> +        # downloadmanager.remove_old_parts()
> +
> +        self._force_close = False
> +        self._tabbed_view = TabbedView()
> +        self._tabbed_view.connect('focus-url-entry', self._on_focus_url_entry)
> +        self._tabbed_view.connect('switch-page', self.__switch_page_cb)
> +
> +        self._tray = HTray()
> +        self.set_tray(self._tray, Gtk.PositionType.BOTTOM)
> +
> +        self._primary_toolbar = PrimaryToolbar(self._tabbed_view, self)
> +        self._edit_toolbar = EditToolbar(self)
> +        self._view_toolbar = ViewToolbar(self)
> +
> +        self._primary_toolbar.connect('add-link', self._link_add_button_cb)
> +
> +        self._primary_toolbar.connect('go-home', self._go_home_button_cb)
> +
> +        self._edit_toolbar_button = ToolbarButton(
> +                page=self._edit_toolbar,
> +                icon_name='toolbar-edit')
> +
> +        self._primary_toolbar.toolbar.insert(
> +                self._edit_toolbar_button, 1)
> +
> +        view_toolbar_button = ToolbarButton(
> +                page=self._view_toolbar,
> +                icon_name='toolbar-view')
> +        self._primary_toolbar.toolbar.insert(
> +                view_toolbar_button, 2)
> +
> +        self._primary_toolbar.show_all()
> +        self.set_toolbar_box(self._primary_toolbar)
> +
> +        self.set_canvas(self._tabbed_view)
> +        self._tabbed_view.show()
> +
> +        self.model = Model()
> +        self.model.connect('add_link', self._add_link_model_cb)
> +
> +        self.connect('key-press-event', self._key_press_cb)
> +
> +        if handle.uri:
> +            self._tabbed_view.current_browser.load_uri(handle.uri)
> +        elif not self._jobject.file_path:
> +            # TODO: we need this hack until we extend the activity API for
> +            # opening URIs and default docs.
> +            self._tabbed_view.load_homepage()
> +
> +        self.messenger = None
> +        self.connect('shared', self._shared_cb)
> +
> +        # Get the Presence Service
> +        self.pservice = presenceservice.get_instance()
> +        try:
> +            name, path = self.pservice.get_preferred_connection()
> +            self.tp_conn_name = name
> +            self.tp_conn_path = path
> +            self.conn = telepathy.client.Connection(name, path)
> +        except TypeError:
> +            _logger.debug('Offline')
> +        self.initiating = None
> +
> +        if self.get_shared_activity() is not None:
> +            _logger.debug('shared: %s', self.get_shared())
> +            # We are joining the activity
> +            _logger.debug('Joined activity')
> +            self.connect('joined', self._joined_cb)
> +            if self.get_shared():
> +                # We've already joined
> +                self._joined_cb()
> +        else:
> +            _logger.debug('Created activity')
> +
> +        # README: this is a workaround to remove old temp file
> +        # http://bugs.sugarlabs.org/ticket/3973
> +        self._cleanup_temp_files()
> +
> +    def _cleanup_temp_files(self):
> +        """Removes temporary files generated by Download Manager that
> +        were cancelled by the user or failed for any reason.
> +
> +        There is a bug in GLib that makes this to happen:
> +            https://bugzilla.gnome.org/show_bug.cgi?id=629301
> +        """
> +
> +        try:
> +            uptime_proc = open('/proc/uptime', 'r').read()
> +            uptime = int(float(uptime_proc.split()[0]))
> +        except EnvironmentError:
> +            logging.warning('/proc/uptime could not be read')
> +            uptime = None
> +
> +        temp_path = os.path.join(self.get_activity_root(), 'instance')
> +        now = int(time.time())
> +        cutoff = now - 24 * 60 * 60  # yesterday
> +        if uptime is not None:
> +            boot_time = now - uptime
> +            cutoff = max(cutoff, boot_time)
> +
> +        for f in os.listdir(temp_path):
> +            if f.startswith('.goutputstream-'):
> +                fpath = os.path.join(temp_path, f)
> +                mtime = int(os.path.getmtime(fpath))
> +                if mtime < cutoff:
> +                    logging.warning('Removing old temporary file: %s', fpath)
> +                    try:
> +                        os.remove(fpath)
> +                    except EnvironmentError:
> +                        logging.error('Temporary file could not be '
> +                                      'removed: %s', fpath)
> +
> +    def _on_focus_url_entry(self, gobject):
> +        self._primary_toolbar.entry.grab_focus()
> +
> +    def _shared_cb(self, activity_):
> +        _logger.debug('My activity was shared')
> +        self.initiating = True
> +        self._setup()
> +
> +        _logger.debug('This is my activity: making a tube...')
> +        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube(SERVICE,
> +                                                                    {})
> +
> +    def _setup(self):
> +        if self.get_shared_activity() is None:
> +            _logger.debug('Failed to share or join activity')
> +            return
> +
> +        bus_name, conn_path, channel_paths = \
> +                self.get_shared_activity().get_channels()
> +
> +        # Work out what our room is called and whether we have Tubes already
> +        room = None
> +        tubes_chan = None
> +        text_chan = None
> +        for channel_path in channel_paths:
> +            channel = telepathy.client.Channel(bus_name, channel_path)
> +            htype, handle = channel.GetHandle()
> +            if htype == telepathy.HANDLE_TYPE_ROOM:
> +                _logger.debug('Found our room: it has handle#%d "%s"',
> +                              handle,
> +                              self.conn.InspectHandles(htype, [handle])[0])
> +                room = handle
> +                ctype = channel.GetChannelType()
> +                if ctype == telepathy.CHANNEL_TYPE_TUBES:
> +                    _logger.debug('Found our Tubes channel at %s',
> +                                  channel_path)
> +                    tubes_chan = channel
> +                elif ctype == telepathy.CHANNEL_TYPE_TEXT:
> +                    _logger.debug('Found our Text channel at %s',
> +                                  channel_path)
> +                    text_chan = channel
> +
> +        if room is None:
> +            _logger.debug("Presence service didn't create a room")
> +            return
> +        if text_chan is None:
> +            _logger.debug("Presence service didn't create a text channel")
> +            return
> +
> +        # Make sure we have a Tubes channel - PS doesn't yet provide one
> +        if tubes_chan is None:
> +            _logger.debug("Didn't find our Tubes channel, requesting one...")
> +            tubes_chan = self.conn.request_channel(
> +                telepathy.CHANNEL_TYPE_TUBES, telepathy.HANDLE_TYPE_ROOM,
> +                room, True)
> +
> +        self.tubes_chan = tubes_chan
> +        self.text_chan = text_chan
> +
> +        tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( \
> +                'NewTube', self._new_tube_cb)
> +
> +    def _list_tubes_reply_cb(self, tubes):
> +        for tube_info in tubes:
> +            self._new_tube_cb(*tube_info)
> +
> +    def _list_tubes_error_cb(self, e):
> +        _logger.debug('ListTubes() failed: %s', e)
> +
> +    def _joined_cb(self, activity_):
> +        if not self.get_shared_activity():
> +            return
> +
> +        _logger.debug('Joined an existing shared activity')
> +
> +        self.initiating = False
> +        self._setup()
> +
> +        _logger.debug('This is not my activity: waiting for a tube...')
> +        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
> +            reply_handler=self._list_tubes_reply_cb,
> +            error_handler=self._list_tubes_error_cb)
> +
> +    def _new_tube_cb(self, identifier, initiator, type, service, params,
> +                     state):
> +        _logger.debug('New tube: ID=%d initator=%d type=%d service=%s '
> +                      'params=%r state=%d', identifier, initiator, type,
> +                      service, params, state)
> +
> +        if (type == telepathy.TUBE_TYPE_DBUS and
> +            service == SERVICE):
> +            if state == telepathy.TUBE_STATE_LOCAL_PENDING:
> +                self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(
> +                        identifier)
> +
> +            self.tube_conn = TubeConnection(self.conn,
> +                self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES],
> +                identifier, group_iface=self.text_chan[
> +                    telepathy.CHANNEL_INTERFACE_GROUP])
> +
> +            _logger.debug('Tube created')
> +            self.messenger = Messenger(self.tube_conn, self.initiating,
> +                                       self.model)
> +
> +    def _get_data_from_file_path(self, file_path):
> +        fd = open(file_path, 'r')
> +        try:
> +            data = fd.read()
> +        finally:
> +            fd.close()
> +        return data
> +
> +    def read_file(self, file_path):
> +        if self.metadata['mime_type'] == 'text/plain':
> +            data = self._get_data_from_file_path(file_path)
> +            self.model.deserialize(data)
> +
> +            for link in self.model.data['shared_links']:
> +                _logger.debug('read: url=%s title=%s d=%s' % (link['url'],
> +                                                              link['title'],
> +                                                              link['color']))
> +                self._add_link_totray(link['url'],
> +                                      base64.b64decode(link['thumb']),
> +                                      link['color'], link['title'],
> +                                      link['owner'], -1, link['hash'])
> +            logging.debug('########## reading %s', data)
> +            self._tabbed_view.set_history(self.model.data['history'])
> +            for number, tab in enumerate(self.model.data['currents']):
> +                tab_page = self._tabbed_view.get_nth_page(number)
> +                tab_page.browser.set_history_index(tab['history_index'])
> +                tab_page.browser.grab_focus()
> +
> +            self._tabbed_view.set_current_page(self.model.data['current_tab'])
> +        elif self.metadata['mime_type'] == 'text/uri-list':
> +            data = self._get_data_from_file_path(file_path)
> +            uris = mime.split_uri_list(data)
> +            if len(uris) == 1:
> +                self._tabbed_view.props.current_browser.load_uri(uris[0])
> +            else:
> +                _logger.error('Open uri-list: Does not support'
> +                              'list of multiple uris by now.')
> +        else:
> +            file_uri = 'file://' + file_path
> +            self._tabbed_view.props.current_browser.load_uri(file_uri)
> +            self._tabbed_view.props.current_browser.grab_focus()
> +
> +    def write_file(self, file_path):
> +        if not self.metadata['mime_type']:
> +            self.metadata['mime_type'] = 'text/plain'
> +
> +        if self.metadata['mime_type'] == 'text/plain':
> +
> +            browser = self._tabbed_view.current_browser
> +
> +            if not self._jobject.metadata['title_set_by_user'] == '1':
> +                if browser.props.title is None:
> +                    self.metadata['title'] = _('Untitled')
> +                else:
> +                    self.metadata['title'] = browser.props.title
> +
> +            self.model.data['history'] = self._tabbed_view.get_history()
> +            current_tab = self._tabbed_view.get_current_page()
> +            self.model.data['current_tab'] = current_tab
> +
> +            self.model.data['currents'] = []
> +            for n in range(0, self._tabbed_view.get_n_pages()):
> +                tab_page = self._tabbed_view.get_nth_page(n)
> +                n_browser = tab_page.browser
> +                if n_browser != None:
> +                    uri = n_browser.get_uri()
> +                    history_index = n_browser.get_history_index()
> +                    info = {'title': n_browser.props.title, 'url': uri,
> +                            'history_index': history_index}
> +
> +                    self.model.data['currents'].append(info)
> +
> +            f = open(file_path, 'w')
> +            try:
> +                logging.debug('########## writing %s', self.model.serialize())
> +                f.write(self.model.serialize())
> +            finally:
> +                f.close()
> +
> +    def _link_add_button_cb(self, button):
> +        self._add_link()
> +
> +    def _go_home_button_cb(self, button):
> +        self._tabbed_view.load_homepage()
> +
> +    def _key_press_cb(self, widget, event):
> +        key_name = Gdk.keyval_name(event.keyval)
> +        browser = self._tabbed_view.props.current_browser
> +
> +        if event.get_state() & Gdk.ModifierType.CONTROL_MASK:
> +
> +            if key_name == 'd':
> +                self._add_link()
> +            elif key_name == 'f':
> +                _logger.debug('keyboard: Find')
> +                self._edit_toolbar_button.set_expanded(True)
> +                self._edit_toolbar.search_entry.grab_focus()
> +            elif key_name == 'l':
> +                _logger.debug('keyboard: Focus url entry')
> +                self._primary_toolbar.entry.grab_focus()
> +            elif key_name == 'minus':
> +                _logger.debug('keyboard: Zoom out')
> +                browser.zoom_out()
> +            elif key_name in ['plus', 'equal']:
> +                _logger.debug('keyboard: Zoom in')
> +                browser.zoom_in()
> +            elif key_name == '0':
> +                _logger.debug('keyboard: Actual size')
> +                browser.set_zoom_level(ZOOM_ORIGINAL)
> +            elif key_name == 'Left':
> +                _logger.debug('keyboard: Go back')
> +                browser.go_back()
> +            elif key_name == 'Right':
> +                _logger.debug('keyboard: Go forward')
> +                browser.go_forward()
> +            elif key_name == 'r':
> +                _logger.debug('keyboard: Reload')
> +                browser.reload()
> +            elif Gdk.keyval_name(event.keyval) == "t":
> +                self._tabbed_view.add_tab()
> +            else:
> +                return False
> +
> +            return True
> +
> +        elif key_name in ('KP_Up', 'KP_Down', 'KP_Left', 'KP_Right'):
> +            scrolled_window = browser.get_parent()
> +
> +            if key_name in ('KP_Up', 'KP_Down'):
> +                adjustment = scrolled_window.get_vadjustment()
> +            elif key_name in ('KP_Left', 'KP_Right'):
> +                adjustment = scrolled_window.get_hadjustment()
> +            value = adjustment.get_value()
> +            step = adjustment.get_step_increment()
> +
> +            if key_name in ('KP_Up', 'KP_Left'):
> +                adjustment.set_value(value - step)
> +            elif key_name in ('KP_Down', 'KP_Right'):
> +                adjustment.set_value(value + step)
> +
> +            return True
> +
> +        elif key_name == 'Escape':
> +            status = browser.get_load_status()
> +            loading = WebKit.LoadStatus.PROVISIONAL <= status \
> +                < WebKit.LoadStatus.FINISHED
> +            if loading:
> +                _logger.debug('keyboard: Stop loading')
> +                browser.stop_loading()
> +
> +        return False
> +
> +    def _add_link(self):
> +        ''' take screenshot and add link info to the model '''
> +
> +        browser = self._tabbed_view.props.current_browser
> +        ui_uri = browser.get_uri()
> +
> +        for link in self.model.data['shared_links']:
> +            if link['hash'] == sha1(ui_uri).hexdigest():
> +                _logger.debug('_add_link: link exist already a=%s b=%s',
> +                              link['hash'], sha1(ui_uri).hexdigest())
> +                return
> +        buf = self._get_screenshot()
> +        timestamp = time.time()
> +        self.model.add_link(ui_uri, browser.props.title, buf,
> +                            profile.get_nick_name(),
> +                            profile.get_color().to_string(), timestamp)
> +
> +        if self.messenger is not None:
> +            self.messenger._add_link(ui_uri, browser.props.title,
> +                                     profile.get_color().to_string(),
> +                                     profile.get_nick_name(),
> +                                     base64.b64encode(buf), timestamp)
> +
> +    def _add_link_model_cb(self, model, index):
> +        ''' receive index of new link from the model '''
> +        link = self.model.data['shared_links'][index]
> +        self._add_link_totray(link['url'], base64.b64decode(link['thumb']),
> +                              link['color'], link['title'],
> +                              link['owner'], index, link['hash'])
> +
> +    def _add_link_totray(self, url, buf, color, title, owner, index, hash):
> +        ''' add a link to the tray '''
> +        item = LinkButton(buf, color, title, owner, hash)
> +        item.connect('clicked', self._link_clicked_cb, url)
> +        item.connect('remove_link', self._link_removed_cb)
> +        # use index to add to the tray
> +        self._tray.add_item(item, index)
> +        item.show()
> +        self._view_toolbar.traybutton.props.sensitive = True
> +        self._view_toolbar.traybutton.props.active = True
> +
> +    def _link_removed_cb(self, button, hash):
> +        ''' remove a link from tray and delete it in the model '''
> +        self.model.remove_link(hash)
> +        self._tray.remove_item(button)
> +        if len(self._tray.get_children()) == 0:
> +            self._view_toolbar.traybutton.props.sensitive = False
> +            self._view_toolbar.traybutton.props.active = False
> +
> +    def _link_clicked_cb(self, button, url):
> +        ''' an item of the link tray has been clicked '''
> +        self._tabbed_view.props.current_browser.load_uri(url)
> +
> +    def _get_screenshot(self):
> +        browser = self._tabbed_view.props.current_browser
> +        window = browser.get_window()
> +        width, height = window.get_width(), window.get_height()
> +
> +        thumb_width, thumb_height = style.zoom(100), style.zoom(80)
> +
> +        thumb_surface = Gdk.Window.create_similar_surface(window,
> +            cairo.CONTENT_COLOR, thumb_width, thumb_height)
> +
> +        cairo_context = cairo.Context(thumb_surface)
> +        thumb_scale_w = thumb_width * 1.0 / width
> +        thumb_scale_h = thumb_height * 1.0 / height
> +        cairo_context.scale(thumb_scale_w, thumb_scale_h)
> +        Gdk.cairo_set_source_window(cairo_context, window, 0, 0)
> +        cairo_context.paint()
> +
> +        thumb_str = StringIO.StringIO()
> +        thumb_surface.write_to_png(thumb_str)
> +        return thumb_str.getvalue()
> +
> +    def can_close(self):
> +        if self._force_close:
> +            return True
> +        elif downloadmanager.can_quit():
> +            return True
> +        else:
> +            alert = Alert()
> +            alert.props.title = ngettext('Download in progress',
> +                                         'Downloads in progress',
> +                                         downloadmanager.num_downloads())
> +            message = ngettext('Stopping now will erase your download',
> +                               'Stopping now will erase your downloads',
> +                               downloadmanager.num_downloads())
> +            alert.props.msg = message
> +            cancel_icon = Icon(icon_name='dialog-cancel')
> +            cancel_label = ngettext('Continue download', 'Continue downloads',
> +                                    downloadmanager.num_downloads())
> +            alert.add_button(Gtk.ResponseType.CANCEL, cancel_label,
> +                             cancel_icon)
> +            stop_icon = Icon(icon_name='dialog-ok')
> +            alert.add_button(Gtk.ResponseType.OK, _('Stop'), stop_icon)
> +            stop_icon.show()
> +            self.add_alert(alert)
> +            alert.connect('response', self.__inprogress_response_cb)
> +            alert.show()
> +            self.present()
> +            return False
> +
> +    def __inprogress_response_cb(self, alert, response_id):
> +        self.remove_alert(alert)
> +        if response_id is Gtk.ResponseType.CANCEL:
> +            logging.debug('Keep on')
> +        elif response_id == Gtk.ResponseType.OK:
> +            logging.debug('Stop downloads and quit')
> +            self._force_close = True
> +            downloadmanager.remove_all_downloads()
> +            self.close()
> +
> +    def __switch_page_cb(self, tabbed_view, page, page_num):
> +        browser = page._browser
> +        status = browser.get_load_status()
> +
> +        if status in (WebKit.LoadStatus.COMMITTED,
> +                      WebKit.LoadStatus.FIRST_VISUALLY_NON_EMPTY_LAYOUT):
> +            self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH))
> +        elif status in (WebKit.LoadStatus.PROVISIONAL,
> +                        WebKit.LoadStatus.FAILED,
> +                        WebKit.LoadStatus.FINISHED):
> +            self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.LEFT_PTR))
> +
> +    def get_document_path(self, async_cb, async_err_cb):
> +        browser = self._tabbed_view.props.current_browser
> +        browser.get_source(async_cb, async_err_cb)
> +
> +    def get_canvas(self):
> +        return self._tabbed_view
> --
> 1.7.10.4
>
> _______________________________________________
> Sugar-devel mailing list
> Sugar-devel at lists.sugarlabs.org
> http://lists.sugarlabs.org/listinfo/sugar-devel



--
.. manuq ..


More information about the Sugar-devel mailing list