Skip to content

Commit 869b0f4

Browse files
authored
Version 16 (#37)
* initial gnome 43+ support, add CodeQL * fix lint errors and warnings, and metadata * SessionAsync is deprecated * wrap some first run errors
1 parent 9991b4b commit 869b0f4

File tree

8 files changed

+242
-95
lines changed

8 files changed

+242
-95
lines changed

.eslintrc.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,8 @@ rules:
197197
prefer-arrow-callback: 'off'
198198
prefer-const: 'off'
199199
prefer-destructuring: 'off'
200-
prefer-named-capture-group: error
200+
prefer-named-capture-group: 'warn'
201+
no-cond-assign: 'warn'
201202
prefer-numeric-literals: error
202203
prefer-object-spread: error
203204
prefer-promise-reject-errors: error

.github/workflows/codeql-analysis.yml

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# For most projects, this workflow file will not need changing; you simply need
2+
# to commit it to your repository.
3+
#
4+
# You may wish to alter this file to override the set of languages analyzed,
5+
# or to provide custom queries or build logic.
6+
#
7+
# ******** NOTE ********
8+
# We have attempted to detect the languages in your repository. Please check
9+
# the `language` matrix defined below to confirm you have the correct set of
10+
# supported CodeQL languages.
11+
#
12+
name: "CodeQL"
13+
14+
on:
15+
push:
16+
branches: [ "master" ]
17+
pull_request:
18+
# The branches below must be a subset of the branches above
19+
branches: [ "master" ]
20+
schedule:
21+
- cron: '15 1 * * 2'
22+
23+
jobs:
24+
analyze:
25+
name: Analyze
26+
runs-on: ubuntu-latest
27+
permissions:
28+
actions: read
29+
contents: read
30+
security-events: write
31+
32+
strategy:
33+
fail-fast: false
34+
matrix:
35+
language: [ 'javascript' ]
36+
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37+
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
38+
39+
steps:
40+
- name: Checkout repository
41+
uses: actions/checkout@v3
42+
43+
# Initializes the CodeQL tools for scanning.
44+
- name: Initialize CodeQL
45+
uses: github/codeql-action/init@v2
46+
with:
47+
languages: ${{ matrix.language }}
48+
# If you wish to specify custom queries, you can do so here or in a config file.
49+
# By default, queries listed here will override any specified in a config file.
50+
# Prefix the list here with "+" to use these queries and those in the config file.
51+
52+
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
53+
# queries: security-extended,security-and-quality
54+
55+
56+
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
57+
# If this step fails, then you should remove it and run the build manually (see below)
58+
- name: Autobuild
59+
uses: github/codeql-action/autobuild@v2
60+
61+
# ℹ️ Command-line programs to run using the OS shell.
62+
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
63+
64+
# If the Autobuild fails above, remove it and uncomment the following three lines.
65+
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
66+
67+
# - run: |
68+
# echo "Run, Build Application using script"
69+
# ./location_of_script_within_repo/buildscript.sh
70+
71+
- name: Perform CodeQL Analysis
72+
uses: github/codeql-action/analyze@v2
73+
with:
74+
category: "/language:${{matrix.language}}"

convenience.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function versionSmaller(a, b) {
6363
}
6464

6565
function currentVersion() {
66-
return ''+Config.PACKAGE_VERSION.replace(/(alpha|beta)/,'0');
66+
return String(Config.PACKAGE_VERSION.replace(/(alpha|beta|rc)/,'0'));
6767
}
6868

6969
function currentVersionEqual(v) {

extension.js

+88-33
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
const {St, Soup, Gio, GLib, Clutter, GObject} = imports.gi;
1313
const {main, panelMenu, popupMenu, messageTray} = imports.ui;
1414
const Util = imports.misc.util;
15+
const ByteArray = imports.byteArray;
1516

1617
const ExtensionUtils = imports.misc.extensionUtils;
1718
const Me = ExtensionUtils.getCurrentExtension();
@@ -23,11 +24,9 @@ const Gettext = imports.gettext.domain('GoogleEarthWallpaper');
2324
const _ = Gettext.gettext;
2425

2526
const GEjsonURL = "https://www.gstatic.com/prettyearth/assets/data/v3/"; // previously was v2
26-
const GEURL = "https://earth.google.com";
2727
const IndicatorName = "GEWallpaperIndicator";
2828
const TIMEOUT_SECONDS = 24 * 3600; // FIXME: this should use the end data from the json data
2929
const TIMEOUT_SECONDS_ON_HTTP_ERROR = 4 * 3600; // retry in one hour if there is a http error
30-
const ICON = "pin";
3130

3231
const providerNames = ['Google Earth', 'Google Maps', 'Bing Maps', 'OpenStreetMap' , 'GNOME Maps'];
3332
let googleearthWallpaperIndicator=null;
@@ -82,21 +81,18 @@ class GEWallpaperIndicator extends panelMenu.Button {
8281
this.link = "https://earthview.withgoogle.com/";
8382
this.imageid = 0;
8483
this.refreshdue = 0; // UNIX timestamp when next refresh is due
85-
this.httpSession = new Soup.SessionAsync();
86-
Soup.Session.prototype.add_feature.call(this.httpSession, new Soup.ProxyResolverDefault());
84+
this.httpSession = null;
85+
86+
// create libSoup session for http requests
87+
this._initSoup();
8788

8889
this._settings.connect('changed::hide', () => {
8990
getActorCompat(this).visible = !this._settings.get_boolean('hide');
9091
});
9192
getActorCompat(this).visible = !this._settings.get_boolean('hide');
92-
93-
this._settings.connect('changed::map-link-provider', this._updateProviderLink.bind(this));
94-
this._settings.connect('changed::notify', this._notifyCurrentImage.bind(this));
9593

9694
getActorCompat(this).add_child(this.icon);
9795
this._setIcon();
98-
// watch for indicator icon settings changes
99-
this._settings.connect('changed::icon', this._setIcon.bind(this));
10096

10197
this.refreshDueItem = new popupMenu.PopupMenuItem(_("<No refresh scheduled>"));
10298
this.descriptionItem = new popupMenu.PopupMenuItem(_("Text Location"));
@@ -107,6 +103,8 @@ class GEWallpaperIndicator extends panelMenu.Button {
107103
this.swallpaperItem = new popupMenu.PopupMenuItem(_("Set lockscreen image now"));
108104
this.refreshItem = new popupMenu.PopupMenuItem(_("Refresh Now"));
109105
this.settingsItem = new popupMenu.PopupMenuItem(_("Extension settings"));
106+
107+
// force word wrapping for potentially long menu items
110108
this._wrapLabelItem(this.descriptionItem);
111109
this._wrapLabelItem(this.copyrightItem);
112110

@@ -130,27 +128,25 @@ class GEWallpaperIndicator extends panelMenu.Button {
130128
this.descriptionItem.setSensitive(false);
131129
this.copyrightItem.setSensitive(false);
132130
this.locationItem.setSensitive(false);
133-
134-
this.extLinkItem.connect('activate', this._open_link.bind(this));
135-
this.dwallpaperItem.connect('activate', this._setDesktopBackground.bind(this));
131+
136132
if (!Convenience.currentVersionGreaterEqual("3.36")) { // lockscreen and desktop wallpaper are the same in GNOME 3.36+
137133
this.swallpaperItem.connect('activate', this._setLockscreenBackground.bind(this));
138134
this.menu.addMenuItem(this.swallpaperItem);
139135
}
140136
this.menu.addMenuItem(new popupMenu.PopupSeparatorMenuItem());
141-
this.refreshItem.connect('activate', this._refresh.bind(this));
142-
this.settingsItem.connect('activate', this._openPrefs.bind(this));
143137
this.menu.addMenuItem(new popupMenu.PopupMenuItem(_("On refresh:"), {reactive : false} ));
144138
this.menu.addMenuItem(this.wallpaperToggle);
145139
if (!Convenience.currentVersionGreaterEqual("3.36")) { // lockscreen and desktop wallpaper are the same in GNOME 3.36+
146140
this.menu.addMenuItem(this.lockscreenToggle);
147141
}
148142
this.menu.addMenuItem(this.notifyToggle);
149143
this.menu.addMenuItem(new popupMenu.PopupSeparatorMenuItem());
150-
this.menu.addMenuItem(this.settingsItem);
151-
152-
getActorCompat(this).connect('button-press-event', this._updateMenu.bind(this));
144+
this.menu.addMenuItem(this.settingsItem);
145+
146+
// connect menu items and settings changes to functions
147+
this._setMenuConnections();
153148

149+
// persistance of notification interval
154150
if (this._settings.get_int('next-refresh') > 0 ) {
155151
this._restorePreviousState();
156152
}
@@ -160,6 +156,33 @@ class GEWallpaperIndicator extends panelMenu.Button {
160156
}
161157
}
162158

159+
// create soup Session
160+
_initSoup() {
161+
this.httpSession = new Soup.Session();
162+
this.httpSession.user_agent = 'User-Agent: Mozilla/5.0 (GNOME Shell/' + imports.misc.config.PACKAGE_VERSION + '; Linux; +https://github.com/neffo/earth-view-wallpaper-gnome-extension ) Google Earth Wallpaper Gnome Extension/' + Me.metadata.version;
163+
164+
}
165+
166+
_setMenuConnections() {
167+
// update link to map of location
168+
this._settings.connect('changed::map-link-provider', this._updateProviderLink.bind(this));
169+
170+
// on notification toggle change immediately create a notification
171+
this._settings.connect('changed::notify', this._notifyCurrentImage.bind(this));
172+
173+
// watch for indicator icon settings changes (including hiding indicator)
174+
this._settings.connect('changed::icon', this._setIcon.bind(this));
175+
176+
// connect menu items clicks to functions
177+
this.extLinkItem.connect('activate', this._open_link.bind(this));
178+
this.dwallpaperItem.connect('activate', this._setDesktopBackground.bind(this));
179+
this.refreshItem.connect('activate', this._refresh.bind(this));
180+
this.settingsItem.connect('activate', this._openPrefs.bind(this));
181+
182+
// update menu when user clicks button
183+
getActorCompat(this).connect('button-press-event', this._updateMenu.bind(this));
184+
}
185+
163186
_open_link () {
164187
Util.spawn(["xdg-open", this.link]);
165188
}
@@ -201,9 +224,9 @@ class GEWallpaperIndicator extends panelMenu.Button {
201224
// update menu text
202225
this.refreshDueItem.label.set_text(_('Next refresh')+': '+this.refreshdue.format('%X')+' ('+Utils.friendly_time_diff(this.refreshdue)+')');
203226
this.locationItem.label.set_text(Utils.friendly_coordinates(this.lat, this.lon));
204-
this.descriptionItem.label.set_text(this.explanation);
205-
this.copyrightItem.label.set_text(this.copyright);
206-
this.extLinkItem.label.set_text(this.provider_text);
227+
this.descriptionItem.label.set_text(this._ifString(this.explanation));
228+
this.copyrightItem.label.set_text(this._ifString(this.copyright));
229+
this.extLinkItem.label.set_text(this._ifString(this.provider_text));
207230
}
208231

209232
_notifyCurrentImage() {
@@ -287,6 +310,9 @@ class GEWallpaperIndicator extends panelMenu.Button {
287310
return widget;
288311
}
289312

313+
_ifString(check) {
314+
return (typeof check === 'string' || check instanceof String)?check:'';
315+
}
290316

291317
_restartTimeout(seconds = null) {
292318
if (this._timeout)
@@ -308,29 +334,50 @@ class GEWallpaperIndicator extends panelMenu.Button {
308334
this._restartTimeout(300); // in case of a timeout
309335
this.refreshDueItem.label.set_text(_('Fetching...'));
310336

337+
// pick random image to fetch
311338
log('locations count: '+Images.imageids.length);
312-
// create an http message
313339
let imgindex = GLib.random_int_range(0,Images.imageids.length);
340+
341+
// create an http message
314342
let url = GEjsonURL+Images.imageids[imgindex]+'.json';
315343
log("fetching: " + url);
316344
let request = Soup.Message.new('GET', url);
345+
request.request_headers.append('Accept', 'application/json');
317346

318347
// queue the http request
319-
this.httpSession.queue_message(request, this._http_process_message.bind(this));
348+
if (Soup.MAJOR_VERSION >= 3) { // soup3 changes this significantly
349+
try {
350+
this.httpSession.send_and_read_async(request, GLib.PRIORITY_DEFAULT, null, this._http_process_message.bind(this));
351+
}
352+
catch(error) {
353+
log('unable to send libsoup json message '+error);
354+
}
355+
}
356+
else {
357+
try {
358+
this.httpSession.queue_message(request, this._http_process_message.bind(this));
359+
}
360+
catch(error) {
361+
log('unable to send libsoup json message '+error);
362+
}
363+
}
320364
}
321365

322366
_http_process_message(httpSession, message) {
323-
if (message.status_code == 200) {
324-
log("Datatype: "+message.response_headers.get_content_type());
325-
let data = message.response_body.data;
367+
try {
368+
let data;
369+
if (Soup.MAJOR_VERSION >= 3) {
370+
data = ByteArray.toString(this.httpSession.send_and_read_finish(message).get_data());
371+
}
372+
else {
373+
log("Datatype: "+message.response_headers.get_content_type());
374+
data = message.response_body.data;
375+
}
326376
log("Recieved "+data.length+" bytes");
327377
this._parseData(data);
328-
} else if (message.status_code == 403) {
329-
log("Access denied: "+message.status_code);
330-
this._updatePending = false;
331-
this._restartTimeout(TIMEOUT_SECONDS_ON_HTTP_ERROR);
332-
} else {
333-
log("Network error occured: "+message.status_code);
378+
}
379+
catch (error) {
380+
log("Network error occured: "+error);
334381
this._updatePending = false;
335382
this._restartTimeout(TIMEOUT_SECONDS_ON_HTTP_ERROR);
336383
}
@@ -342,13 +389,14 @@ class GEWallpaperIndicator extends panelMenu.Button {
342389
if (imagejson.id != '') {
343390
this.title = _("Google Earth Wallpaper");
344391
let location = "";
392+
345393
if ('geocode' in imagejson) {
346394
//location = imagejson.geocode.administrative_area_level_1 +', '+imagejson.geocode.country;
347395
location = Object.values(imagejson.geocode).join(", ");
348396
} else {
349397
location = [imagejson.region,imagejson.country].filter(Boolean).join(', ');
350398
}
351-
let coordinates = Utils.friendly_coordinates(imagejson.lat,imagejson.lng);
399+
352400
this.explanation = location.trim(); // + '\n'+ coordinates;
353401
this.copyright = imagejson.attribution;
354402
this.lat = imagejson.lat;
@@ -359,6 +407,7 @@ class GEWallpaperIndicator extends panelMenu.Button {
359407

360408
let GEWallpaperDir = this._settings.get_string('download-folder');
361409
let userPicturesDir = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_PICTURES); // XDG pictures directory
410+
362411
if (GEWallpaperDir == '') {
363412
GEWallpaperDir = userPicturesDir + "/GoogleEarthWallpaper/";
364413
this._settings.set_string('download-folder',GEWallpaperDir);
@@ -386,19 +435,23 @@ class GEWallpaperIndicator extends panelMenu.Button {
386435
this._setBackground();
387436
this._updatePending = false;
388437
}
438+
389439
this._settings.set_string('image-details',[
390440
this.explanation.replace(/\|/gm, ''), // just incase (see below)
391441
this.copyright.replace(/\|/gm, '&'), // i think copyright info uses | instead of &
392442
this.lat.toString(),
393443
this.lon.toString(),
394444
this.zoom.toString()].join('|'));
395445
this._settings.set_int('image-id',imagejson.id);
396-
} else {
446+
}
447+
else {
448+
log('refresh failed, no valid image returned');
397449
this.title = _("No wallpaper available");
398450
this.explanation = _("Something went wrong...");
399451
this.filename = "";
400452
this._updatePending = false;
401453
}
454+
402455
this._updateMenu();
403456
this._notifyCurrentImage();
404457
this._restartTimeout(this._settings.get_int('refresh-interval'));
@@ -407,7 +460,9 @@ class GEWallpaperIndicator extends panelMenu.Button {
407460
_delete_previous(to_delete) {
408461
if (to_delete == '')
409462
return;
463+
410464
let deletepictures = this._settings.get_boolean('delete-previous');
465+
411466
if (deletepictures) {
412467
let oldfile = Gio.file_new_for_path(to_delete);
413468
if (oldfile.query_exists(null)) {

0 commit comments

Comments
 (0)