From c528401b628337c3c66987d1e88a859cb116870e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Fri, 30 Nov 2012 16:36:12 +0100 Subject: [PATCH] remoteSearch: Factor out collectFromDatadirsAsync() utility function Processing files from a subdirectory of various share/gnome-shell directories asynchronously is a common enough pattern to share the common code. https://bugzilla.gnome.org/show_bug.cgi?id=689304 --- js/misc/fileUtils.js | 54 ++++++++++++++++++ js/ui/remoteSearch.js | 124 ++++++++++++++++-------------------------- 2 files changed, 100 insertions(+), 78 deletions(-) diff --git a/js/misc/fileUtils.js b/js/misc/fileUtils.js index 4e620254b..f130b2bbd 100644 --- a/js/misc/fileUtils.js +++ b/js/misc/fileUtils.js @@ -2,6 +2,8 @@ const Gio = imports.gi.Gio; const GLib = imports.gi.GLib; +const Lang = imports.lang; +const Params = imports.misc.params; function listDirAsync(file, callback) { let allFiles = []; @@ -23,6 +25,58 @@ function listDirAsync(file, callback) { }); } +function _collectFromDirectoryAsync(dir, loadState) { + 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); + return; + } + + loadState.numLoading++; + 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); + loadState.numLoading--; + if (loadState.loadedCallback && + loadState.numLoading == 0) + loadState.loadedCallback(loadState.data); + })); + }); +} + +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; + } + + let dataDirs = GLib.get_system_data_dirs(); + if (params.includeUserDir) + dataDirs.unshift(GLib.get_user_data_dir()); + + 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); + } +} + function deleteGFile(file) { // Work around 'delete' being a keyword in JS. return file['delete'](null); diff --git a/js/ui/remoteSearch.js b/js/ui/remoteSearch.js index c9b25c6ac..8494e7465 100644 --- a/js/ui/remoteSearch.js +++ b/js/ui/remoteSearch.js @@ -32,90 +32,58 @@ const SearchProviderIface = var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface); function loadRemoteSearchProviders(addProviderCallback) { - let loadState = { loadedProviders: [], - objectPaths: {}, - numLoading: 0, - addProviderCallback: addProviderCallback }; + let data = { loadedProviders: [], + objectPaths: {}, + addProviderCallback: addProviderCallback }; + FileUtils.collectFromDatadirsAsync('search-providers', + { loadedCallback: remoteProvidersLoaded, + processFile: loadRemoteSearchProvider, + data: data + }); +} - let dataDirs = GLib.get_system_data_dirs(); - for (let i = 0; i < dataDirs.length; i++) { - let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'search-providers']); - let dir = Gio.file_new_for_path(path); +function loadRemoteSearchProvider(file, info, data) { + let keyfile = new GLib.KeyFile(); + let path = file.get_path(); - dir.query_info_async('standard:type', Gio.FileQueryInfoFlags.NONE, - GLib.PRIORITY_DEFAULT, null, - function(object, res) { - let exists = false; - try { - object.query_info_finish(res); - exists = true; - } catch (e) { - } - - if (!exists) - return; - - loadState.numLoading++; - loadRemoteSearchProvidersFromDir(dir, loadState); - }); + try { + keyfile.load_from_file(path, 0); + } catch(e) { + return; } -}; -function loadRemoteSearchProvidersFromDir(dir, loadState) { - let dirPath = dir.get_path(); - FileUtils.listDirAsync(dir, Lang.bind(this, function(files) { - for (let i = 0; i < files.length; i++) { - let keyfile = new GLib.KeyFile(); - let path = GLib.build_filenamev([dirPath, files[i].get_name()]); - - try { - keyfile.load_from_file(path, 0); - } catch(e) { - continue; - } - - if (!keyfile.has_group(KEY_FILE_GROUP)) - continue; - - let remoteProvider; - try { - let group = KEY_FILE_GROUP; - let busName = keyfile.get_string(group, 'BusName'); - let objectPath = keyfile.get_string(group, 'ObjectPath'); - - if (loadState.objectPaths[objectPath]) - continue; - - let appInfo = null; - try { - let desktopId = keyfile.get_string(group, 'DesktopId'); - appInfo = Gio.DesktopAppInfo.new(desktopId); - } catch (e) { - log('Ignoring search provider ' + path + ': missing DesktopId'); - continue; - } - - remoteProvider = new RemoteSearchProvider(appInfo, - busName, - objectPath); - loadState.objectPaths[objectPath] = remoteProvider; - loadState.loadedProviders.push(remoteProvider); - } catch(e) { - log('Failed to add search provider %s: %s'.format(path, e.toString())); - continue; - } - } - - remoteProvidersDirLoaded(loadState); - })); - -}; - -function remoteProvidersDirLoaded(loadState) { - loadState.numLoading--; - if (loadState.numLoading > 0) + if (!keyfile.has_group(KEY_FILE_GROUP)) return; + let remoteProvider; + try { + let group = KEY_FILE_GROUP; + let busName = keyfile.get_string(group, 'BusName'); + let objectPath = keyfile.get_string(group, 'ObjectPath'); + + if (data.objectPaths[objectPath]) + return; + + let appInfo = null; + try { + let desktopId = keyfile.get_string(group, 'DesktopId'); + appInfo = Gio.DesktopAppInfo.new(desktopId); + } catch (e) { + log('Ignoring search provider ' + path + ': missing DesktopId'); + return; + } + + remoteProvider = new RemoteSearchProvider(appInfo, + busName, + objectPath); + data.objectPaths[objectPath] = remoteProvider; + data.loadedProviders.push(remoteProvider); + } catch(e) { + log('Failed to add search provider %s: %s'.format(path, e.toString())); + } +} + +function remoteProvidersLoaded(loadState) { let searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA }); let sortOrder = searchSettings.get_strv('sort-order'); let numSorted = sortOrder.length;