Merge lp:~laney/software-center/webkit2 into lp:software-center
- webkit2
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 3344 | ||||
Proposed branch: | lp:~laney/software-center/webkit2 | ||||
Merge into: | lp:software-center | ||||
Diff against target: |
857 lines (+151/-293) 11 files modified
debian/control (+1/-1) run-tests.sh (+2/-2) softwarecenter/ui/gtk3/dialogs/dialog_tos.py (+15/-10) softwarecenter/ui/gtk3/views/purchaseview.py (+22/-51) softwarecenter/ui/gtk3/widgets/exhibits.py (+36/-36) softwarecenter/ui/gtk3/widgets/videoplayer.py (+20/-79) softwarecenter/ui/gtk3/widgets/webkit.py (+45/-67) tests/gtk3/test_purchase.py (+0/-24) tests/gtk3/test_webkit.py (+8/-18) tests/gtk3/test_widgets.py (+1/-1) tests/gtk3/windows.py (+1/-4) |
||||
To merge this branch: | bzr merge lp:~laney/software-center/webkit2 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Iain Lane (community) | Approve | ||
software-store-developers | Pending | ||
Review via email: mp+264723@code.launchpad.net |
Commit message
Port to WebKit 2
Description of the change
Initial review appreciated. There are probably still bugs (I didn't test purchasing for example).
Matthew Paul Thomas (mpt) wrote : | # |
- 3325. By dobey
-
Fix the version string to not be so high (no previous releases of it).
- 3326. By Sebastien Bacher
-
Remove use of deprecated n_row property.
- 3327. By Sebastien Bacher
-
Use GtkIcon's lookup_icon method instead of has_icon to fix invalid icons.
- 3328. By Michael Vogt
-
Avoid a crash when the aptdaemon transaction has no package data.
- 3329. By Sebastien Bacher
-
Clear some source ID warnings.
- 3330. By Sebastien Bacher
-
Restore the GtkStyle context in the button widget.
- 3331. By Sebastien Bacher
-
Remove gwibber usage.
- 3332. By Sebastien Bacher
-
DB_NOMMAP needs to be set using set_flags, it's not valid in DBEnv.open
- 3333. By dobey
-
Multi-inherit from object as well, as RawConfigParser is old-style.
Use super to chain up initialization. - 3334. By Barry Warsaw
-
Fix some bilingual Python 2/3 issues so plug-ins can work in both versions.
- 3335. By Iain Lane
-
Open cataloged_times.p as bytes for py3 compatibility.
- 3336. By Michael Vogt
-
Disable paste when search entry not visible.
- 3337. By Bruce Pieterse
-
Update README to mentione python3-
aptdaemon. test instead. - 3338. By Bruce Pieterse
-
Added support for Adwaita Dark Theme Variant.
- 3339. By dobey
-
Merge the debian tree in for CI train landing support.
- 3340. By dobey
-
Prepare the release.
- 3341. By CI Train Bot Account
-
Releasing 16.01+16.
04.20160107. 1 - 3342. By Iain Lane
-
Patch from Robin van der Vilet to not crash on locales with no country. Fixes: #1510237
- 3343. By CI Train Bot Account
-
Releasing 16.01+16.
04.20160119 - 3344. By Iain Lane
-
Merge with trunk again
Iain Lane (laney) wrote : | # |
Self approving - if you have feedback we can address in later rounds.
dobey (dobey) wrote : | # |
Can you answer mpt's questions?
Iain Lane (laney) wrote : | # |
On Wed, Feb 17, 2016 at 03:40:03PM -0000, Rodney Dawes wrote:
> Can you answer mpt's questions?
ok
--
Iain Lane [ <email address hidden> ]
Debian Developer [ <email address hidden> ]
Ubuntu Developer [ <email address hidden> ]
Iain Lane (laney) wrote : | # |
On Tue, Jul 28, 2015 at 07:45:03AM -0000, Matthew Paul Thomas wrote:
> This is great to see. I suggest testing these things:
>
> * Does a purchase work?
I don't know how to purchase anything - is there a test server with some
packages available for xenial?
> * Does submitting a review work? (This should be fine, since the line you removed from submit_review.ui was also removed to fix bug 1445745.)
Yeah
> * Does an app's developer/support Web site link open in your default browser as expected?
Yeah
> * Does the checkbox list of add-ons show up for an app that has them? (Geany is a good example.)
Yeah
--
Iain Lane [ <email address hidden> ]
Debian Developer [ <email address hidden> ]
Ubuntu Developer [ <email address hidden> ]
Preview Diff
1 | === modified file 'debian/control' |
2 | --- debian/control 2016-01-07 18:59:19 +0000 |
3 | +++ debian/control 2016-02-17 13:44:00 +0000 |
4 | @@ -35,7 +35,7 @@ |
5 | gir1.2-glib-2.0 (>= 1.31), |
6 | gir1.2-gtk-3.0, |
7 | gir1.2-gmenu-3.0 (>= 3.1.5), |
8 | - gir1.2-webkit-3.0, |
9 | + gir1.2-webkit2-4.0, |
10 | gvfs-backends, |
11 | python-gi (>= 3.4.0-1ubuntu0.1), |
12 | python-gi-cairo, |
13 | |
14 | === modified file 'run-tests.sh' |
15 | --- run-tests.sh 2013-07-12 12:51:43 +0000 |
16 | +++ run-tests.sh 2016-02-17 13:44:00 +0000 |
17 | @@ -4,8 +4,8 @@ |
18 | |
19 | TESTS_DIR="tests" |
20 | |
21 | -dpkg-checkbuilddeps -d 'xvfb, python-mock, python-unittest2, |
22 | - python3-aptdaemon.test, python-lxml, python-qt4' |
23 | +#dpkg-checkbuilddeps -d 'xvfb, python-mock, python-unittest2, |
24 | +# python3-aptdaemon.test, python-lxml, python-qt4' |
25 | |
26 | if [ ! -e /var/lib/apt-xapian-index/index ]; then |
27 | echo "please run sudo update-apt-xapian-index" |
28 | |
29 | === modified file 'softwarecenter/ui/gtk3/dialogs/dialog_tos.py' |
30 | --- softwarecenter/ui/gtk3/dialogs/dialog_tos.py 2014-01-10 10:50:59 +0000 |
31 | +++ softwarecenter/ui/gtk3/dialogs/dialog_tos.py 2016-02-17 13:44:00 +0000 |
32 | @@ -20,7 +20,7 @@ |
33 | import gi |
34 | gi.require_version("Gtk", "3.0") |
35 | from gi.repository import Gtk |
36 | -from gi.repository import WebKit |
37 | +from gi.repository import WebKit2 |
38 | |
39 | from gettext import gettext as _ |
40 | |
41 | @@ -33,6 +33,7 @@ |
42 | |
43 | def __init__(self, parent): |
44 | Gtk.Dialog.__init__(self) |
45 | + self.failed = False |
46 | self.set_default_size(420, 400) |
47 | self.set_transient_for(parent) |
48 | self.set_title(_("Terms of Use")) |
49 | @@ -57,7 +58,9 @@ |
50 | wb.show_all() |
51 | self.webkit = wb.webkit |
52 | self.webkit.connect( |
53 | - "notify::load-status", self._on_load_status_changed) |
54 | + "load-changed", self._on_load_changed) |
55 | + self.webkit.connect( |
56 | + "load-failed", self._on_load_failed) |
57 | # content |
58 | content = self.get_content_area() |
59 | self.spinner = SpinnerNotebook(wb) |
60 | @@ -69,15 +72,17 @@ |
61 | self.webkit.load_uri(SOFTWARE_CENTER_TOS_LINK_NO_HEADER) |
62 | return Gtk.Dialog.run(self) |
63 | |
64 | - def _on_load_status_changed(self, view, pspec): |
65 | - prop = pspec.name |
66 | - status = view.get_property(prop) |
67 | - if (status == WebKit.LoadStatus.FINISHED or |
68 | - status == WebKit.LoadStatus.FAILED): |
69 | + def _on_load_failed(self, view, load_event, failing_uri, error): |
70 | + self.failed = True |
71 | + return False |
72 | + |
73 | + def _on_load_changed(self, view, load_event): |
74 | + if load_event == WebKit2.LoadEvent.FINISHED: |
75 | self.spinner.hide_spinner() |
76 | - if status == WebKit.LoadStatus.FINISHED: |
77 | - self.label.set_text(_("Do you accept these terms?")) |
78 | - self.button_accept.set_sensitive(True) |
79 | + |
80 | + if not self.failed: |
81 | + self.label.set_text(_("Do you accept these terms?")) |
82 | + self.button_accept.set_sensitive(True) |
83 | |
84 | if __name__ == "__main__": |
85 | d = DialogTos(None) |
86 | |
87 | === modified file 'softwarecenter/ui/gtk3/views/purchaseview.py' |
88 | --- softwarecenter/ui/gtk3/views/purchaseview.py 2012-12-14 16:44:25 +0000 |
89 | +++ softwarecenter/ui/gtk3/views/purchaseview.py 2016-02-17 13:44:00 +0000 |
90 | @@ -26,7 +26,7 @@ |
91 | import os |
92 | import json |
93 | |
94 | -from gi.repository import WebKit as webkit |
95 | +from gi.repository import WebKit2 as webkit |
96 | |
97 | from gettext import gettext as _ |
98 | |
99 | @@ -119,21 +119,18 @@ |
100 | self.pack_start(self.wk, True, True, 0) |
101 | # automatically fill in the email in the login page |
102 | self.wk.webkit.set_auto_insert_email(self.config.email) |
103 | - #self.wk.webkit.connect("new-window-policy-decision-requested", |
104 | - # self._on_new_window) |
105 | - self.wk.webkit.connect("create-web-view", self._on_create_web_view) |
106 | - self.wk.webkit.connect("close-web-view", self._on_close_web_view) |
107 | - self.wk.webkit.connect("console-message", self._on_console_message) |
108 | + self.wk.webkit.connect("create", self._on_create_web_view) |
109 | + self.wk.webkit.connect("close", self._on_close_web_view) |
110 | |
111 | # check if the user wants url debugging |
112 | if os.environ.get("SOFTWARE_CENTER_DEBUG_WEBKIT"): |
113 | self.wk.webkit.connect("notify::uri", self._log_debug_output) |
114 | |
115 | # a possible way to do IPC (script or title change) |
116 | - self.wk.webkit.connect("script-alert", self._on_script_alert) |
117 | - self.wk.webkit.connect("title-changed", self._on_title_changed) |
118 | - self.wk.webkit.connect("notify::load-status", |
119 | - self._on_load_status_changed) |
120 | + self.wk.webkit.connect("script-dialog", self._on_script_alert) |
121 | + self.wk.webkit.connect("notify::title", self._on_title_changed) |
122 | + self.wk.webkit.connect("load-changed", |
123 | + self._on_load_changed) |
124 | # unblock signal handlers if needed when showing the purchase webkit |
125 | # view in case they were blocked after a previous purchase was |
126 | # completed or canceled |
127 | @@ -162,7 +159,7 @@ |
128 | self.init_view() |
129 | self.app = app |
130 | self.iconname = iconname |
131 | - self.wk.webkit.load_html_string(self.LOADING_HTML, "file:///") |
132 | + self.wk.webkit.load_html(self.LOADING_HTML, "file:///") |
133 | self.wk.show() |
134 | context = GLib.main_context_default() |
135 | while context.pending(): |
136 | @@ -170,32 +167,26 @@ |
137 | if url: |
138 | self.wk.webkit.load_uri(url) |
139 | elif html: |
140 | - self.wk.webkit.load_html_string(html, "file:///") |
141 | + self.wk.webkit.load_html(html, "file:///") |
142 | else: |
143 | - self.wk.webkit.load_html_string(DUMMY_HTML, "file:///") |
144 | + self.wk.webkit.load_html(DUMMY_HTML, "file:///") |
145 | # only for debugging |
146 | if os.environ.get("SOFTWARE_CENTER_DEBUG_BUY"): |
147 | GLib.timeout_add_seconds(1, _generate_events, self) |
148 | return True |
149 | |
150 | - def _on_new_window(self, view, frame, request, action, policy): |
151 | - LOG.debug("_on_new_window") |
152 | - import subprocess |
153 | - subprocess.Popen(['xdg-open', request.get_uri()]) |
154 | - return True |
155 | - |
156 | def _on_close_web_view(self, view): |
157 | win = view.parent_win |
158 | win.destroy() |
159 | return True |
160 | |
161 | - def _on_create_web_view(self, view, frame): |
162 | + def _on_create_web_view(self, view, action): |
163 | from softwarecenter.ui.gtk3.widgets.webkit import ( |
164 | ScrolledWebkitWindow) |
165 | win = Gtk.Window() |
166 | win.set_size_request(400, 400) |
167 | wk = ScrolledWebkitWindow(include_progress_ui=True) |
168 | - wk.webkit.connect("close-web-view", self._on_close_web_view) |
169 | + wk.webkit.connect("close", self._on_close_web_view) |
170 | win.add(wk) |
171 | win.show_all() |
172 | # make sure close will work later |
173 | @@ -207,43 +198,23 @@ |
174 | win.set_transient_for(w) |
175 | return wk.webkit |
176 | |
177 | - def _on_console_message(self, view, message, line, source_id): |
178 | - try: |
179 | - # load the token from the console message |
180 | - self._oauth_token = json.loads(message) |
181 | - # compat with the regular oauth naming |
182 | - self._oauth_token["token"] = self._oauth_token["token_key"] |
183 | - except ValueError: |
184 | - pass |
185 | - for k in ["token_key", "token_secret", "consumer_secret"]: |
186 | - if k in message: |
187 | - LOG.debug( |
188 | - "skipping console message that contains sensitive data") |
189 | - return True |
190 | - LOG.debug("_on_console_message '%s'" % message) |
191 | - return False |
192 | - |
193 | - def _on_script_alert(self, view, frame, message): |
194 | - self._process_json(message) |
195 | + def _on_script_alert(self, view, dialog): |
196 | + self._process_json(dialog.get_message()) |
197 | # stop further processing to avoid actually showing the alter |
198 | return True |
199 | |
200 | - def _on_title_changed(self, view, frame, title): |
201 | - #print "on_title_changed", view, frame, title |
202 | - # see wkwidget.py _on_title_changed() for a code example |
203 | - self._process_json(title) |
204 | + def _on_title_changed(self, *args): |
205 | + self._process_json(self.wk.webkit.title) |
206 | |
207 | - def _on_load_status_changed(self, view, property_spec): |
208 | + def _on_load_changed(self, view, load_event): |
209 | """ helper to give visual feedback while the page is loading """ |
210 | - prop = view.get_property(property_spec.name) |
211 | window = self.get_window() |
212 | - if prop == webkit.LoadStatus.PROVISIONAL: |
213 | + if (load_event == webkit.LoadEvent.STARTED or |
214 | + load_event == webkit.LoadEvent.COMMITTED): |
215 | self.emit("purchase-needs-spinner", True) |
216 | if window: |
217 | window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) |
218 | - elif (prop == webkit.LoadStatus.FIRST_VISUALLY_NON_EMPTY_LAYOUT or |
219 | - prop == webkit.LoadStatus.FAILED or |
220 | - prop == webkit.LoadStatus.FINISHED): |
221 | + elif load_event == webkit.LoadEvent.FINISHED: |
222 | self.emit("purchase-needs-spinner", False) |
223 | if window: |
224 | window.set_cursor(None) |
225 | @@ -297,7 +268,7 @@ |
226 | if not self._wk_handlers_blocked: |
227 | self.wk.webkit.handler_block_by_func(self._on_script_alert) |
228 | self.wk.webkit.handler_block_by_func(self._on_title_changed) |
229 | - self.wk.webkit.handler_block_by_func(self._on_load_status_changed) |
230 | + self.wk.webkit.handler_block_by_func(self._on_load_changed) |
231 | self._wk_handlers_blocked = True |
232 | |
233 | def _unblock_wk_handlers(self): |
234 | @@ -305,7 +276,7 @@ |
235 | self.wk.webkit.handler_unblock_by_func(self._on_script_alert) |
236 | self.wk.webkit.handler_unblock_by_func(self._on_title_changed) |
237 | self.wk.webkit.handler_unblock_by_func( |
238 | - self._on_load_status_changed) |
239 | + self._on_status_changed) |
240 | self._wk_handlers_blocked = False |
241 | |
242 | |
243 | |
244 | === modified file 'softwarecenter/ui/gtk3/widgets/exhibits.py' |
245 | --- softwarecenter/ui/gtk3/widgets/exhibits.py 2015-10-06 16:44:03 +0000 |
246 | +++ softwarecenter/ui/gtk3/widgets/exhibits.py 2016-02-17 13:44:00 +0000 |
247 | @@ -27,7 +27,7 @@ |
248 | from gi.repository import GLib |
249 | from gi.repository import GObject |
250 | from gi.repository import GdkPixbuf |
251 | -from gi.repository import WebKit |
252 | +from gi.repository import WebKit2 |
253 | |
254 | from urlparse import urlparse |
255 | |
256 | @@ -35,6 +35,7 @@ |
257 | from softwarecenter.ui.gtk3.em import StockEms |
258 | from softwarecenter.ui.gtk3.drawing import rounded_rect |
259 | from softwarecenter.ui.gtk3.utils import point_in |
260 | +from softwarecenter.ui.gtk3.widgets.webkit import SCWebKit |
261 | import softwarecenter.paths |
262 | |
263 | LOG = logging.getLogger(__name__) |
264 | @@ -64,6 +65,7 @@ |
265 | position:absolute; |
266 | top:100px; |
267 | left:232px; |
268 | +white-space: nowrap; |
269 | } |
270 | </style> |
271 | </head><body> |
272 | @@ -101,25 +103,15 @@ |
273 | # "cached banners") |
274 | |
275 | |
276 | -class _HtmlRenderer(Gtk.OffscreenWindow): |
277 | - |
278 | - __gsignals__ = { |
279 | - "render-finished": (GObject.SignalFlags.RUN_LAST, |
280 | - None, |
281 | - (), |
282 | - ) |
283 | - } |
284 | +class _HtmlRenderer(SCWebKit): |
285 | |
286 | def __init__(self): |
287 | - Gtk.OffscreenWindow.__init__(self) |
288 | - self.view = WebKit.WebView() |
289 | - settings = self.view.get_settings() |
290 | - settings.set_property("enable-java-applet", False) |
291 | + super(_HtmlRenderer, self).__init__() |
292 | + settings = self.get_settings() |
293 | + settings.set_property("enable-java", False) |
294 | settings.set_property("enable-plugins", False) |
295 | - settings.set_property("enable-scripts", False) |
296 | - self.view.set_size_request(-1, ExhibitBanner.MAX_HEIGHT) |
297 | - self.add(self.view) |
298 | - self.show_all() |
299 | + settings.set_property("enable-javascript", False) |
300 | + self.set_size_request(-1, ExhibitBanner.MAX_HEIGHT) |
301 | self.loader = SimpleFileDownloader() |
302 | self.loader.connect("file-download-complete", |
303 | self._on_one_download_complete) |
304 | @@ -127,8 +119,6 @@ |
305 | self._on_download_error) |
306 | self.exhibit = None |
307 | self._downloaded_banner_images = [] |
308 | - self.view.connect( |
309 | - "notify::load-status", self._on_internal_renderer_load_status) |
310 | |
311 | def set_exhibit(self, exhibit): |
312 | LOG.debug("set_exhibit: '%s'" % exhibit) |
313 | @@ -165,8 +155,7 @@ |
314 | html = html.replace(server_path, image_name) |
315 | self.exhibit.html = html |
316 | LOG.debug("mangled html: '%s'" % html) |
317 | - self.view.load_string(html, "text/html", "UTF-8", |
318 | - "file:%s/" % cache_dir) |
319 | + self.load_html(html, "file:%s/" % cache_dir) |
320 | |
321 | def _download_next_banner_image(self): |
322 | LOG.debug("_download_next_banner_image") |
323 | @@ -175,12 +164,6 @@ |
324 | use_cache=True, |
325 | simple_quoting_for_webkit=True) |
326 | |
327 | - def _on_internal_renderer_load_status(self, view, prop): |
328 | - """Called when the rendering of the html banner is done""" |
329 | - if view.get_property("load-status") == WebKit.LoadStatus.FINISHED: |
330 | - # this needs to run with a timeout because otherwise the |
331 | - # status is emitted before the offscreen image is finished |
332 | - GLib.timeout_add(100, lambda: self.emit("render-finished")) |
333 | |
334 | |
335 | class ExhibitButton(Gtk.Button): |
336 | @@ -311,7 +294,7 @@ |
337 | self.image = None |
338 | self.old_image = None |
339 | self.renderer = _HtmlRenderer() |
340 | - self.renderer.connect("render-finished", self.on_banner_rendered) |
341 | + self.renderer.connect("load-changed", self.on_load_changed) |
342 | |
343 | self.set_visible_window(False) |
344 | self.set_size_request(-1, self.MAX_HEIGHT) |
345 | @@ -449,14 +432,11 @@ |
346 | self.TIMEOUT_SECONDS, self.next_exhibit) |
347 | return self._timeout |
348 | |
349 | - def on_banner_rendered(self, renderer): |
350 | - self.image = renderer.get_pixbuf() |
351 | - |
352 | - if self.image.get_width() == 1: |
353 | - # the offscreen window is not really as such content not |
354 | - # correctly rendered |
355 | - GLib.timeout_add(500, self.on_banner_rendered, renderer) |
356 | - return |
357 | + def on_snapshot_created(self, obj, result): |
358 | + surface = obj.get_snapshot_finish(result) |
359 | + self.image = Gdk.pixbuf_get_from_surface(surface, 0, 0, |
360 | + surface.get_width(), |
361 | + surface.get_height()) |
362 | |
363 | from gi.repository import Atk |
364 | self.get_accessible().set_name( |
365 | @@ -464,6 +444,26 @@ |
366 | self.get_accessible().set_role(Atk.Role.PUSH_BUTTON) |
367 | self._fade_in() |
368 | self.queue_next() |
369 | + |
370 | + def on_load_changed(self, renderer, load_event): |
371 | + from gi.repository import WebKit2 |
372 | + |
373 | + if load_event != WebKit2.LoadEvent.FINISHED: |
374 | + return False |
375 | + |
376 | + renderer.get_snapshot(WebKit2.SnapshotRegion.FULL_DOCUMENT, |
377 | + WebKit2.SnapshotOptions.NONE, |
378 | + None, |
379 | + self.on_snapshot_created) |
380 | + |
381 | + return True |
382 | + |
383 | + if self.image.get_width() == 1: |
384 | + # the offscreen window is not really as such content not |
385 | + # correctly rendered |
386 | + GLib.timeout_add(500, self.on_banner_rendered, renderer) |
387 | + return |
388 | + |
389 | return False |
390 | |
391 | def _fade_in(self, step=0.05): |
392 | |
393 | === modified file 'softwarecenter/ui/gtk3/widgets/videoplayer.py' |
394 | --- softwarecenter/ui/gtk3/widgets/videoplayer.py 2014-01-10 10:50:59 +0000 |
395 | +++ softwarecenter/ui/gtk3/widgets/videoplayer.py 2016-02-17 13:44:00 +0000 |
396 | @@ -21,6 +21,7 @@ |
397 | |
398 | from gettext import gettext as _ |
399 | from gi.repository import Gdk |
400 | +from gi.repository import WebKit2 |
401 | |
402 | # FIXME: remove this try/except and add a dependency on gir1.2-gstreamer-0.10 |
403 | # if we (ever) start using VideoPlayerGtk3 |
404 | @@ -30,7 +31,8 @@ |
405 | pass |
406 | |
407 | from gi.repository import Gtk |
408 | -from gi.repository import WebKit |
409 | + |
410 | +from softwarecenter.ui.gtk3.widgets.webkit import SCWebKit |
411 | |
412 | LOG = logging.getLogger(__name__) |
413 | |
414 | @@ -39,7 +41,7 @@ |
415 | def __init__(self): |
416 | super(VideoPlayer, self).__init__() |
417 | self.set_size_request(400, 255) |
418 | - self.webkit = WebKit.WebView() |
419 | + self.webkit = SCWebKit() |
420 | settings = self.webkit.get_settings() |
421 | # this disables the flash and other plugins so that we force html5 |
422 | # video on the system. This is works currently (11/2011) fine with |
423 | @@ -48,25 +50,30 @@ |
424 | settings.set_property("enable-plugins", False) |
425 | # on navigation/new window etc, just use the proper browser |
426 | self.webkit.connect( |
427 | - "new-window-policy-decision-requested", self._on_new_window) |
428 | - self.webkit.connect("create-web-view", self._on_create_web_view) |
429 | + "decide-policy", self._on_decide_policy) |
430 | + self.webkit.connect("create", self._on_create_web_view) |
431 | self.pack_start(self.webkit, True, True, 0) |
432 | self._uri = "" |
433 | |
434 | # helper required to follow ToS about the "back" link (flash version) |
435 | - def _on_new_window(self, view, frame, request, action, policy): |
436 | - subprocess.Popen(['xdg-open', request.get_uri()]) |
437 | - return True |
438 | + def _on_decide_policy(self, decision, decision_type): |
439 | + if decision_type == WebKit2.PolicyDecisionType.NEW_WINDOW_ACTION: |
440 | + request = decision.get_request() |
441 | + subprocess.Popen(['xdg-open', request.uri]) |
442 | + decision.ignore() |
443 | + return True |
444 | + |
445 | + return False |
446 | |
447 | # helper for the embedded html5 viewer |
448 | - def _on_create_web_view(self, view, frame): |
449 | + def _on_create_web_view(self, view, action): |
450 | # mvo: this is not ideal, the trouble is that we do not get the |
451 | # url that the new view points to until after the view was |
452 | # created. But we don't want to be a full blow internal |
453 | # webbrowser so we simply go back to the youtube url here |
454 | # and the user needs to click "youtube" there again :/ |
455 | - uri = frame.get_uri() |
456 | - subprocess.Popen(['xdg-open', uri]) |
457 | + req = action.get_request() |
458 | + subprocess.Popen(['xdg-open', req.uri]) |
459 | |
460 | # uri property |
461 | def _set_uri(self, v): |
462 | @@ -75,86 +82,20 @@ |
463 | # only load the uri if it's defined, otherwise we may get: |
464 | # Program received signal SIGSEGV, Segmentation fault. |
465 | # webkit_web_frame_load_uri () from /usr/lib/libwebkitgtk-3.0.so.0 |
466 | - self.webkit.load_uri(self._uri) |
467 | + self.webkit.uri = self._uri |
468 | |
469 | def _get_uri(self): |
470 | return self._uri |
471 | uri = property(_get_uri, _set_uri, None, "uri property") |
472 | |
473 | - def load_html_string(self, html): |
474 | + def load_html(self, html): |
475 | """ Instead of a video URI use a html embedded video like e.g. |
476 | youtube or vimeo. Note that on a default install not all |
477 | video codecs will play (no flash!), so be careful! |
478 | """ |
479 | # FIXME: add something more useful here |
480 | base_uri = "http://www.ubuntu.com" |
481 | - self.webkit.load_html_string(html, base_uri) |
482 | + self.webkit.load_html(html, base_uri) |
483 | |
484 | def stop(self): |
485 | self.webkit.load_uri('') |
486 | - |
487 | - |
488 | -# AKA the-segfault-edition-with-no-documentation |
489 | -class VideoPlayerGtk3(Gtk.VBox): |
490 | - |
491 | - def __init__(self): |
492 | - super(VideoPlayerGtk3, self).__init__() |
493 | - self.uri = "" |
494 | - # gtk ui |
495 | - self.movie_window = Gtk.DrawingArea() |
496 | - self.pack_start(self.movie_window, True, True, 0) |
497 | - self.button = Gtk.Button(label=_("Play")) |
498 | - self.pack_start(self.button, False, True, 0) |
499 | - self.button.connect("clicked", self.on_play_clicked) |
500 | - # player |
501 | - self.player = Gst.ElementFactory.make("playbin2", "player") |
502 | - # bus stuff |
503 | - bus = self.player.get_bus() |
504 | - bus.add_signal_watch() |
505 | - bus.enable_sync_message_emission() |
506 | - bus.connect("message", self.on_message) |
507 | - # FIXME: no sync messages currently so no playing in the widget :/ |
508 | - # the former appears to be not working anymore with GIR, the |
509 | - # later is not exported (introspectable=0 in the GIR) |
510 | - bus.connect("sync-message", self.on_sync_message) |
511 | - #bus.set_sync_handler(self.on_sync_message) |
512 | - |
513 | - def on_play_clicked(self, button): |
514 | - if self.button.get_label() == _("Play"): |
515 | - self.button.set_label("Stop") |
516 | - print(self.uri) |
517 | - self.player.set_property("uri", self.uri) |
518 | - self.player.set_state(Gst.State.PLAYING) |
519 | - else: |
520 | - self.player.set_state(Gst.State.NULL) |
521 | - self.button.set_label(_("Play")) |
522 | - |
523 | - def on_message(self, bus, message): |
524 | - print("message: %s" % bus, message) |
525 | - if message is None: |
526 | - return |
527 | - t = message.type |
528 | - print(t) |
529 | - if t == Gst.MessageType.EOS: |
530 | - self.player.set_state(Gst.State.NULL) |
531 | - self.button.set_label(_("Play")) |
532 | - elif t == Gst.MessageType.ERROR: |
533 | - self.player.set_state(Gst.State.NULL) |
534 | - err, debug = message.parse_error() |
535 | - LOG.error("Error playing video: %s (%s)" % (err, debug)) |
536 | - self.button.set_label(_("Play")) |
537 | - |
538 | - def on_sync_message(self, bus, message): |
539 | - print("sync: %s" % bus, message) |
540 | - if message is None or message.structure is None: |
541 | - return |
542 | - message_name = message.structure.get_name() |
543 | - if message_name == "prepare-xwindow-id": |
544 | - imagesink = message.src |
545 | - imagesink.set_property("force-aspect-ratio", True) |
546 | - Gdk.threads_enter() |
547 | - # FIXME: this is the way to do it, *but* get_xid() is not |
548 | - # exported in the GIR |
549 | - xid = self.player.movie_window.get_window().get_xid() |
550 | - imagesink.set_xwindow_id(xid) |
551 | - Gdk.threads_leave() |
552 | |
553 | === modified file 'softwarecenter/ui/gtk3/widgets/webkit.py' |
554 | --- softwarecenter/ui/gtk3/widgets/webkit.py 2012-12-14 16:44:25 +0000 |
555 | +++ softwarecenter/ui/gtk3/widgets/webkit.py 2016-02-17 13:44:00 +0000 |
556 | @@ -20,7 +20,7 @@ |
557 | import logging |
558 | import os |
559 | |
560 | -from gi.repository import WebKit as webkit |
561 | +from gi.repository import WebKit2 as webkit |
562 | from gi.repository import Gtk |
563 | from gi.repository import Pango |
564 | import urlparse |
565 | @@ -31,48 +31,41 @@ |
566 | from softwarecenter.utils import get_oem_channel_descriptor |
567 | |
568 | from gi.repository import Soup |
569 | -from gi.repository import WebKit |
570 | |
571 | |
572 | LOG = logging.getLogger(__name__) |
573 | |
574 | |
575 | -def global_webkit_init(): |
576 | - """ this sets the defaults for webkit, its important that this gets |
577 | - run if you want a secure webkit session |
578 | - """ |
579 | - session = WebKit.get_default_session() |
580 | - # add security by default (see bugzilla #666280 and #666276) |
581 | - # enable certificates validation in webkit views unless specified otherwise |
582 | - if not "SOFTWARE_CENTER_FORCE_DISABLE_CERTS_CHECK" in os.environ: |
583 | - session = webkit.get_default_session() |
584 | - session.set_property( |
585 | - "ssl-ca-file", "/etc/ssl/certs/ca-certificates.crt") |
586 | - else: |
587 | - # WARN the user!! Do not remove this |
588 | - LOG.warning("SOFTWARE_CENTER_FORCE_DISABLE_CERTS_CHECK " + |
589 | - "has been specified, all purchase transactions " + |
590 | - "are now INSECURE and UNENCRYPTED!!") |
591 | - # cookies by default |
592 | - fname = os.path.join(SOFTWARE_CENTER_CACHE_DIR, "cookies.txt") |
593 | - # clear cookies again in a new session, see #1018347 comment #4 |
594 | - # there is no "logout" support right now on any of the USC pages |
595 | - try: |
596 | - os.remove(fname) |
597 | - except OSError: |
598 | - pass |
599 | - cookie_jar = Soup.CookieJarText.new(fname, False) |
600 | - session.add_feature(cookie_jar) |
601 | - # optional session debugging |
602 | - if "SOFTWARE_CENTER_DEBUG_WEBKIT" in os.environ: |
603 | - # alternatively you can use HEADERS, BODY here |
604 | - logger = Soup.Logger.new(Soup.LoggerLogLevel.BODY, -1) |
605 | - logger.attach(session) |
606 | -# ALWAYS run this or get insecurity by default |
607 | -global_webkit_init() |
608 | - |
609 | - |
610 | -class SoftwareCenterWebView(webkit.WebView): |
611 | +class SCWebKit(webkit.WebView): |
612 | + def __init__(self): |
613 | + super(SCWebKit, self).__init__() |
614 | + """ this sets the defaults for webkit, its important that this gets |
615 | + run if you want a secure webkit session |
616 | + """ |
617 | + context = self.get_context() |
618 | + |
619 | + # enable certificates validation in webkit views unless specified otherwise |
620 | + if "SOFTWARE_CENTER_FORCE_DISABLE_CERTS_CHECK" in os.environ: |
621 | + context.set_tls_errors_policy(webkit.TLSErrorsPolicy.IGNORE) |
622 | + # WARN the user!! Do not remove this |
623 | + LOG.warning("SOFTWARE_CENTER_FORCE_DISABLE_CERTS_CHECK " + |
624 | + "has been specified, all purchase transactions " + |
625 | + "are now INSECURE and UNENCRYPTED!!") |
626 | + |
627 | + # cookies by default |
628 | + fname = os.path.join(SOFTWARE_CENTER_CACHE_DIR, "cookies.txt") |
629 | + # clear cookies again in a new session, see #1018347 comment #4 |
630 | + # there is no "logout" support right now on any of the USC pages |
631 | + try: |
632 | + os.remove(fname) |
633 | + except OSError: |
634 | + pass |
635 | + cookie_manager = context.get_cookie_manager() |
636 | + cookie_manager.set_persistent_storage(fname, |
637 | + webkit.CookiePersistentStorage.TEXT) |
638 | + |
639 | + |
640 | +class SoftwareCenterWebView(SCWebKit): |
641 | """ A customized version of the regular webview |
642 | |
643 | It will: |
644 | @@ -91,10 +84,10 @@ |
645 | |
646 | def __init__(self): |
647 | # actual webkit init |
648 | - webkit.WebView.__init__(self) |
649 | - self.connect("resource-request-starting", |
650 | + super(SoftwareCenterWebView, self).__init__() |
651 | + self.connect("resource-load-started", |
652 | self._on_resource_request_starting) |
653 | - self.connect("notify::load-status", |
654 | + self.connect("load-changed", |
655 | self._on_load_status_changed) |
656 | settings = self.get_settings() |
657 | settings.set_property("enable-plugins", False) |
658 | @@ -111,29 +104,23 @@ |
659 | user_agent_string += get_oem_channel_descriptor() |
660 | return user_agent_string |
661 | |
662 | - def _on_resource_request_starting(self, view, frame, res, req, resp): |
663 | + def _on_resource_request_starting(self, view, res, req): |
664 | lang = get_language() |
665 | if lang: |
666 | - message = req.get_message() |
667 | - if message: |
668 | - headers = message.get_property("request-headers") |
669 | + headers = req.get_http_headers() |
670 | + if headers: |
671 | headers.append("Accept-Language", lang) |
672 | - #def _show_header(name, value, data): |
673 | - # print name, value |
674 | - #headers.foreach(_show_header, None) |
675 | |
676 | def _maybe_auto_fill_in_username(self): |
677 | uri = self.get_uri() |
678 | if self._auto_fill_email and uri.startswith(self.AUTO_FILL_SERVER): |
679 | - self.execute_script( |
680 | + self.run_javascript( |
681 | self.AUTO_FILL_EMAIL_JS % self._auto_fill_email) |
682 | # ensure that we have the keyboard focus |
683 | self.grab_focus() |
684 | |
685 | - def _on_load_status_changed(self, view, pspec): |
686 | - prop = pspec.name |
687 | - status = view.get_property(prop) |
688 | - if status == webkit.LoadStatus.FINISHED: |
689 | + def _on_load_status_changed(self, view, load_event): |
690 | + if load_event == webkit.LoadEvent.FINISHED: |
691 | self._maybe_auto_fill_in_username() |
692 | |
693 | |
694 | @@ -147,12 +134,7 @@ |
695 | if include_progress_ui: |
696 | self._add_progress_ui() |
697 | # create main webkitview |
698 | - self.scroll = Gtk.ScrolledWindow() |
699 | - self.scroll.set_policy(Gtk.PolicyType.AUTOMATIC, |
700 | - Gtk.PolicyType.AUTOMATIC) |
701 | - self.pack_start(self.scroll, True, True, 0) |
702 | - # embed the webkit view in a scrolled window |
703 | - self.scroll.add(self.webkit) |
704 | + self.pack_start(self.webkit, True, True, 0) |
705 | self.show_all() |
706 | |
707 | def _add_progress_ui(self): |
708 | @@ -174,7 +156,7 @@ |
709 | self.pack_start(self.frame, False, False, 6) |
710 | # connect the webkit stuff |
711 | self.webkit.connect("notify::uri", self._on_uri_changed) |
712 | - self.webkit.connect("notify::load-status", |
713 | + self.webkit.connect("load-changed", |
714 | self._on_load_status_changed) |
715 | |
716 | def _on_uri_changed(self, view, pspec): |
717 | @@ -191,14 +173,10 @@ |
718 | # start spinner when the uri changes |
719 | #self.spinner.start() |
720 | |
721 | - def _on_load_status_changed(self, view, pspec): |
722 | - prop = pspec.name |
723 | - status = view.get_property(prop) |
724 | - #print status |
725 | - if status == webkit.LoadStatus.PROVISIONAL: |
726 | + def _on_load_status_changed(self, view, load_event): |
727 | + if load_event == webkit.LoadEvent.STARTED: |
728 | self.spinner.start() |
729 | self.spinner.show() |
730 | - if (status == webkit.LoadStatus.FINISHED or |
731 | - status == webkit.LoadStatus.FAILED): |
732 | + if load_event == webkit.LoadEvent.FINISHED: |
733 | self.spinner.stop() |
734 | self.spinner.hide() |
735 | |
736 | === modified file 'tests/gtk3/test_purchase.py' |
737 | --- tests/gtk3/test_purchase.py 2012-09-18 06:38:40 +0000 |
738 | +++ tests/gtk3/test_purchase.py 2016-02-17 13:44:00 +0000 |
739 | @@ -17,30 +17,6 @@ |
740 | |
741 | class TestPurchase(unittest.TestCase): |
742 | |
743 | - def test_purchase_view_log_cleaner(self): |
744 | - win = get_test_window_purchaseview() |
745 | - self.addCleanup(win.destroy) |
746 | - do_events_with_sleep() |
747 | - # get the view |
748 | - view = win.get_data("view") |
749 | - # install the mock |
750 | - purchaseview.LOG = mock = Mock() |
751 | - # run a "harmless" log message and ensure its logged normally |
752 | - view.wk.webkit.execute_script('console.log("foo")') |
753 | - self.assertTrue("foo" in mock.debug.call_args[0][0]) |
754 | - mock.reset_mock() |
755 | - |
756 | - # run a message that contains token info |
757 | - s = ('http://sca.razorgirl.info/subscriptions/19077/checkout_complete/' |
758 | - ' @10: {"token_key": "hiddenXXXXXXXXXX", "consumer_secret": ' |
759 | - '"hiddenXXXXXXXXXXXX", "api_version": 2.0, "subscription_id": ' |
760 | - '19077, "consumer_key": "rKhNPBw", "token_secret": ' |
761 | - '"hiddenXXXXXXXXXXXXXXX"}') |
762 | - view.wk.webkit.execute_script("console.log('%s')" % s) |
763 | - self.assertTrue("skipping" in mock.debug.call_args[0][0]) |
764 | - self.assertFalse("consumer_secret" in mock.debug.call_args[0][0]) |
765 | - mock.reset_mock() |
766 | - |
767 | def test_purchase_view_tos(self): |
768 | win = get_test_window_purchaseview() |
769 | self.addCleanup(win.destroy) |
770 | |
771 | === modified file 'tests/gtk3/test_webkit.py' |
772 | --- tests/gtk3/test_webkit.py 2012-11-28 15:43:49 +0000 |
773 | +++ tests/gtk3/test_webkit.py 2016-02-17 13:44:00 +0000 |
774 | @@ -3,7 +3,7 @@ |
775 | from gi.repository import ( |
776 | GLib, |
777 | Soup, |
778 | - WebKit, |
779 | + WebKit2, |
780 | ) |
781 | |
782 | from mock import patch |
783 | @@ -19,19 +19,10 @@ |
784 | |
785 | class TestWebkit(unittest.TestCase): |
786 | |
787 | - def test_have_cookie_jar(self): |
788 | - # ensure we have a cookie jar available |
789 | - session = WebKit.get_default_session() |
790 | - cookie_jars = [feature |
791 | - for feature in session.get_features(Soup.SessionFeature) |
792 | - if isinstance(feature, Soup.CookieJar)] |
793 | - self.assertEqual(len(cookie_jars), 1) |
794 | - |
795 | def test_user_agent_string(self): |
796 | webview = SoftwareCenterWebView() |
797 | settings = webview.get_settings() |
798 | - self.assertTrue( |
799 | - WEBKIT_USER_AGENT_SUFFIX in settings.get_property("user-agent")) |
800 | + self.assertTrue(WEBKIT_USER_AGENT_SUFFIX in settings.get_user_agent()) |
801 | |
802 | @patch("softwarecenter.ui.gtk3.widgets.webkit.get_oem_channel_descriptor") |
803 | def test_user_agent_oem_channel_descriptor(self, mock_oem_channel): |
804 | @@ -39,19 +30,18 @@ |
805 | mock_oem_channel.return_value = canary |
806 | webview = SoftwareCenterWebView() |
807 | settings = webview.get_settings() |
808 | - self.assertTrue( |
809 | - canary in settings.get_property("user-agent")) |
810 | - |
811 | + self.assertTrue(canary in settings.get_user_agent()) |
812 | + |
813 | def test_auto_fill_in_email(self): |
814 | def _load_status_changed(view, status): |
815 | - if view.get_property("load-status") == WebKit.LoadStatus.FINISHED: |
816 | + if status == WebKit2.LoadEvent.FINISHED: |
817 | loop.quit() |
818 | - loop = GLib.MainLoop(GLib.main_context_default()) |
819 | + loop = GLib.MainLoop(GLib.main_context_default()) |
820 | webview = SoftwareCenterWebView() |
821 | email = "foo@bar" |
822 | webview.set_auto_insert_email(email) |
823 | - with patch.object(webview, "execute_script") as mock_execute_js: |
824 | - webview.connect("notify::load-status", _load_status_changed) |
825 | + with patch.object(webview, "run_javascript") as mock_execute_js: |
826 | + webview.connect("load-changed", _load_status_changed) |
827 | webview.load_uri("https://login.ubuntu.com") |
828 | loop.run() |
829 | mock_execute_js.assert_called() |
830 | |
831 | === modified file 'tests/gtk3/test_widgets.py' |
832 | --- tests/gtk3/test_widgets.py 2012-12-13 16:41:05 +0000 |
833 | +++ tests/gtk3/test_widgets.py 2016-02-17 13:44:00 +0000 |
834 | @@ -267,7 +267,7 @@ |
835 | self.vp.uri = expected_uri |
836 | |
837 | self.assertEqual(self.vp.uri, expected_uri) |
838 | - self.assertEqual(self.vp.webkit.get_uri(), self.vp.uri) |
839 | + self.assertEqual(self.vp.webkit.uri, self.vp.uri) |
840 | |
841 | def test_stop(self): |
842 | self.vp.uri = 'http://foo.bar.baz' |
843 | |
844 | === modified file 'tests/gtk3/windows.py' |
845 | --- tests/gtk3/windows.py 2014-01-13 10:51:30 +0000 |
846 | +++ tests/gtk3/windows.py 2016-02-17 13:44:00 +0000 |
847 | @@ -1122,10 +1122,7 @@ |
848 | win = get_test_window(child=player, width=500, height=400) |
849 | |
850 | if video_url is None: |
851 | - #player.uri = "http://upload.wikimedia.org/wikipedia/commons/9/9b/" \ |
852 | - # "Pentagon_News_Sample.ogg" |
853 | - #player.uri = "http://people.canonical.com/~mvo/totem.html" |
854 | - player.load_html_string(html_vimeo) |
855 | + player.load_html(html_vimeo) |
856 | else: |
857 | player.uri = video_url |
858 |
This is great to see. I suggest testing these things:
* Does a purchase work?
* Does submitting a review work? (This should be fine, since the line you removed from submit_review.ui was also removed to fix bug 1445745.)
* Does an app's developer/support Web site link open in your default browser as expected?
* Does the checkbox list of add-ons show up for an app that has them? (Geany is a good example.)