2010-10-03 19:48:56 +00:00
|
|
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
|
|
2010-11-17 16:43:08 +00:00
|
|
|
const Gdk = imports.gi.Gdk;
|
|
|
|
const Gio = imports.gi.Gio;
|
|
|
|
const GLib = imports.gi.GLib;
|
|
|
|
const Shell = imports.gi.Shell;
|
|
|
|
|
|
|
|
const Main = imports.ui.main;
|
|
|
|
|
|
|
|
const Gettext = imports.gettext.domain('gnome-shell');
|
|
|
|
const _ = Gettext.gettext;
|
|
|
|
|
2010-10-03 19:48:56 +00:00
|
|
|
/* http://daringfireball.net/2010/07/improved_regex_for_matching_urls */
|
2011-01-19 02:06:53 +00:00
|
|
|
const _urlRegexp = new RegExp('\\b(([a-z][\\w-]+:(/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)([^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:\'\\".,<>?«»“”‘’]))', 'gi');
|
2010-10-03 19:48:56 +00:00
|
|
|
|
|
|
|
// findUrls:
|
|
|
|
// @str: string to find URLs in
|
|
|
|
//
|
|
|
|
// Searches @str for URLs and returns an array of objects with %url
|
|
|
|
// properties showing the matched URL string, and %pos properties indicating
|
|
|
|
// the position within @str where the URL was found.
|
|
|
|
//
|
|
|
|
// Return value: the list of match objects, as described above
|
|
|
|
function findUrls(str) {
|
|
|
|
let res = [], match;
|
|
|
|
while ((match = _urlRegexp.exec(str)))
|
|
|
|
res.push({ url: match[0], pos: match.index });
|
|
|
|
return res;
|
|
|
|
}
|
2010-11-17 16:43:08 +00:00
|
|
|
|
|
|
|
// spawn:
|
|
|
|
// @argv: an argv array
|
|
|
|
//
|
|
|
|
// Runs @argv in the background, handling any errors that occur
|
|
|
|
// when trying to start the program.
|
|
|
|
function spawn(argv) {
|
|
|
|
try {
|
|
|
|
trySpawn(argv);
|
|
|
|
} catch (err) {
|
|
|
|
_handleSpawnError(argv[0], err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// spawnCommandLine:
|
|
|
|
// @command_line: a command line
|
|
|
|
//
|
|
|
|
// Runs @command_line in the background, handling any errors that
|
|
|
|
// occur when trying to parse or start the program.
|
|
|
|
function spawnCommandLine(command_line) {
|
|
|
|
try {
|
|
|
|
let [success, argc, argv] = GLib.shell_parse_argv(command_line);
|
|
|
|
trySpawn(argv);
|
|
|
|
} catch (err) {
|
|
|
|
_handleSpawnError(command_line, err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// spawnDesktop:
|
|
|
|
// @id: a desktop file ID
|
|
|
|
//
|
|
|
|
// Spawns the desktop file identified by @id using startup notification,
|
|
|
|
// etc, handling any errors that occur when trying to find or start
|
|
|
|
// the program.
|
|
|
|
function spawnDesktop(id) {
|
|
|
|
try {
|
|
|
|
trySpawnDesktop(id);
|
|
|
|
} catch (err) {
|
|
|
|
_handleSpawnError(id, err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// trySpawn:
|
|
|
|
// @argv: an argv array
|
|
|
|
//
|
|
|
|
// Runs @argv in the background. If launching @argv fails,
|
|
|
|
// this will throw an error.
|
|
|
|
function trySpawn(argv)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
GLib.spawn_async(null, argv, null,
|
|
|
|
GLib.SpawnFlags.SEARCH_PATH,
|
|
|
|
null, null);
|
|
|
|
} catch (err) {
|
2011-01-27 20:26:58 +00:00
|
|
|
if (err.code == GLib.SpawnError.G_SPAWN_ERROR_NOENT) {
|
|
|
|
err.message = _("Command not found");
|
|
|
|
} else {
|
|
|
|
// The exception from gjs contains an error string like:
|
|
|
|
// Error invoking GLib.spawn_command_line_async: Failed to
|
|
|
|
// execute child process "foo" (No such file or directory)
|
|
|
|
// We are only interested in the part in the parentheses. (And
|
|
|
|
// we can't pattern match the text, since it gets localized.)
|
|
|
|
err.message = err.message.replace(/.*\((.+)\)/, '$1');
|
|
|
|
}
|
|
|
|
|
2010-11-17 16:43:08 +00:00
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// trySpawnCommandLine:
|
|
|
|
// @command_line: a command line
|
|
|
|
//
|
|
|
|
// Runs @command_line in the background. If launching @command_line
|
|
|
|
// fails, this will throw an error.
|
|
|
|
function trySpawnCommandLine(command_line) {
|
|
|
|
let success, argc, argv;
|
|
|
|
|
|
|
|
try {
|
|
|
|
[success, argc, argv] = GLib.shell_parse_argv(command_line);
|
|
|
|
} catch (err) {
|
|
|
|
// Replace "Error invoking GLib.shell_parse_argv: " with
|
|
|
|
// something nicer
|
|
|
|
err.message = err.message.replace(/[^:]*: /, _("Could not parse command:") + "\n");
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
|
|
|
|
trySpawn(argv);
|
|
|
|
}
|
|
|
|
|
|
|
|
// trySpawnDesktop:
|
|
|
|
// @id: a desktop file ID
|
|
|
|
//
|
|
|
|
// Spawns the desktop file identified by @id using startup notification.
|
|
|
|
// On error, throws an exception.
|
|
|
|
function trySpawnDesktop(id) {
|
|
|
|
let app;
|
|
|
|
|
|
|
|
// shell_app_system_load_from_desktop_file() will end up returning
|
|
|
|
// a stupid error message if the desktop file doesn't exist, but
|
|
|
|
// that's the only case it returns an error for, so we just
|
|
|
|
// substitute our own error in instead
|
|
|
|
try {
|
|
|
|
app = Shell.AppSystem.get_default().load_from_desktop_file(id + '.desktop');
|
|
|
|
} catch (err) {
|
|
|
|
throw new Error(_("No such application"));
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
app.launch();
|
|
|
|
} catch(err) {
|
|
|
|
// see trySpawn
|
|
|
|
err.message = err.message.replace(/.*\((.+)\)/, '$1');
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function _handleSpawnError(command, err) {
|
|
|
|
let title = _("Execution of '%s' failed:").format(command);
|
2011-03-15 22:31:16 +00:00
|
|
|
Main.notifyProblem(title, err.message);
|
2010-11-17 16:43:08 +00:00
|
|
|
}
|
2010-12-17 20:30:12 +00:00
|
|
|
|
|
|
|
// killall:
|
|
|
|
// @processName: a process name
|
|
|
|
//
|
|
|
|
// Kills @processName. If no process with the given name is found,
|
|
|
|
// this will fail silently.
|
|
|
|
function killall(processName) {
|
|
|
|
try {
|
|
|
|
// pkill is more portable than killall, but on Linux at least
|
|
|
|
// it won't match if you pass more than 15 characters of the
|
|
|
|
// process name... However, if you use the '-f' flag to match
|
|
|
|
// the entire command line, it will work, but we have to be
|
|
|
|
// careful in that case that we can match
|
|
|
|
// '/usr/bin/processName' but not 'gedit processName.c' or
|
|
|
|
// whatever...
|
|
|
|
|
|
|
|
let argv = ['pkill', '-f', '^([^ ]*/)?' + processName + '($| )'];
|
|
|
|
GLib.spawn_sync(null, argv, null, GLib.SpawnFlags.SEARCH_PATH, null, null);
|
|
|
|
// It might be useful to return success/failure, but we'd need
|
|
|
|
// a wrapper around WIFEXITED and WEXITSTATUS. Since none of
|
|
|
|
// the current callers care, we don't bother.
|
|
|
|
} catch (e) {
|
|
|
|
logError(e, 'Failed to kill ' + processName);
|
|
|
|
}
|
|
|
|
}
|
2011-01-25 21:08:12 +00:00
|
|
|
|
|
|
|
// This was ported from network-manager-applet
|
|
|
|
// Copyright 2007 - 2011 Red Hat, Inc.
|
|
|
|
// Author: Dan Williams <dcbw@redhat.com>
|
|
|
|
|
|
|
|
const _IGNORED_WORDS = [
|
|
|
|
'Semiconductor',
|
|
|
|
'Components',
|
|
|
|
'Corporation',
|
|
|
|
'Communications',
|
|
|
|
'Company',
|
|
|
|
'Corp.',
|
|
|
|
'Corp',
|
|
|
|
'Co.',
|
|
|
|
'Inc.',
|
|
|
|
'Inc',
|
|
|
|
'Incorporated',
|
|
|
|
'Ltd.',
|
|
|
|
'Limited.',
|
|
|
|
'Intel?',
|
|
|
|
'chipset',
|
|
|
|
'adapter',
|
|
|
|
'[hex]',
|
|
|
|
'NDIS',
|
|
|
|
'Module'
|
|
|
|
];
|
|
|
|
|
|
|
|
const _IGNORED_PHRASES = [
|
|
|
|
'Multiprotocol MAC/baseband processor',
|
|
|
|
'Wireless LAN Controller',
|
|
|
|
'Wireless LAN Adapter',
|
|
|
|
'Wireless Adapter',
|
|
|
|
'Network Connection',
|
|
|
|
'Wireless Cardbus Adapter',
|
|
|
|
'Wireless CardBus Adapter',
|
|
|
|
'54 Mbps Wireless PC Card',
|
|
|
|
'Wireless PC Card',
|
|
|
|
'Wireless PC',
|
|
|
|
'PC Card with XJACK(r) Antenna',
|
|
|
|
'Wireless cardbus',
|
|
|
|
'Wireless LAN PC Card',
|
|
|
|
'Technology Group Ltd.',
|
|
|
|
'Communication S.p.A.',
|
|
|
|
'Business Mobile Networks BV',
|
|
|
|
'Mobile Broadband Minicard Composite Device',
|
|
|
|
'Mobile Communications AB',
|
|
|
|
'(PC-Suite Mode)'
|
|
|
|
];
|
|
|
|
|
|
|
|
function fixupPCIDescription(desc) {
|
|
|
|
desc.replace(/[_,]/, ' ');
|
|
|
|
|
|
|
|
/* Attempt to shorten ID by ignoring certain phrases */
|
|
|
|
for (let i = 0; i < _IGNORED_PHRASES.length; i++) {
|
|
|
|
let item = _IGNORED_PHRASES[i];
|
|
|
|
let pos = desc.indexOf(item);
|
|
|
|
if (pos != -1) {
|
|
|
|
let before = desc.substring(0, pos);
|
|
|
|
let after = desc.substring(pos + item.length, desc.length);
|
|
|
|
desc = before + after;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Attmept to shorten ID by ignoring certain individual words */
|
|
|
|
let words = desc.split(' ');
|
|
|
|
let out = [ ];
|
|
|
|
for (let i = 0; i < words; i++) {
|
|
|
|
let item = words[i];
|
|
|
|
|
|
|
|
// skip empty items (that come out from consecutive spaces)
|
|
|
|
if (item.length == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (_IGNORED_WORDS.indexOf(item) == -1) {
|
|
|
|
out.push(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return out.join(' ');
|
|
|
|
}
|