[gnome-shell] Synchronize shell startup



commit da4238ec681c7ca5f682867933e1f8fcbc623bf8
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Mon Nov 4 10:07:44 2013 -0500

    Synchronize shell startup
    
    The asynchronous nature of extension loading, session loading, and more,
    makes the code racy as to what is initialized first, and hard to debug.
    Additionally, since gjs is single-threaded, the only code we're running
    in a thread anyway is readdir, which is going to be I/O bound, so the
    code here is actually likely to be faster.
    
    Drop this in favor of some good old fashioned synchronous loading.

 js/extensionPrefs/main.js |    4 +-
 js/misc/extensionUtils.js |   10 +------
 js/misc/fileUtils.js      |   61 ++++++++++----------------------------------
 js/ui/extensionSystem.js  |    6 ++--
 js/ui/main.js             |    5 ---
 js/ui/remoteSearch.js     |   19 +------------
 js/ui/sessionMode.js      |   49 +++++++++++++++--------------------
 7 files changed, 43 insertions(+), 111 deletions(-)
---
diff --git a/js/extensionPrefs/main.js b/js/extensionPrefs/main.js
index 8e3355d..a3f516e 100644
--- a/js/extensionPrefs/main.js
+++ b/js/extensionPrefs/main.js
@@ -206,11 +206,11 @@ const Application = new Lang.Class({
     _scanExtensions: function() {
         let finder = new ExtensionUtils.ExtensionFinder();
         finder.connect('extension-found', Lang.bind(this, this._extensionFound));
-        finder.connect('extensions-loaded', Lang.bind(this, this._extensionsLoaded));
         finder.scanExtensions();
+        this._extensionsLoaded();
     },
 
-    _extensionFound: function(signals, extension) {
+    _extensionFound: function(finder, extension) {
         let iter = this._model.append();
         this._model.set(iter, [0, 1], [extension.uuid, extension.metadata.name]);
         this._extensionIters[extension.uuid] = iter;
diff --git a/js/misc/extensionUtils.js b/js/misc/extensionUtils.js
index 7c6769a..afdc3cd 100644
--- a/js/misc/extensionUtils.js
+++ b/js/misc/extensionUtils.js
@@ -174,17 +174,9 @@ const ExtensionFinder = new Lang.Class({
         this.emit('extension-found', extension);
     },
 
-    _extensionsLoaded: function() {
-        this.emit('extensions-loaded');
-    },
-
     scanExtensions: function() {
         let perUserDir = Gio.File.new_for_path(global.userdatadir);
-        FileUtils.collectFromDatadirsAsync('extensions',
-                                           { processFile: Lang.bind(this, this._loadExtension),
-                                             loadedCallback: Lang.bind(this, this._extensionsLoaded),
-                                             includeUserDir: true,
-                                             data: perUserDir });
+        FileUtils.collectFromDatadirs('extensions', true, Lang.bind(this, this._loadExtension, perUserDir));
     }
 });
 Signals.addSignalMethods(ExtensionFinder.prototype);
diff --git a/js/misc/fileUtils.js b/js/misc/fileUtils.js
index 767c005..cec06d9 100644
--- a/js/misc/fileUtils.js
+++ b/js/misc/fileUtils.js
@@ -25,60 +25,27 @@ function listDirAsync(file, callback) {
     });
 }
 
-function _collectFromDirectoryAsync(dir, loadState) {
-    function done() {
-        loadState.numLoading--;
-        if (loadState.loadedCallback &&
-            loadState.numLoading == 0)
-            loadState.loadedCallback(loadState.data);
-    }
-
-    dir.query_info_async('standard::type', Gio.FileQueryInfoFlags.NONE,
-        GLib.PRIORITY_DEFAULT, null, function(object, res) {
-            try {
-                object.query_info_finish(res);
-            } catch (e) {
-                if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
-                    log(e.message);
-                done();
-                return;
-            }
-
-            listDirAsync(dir, Lang.bind(this, function(infos) {
-                for (let i = 0; i < infos.length; i++)
-                    loadState.processFile(dir.get_child(infos[i].get_name()),
-                                          infos[i], loadState.data);
-                done();
-            }));
-        });
-}
-
-function collectFromDatadirsAsync(subdir, params) {
-    params = Params.parse(params, { includeUserDir: false,
-                                    processFile: null,
-                                    loadedCallback: null,
-                                    data: null });
-    let loadState = { data: params.data,
-                      numLoading: 0,
-                      loadedCallback: params.loadedCallback,
-                      processFile: params.processFile };
-
-    if (params.processFile == null) {
-        if (params.loadedCallback)
-            params.loadedCallback(params.data);
-        return;
-    }
-
+function collectFromDatadirs(subdir, includeUserDir, processFile) {
     let dataDirs = GLib.get_system_data_dirs();
-    if (params.includeUserDir)
+    if (includeUserDir)
         dataDirs.unshift(GLib.get_user_data_dir());
-    loadState.numLoading = dataDirs.length;
 
     for (let i = 0; i < dataDirs.length; i++) {
         let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', subdir]);
         let dir = Gio.File.new_for_path(path);
 
-        _collectFromDirectoryAsync(dir, loadState);
+        let fileEnum;
+        try {
+            fileEnum = dir.enumerate_children('standard::name,standard::type',
+                                              Gio.FileQueryInfoFlags.NONE, null);
+        } catch (e) {
+            fileEnum = null;
+        }
+        if (fileEnum != null) {
+            let info;
+            while ((info = fileEnum.next_file(null)))
+                processFile(fileEnum.get_child(info), info);
+        }
     }
 }
 
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
index dde7b82..40a4887 100644
--- a/js/ui/extensionSystem.js
+++ b/js/ui/extensionSystem.js
@@ -253,7 +253,7 @@ function onEnabledExtensionsChanged() {
     newEnabledExtensions.filter(function(uuid) {
         return enabledExtensions.indexOf(uuid) == -1;
     }).forEach(function(uuid) {
-            enableExtension(uuid);
+        enableExtension(uuid);
     });
 
     // Find and disable all the newly disabled extensions: UUIDs found in the
@@ -261,7 +261,7 @@ function onEnabledExtensionsChanged() {
     enabledExtensions.filter(function(item) {
         return newEnabledExtensions.indexOf(item) == -1;
     }).forEach(function(uuid) {
-            disableExtension(uuid);
+        disableExtension(uuid);
     });
 
     enabledExtensions = newEnabledExtensions;
@@ -272,7 +272,7 @@ function _loadExtensions() {
     enabledExtensions = getEnabledExtensions();
 
     let finder = new ExtensionUtils.ExtensionFinder();
-    finder.connect('extension-found', function(signals, extension) {
+    finder.connect('extension-found', function(finder, extension) {
         loadExtension(extension);
     });
     finder.scanExtensions();
diff --git a/js/ui/main.js b/js/ui/main.js
index 6f961be..cf1a9a4 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -112,11 +112,6 @@ function start() {
     Gio.DesktopAppInfo.set_desktop_env('GNOME');
 
     sessionMode = new SessionMode.SessionMode();
-    sessionMode.connect('sessions-loaded', _sessionsLoaded);
-    sessionMode.init();
-}
-
-function _sessionsLoaded() {
     sessionMode.connect('updated', _sessionUpdated);
     _initializePrefs();
     _initializeUI();
diff --git a/js/ui/remoteSearch.js b/js/ui/remoteSearch.js
index cd95069..4e7574c 100644
--- a/js/ui/remoteSearch.js
+++ b/js/ui/remoteSearch.js
@@ -7,6 +7,7 @@ const Lang = imports.lang;
 const St = imports.gi.St;
 const Shell = imports.gi.Shell;
 
+const FileUtils = imports.misc.fileUtils;
 const Search = imports.ui.search;
 
 const KEY_FILE_GROUP = 'Shell Search Provider';
@@ -122,23 +123,7 @@ function loadRemoteSearchProviders(callback) {
         return;
     }
 
-    let dataDirs = GLib.get_system_data_dirs();
-    dataDirs.forEach(function(dataDir) {
-        let path = GLib.build_filenamev([dataDir, 'gnome-shell', 'search-providers']);
-        let dir = Gio.File.new_for_path(path);
-        let fileEnum;
-        try {
-            fileEnum = dir.enumerate_children('standard::name,standard::type',
-                                              Gio.FileQueryInfoFlags.NONE, null);
-        } catch (e) {
-            fileEnum = null;
-        }
-        if (fileEnum != null) {
-            let info;
-            while ((info = fileEnum.next_file(null)))
-                loadRemoteSearchProvider(fileEnum.get_child(info));
-        }
-    });
+    FileUtils.collectFromDatadirs('search-providers', false, loadRemoteSearchProvider);
 
     let sortOrder = searchSettings.get_strv('sort-order');
 
diff --git a/js/ui/sessionMode.js b/js/ui/sessionMode.js
index eb04c62..510adc5 100644
--- a/js/ui/sessionMode.js
+++ b/js/ui/sessionMode.js
@@ -102,19 +102,12 @@ const _modes = {
     }
 };
 
-function _getModes(modesLoadedCallback) {
-    FileUtils.collectFromDatadirsAsync('modes',
-                                       { processFile: _loadMode,
-                                         loadedCallback: modesLoadedCallback,
-                                         data: _modes });
-}
-
-function _loadMode(file, info, loadedData) {
+function _loadMode(file, info) {
     let name = info.get_name();
     let suffix = name.indexOf('.json');
     let modeName = suffix == -1 ? name : name.slice(name, suffix);
 
-    if (loadedData.hasOwnProperty(modeName))
+    if (_modes.hasOwnProperty(modeName))
         return;
 
     let fileContent, success, tag, newMode;
@@ -125,18 +118,23 @@ function _loadMode(file, info, loadedData) {
         return;
     }
 
-    loadedData[modeName] = {};
+    _modes[modeName] = {};
     let propBlacklist = ['unlockDialog'];
     for (let prop in loadedData[DEFAULT_MODE]) {
         if (newMode[prop] !== undefined &&
             propBlacklist.indexOf(prop) == -1)
-            loadedData[modeName][prop]= newMode[prop];
+            loadedData[modeName][prop] = newMode[prop];
     }
-    loadedData[modeName]['isPrimary'] = true;
+    _modes[modeName]['isPrimary'] = true;
+}
+
+function _getModes() {
+    FileUtils.collectFromDatadirs('modes', false, _loadMode);
 }
 
 function listModes() {
-    _getModes(function(modes) {
+    let modes = _getModes();
+    modes.forEach(function() {
         let names = Object.getOwnPropertyNames(modes);
         for (let i = 0; i < names.length; i++)
             if (_modes[names[i]].isPrimary)
@@ -149,17 +147,12 @@ function listModes() {
 const SessionMode = new Lang.Class({
     Name: 'SessionMode',
 
-    init: function() {
-        _getModes(Lang.bind(this, function(modes) {
-            this._modes = modes;
-            let primary = modes[global.session_mode] &&
-                          modes[global.session_mode].isPrimary;
-            let mode = primary ? global.session_mode : 'user';
-            this._modeStack = [mode];
-            this._sync();
-
-            this.emit('sessions-loaded');
-        }));
+    _init: function() {
+        let isPrimary = (_modes[global.session_mode] &&
+                         _modes[global.session_mode].isPrimary);
+        let mode = isPrimary ? global.session_mode : 'user';
+        this._modeStack = [mode];
+        this._sync();
     },
 
     pushMode: function(mode) {
@@ -186,13 +179,13 @@ const SessionMode = new Lang.Class({
     },
 
     _sync: function() {
-        let params = this._modes[this.currentMode];
+        let params = _modes[this.currentMode];
         let defaults;
         if (params.parentMode)
-            defaults = Params.parse(this._modes[params.parentMode],
-                                    this._modes[DEFAULT_MODE]);
+            defaults = Params.parse(_modes[params.parentMode],
+                                    _modes[DEFAULT_MODE]);
         else
-            defaults = this._modes[DEFAULT_MODE];
+            defaults = _modes[DEFAULT_MODE];
         params = Params.parse(params, defaults);
 
         // A simplified version of Lang.copyProperties, handles


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]