~ubuntu-branches/ubuntu/raring/software-center/raring-proposed

« back to all changes in this revision

Viewing changes to softwarecenter/ui/gtk3/widgets/webkit.py

  • Committer: Package Import Robot
  • Author(s): Michael Vogt
  • Date: 2012-10-11 15:33:05 UTC
  • mfrom: (195.1.18 quantal)
  • Revision ID: package-import@ubuntu.com-20121011153305-fm5ln7if3rpzts4n
Tags: 5.4.1.1
* lp:~mvo/software-center/reinstall-previous-purchase-token-fix:
  - fix reinstall previous purchases that have a system-wide
    license key LP: #1065481
* lp:~mvo/software-center/lp1060106:
  - Add missing gettext init for utils/update-software-center-agent
    (LP: #1060106)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2010 Canonical
 
2
#
 
3
# Authors:
 
4
#  Michael Vogt
 
5
#  Gary Lasker
 
6
#
 
7
# This program is free software; you can redistribute it and/or modify it under
 
8
# the terms of the GNU General Public License as published by the Free Software
 
9
# Foundation; version 3.
 
10
#
 
11
# This program is distributed in the hope that it will be useful, but WITHOUT
 
12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
13
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 
14
# details.
 
15
#
 
16
# You should have received a copy of the GNU General Public License along with
 
17
# this program; if not, write to the Free Software Foundation, Inc.,
 
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
19
 
 
20
import logging
 
21
import os
 
22
 
 
23
from gi.repository import WebKit as webkit
 
24
from gi.repository import Gtk
 
25
from gi.repository import Pango
 
26
import urlparse
 
27
 
 
28
from softwarecenter.i18n import get_language
 
29
from softwarecenter.paths import SOFTWARE_CENTER_CACHE_DIR
 
30
from softwarecenter.enums import WEBKIT_USER_AGENT_SUFFIX
 
31
from softwarecenter.utils import get_oem_channel_descriptor
 
32
 
 
33
from gi.repository import Soup
 
34
from gi.repository import WebKit
 
35
 
 
36
 
 
37
LOG = logging.getLogger(__name__)
 
38
 
 
39
 
 
40
def global_webkit_init():
 
41
    """ this sets the defaults for webkit, its important that this gets
 
42
        run if you want a secure webkit session
 
43
    """
 
44
    session = WebKit.get_default_session()
 
45
    # add security by default (see bugzilla #666280 and #666276)
 
46
    # enable certificates validation in webkit views unless specified otherwise
 
47
    if not "SOFTWARE_CENTER_FORCE_DISABLE_CERTS_CHECK" in os.environ:
 
48
        session = webkit.get_default_session()
 
49
        session.set_property(
 
50
            "ssl-ca-file", "/etc/ssl/certs/ca-certificates.crt")
 
51
    else:
 
52
        # WARN the user!! Do not remove this
 
53
        LOG.warning("SOFTWARE_CENTER_FORCE_DISABLE_CERTS_CHECK " +
 
54
                    "has been specified, all purchase transactions " +
 
55
                    "are now INSECURE and UNENCRYPTED!!")
 
56
    # cookies by default
 
57
    fname = os.path.join(SOFTWARE_CENTER_CACHE_DIR, "cookies.txt")
 
58
    # clear cookies again in a new session, see #1018347 comment #4
 
59
    # there is no "logout" support right now on any of the USC pages
 
60
    try:
 
61
        os.remove(fname)
 
62
    except OSError:
 
63
        pass
 
64
    cookie_jar = Soup.CookieJarText.new(fname, False)
 
65
    session.add_feature(cookie_jar)
 
66
    # optional session debuggin
 
67
    if "SOFTWARE_CENTER_DEBUG_WEBKIT" in os.environ:
 
68
        # alternatively you can use HEADERS, BODY here
 
69
        logger = Soup.Logger.new(Soup.LoggerLogLevel.BODY, -1)
 
70
        logger.attach(session)
 
71
# ALWAYS run this or get insecurity by default
 
72
global_webkit_init()
 
73
 
 
74
 
 
75
class SoftwareCenterWebView(webkit.WebView):
 
76
    """ A customized version of the regular webview
 
77
 
 
78
    It will:
 
79
    - send Accept-Language headers from the users language
 
80
    - disable plugings
 
81
    - send a custom user-agent string
 
82
    - auto-fill in id_email in login.ubuntu.com
 
83
    """
 
84
 
 
85
    # javascript to auto fill email login on login.ubuntu.com
 
86
    AUTO_FILL_SERVER = "https://login.ubuntu.com"
 
87
    AUTO_FILL_EMAIL_JS = """
 
88
document.getElementById("id_email").value="%s";
 
89
document.getElementById("id_password").focus();
 
90
"""
 
91
 
 
92
    def __init__(self):
 
93
        # actual webkit init
 
94
        webkit.WebView.__init__(self)
 
95
        self.connect("resource-request-starting",
 
96
                     self._on_resource_request_starting)
 
97
        self.connect("notify::load-status",
 
98
            self._on_load_status_changed)
 
99
        settings = self.get_settings()
 
100
        settings.set_property("enable-plugins", False)
 
101
        settings.set_property("user-agent", self._get_user_agent_string())
 
102
        self._auto_fill_email = ""
 
103
 
 
104
    def set_auto_insert_email(self, email):
 
105
        self._auto_fill_email = email
 
106
 
 
107
    def _get_user_agent_string(self):
 
108
        settings = self.get_settings()
 
109
        user_agent_string = settings.get_property("user-agent")
 
110
        user_agent_string += " %s " % WEBKIT_USER_AGENT_SUFFIX
 
111
        user_agent_string += get_oem_channel_descriptor()
 
112
        return user_agent_string
 
113
 
 
114
    def _on_resource_request_starting(self, view, frame, res, req, resp):
 
115
        lang = get_language()
 
116
        if lang:
 
117
            message = req.get_message()
 
118
            if message:
 
119
                headers = message.get_property("request-headers")
 
120
                headers.append("Accept-Language", lang)
 
121
        #def _show_header(name, value, data):
 
122
        #    print name, value
 
123
        #headers.foreach(_show_header, None)
 
124
 
 
125
    def _maybe_auto_fill_in_username(self):
 
126
        uri = self.get_uri()
 
127
        if self._auto_fill_email and uri.startswith(self.AUTO_FILL_SERVER):
 
128
            self.execute_script(
 
129
                self.AUTO_FILL_EMAIL_JS % self._auto_fill_email)
 
130
            # ensure that we have the keyboard focus
 
131
            self.grab_focus()
 
132
 
 
133
    def _on_load_status_changed(self, view, pspec):
 
134
        prop = pspec.name
 
135
        status = view.get_property(prop)
 
136
        if status == webkit.LoadStatus.FINISHED:
 
137
            self._maybe_auto_fill_in_username()
 
138
 
 
139
 
 
140
class ScrolledWebkitWindow(Gtk.VBox):
 
141
 
 
142
    def __init__(self, include_progress_ui=False):
 
143
        super(ScrolledWebkitWindow, self).__init__()
 
144
        # get webkit
 
145
        self.webkit = SoftwareCenterWebView()
 
146
        # add progress UI if needed
 
147
        if include_progress_ui:
 
148
            self._add_progress_ui()
 
149
        # create main webkitview
 
150
        self.scroll = Gtk.ScrolledWindow()
 
151
        self.scroll.set_policy(Gtk.PolicyType.AUTOMATIC,
 
152
                               Gtk.PolicyType.AUTOMATIC)
 
153
        self.pack_start(self.scroll, True, True, 0)
 
154
        # embed the webkit view in a scrolled window
 
155
        self.scroll.add(self.webkit)
 
156
        self.show_all()
 
157
 
 
158
    def _add_progress_ui(self):
 
159
        # create toolbar box
 
160
        self.header = Gtk.HBox()
 
161
        # add spinner
 
162
        self.spinner = Gtk.Spinner()
 
163
        self.header.pack_start(self.spinner, False, False, 6)
 
164
        # add a url to the toolbar
 
165
        self.url = Gtk.Label()
 
166
        self.url.set_ellipsize(Pango.EllipsizeMode.END)
 
167
        self.url.set_alignment(0.0, 0.5)
 
168
        self.url.set_text("")
 
169
        self.header.pack_start(self.url, True, True, 0)
 
170
        # frame around the box
 
171
        self.frame = Gtk.Frame()
 
172
        self.frame.set_border_width(3)
 
173
        self.frame.add(self.header)
 
174
        self.pack_start(self.frame, False, False, 6)
 
175
        # connect the webkit stuff
 
176
        self.webkit.connect("notify::uri", self._on_uri_changed)
 
177
        self.webkit.connect("notify::load-status",
 
178
            self._on_load_status_changed)
 
179
 
 
180
    def _on_uri_changed(self, view, pspec):
 
181
        prop = pspec.name
 
182
        uri = view.get_property(prop)
 
183
        # the full uri is irellevant for the purchase view, but it is
 
184
        # interessting to know what protocol/netloc is in use so that the
 
185
        # user can verify its https on sites he is expecting
 
186
        scheme, netloc, path, params, query, frag = urlparse.urlparse(uri)
 
187
        if scheme == "file" and netloc == "":
 
188
            self.url.set_text("")
 
189
        else:
 
190
            self.url.set_text("%s://%s" % (scheme, netloc))
 
191
        # start spinner when the uri changes
 
192
        #self.spinner.start()
 
193
 
 
194
    def _on_load_status_changed(self, view, pspec):
 
195
        prop = pspec.name
 
196
        status = view.get_property(prop)
 
197
        #print status
 
198
        if status == webkit.LoadStatus.PROVISIONAL:
 
199
            self.spinner.start()
 
200
            self.spinner.show()
 
201
        if (status == webkit.LoadStatus.FINISHED or
 
202
            status == webkit.LoadStatus.FAILED):
 
203
            self.spinner.stop()
 
204
            self.spinner.hide()