Bug 280725 - use generic/automatic remoting for xremote r=caillon sr=bryner

This commit is contained in:
bsmedberg%covad.net 2005-04-04 19:08:55 +00:00
Родитель 985bf5fe92
Коммит 2d9f9646a3
54 изменённых файлов: 1709 добавлений и 857 удалений

Просмотреть файл

@ -201,7 +201,6 @@ tier_9_dirs += \
embedding \
editor \
xpfe/appshell \
xpfe/components/xremote/public \
$(NULL)
ifdef MOZ_OJI
@ -243,6 +242,7 @@ endif
tier_50_dirs += \
db \
xpfe \
toolkit/components \
$(NULL)
ifndef MOZ_XUL_APP

Просмотреть файл

@ -640,6 +640,9 @@ xpinstall/wizard/windows/GetShortPathName/Makefile
"
MAKEFILES_xpfe="
widget/src/xremoteclient/Makefile
toolkit/components/Makefile
toolkit/components/remote/Makefile
xpfe/Makefile
xpfe/browser/Makefile
xpfe/browser/public/Makefile

Просмотреть файл

@ -36,7 +36,7 @@
#
# ***** END LICENSE BLOCK *****
## $Id: mozilla.in,v 1.11 2005-02-01 17:36:47 gerv%gerv.net Exp $
## $Id: mozilla.in,v 1.12 2005-04-04 19:08:49 bsmedberg%covad.net Exp $
##
## Usage:
##
@ -141,76 +141,10 @@ moreargs=""
debugging=0
MOZILLA_BIN="${progbase}-bin"
# The following is to check for a currently running instance.
# This is taken almost verbatim from the Mozilla RPM package's launch script.
MOZ_CLIENT_PROGRAM="$dist_bin/mozilla-xremote-client"
check_running() {
"${run_moz}" "$MOZ_CLIENT_PROGRAM" -a "${progbase}" 'ping()' 2>/dev/null >/dev/null
RETURN_VAL=$?
if [ $RETURN_VAL -eq 0 ]; then
echo 1
return 1
else
echo 0
return 0
fi
}
if [ "$OSTYPE" = "beos" ]; then
mimeset -F "$MOZILLA_BIN"
fi
ALREADY_RUNNING=`check_running`
################################################################ Parse Arguments
# If there's a command line argument but it doesn't begin with a -
# it's probably a url. Try to send it to a running instance.
_USE_EXIST=0
_optOne="$1"
case "${_optOne}" in
-*)
;;
*)
_USE_EXIST=1
;;
esac
_optLast=
for i in "$@"; do
_optLast="${i}"
done #last arg
if [ `expr "${_optLast}" : '.*:/.*'` -eq 0 -a \( -f "${_optLast}" -o -d "${_optLast}" \) ]; then
# Last argument seems to be a local file/directory
# Check, if it is absolutely specified (ie. /home/foo/file vs. ./file)
# If it is just "relatively" (./file) specified, make it absolutely
[ `expr "${_optLast}" : '/.*'` -eq 0 ] && _optLast="file://`pwd`/${_optLast}"
fi
################################################################ Parse Arguments
########################################################################### Main
if [ $ALREADY_RUNNING -eq 1 ]; then
# There's an instance already running. Use it.
# Any command line args passed in?
if [ $# -gt 0 ]; then
# There were "some" command line args.
if [ ${_USE_EXIST} -eq 1 ]; then
# We should use an existing instance, as _USE_EXIST=$_USE_EXIST=-1
_remote_cmd="openURL(${_optLast})"
"${run_moz}" "$MOZ_CLIENT_PROGRAM" -a "${progbase}" "${_remote_cmd}"
unset _remote_cmd
exit $?
fi
else
# No command line args. Open new window/tab
#exec "${run_moz}" "$MOZ_CLIENT_PROGRAM" -a "${progbase}" "xfeDoCommand(openBrowser)"
"${run_moz}" "$MOZ_CLIENT_PROGRAM" -a "${progbase}" "xfeDoCommand(openBrowser)"
exit $?
fi
fi
# Default action - no running instance or _USE_EXIST (${_USE_EXIST}) ! -eq 1
########################################################################### Main
while [ $# -gt 0 ]
do
case "$1" in

Просмотреть файл

@ -61,6 +61,7 @@ const nsIWebNavigationInfo = Components.interfaces.nsIWebNavigationInfo;
const NS_BINDING_ABORTED = 0x80020006;
const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
const NS_ERROR_ABORT = Components.results.NS_ERROR_ABORT;
function needHomepageOverride(prefb) {
var savedmstone;
@ -94,7 +95,7 @@ function openWindow(parent, url, target, features, args)
.createInstance(nsISupportsString);
argstring.data = args;
}
wwatch.openWindow(parent, url, target, features, argstring);
return wwatch.openWindow(parent, url, target, features, argstring);
}
function getMostRecentWindow(aType) {
@ -168,6 +169,63 @@ var nsBrowserContentHandler = {
cmdLine.preventDefault = true;
}
try {
var remoteCommand = cmdLine.handleFlagWithParam("remote", true);
}
catch (e) {
throw NS_ERROR_ABORT;
}
if (remoteCommand != null) {
try {
var a = /^\s*(\w+)\(([^\)]*)\)\s*$/.exec(remoteCommand);
var remoteVerb = a[1].toLowerCase();
var remoteParams = a[2].split(",");
switch (remoteVerb) {
case "openurl":
case "openfile":
// openURL(<url>)
// openURL(<url>,new-window)
// openURL(<url>,new-tab)
var uri = cmdLine.resolveURI(remoteParams[0]);
var location = nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW;
if (/new-window/.test(remoteParams[1]))
location = nsIBrowserDOMWindow.OPEN_NEWWINDOW;
else if (/new-tab/.test(remoteParams[1]))
location = nsIBrowserDOMWindow.OPEN_NEWTAB;
handURIToExistingBrowser(uri, location);
break;
case "xfedocommand":
// xfeDoCommand(openBrowser)
if (remoteParams[0].toLowerCase() != "openbrowser")
throw NS_ERROR_ABORT;
openWindow(null, this.chromeURL, "_blank",
"chrome,dialog=no,all" + this.getFeatures(cmdLine),
this.defaultArgs);
break;
default:
// Somebody sent us a remote command we don't know how to process:
// just abort.
throw NS_ERROR_ABORT;
}
cmdLine.preventDefault = true;
}
catch (e) {
// If we had a -remote flag but failed to process it, throw
// NS_ERROR_ABORT so that the xremote code knows to return a failure
// back to the handling code.
throw NS_ERROR_ABORT;
}
}
try {
var uriparam;
while ((uriparam = cmdLine.handleFlagWithParam("new-window", false))) {
@ -288,6 +346,28 @@ const bch_contractID = "@mozilla.org/browser/clh;1";
const bch_CID = Components.ID("{5d0ce354-df01-421a-83fb-7ead0990c24e}");
const CONTRACTID_PREFIX = "@mozilla.org/uriloader/content-handler;1?type=";
function handURIToExistingBrowser(uri, location)
{
var navWin = getMostRecentWindow("navigator:browser");
if (!navWin) {
// if we couldn't load it in an existing window, open a new one
openWindow(null, nsBrowserContentHandler.chromeURL, "_blank",
"chrome,dialog=no,all" + nsBrowserContentHandler.getFeatures(cmdLine),
uri.spec);
return;
}
var navNav = navWin.QueryInterface(nsIInterfaceRequestor)
.getInterface(nsIWebNavigation);
var rootItem = navNav.QueryInterface(nsIDocShellTreeItem).rootTreeItem;
var rootWin = rootItem.QueryInterface(nsIInterfaceRequestor)
.getInterface(nsIDOMWindow);
var bwin = rootWin.QueryInterface(nsIDOMChromeWindow).browserDOMWindow;
bwin.openURI(uri, null, location,
nsIBrowserDOMWindow.OPEN_EXTERNAL);
}
var nsDefaultCommandLineHandler = {
/* nsISupports */
QueryInterface : function dch_QI(iid) {
@ -335,28 +415,15 @@ var nsDefaultCommandLineHandler = {
}
if (urilist.length) {
existingWindow:
if (cmdLine.state != nsICommandLine.STATE_INITIAL_LAUNCH &&
urilist.length == 1) {
// Try to find an existing window and load our URI into the
// current tab, new tab, or new window as prefs determine.
try {
var navWin = getMostRecentWindow("navigator:browser");
if (!navWin)
break existingWindow;
var navNav = navWin.QueryInterface(nsIInterfaceRequestor)
.getInterface(nsIWebNavigation);
var rootItem = navNav.QueryInterface(nsIDocShellTreeItem).rootTreeItem;
var rootWin = rootItem.QueryInterface(nsIInterfaceRequestor)
.getInterface(nsIDOMWindow);
var bwin = rootWin.QueryInterface(nsIDOMChromeWindow).browserDOMWindow;
bwin.openURI(urilist[0], null, nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW,
nsIBrowserDOMWindow.OPEN_EXTERNAL);
handURIToExistingBrowser(urilist[0], nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW);
return;
}
catch (e) {
dump("Failed to hand off external URL to extant window: " + e + "\n");
}
}

Просмотреть файл

@ -36,7 +36,7 @@
#
# ***** END LICENSE BLOCK *****
## $Id: mozilla.in,v 1.4 2005-02-01 18:04:15 gerv%gerv.net Exp $
## $Id: mozilla.in,v 1.5 2005-04-04 19:08:49 bsmedberg%covad.net Exp $
##
## Usage:
##
@ -140,88 +140,10 @@ moreargs=""
debugging=0
MOZILLA_BIN="${progbase}-bin"
# The following is to check for a currently running instance.
# This is taken almost verbatim from the Mozilla RPM package's launch script.
MOZ_CLIENT_PROGRAM="$dist_bin/mozilla-xremote-client"
check_running() {
"${run_moz}" "$MOZ_CLIENT_PROGRAM" -a "${progbase}" 'ping()' 2>/dev/null >/dev/null
RETURN_VAL=$?
if [ $RETURN_VAL -eq 0 ]; then
echo 1
return 1
else
echo 0
return 0
fi
}
if [ "$OSTYPE" = "beos" ]; then
mimeset -F "$MOZILLA_BIN"
fi
ALREADY_RUNNING=`check_running`
################################################################ Parse Arguments
# If there's a command line argument but it doesn't begin with a -
# it's probably a url. Try to send it to a running instance.
_USE_EXIST=0
_NEW_WINDOW=
_optOne="$1"
case "${_optOne}" in
-*)
;;
*)
_USE_EXIST=1
;;
esac
_optOthers=
_optLast=
for i in "$@"; do
_optLast="${i}"
done #last arg
for i in "$@"; do
[ $i = ${_optLast} ] && break
_optOthers="${_optOthers} ${i}"
done #others arg
#???: needs check if othersopt begin with -* ?
if [ `expr "${_optLast}" : '.*:/.*'` -eq 0 -a \( -f "${_optLast}" -o -d "${_optLast}" \) ]; then
# Last argument seems to be a local file/directory
# Check, if it is absolutely specified (ie. /home/foo/file vs. ./file)
# If it is just "relatively" (./file) specified, make it absolutely
[ `expr "${_optLast}" : '/.*'` -eq 0 ] && _optLast="file://`pwd`/${_optLast}"
elif [ `expr "${_optLast}" : '.*:/.*'` -gt 0 -o -n "${_optOthers}" ]; then #???? like before...
_NEW_WINDOW=1
fi
################################################################ Parse Arguments
########################################################################### Main
if [ $ALREADY_RUNNING -eq 1 ]; then
# There's an instance already running. Use it.
# Any command line args passed in?
if [ $# -gt 0 ]; then
# There were "some" command line args.
if [ ${_USE_EXIST} -eq 1 ]; then
# We should use an existing instance, as _USE_EXIST=$_USE_EXIST=-1
_open_type="window"
#_open_type="tab"
_remote_cmd="openURL(${_optLast} , new-${_open_type})"
"${run_moz}" "$MOZ_CLIENT_PROGRAM" -a "${progbase}" "${_remote_cmd}"
unset _remote_cmd _open_type
exit $?
fi
else
# No command line args. Open new window/tab
#exec "${run_moz}" "$MOZ_CLIENT_PROGRAM" -a "${progbase}" "xfeDoCommand(openBrowser)"
"${run_moz}" "$MOZ_CLIENT_PROGRAM" -a "${progbase}" "xfeDoCommand(openInbox)"
exit $?
fi
fi
# Default action - no running instance or _USE_EXIST (${_USE_EXIST}) ! -eq 1
########################################################################### Main
while [ $# -gt 0 ]
do
case "$1" in

Просмотреть файл

@ -45,6 +45,43 @@ const nsISupportsString = Components.interfaces.nsISupportsString;
const nsIWindowMediator = Components.interfaces.nsIWindowMediator;
const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
const NS_ERROR_ABORT = Components.results.NS_ERROR_ABORT;
function mayOpenURI(uri)
{
var ext = Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
.getService(Components.interfaces.nsIExternalProtocolService);
return ext.isExposedProtocol(uri.scheme);
}
function openURI(uri)
{
if (!mayOpenURI())
throw Components.results.NS_ERROR_FAILURE;
var io = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var channel = io.newChannelFromURI(uri);
var loader = Components.classes["@mozilla.org/uriloader;1"]
.getService(Components.interfaces.nsIURILoader);
var listener = {
onStartURIOpen: function(uri) { return false; },
doContent: function(ctype, preferred, request, handler) { return false; },
isPreferred: function(ctype, desired) { return false; },
canHandleContent: function(ctype, preferred, desired) { return false; },
loadCookie: null,
parentContentListener: null,
getInterface: function(iid) {
if (iid.equals(Components.interfaces.nsIURIContentListener))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
}
};
loader.openURI(channel, true, listener);
}
var nsMailDefaultHandler = {
/* nsISupports */
@ -62,6 +99,84 @@ var nsMailDefaultHandler = {
handle : function mdh_handle(cmdLine) {
var uri;
try {
var remoteCommand = cmdLine.handleFlagWithParam("remote", true);
}
catch (e) {
throw NS_ERROR_ABORT;
}
if (remoteCommand != null) {
try {
var a = /^\s*(\w+)\(([^\)]*)\)\s*$/.exec(remoteCommand);
var remoteVerb = a[1].toLowerCase();
var remoteParams = a[2].split(",");
switch (remoteVerb) {
case "openurl":
var xuri = cmdLine.resolveURI(remoteParams[0]);
openURI(xuri);
break;
case "mailto":
var xuri = cmdLine.resolveURI("mailto:" + remoteParams[0]);
openURI(xuri);
break;
case "xfedocommand":
// xfeDoCommand(openBrowser)
switch (remoteParams[0].toLowerCase()) {
case "openinbox":
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.classes.nsIWindowMediator);
var win = wm.getMostRecentWindow("mail:3pane");
if (win) {
win.focus();
}
else {
var wwatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(nsIWindowWatcher);
// Bug 277798 - we have to pass an argument to openWindow(), or
// else it won't honor the dialog=no instruction.
var argstring = Components.classes["@mozilla.org/supports-string;1"]
.createInstance(nsISupportsString);
wwatch.openWindow(null, "chrome://messenger/content/", "_blank",
"chrome,dialog=no,all", argstring);
}
break;
case "composemessage":
var wwatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(nsIWindowWatcher);
var argstring = Components.classes["@mozilla.org/supports-string;1"]
.createInstance(nsISupportsString);
wwatch.openWindow(null, "chrome://messenger/content/messengercompose/messengercompose.xul", "_blank",
"chrome,dialog=no,all", argstring);
break;
default:
throw Components.results.NS_ERROR_ABORT;
}
break;
default:
// Somebody sent us a remote command we don't know how to process:
// just abort.
throw Components.results.NS_ERROR_ABORT;
}
cmdLine.preventDefault = true;
}
catch (e) {
// If we had a -remote flag but failed to process it, throw
// NS_ERROR_ABORT so that the xremote code knows to return a failure
// back to the handling code.
dump(e);
throw Components.results.NS_ERROR_ABORT;
}
}
var count = cmdLine.length;
if (count) {
var i = 0;

Просмотреть файл

@ -49,7 +49,6 @@ DIRS = \
obsolete \
profile \
xre \
components \
mozapps \
themes \
$(NULL)

Просмотреть файл

@ -43,7 +43,16 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = \
# These component dirs are built for all apps (including seamonkey)
ifdef MOZ_ENABLE_XREMOTE
DIRS += remote
endif
# These component dirs are built only for XUL apps
ifdef MOZ_XUL_APP
DIRS += \
console \
filepicker \
printing \
@ -62,7 +71,7 @@ DIRS += \
typeaheadfind \
downloads \
$(NULL)
endif
endif # MOZ_THUNDERBIRD
ifeq ($(OS_ARCH),WINNT)
DIRS += alerts
@ -76,4 +85,6 @@ DIRS += \
EXTRA_PP_COMPONENTS = nsDefaultCLH.js
endif # MOZ_XUL_APP
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -39,6 +39,7 @@
interface nsIFile;
interface nsIURI;
interface nsIDOMWindow;
/**
* Represents the command line used to invoke a XUL application. This may be the
@ -54,7 +55,7 @@ interface nsIURI;
* yet. Please use with care.
*/
[scriptable, uuid(d2368f41-b2ed-424e-891e-f7aedd92d5d3)]
[scriptable, uuid(bc3173bd-aa46-46a0-9d25-d9867a9659b6)]
interface nsICommandLine : nsISupports
{
/**
@ -149,6 +150,12 @@ interface nsICommandLine : nsISupports
*/
readonly attribute nsIFile workingDirectory;
/**
* A window to be targeted by this command line. In most cases, this will
* be null (xremote will sometimes set this attribute).
*/
readonly attribute nsIDOMWindow windowContext;
/**
* Resolve a file-path argument into an nsIFile. This method gracefully
* handles relative or absolute file paths, according to the working

Просмотреть файл

@ -50,7 +50,7 @@
* Smedberg <benjamin@smedbergs.us>.
*/
[uuid(8089187e-2f73-48dc-a8e1-baa2633618e3)]
[uuid(c1f4cfbf-a41f-4628-aa6c-9fb914478af8)]
interface nsICommandLineRunner : nsICommandLine
{
/**
@ -65,6 +65,11 @@ interface nsICommandLineRunner : nsICommandLine
void init(in long argc, in nsCharPtrArray argv,
in nsIFile workingDir, in unsigned long state);
/**
* Set the windowContext parameter.
*/
void setWindowContext(in nsIDOMWindow aWindow);
/**
* Process the command-line handlers in the proper order, calling "handle()" on
* each.

Просмотреть файл

@ -58,6 +58,7 @@ REQUIRES = \
string \
necko \
unicharutil \
dom \
$(NULL)
CPPSRCS = \

Просмотреть файл

@ -39,6 +39,7 @@
#include "nsICategoryManager.h"
#include "nsICommandLineHandler.h"
#include "nsIDOMWindow.h"
#include "nsIFile.h"
#include "nsISimpleEnumerator.h"
#include "nsIStringEnumerator.h"
@ -90,6 +91,7 @@ protected:
nsStringArray mArgs;
PRUint32 mState;
nsCOMPtr<nsIFile> mWorkingDir;
nsCOMPtr<nsIDOMWindow> mWindowContext;
PRBool mPreventDefault;
};
@ -245,6 +247,20 @@ nsCommandLine::GetWorkingDirectory(nsIFile* *aResult)
return NS_OK;
}
NS_IMETHODIMP
nsCommandLine::GetWindowContext(nsIDOMWindow* *aResult)
{
NS_IF_ADDREF(*aResult = mWindowContext);
return NS_OK;
}
NS_IMETHODIMP
nsCommandLine::SetWindowContext(nsIDOMWindow* aValue)
{
mWindowContext = aValue;
return NS_OK;
}
NS_IMETHODIMP
nsCommandLine::ResolveFile(const nsAString& aArgument, nsIFile* *aResult)
{

Просмотреть файл

@ -0,0 +1,82 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Christopher Blizzard <blizzard@mozilla.org>.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = toolkitcomps
LIBRARY_NAME = remoteservice
EXPORT_LIBRARY = 1
IS_COMPONENT = 1
MODULE_NAME = RemoteServiceModule
REQUIRES = \
xpcom \
string \
appcomps \
toolkitcomps \
appcomps \
xulapp \
widget \
gfx \
dom \
docshell \
$(NULL)
XPIDLSRCS = nsIRemoteService.idl
ifneq (,$(filter gtk gtk2,$(MOZ_WIDGET_TOOLKIT)))
CPPSRCS += nsGTKRemoteService.cpp
endif
ifeq (photon,$(MOZ_WIDGET_TOOLKIT))
CPPSRCS += nsPhMozRemoteHelper.cpp
endif
include $(topsrcdir)/config/rules.mk
ifeq (gtk2,$(MOZ_WIDGET_TOOLKIT))
CXXFLAGS += $(MOZ_GTK2_CFLAGS)
endif
ifeq (gtk,$(MOZ_WIDGET_TOOLKIT))
CXXFLAGS += $(MOZ_GTK_CFLAGS)
endif

Просмотреть файл

@ -0,0 +1,576 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=8:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Christopher Blizzard.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Christopher Blizzard <blizzard@mozilla.org>
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsGTKRemoteService.h"
#include <X11/Xatom.h> // for XA_STRING
#include <stdlib.h>
#include <gtk/gtkinvisible.h> // For some reason GTK+ doesn't include this file
// automatically from gtk.h
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include "nsIBaseWindow.h"
#include "nsIDocShell.h"
#include "nsIDOMWindow.h"
#include "nsIGenericFactory.h"
#include "nsILocalFile.h"
#include "nsIObserverService.h"
#include "nsIScriptGlobalObject.h"
#include "nsIServiceManager.h"
#include "nsIWeakReference.h"
#include "nsIWidget.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "prprf.h"
#include "prenv.h"
#include "nsCRT.h"
#ifdef MOZ_XUL_APP
#include "nsICommandLineRunner.h"
#include "nsXULAppAPI.h"
#else
#include "nsISuiteRemoteService.h"
#endif
#define MOZILLA_VERSION_PROP "_MOZILLA_VERSION"
#define MOZILLA_LOCK_PROP "_MOZILLA_LOCK"
#define MOZILLA_COMMAND_PROP "_MOZILLA_COMMAND"
#define MOZILLA_RESPONSE_PROP "_MOZILLA_RESPONSE"
#define MOZILLA_USER_PROP "_MOZILLA_USER"
#define MOZILLA_PROFILE_PROP "_MOZILLA_PROFILE"
#define MOZILLA_PROGRAM_PROP "_MOZILLA_PROGRAM"
#define MOZILLA_COMMANDLINE_PROP "_MOZILLA_COMMANDLINE"
#ifdef MOZ_XUL_APP
const unsigned char kRemoteVersion[] = "5.1";
#else
const unsigned char kRemoteVersion[] = "5.0";
#endif
NS_IMPL_QUERY_INTERFACE2(nsGTKRemoteService,
nsIRemoteService,
nsIObserver);
NS_IMETHODIMP_(nsrefcnt)
nsGTKRemoteService::AddRef()
{
return 1;
}
NS_IMETHODIMP_(nsrefcnt)
nsGTKRemoteService::Release()
{
return 1;
}
NS_IMETHODIMP
nsGTKRemoteService::Startup(const char* aAppName, const char* aProfileName)
{
NS_ASSERTION(aAppName, "Don't pass a null appname!");
EnsureAtoms();
if (mServerWindow) return NS_ERROR_ALREADY_INITIALIZED;
mAppName = aAppName;
ToLowerCase(mAppName);
mProfileName = aProfileName;
mServerWindow = gtk_invisible_new();
gtk_widget_realize(mServerWindow);
HandleCommandsFor(mServerWindow, nsnull);
if (!mWindows.IsInitialized())
mWindows.Init();
mWindows.EnumerateRead(StartupHandler, this);
nsCOMPtr<nsIObserverService> obs
(do_GetService("@mozilla.org/observer-service;1"));
if (obs) {
obs->AddObserver(this, "xpcom-shutdown", PR_FALSE);
obs->AddObserver(this, "quit-application", PR_FALSE);
}
return NS_OK;
}
PLDHashOperator
nsGTKRemoteService::StartupHandler(const void* aKey,
nsIWeakReference* aData,
void* aClosure)
{
GtkWidget* widget = (GtkWidget*) aKey;
nsGTKRemoteService* aThis = (nsGTKRemoteService*) aClosure;
aThis->HandleCommandsFor(widget, aData);
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
nsGTKRemoteService::RegisterWindow(nsIDOMWindow* aWindow)
{
// get the native window for this instance
nsCOMPtr<nsIScriptGlobalObject> scriptObject
(do_QueryInterface(aWindow));
NS_ENSURE_TRUE(scriptObject, NS_ERROR_FAILURE);
nsCOMPtr<nsIBaseWindow> baseWindow
(do_QueryInterface(scriptObject->GetDocShell()));
NS_ENSURE_TRUE(baseWindow, NS_ERROR_FAILURE);
nsCOMPtr<nsIWidget> mainWidget;
baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
NS_ENSURE_TRUE(mainWidget, NS_ERROR_FAILURE);
// walk up the widget tree and find the toplevel window in the
// hierarchy
nsCOMPtr<nsIWidget> tempWidget (dont_AddRef(mainWidget->GetParent()));
while (tempWidget) {
tempWidget = dont_AddRef(tempWidget->GetParent());
if (tempWidget)
mainWidget = tempWidget;
}
GtkWidget* widget =
(GtkWidget*) mainWidget->GetNativeData(NS_NATIVE_SHELLWIDGET);
NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
nsCOMPtr<nsIWeakReference> weak = do_GetWeakReference(aWindow);
NS_ENSURE_TRUE(weak, NS_ERROR_FAILURE);
if (!mWindows.IsInitialized())
mWindows.Init();
mWindows.Put(widget, weak);
// If Startup() has already been called, immediately register this window.
if (mServerWindow) {
HandleCommandsFor(widget, weak);
}
return NS_OK;
}
NS_IMETHODIMP
nsGTKRemoteService::Shutdown()
{
if (!mServerWindow)
return NS_ERROR_NOT_INITIALIZED;
gtk_widget_destroy(mServerWindow);
mServerWindow = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsGTKRemoteService::Observe(nsISupports* aSubject,
const char *aTopic,
const PRUnichar *aData)
{
// This can be xpcom-shutdown or quit-application, but it's the same either
// way.
Shutdown();
return NS_OK;
}
#define ARRAY_LENGTH(array_) (sizeof(array_)/sizeof(array_[0]))
// Minimize the roundtrips to the X server by getting all the atoms at once
static char *XAtomNames[] = {
MOZILLA_VERSION_PROP,
MOZILLA_LOCK_PROP,
MOZILLA_COMMAND_PROP,
MOZILLA_RESPONSE_PROP,
MOZILLA_USER_PROP,
MOZILLA_PROFILE_PROP,
MOZILLA_PROGRAM_PROP,
MOZILLA_COMMANDLINE_PROP
};
static Atom XAtoms[ARRAY_LENGTH(XAtomNames)];
void
nsGTKRemoteService::EnsureAtoms(void)
{
if (sMozVersionAtom)
return;
XInternAtoms(GDK_DISPLAY(), XAtomNames, ARRAY_LENGTH(XAtomNames),
False, XAtoms);
int i = 0;
sMozVersionAtom = XAtoms[i++];
sMozLockAtom = XAtoms[i++];
sMozCommandAtom = XAtoms[i++];
sMozResponseAtom = XAtoms[i++];
sMozUserAtom = XAtoms[i++];
sMozProfileAtom = XAtoms[i++];
sMozProgramAtom = XAtoms[i++];
sMozCommandLineAtom = XAtoms[i++];
}
#ifndef MOZ_XUL_APP
const char*
nsGTKRemoteService::HandleCommand(char* aCommand, nsIDOMWindow* aWindow)
{
nsresult rv;
nsCOMPtr<nsISuiteRemoteService> remote
(do_GetService("@mozilla.org/browser/xremoteservice;2"));
if (!remote)
return "509 internal error";
rv = remote->ParseCommand(aCommand, aWindow);
if (NS_SUCCEEDED(rv))
return "200 executed command";
if (NS_ERROR_INVALID_ARG == rv)
return "500 command not parseable";
if (NS_ERROR_NOT_IMPLEMENTED == rv)
return "501 unrecognized command";
return "509 internal error";
}
#else //MOZ_XUL_APP
const char*
nsGTKRemoteService::HandleCommand(char* aCommand, nsIDOMWindow* aWindow)
{
nsresult rv;
nsCOMPtr<nsICommandLineRunner> cmdline
(do_CreateInstance("@mozilla.org/toolkit/command-line;1", &rv));
if (NS_FAILED(rv))
return "509 internal error";
// 1) Make sure that it looks remotely valid with parens
// 2) Treat ping() immediately and specially
nsCAutoString command(aCommand);
PRInt32 p1, p2;
p1 = command.FindChar('(');
p2 = command.FindChar(')');
if (p1 == kNotFound || p2 == kNotFound || p1 == 0 || p2 < p1) {
return "500 command not parseable";
}
command.Truncate(p1);
command.Trim(" ", PR_TRUE, PR_TRUE);
ToLowerCase(command);
#ifdef DEBUG_bsmedberg
printf("Processing xremote command: %s\n", command.get());
#endif
if (!command.EqualsLiteral("ping")) {
char* argv[3] = {"dummyappname", "-remote", aCommand};
rv = cmdline->Init(3, argv, nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT);
if (NS_FAILED(rv))
return "509 internal error";
if (aWindow)
cmdline->SetWindowContext(aWindow);
rv = cmdline->Run();
if (NS_ERROR_ABORT == rv)
return "500 command not parseable";
if (NS_FAILED(rv))
return "509 internal error";
}
return "200 executed command";
}
const char*
nsGTKRemoteService::HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow)
{
nsresult rv;
nsCOMPtr<nsICommandLineRunner> cmdline
(do_CreateInstance("@mozilla.org/toolkit/command-line;1", &rv));
if (NS_FAILED(rv))
return "509 internal error";
// the commandline property is constructed as an array of PRInt32
// followed by a series of null-terminated strings:
//
// [argc][offsetargv0][offsetargv1...]<workingdir>\0<argv[0]>\0argv[1]...\0
// (offset is from the beginning of the buffer)
PRInt32 argc = *NS_REINTERPRET_CAST(PRInt32*, aBuffer);
char *wd = aBuffer + ((argc + 1) * sizeof(PRInt32));
#ifdef DEBUG_bsmedberg
printf("Receiving command line:\n"
" wd:\t%s\n"
" argc:\t%i\n",
wd, argc);
#endif
nsCOMPtr<nsILocalFile> lf;
rv = NS_NewNativeLocalFile(nsDependentCString(wd), PR_TRUE,
getter_AddRefs(lf));
if (NS_FAILED(rv))
return "509 internal error";
char **argv = (char**) malloc(sizeof(char*) * argc);
if (!argv) return "509 internal error";
PRInt32 *offset = NS_REINTERPRET_CAST(PRInt32*, aBuffer) + 1;
for (int i = 0; i < argc; ++i) {
argv[i] = aBuffer + offset[i];
#ifdef DEBUG_bsmedberg
printf(" argv[%i]:\t%s\n", i, argv[i]);
#endif
}
rv = cmdline->Init(argc, argv, lf, nsICommandLine::STATE_REMOTE_AUTO);
free (argv);
if (NS_FAILED(rv)) {
return "509 internal error";
}
if (aWindow)
cmdline->SetWindowContext(aWindow);
rv = cmdline->Run();
if (NS_ERROR_ABORT == rv)
return "500 command not parseable";
if (NS_FAILED(rv))
return "509 internal error";
return "200 executed command";
}
#endif // MOZ_XUL_APP
void
nsGTKRemoteService::HandleCommandsFor(GtkWidget* widget,
nsIWeakReference* aWindow)
{
#ifdef MOZ_WIDGET_GTK2
g_signal_connect(G_OBJECT(widget), "property_notify_event",
G_CALLBACK(HandlePropertyChange), aWindow);
#else // GTK+
gtk_signal_connect(GTK_OBJECT(widget), "property_notify_event",
GTK_SIGNAL_FUNC(HandlePropertyChange), aWindow);
#endif
gtk_widget_add_events(widget, GDK_PROPERTY_CHANGE_MASK);
Window window = GDK_WINDOW_XWINDOW(widget->window);
// set our version
XChangeProperty(GDK_DISPLAY(), window, sMozVersionAtom, XA_STRING,
8, PropModeReplace, kRemoteVersion, sizeof(kRemoteVersion) - 1);
// get our username
unsigned char *logname;
logname = (unsigned char*) PR_GetEnv("LOGNAME");
if (logname) {
// set the property on the window if it's available
XChangeProperty(GDK_DISPLAY(), window, sMozUserAtom, XA_STRING,
8, PropModeReplace, logname, strlen((char*) logname));
}
XChangeProperty(GDK_DISPLAY(), window, sMozProgramAtom, XA_STRING,
8, PropModeReplace, (unsigned char*) mAppName.get(), mAppName.Length());
if (!mProfileName.IsEmpty()) {
XChangeProperty(GDK_DISPLAY(), window, sMozProfileAtom, XA_STRING,
8, PropModeReplace, (unsigned char*) mProfileName.get(), mProfileName.Length());
}
}
#ifdef MOZ_WIDGET_GTK2
#define CMP_GATOM_XATOM(gatom,xatom) (gatom == gdk_x11_xatom_to_atom(xatom))
#else
#define CMP_GATOM_XATOM(gatom,xatom) (gatom == xatom)
#endif
gboolean
nsGTKRemoteService::HandlePropertyChange(GtkWidget *aWidget,
GdkEventProperty *pevent,
nsIWeakReference* aThis)
{
nsCOMPtr<nsIDOMWindow> window (do_QueryReferent(aThis));
if (pevent->state == GDK_PROPERTY_NEW_VALUE &&
CMP_GATOM_XATOM(pevent->atom, sMozCommandAtom)) {
// We got a new command atom.
int result;
Atom actual_type;
int actual_format;
unsigned long nitems, bytes_after;
char *data = 0;
result = XGetWindowProperty (GDK_DISPLAY(),
GDK_WINDOW_XWINDOW(pevent->window),
sMozCommandAtom,
0, /* long_offset */
(65536 / sizeof (long)), /* long_length */
True, /* atomic delete after */
XA_STRING, /* req_type */
&actual_type, /* actual_type return */
&actual_format, /* actual_format_return */
&nitems, /* nitems_return */
&bytes_after, /* bytes_after_return */
(unsigned char **)&data); /* prop_return
(we only care
about the first ) */
#ifdef DEBUG_bsmedberg
printf("Handling command: %s\n", data);
#endif
// Failed to get property off the window?
if (result != Success)
return FALSE;
// Failed to get the data off the window or it was the wrong type?
if (!data || !*data)
return FALSE;
// cool, we got the property data.
const char *response = HandleCommand(data, window);
// put the property onto the window as the response
XChangeProperty (GDK_DISPLAY(), GDK_WINDOW_XWINDOW(pevent->window),
sMozResponseAtom, XA_STRING,
8, PropModeReplace, (const unsigned char *)response, strlen (response));
XFree(data);
return TRUE;
}
#ifdef MOZ_XUL_APP
if (pevent->state == GDK_PROPERTY_NEW_VALUE &&
CMP_GATOM_XATOM(pevent->atom, sMozCommandLineAtom)) {
// We got a new commandline atom.
int result;
Atom actual_type;
int actual_format;
unsigned long nitems, bytes_after;
char *data = 0;
result = XGetWindowProperty (GDK_DISPLAY(),
GDK_WINDOW_XWINDOW(pevent->window),
sMozCommandLineAtom,
0, /* long_offset */
(65536 / sizeof (long)), /* long_length */
True, /* atomic delete after */
XA_STRING, /* req_type */
&actual_type, /* actual_type return */
&actual_format, /* actual_format_return */
&nitems, /* nitems_return */
&bytes_after, /* bytes_after_return */
(unsigned char **)&data); /* prop_return
(we only care
about the first ) */
// Failed to get property off the window?
if (result != Success)
return FALSE;
// Failed to get the data off the window or it was the wrong type?
if (!data || !*data)
return FALSE;
// cool, we got the property data.
const char *response = HandleCommandLine(data, window);
// put the property onto the window as the response
XChangeProperty (GDK_DISPLAY(), GDK_WINDOW_XWINDOW(pevent->window),
sMozResponseAtom, XA_STRING,
8, PropModeReplace, (const unsigned char *)response, strlen (response));
XFree(data);
return TRUE;
}
#endif //MOZ_XUL_APP
if (pevent->state == GDK_PROPERTY_NEW_VALUE &&
CMP_GATOM_XATOM(pevent->atom, sMozResponseAtom)) {
// client accepted the response. party on wayne.
return TRUE;
}
if (pevent->state == GDK_PROPERTY_NEW_VALUE &&
CMP_GATOM_XATOM(pevent->atom, sMozLockAtom)) {
// someone locked the window
return TRUE;
}
return FALSE;
}
Atom nsGTKRemoteService::sMozVersionAtom;
Atom nsGTKRemoteService::sMozLockAtom;
Atom nsGTKRemoteService::sMozCommandAtom;
Atom nsGTKRemoteService::sMozResponseAtom;
Atom nsGTKRemoteService::sMozUserAtom;
Atom nsGTKRemoteService::sMozProfileAtom;
Atom nsGTKRemoteService::sMozProgramAtom;
Atom nsGTKRemoteService::sMozCommandLineAtom;
// {C0773E90-5799-4eff-AD03-3EBCD85624AC}
#define NS_REMOTESERVICE_CID \
{ 0xc0773e90, 0x5799, 0x4eff, { 0xad, 0x3, 0x3e, 0xbc, 0xd8, 0x56, 0x24, 0xac } }
NS_GENERIC_FACTORY_CONSTRUCTOR(nsGTKRemoteService)
static const nsModuleComponentInfo components[] =
{
{ "Remote Service",
NS_REMOTESERVICE_CID,
"@mozilla.org/toolkit/remote-service;1",
nsGTKRemoteServiceConstructor
}
};
NS_IMPL_NSGETMODULE(RemoteServiceModule, components)

Просмотреть файл

@ -0,0 +1,108 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Christopher Blizzard.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Christopher Blizzard <blizzard@mozilla.org>
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __nsGTKRemoteService_h__
#define __nsGTKRemoteService_h__
#include "nsIRemoteService.h"
#include "nsIObserver.h"
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include "nsString.h"
#include "nsInterfaceHashtable.h"
class nsIDOMWindow;
class nsIWeakReference;
class nsIWidget;
class nsGTKRemoteService : public nsIRemoteService,
public nsIObserver
{
public:
// We will be a static singleton, so don't use the ordinary methods.
NS_DECL_ISUPPORTS
NS_DECL_NSIREMOTESERVICE
NS_DECL_NSIOBSERVER
nsGTKRemoteService() :
mServerWindow(NULL) { }
private:
~nsGTKRemoteService() { }
void HandleCommandsFor(GtkWidget* aWidget,
nsIWeakReference* aWindow);
static void EnsureAtoms();
static PLDHashOperator StartupHandler(const void* aKey,
nsIWeakReference* aData,
void* aData);
static const char* HandleCommand(char* aCommand, nsIDOMWindow* aWindow);
#ifdef MOZ_XUL_APP
static const char* HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow);
#endif
static gboolean HandlePropertyChange(GtkWidget *widget,
GdkEventProperty *event,
nsIWeakReference* aThis);
GtkWidget* mServerWindow;
nsCString mAppName;
nsCString mProfileName;
nsInterfaceHashtable<nsVoidPtrHashKey, nsIWeakReference> mWindows;
static Atom sMozVersionAtom;
static Atom sMozLockAtom;
static Atom sMozCommandAtom;
static Atom sMozResponseAtom;
static Atom sMozUserAtom;
static Atom sMozProfileAtom;
static Atom sMozProgramAtom;
static Atom sMozCommandLineAtom;
};
#endif // __nsGTKRemoteService_h__

Просмотреть файл

@ -0,0 +1,78 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Christopher Blizzard <blizzard@mozilla.org>. Portions created by Christopher Blizzard are Copyright (C) Christopher Blizzard. All Rights Reserved.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIDOMWindow;
/**
* Start and stop the remote service (xremote/phremote), and register
* windows with the service for backwards compatibility with old xremote
* clients.
*
* @status FLUID This interface is not frozen and is not intended for embedders
* who want a frozen API. If you are an embedder and need this
* functionality, contact Benjamin Smedberg about the possibility
* of freezing the functionality you need.
*/
[scriptable, uuid(a2240f6a-f1e4-4548-9e1a-6f3bc9b2426c)]
interface nsIRemoteService : nsISupports
{
/**
* Start the remote service. This should not be done until app startup
* appears to have been successful.
*
* @param appName (Required) Sets a window property identifying the
* application.
* @param profileName (May be null) Sets a window property identifying the
* profile name.
*/
void startup(in string appName, in string profileName);
/**
* Register a XUL window with the xremote service. The window will be
* configured to accept incoming remote requests. If this method is called
* before startup(), the registration will happen once startup() is called.
*/
void registerWindow(in nsIDOMWindow aWindow);
/**
* Stop the remote service from accepting additional requests.
*/
void shutdown();
};

Просмотреть файл

@ -221,9 +221,6 @@ endif
ifdef MOZ_ENABLE_PHOTON
COMPONENT_LIBS += widget_photon
endif
ifdef MOZ_ENABLE_XREMOTE
COMPONENT_LIBS += xremote_client
endif
ifdef MOZ_OJI
STATIC_LIBS += jsj

Просмотреть файл

@ -131,12 +131,6 @@
#define XPRINT_MODULES
#endif
#ifdef MOZ_ENABLE_XREMOTE
#define XREMOTE_MODULES MODULE(XRemoteClientModule)
#else
#define XREMOTE_MODULES
#endif
#ifdef OJI
#define OJI_MODULES MODULE(nsCJVMManagerModule)
#else
@ -167,7 +161,6 @@
POSTSCRIPT_MODULES \
GFX_MODULES \
WIDGET_MODULES \
XREMOTE_MODULES \
MODULE(nsImageLib2Module) \
ICON_MODULE \
MODULE(nsPluginModule) \

Просмотреть файл

@ -153,6 +153,11 @@ endif
SHARED_LIBRARY_LIBS += ../profile/src/$(LIB_PREFIX)profile_s.$(LIB_SUFFIX)
ifdef MOZ_ENABLE_XREMOTE
SHARED_LIBRARY_LIBS += $(DEPTH)/widget/src/xremoteclient/$(LIB_PREFIX)xremote_client_s.$(LIB_SUFFIX)
LOCAL_INCLUDES += -I$(topsrcdir)/widget/src/xremoteclient
endif
include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES += -I$(topsrcdir)/xpfe/bootstrap -I$(srcdir)/../profile/src

Просмотреть файл

@ -102,6 +102,7 @@
#include "nsAppDirectoryServiceDefs.h"
#include "nsXULAppAPI.h"
#include "nsXREDirProvider.h"
#include "nsToolkitCompsCID.h"
#include "nsINIParser.h"
@ -130,9 +131,12 @@
// for X remote support
#ifdef MOZ_ENABLE_XREMOTE
#include "nsXRemoteClientCID.h"
#include "nsIXRemoteClient.h"
#include "nsIXRemoteService.h"
#ifdef MOZ_WIDGET_PHOTON
#include "PhRemoteClient.h"
#else
#include "XRemoteClient.h"
#endif
#include "nsIRemoteService.h"
#endif
#ifdef NS_TRACE_MALLOC
@ -906,44 +910,73 @@ HandleRemoteArgument(const char* remote)
return 1;
}
// start XPCOM
ScopedXPCOMStartup xpcom;
rv = xpcom.Initialize();
NS_ENSURE_SUCCESS(rv, 1);
XRemoteClient client;
rv = client.Init();
if (NS_FAILED(rv)) {
PR_fprintf(PR_STDERR, "Error: Failed to connect to X server.\n");
return 1;
}
{ // scope the comptr so we don't hold on to XPCOM objects beyond shutdown
// try to get the X remote client
nsCOMPtr<nsIXRemoteClient> client (do_CreateInstance(NS_XREMOTECLIENT_CONTRACTID));
NS_ENSURE_TRUE(client, 1);
nsXPIDLCString response;
PRBool success = PR_FALSE;
rv = client.SendCommand(program.get(), username, profile, remote,
getter_Copies(response), &success);
// did the command fail?
if (NS_FAILED(rv)) {
PR_fprintf(PR_STDERR, "Error: Failed to send command: %s\n",
response ? response.get() : "No response included");
return 1;
}
// try to init - connects to the X server and stuff
rv = client->Init();
if (NS_FAILED(rv)) {
PR_fprintf(PR_STDERR, "Error: Failed to connect to X server.\n");
return 1;
}
nsXPIDLCString response;
PRBool success = PR_FALSE;
rv = client->SendCommand(program.get(), username, profile, remote,
getter_Copies(response), &success);
// did the command fail?
if (NS_FAILED(rv)) {
PR_fprintf(PR_STDERR, "Error: Failed to send command: %s\n",
response ? response.get() : "No response included");
return 1;
}
if (!success) {
PR_fprintf(PR_STDERR, "Error: No running window found\n");
return 2;
}
client->Shutdown();
if (!success) {
PR_fprintf(PR_STDERR, "Error: No running window found\n");
return 2;
}
return 0;
}
static PRBool
RemoteCommandLine()
{
nsresult rv;
ArgResult ar;
nsCAutoString program(gAppData->appName);
ToLowerCase(program);
const char *username = getenv("LOGNAME");
const char *temp = nsnull;
ar = CheckArg("a", &temp);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
return PR_FALSE;
} else if (ar == ARG_FOUND) {
program.Assign(temp);
}
ar = CheckArg("u", &username);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
return PR_FALSE;
}
XRemoteClient client;
rv = client.Init();
if (NS_FAILED(rv))
return PR_FALSE;
nsXPIDLCString response;
PRBool success = PR_FALSE;
rv = client.SendCommandLine(program.get(), username, nsnull,
gArgc, gArgv,
getter_Copies(response), &success);
// did the command fail?
if (NS_FAILED(rv) || !success)
return PR_FALSE;
return PR_TRUE;
}
#endif // MOZ_ENABLE_XREMOTE
#if defined(XP_UNIX) && !defined(XP_MACOSX)
@ -1768,6 +1801,10 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
if (ar) {
return HandleRemoteArgument(xremotearg);
}
// Try to remote the entire command line. If this fails, start up normally.
if (RemoteCommandLine())
return 0;
#endif
nsCOMPtr<nsIProfileLock> profileLock;
@ -1990,10 +2027,10 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
#ifdef MOZ_ENABLE_XREMOTE
// if we have X remote support and we have our one window up and
// running start listening for requests on the proxy window.
nsCOMPtr<nsIXRemoteService> remoteService;
remoteService = do_GetService(NS_IXREMOTESERVICE_CONTRACTID);
nsCOMPtr<nsIRemoteService> remoteService;
remoteService = do_GetService("@mozilla.org/toolkit/remote-service;1");
if (remoteService)
remoteService->Startup(aAppData->appName);
remoteService->Startup(gAppData->appName, nsnull);
#endif /* MOZ_ENABLE_XREMOTE */
// enable win32 DDE responses and Mac appleevents responses

Просмотреть файл

@ -69,7 +69,6 @@ EXPORTS = \
nsIDragSessionXlib.h \
nsIDragSessionMac.h \
nsIDragSessionOS2.h \
nsIXRemoteWidgetHelper.h \
nsIPluginWidget.h \
nsINativeKeyBindings.h \
$(NULL)
@ -101,7 +100,6 @@ XPIDLSRCS = \
nsIMenuRollup.idl \
nsIBaseWindow.idl \
nsIBidiKeyboard.idl \
nsIXRemoteClient.idl \
nsIFullScreen.idl \
nsINativeScrollbar.idl \
$(NULL)

Просмотреть файл

@ -90,6 +90,7 @@ typedef nsEventStatus (*PR_CALLBACK EVENT_CALLBACK)(nsGUIEvent *event);
#define NS_NATIVE_OFFSETY 7
#define NS_NATIVE_PLUGIN_PORT 8
#define NS_NATIVE_SCREEN 9
#define NS_NATIVE_SHELLWIDGET 10 // Get the shell GtkWidget
// {18032AD5-B265-11d1-AA2A-000000000000}
#define NS_IWIDGET_IID \

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -94,9 +94,5 @@ ifdef MOZ_ENABLE_PHOTON
DIRS += photon
endif
ifdef MOZ_ENABLE_XREMOTE
DIRS += xremoteclient
endif
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -60,7 +60,6 @@ REQUIRES = xpcom \
dom \
uconv \
necko \
xremoteservice \
view \
util \
unicharutil \
@ -92,7 +91,6 @@ CPPSRCS = \
nsWidgetFactory.cpp \
nsWindow.cpp \
nsGtkIMEHelper.cpp \
nsGtkMozRemoteHelper.cpp \
$(NULL)
SHARED_LIBRARY_LIBS = $(DIST)/lib/libxpwidgets_s.a

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -57,7 +57,6 @@
#include "nsHTMLFormatConverter.h"
#include "nsDragService.h"
#include "nsSound.h"
#include "nsGtkMozRemoteHelper.h"
#include "nsBidiKeyboard.h"
#include "nsGtkIMEHelper.h"
@ -77,7 +76,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsGtkXRemoteWidgetHelper)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
static const nsModuleComponentInfo components[] =
@ -146,10 +144,6 @@ static const nsModuleComponentInfo components[] =
// "@mozilla.org/widget/dragservice/gtk;1",
"@mozilla.org/widget/dragservice;1",
nsDragServiceConstructor },
{ NS_IXREMOTEWIDGETHELPER_CLASSNAME,
NS_GTKXREMOTEWIDGETHELPER_CID,
NS_IXREMOTEWIDGETHELPER_CONTRACTID,
nsGtkXRemoteWidgetHelperConstructor },
{ "Gtk Bidi Keyboard",
NS_BIDIKEYBOARD_CID,
"@mozilla.org/widget/bidikeyboard;1",

Просмотреть файл

@ -79,8 +79,6 @@
#include "nsGtkUtils.h" // for nsGtkUtils::gdk_window_flash()
#include "nsGtkMozRemoteHelper.h"
#include "nsIDragService.h"
#include "nsIDragSessionGTK.h"
@ -159,11 +157,6 @@ void handle_toplevel_configure (
GtkMozArea * aArea,
nsWindow * aWindow);
gboolean handle_toplevel_property_change (
GtkWidget *aGtkWidget,
GdkEventProperty *event,
nsWindow *aWindow);
// are we grabbing?
PRBool nsWindow::sIsGrabbing = PR_FALSE;
nsWindow *nsWindow::sGrabWindow = NULL;
@ -1984,12 +1977,7 @@ NS_METHOD nsWindow::CreateNative(GtkObject *parentWidget)
// set up all the focus handling
if (mShell) {
gtk_signal_connect(GTK_OBJECT(mShell),
"property_notify_event",
GTK_SIGNAL_FUNC(handle_toplevel_property_change),
this);
mask = (GdkEventMask) (GDK_PROPERTY_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
mask = (GdkEventMask) (GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_FOCUS_CHANGE_MASK );
gdk_window_set_events(mShell->window,
@ -2203,6 +2191,9 @@ void * nsWindow::GetNativeData(PRUint32 aDataType)
}
return NULL;
}
else if (aDataType == NS_NATIVE_SHELLWIDGET) {
return (void *) mShell;
}
return nsWidget::GetNativeData(aDataType);
}
@ -2897,17 +2888,6 @@ void handle_toplevel_configure (
aWindow->OnMove(x, y);
}
gboolean handle_toplevel_property_change (
GtkWidget *aGtkWidget,
GdkEventProperty *event,
nsWindow *aWindow)
{
nsIWidget *widget = NS_STATIC_CAST(nsIWidget *, aWindow);
return nsGtkMozRemoteHelper::HandlePropertyChange(aGtkWidget, event,
widget);
}
void
nsWindow::HandleXlibConfigureNotifyEvent(XEvent *event)
{

Просмотреть файл

@ -61,7 +61,6 @@ REQUIRES = xpcom \
uconv \
intl \
gtkxtbin \
xremoteservice \
imglib2 \
$(NULL)
@ -80,7 +79,6 @@ CPPSRCS = \
nsCommonWidget.cpp \
nsLookAndFeel.cpp \
nsGtkKeyUtils.cpp \
nsGtkMozRemoteHelper.cpp \
nsClipboard.cpp \
nsDragService.cpp \
nsFilePicker.cpp \

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -42,7 +42,6 @@
#include "nsBaseWidget.h"
#include "nsLookAndFeel.h"
#include "nsWindow.h"
#include "nsGtkMozRemoteHelper.h"
#include "nsTransferable.h"
#include "nsClipboardHelper.h"
#include "nsHTMLFormatConverter.h"
@ -71,7 +70,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppShell)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsLookAndFeel)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsGtkXRemoteWidgetHelper)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsClipboard, Init)
@ -171,10 +169,6 @@ static const nsModuleComponentInfo components[] =
NS_SOUND_CID,
"@mozilla.org/sound;1",
nsSoundConstructor },
{ NS_IXREMOTEWIDGETHELPER_CLASSNAME,
NS_GTKXREMOTEWIDGETHELPER_CID,
NS_IXREMOTEWIDGETHELPER_CONTRACTID,
nsGtkXRemoteWidgetHelperConstructor },
{ "Transferable",
NS_TRANSFERABLE_CID,
"@mozilla.org/widget/transferable;1",

Просмотреть файл

@ -52,7 +52,6 @@
#include "nsGtkKeyUtils.h"
#include "nsGtkCursors.h"
#include "nsGtkMozRemoteHelper.h"
#include <gtk/gtkwindow.h>
#include <gdk/gdkx.h>
@ -150,8 +149,6 @@ static gboolean visibility_notify_event_cb(GtkWidget *widget,
GdkEventVisibility *event);
static gboolean window_state_event_cb (GtkWidget *widget,
GdkEventWindowState *event);
static gboolean property_notify_event_cb (GtkWidget *widget,
GdkEventProperty *event);
static void style_set_cb (GtkWidget *widget,
GtkStyle *previous_style,
gpointer data);
@ -1053,6 +1050,9 @@ nsWindow::GetNativeData(PRUint32 aDataType)
break;
}
case NS_NATIVE_SHELLWIDGET:
return (void *) mShell;
default:
NS_WARNING("nsWindow::GetNativeData called with bad value");
return nsnull;
@ -2412,14 +2412,8 @@ nsWindow::NativeCreate(nsIWidget *aParent,
G_CALLBACK(configure_event_cb), NULL);
g_signal_connect(G_OBJECT(mShell), "delete_event",
G_CALLBACK(delete_event_cb), NULL);
// we need to add this to the shell since versions of gtk
// before 2.0.3 forgot to set property_notify events on the
// shell window
gtk_widget_add_events(mShell, GDK_PROPERTY_CHANGE_MASK);
g_signal_connect(G_OBJECT(mShell), "window_state_event",
G_CALLBACK(window_state_event_cb), NULL);
g_signal_connect(G_OBJECT(mShell), "property_notify_event",
G_CALLBACK(property_notify_event_cb), NULL);
g_signal_connect(G_OBJECT(mShell), "style_set",
G_CALLBACK(style_set_cb), NULL);
}
@ -3892,19 +3886,6 @@ window_state_event_cb (GtkWidget *widget, GdkEventWindowState *event)
return FALSE;
}
/* static */
gboolean
property_notify_event_cb (GtkWidget *widget, GdkEventProperty *event)
{
nsIWidget *nswidget = (nsIWidget *)get_window_for_gtk_widget(widget);
if (!nswidget)
return FALSE;
nsGtkMozRemoteHelper::HandlePropertyChange(widget, event, nswidget);
return FALSE;
}
/* static */
void
style_set_cb (GtkWidget *widget, GtkStyle *previous_style, gpointer data)

Просмотреть файл

Просмотреть файл

@ -35,6 +35,10 @@
#
# ***** END LICENSE BLOCK *****
# NOTE: This directory is part of tier 50, and is linked directly into
# the application binaries. The fact that it's under mozilla/widget is a fluke
# of tree history.
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
@ -42,21 +46,13 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = widget
LIBRARY_NAME = xremote_client
EXPORT_LIBRARY = 1
IS_COMPONENT = 1
MODULE_NAME = XRemoteClientModule
LIBXUL_LIBRARY = 1
MODULE = xremoteclient
LIBRARY_NAME = xremote_client_s
FORCE_STATIC_LIB = 1
PACKAGE_FILE = xremoteclient.pkg
REQUIRES = xpcom \
$(NULL)
CPPSRCS = \
XRemoteClientFactory.cpp \
$(NULL)
REQUIRES = \
xpcom \
$(NULL)
ifdef MOZ_ENABLE_PHOTON
CPPSRCS += PhRemoteClient.cpp
@ -73,9 +69,6 @@ ifdef MOZ_ENABLE_PHOTON
EXTRA_DSO_LDOPTS += -lph
endif
EXPORTS = \
nsXRemoteClientCID.h
PROGRAM = mozilla-xremote-client$(BIN_SUFFIX)
PROGOBJS = mozilla-xremote-client.$(OBJ_SUFFIX) \
@ -101,8 +94,8 @@ endif
ifndef MOZ_ENABLE_PHOTON
XRemoteClient_standalone.$(OBJ_SUFFIX): XRemoteClient.cpp
$(CXX) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) -DXREMOTE_STANDALONE $<
$(CXX) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $<
else
XRemoteClient_standalone.$(OBJ_SUFFIX): PhRemoteClient.cpp
$(CXX) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) -DXREMOTE_STANDALONE $<
$(CXX) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $<
endif

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* vim:set ts=8 sw=2 et cindent: */
@ -45,8 +45,10 @@
#include "prsystem.h"
#include "prlog.h"
#include "prenv.h"
#include "prdtoa.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/time.h>
#include <sys/types.h>
@ -59,11 +61,16 @@
#define MOZILLA_VERSION_PROP "_MOZILLA_VERSION"
#define MOZILLA_LOCK_PROP "_MOZILLA_LOCK"
#define MOZILLA_COMMAND_PROP "_MOZILLA_COMMAND"
#define MOZILLA_COMMANDLINE_PROP "_MOZILLA_COMMANDLINE"
#define MOZILLA_RESPONSE_PROP "_MOZILLA_RESPONSE"
#define MOZILLA_USER_PROP "_MOZILLA_USER"
#define MOZILLA_PROFILE_PROP "_MOZILLA_PROFILE"
#define MOZILLA_PROGRAM_PROP "_MOZILLA_PROGRAM"
#ifndef MAX_PATH
#define MAX_PATH 1024
#endif
#define ARRAY_LENGTH(array_) (sizeof(array_)/sizeof(array_[0]))
static PRLogModuleInfo *sRemoteLm = NULL;
@ -91,10 +98,6 @@ XRemoteClient::~XRemoteClient()
Shutdown();
}
#ifndef XREMOTE_STANDALONE
NS_IMPL_ISUPPORTS1(XRemoteClient, nsIXRemoteClient)
#endif
// Minimize the roundtrips to the X-server
static char *XAtomNames[] = {
MOZILLA_VERSION_PROP,
@ -104,17 +107,19 @@ static char *XAtomNames[] = {
"WM_STATE",
MOZILLA_USER_PROP,
MOZILLA_PROFILE_PROP,
MOZILLA_PROGRAM_PROP
MOZILLA_PROGRAM_PROP,
MOZILLA_COMMANDLINE_PROP
};
static Atom XAtoms[ARRAY_LENGTH(XAtomNames)];
NS_IMETHODIMP
XRemoteClient::Init (void)
nsresult
XRemoteClient::Init()
{
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("XRemoteClient::Init"));
if (mInitialized)
return NS_OK;
// try to open the display
mDisplay = XOpenDisplay(0);
if (!mDisplay)
@ -132,19 +137,21 @@ XRemoteClient::Init (void)
mMozUserAtom = XAtoms[i++];
mMozProfileAtom = XAtoms[i++];
mMozProgramAtom = XAtoms[i++];
mMozCommandLineAtom = XAtoms[i++];
mInitialized = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
void
XRemoteClient::Shutdown (void)
{
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("XRemoteClient::Shutdown"));
if (!mInitialized)
return NS_OK;
return;
// shut everything down
XCloseDisplay(mDisplay);
mDisplay = 0;
@ -153,10 +160,9 @@ XRemoteClient::Shutdown (void)
free(mLockData);
mLockData = 0;
}
return NS_OK;
}
NS_IMETHODIMP
nsresult
XRemoteClient::SendCommand (const char *aProgram, const char *aUsername,
const char *aProfile, const char *aCommand,
char **aResponse, PRBool *aWindowFound)
@ -165,7 +171,7 @@ XRemoteClient::SendCommand (const char *aProgram, const char *aUsername,
*aWindowFound = PR_FALSE;
Window w = FindBestWindow(aProgram, aUsername, aProfile);
Window w = FindBestWindow(aProgram, aUsername, aProfile, PR_FALSE);
nsresult rv = NS_OK;
@ -199,6 +205,50 @@ XRemoteClient::SendCommand (const char *aProgram, const char *aUsername,
return rv;
}
nsresult
XRemoteClient::SendCommandLine (const char *aProgram, const char *aUsername,
const char *aProfile,
PRInt32 argc, char **argv,
char **aResponse, PRBool *aWindowFound)
{
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("XRemoteClient::SendCommandLine"));
*aWindowFound = PR_FALSE;
Window w = FindBestWindow(aProgram, aUsername, aProfile, PR_TRUE);
nsresult rv = NS_OK;
if (w) {
// ok, let the caller know that we at least found a window.
*aWindowFound = PR_TRUE;
// make sure we get the right events on that window
XSelectInput(mDisplay, w,
(PropertyChangeMask|StructureNotifyMask));
PRBool destroyed = PR_FALSE;
// get the lock on the window
rv = GetLock(w, &destroyed);
if (NS_SUCCEEDED(rv)) {
// send our command
rv = DoSendCommandLine(w, argc, argv, aResponse, &destroyed);
// if the window was destroyed, don't bother trying to free the
// lock.
if (!destroyed)
FreeLock(w); // doesn't really matter what this returns
}
}
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("SendCommandLine returning 0x%x\n", rv));
return rv;
}
Window
XRemoteClient::CheckWindow(Window aWindow)
{
@ -389,7 +439,8 @@ XRemoteClient::GetLock(Window aWindow, PRBool *aDestroyed)
Window
XRemoteClient::FindBestWindow(const char *aProgram, const char *aUsername,
const char *aProfile)
const char *aProfile,
PRBool aSupportsCommandLine)
{
Window root = RootWindowOfScreen(DefaultScreenOfDisplay(mDisplay));
Window bestWindow = 0;
@ -432,7 +483,12 @@ XRemoteClient::FindBestWindow(const char *aProgram, const char *aUsername,
if (!data_return)
continue;
PRFloat64 version = PR_strtod((char*) data_return, nsnull);
XFree(data_return);
if (aSupportsCommandLine && !(version >= 5.1 && version < 6))
continue;
data_return = 0;
if (status != Success || type == None)
@ -518,6 +574,9 @@ XRemoteClient::FindBestWindow(const char *aProgram, const char *aUsername,
}
}
// Check to see if the window supports the new command-line passing
// protocol, if that is requested.
// If we got this far, this is the best window so far. It passed
// all the tests.
bestWindow = w;
@ -571,129 +630,208 @@ nsresult
XRemoteClient::DoSendCommand(Window aWindow, const char *aCommand,
char **aResponse, PRBool *aDestroyed)
{
PRBool done = PR_FALSE;
PRBool accepted = PR_FALSE;
*aDestroyed = PR_FALSE;
PR_LOG(sRemoteLm, PR_LOG_DEBUG,
("(writing " MOZILLA_COMMAND_PROP " \"%s\" to 0x%x)\n",
aCommand, (unsigned int) aWindow));
("(writing " MOZILLA_COMMAND_PROP " \"%s\" to 0x%x)\n",
aCommand, (unsigned int) aWindow));
XChangeProperty (mDisplay, aWindow, mMozCommandAtom, XA_STRING, 8,
PropModeReplace, (unsigned char *)aCommand,
strlen(aCommand));
PropModeReplace, (unsigned char *)aCommand,
strlen(aCommand));
if (!WaitForResponse(aWindow, aResponse, aDestroyed, mMozCommandAtom))
return NS_ERROR_FAILURE;
return NS_OK;
}
/* like strcpy, but return the char after the final null */
static char*
estrcpy(char* s, char* d)
{
while (*s)
*d++ = *s++;
*d++ = '\0';
return d;
}
nsresult
XRemoteClient::DoSendCommandLine(Window aWindow, PRInt32 argc, char **argv,
char **aResponse, PRBool *aDestroyed)
{
int i;
*aDestroyed = PR_FALSE;
char cwdbuf[MAX_PATH];
if (!getcwd(cwdbuf, MAX_PATH))
return NS_ERROR_UNEXPECTED;
// the commandline property is constructed as an array of PRInt32
// followed by a series of null-terminated strings:
//
// [argc][offsetargv0][offsetargv1...]<workingdir>\0<argv[0]>\0argv[1]...\0
// (offset is from the beginning of the buffer)
PRInt32 argvlen = strlen(cwdbuf);
for (i = 0; i < argc; ++i)
argvlen += strlen(argv[i]);
PRInt32* buffer = (PRInt32*) malloc(argvlen + argc + 1 +
sizeof(PRInt32) * (argc + 1));
if (!buffer)
return NS_ERROR_OUT_OF_MEMORY;
buffer[0] = argc;
char *bufend = (char*) (buffer + argc + 1);
bufend = estrcpy(cwdbuf, bufend);
for (int i = 0; i < argc; ++i) {
buffer[i + 1] = bufend - ((char*) buffer);
bufend = estrcpy(argv[i], bufend);
}
#ifdef DEBUG_bsmedberg
PRInt32 debug_argc = *buffer;
char *debug_workingdir = (char*) (buffer + argc + 1);
printf("Sending command line:\n"
" working dir: %s\n"
" argc:\t%i",
debug_workingdir,
debug_argc);
PRInt32 *debug_offset = buffer + 1;
for (int debug_i = 0; debug_i < debug_argc; ++debug_i)
printf(" argv[%i]:\t%s\n", debug_i,
((char*) buffer) + debug_offset[debug_i]);
#endif
XChangeProperty (mDisplay, aWindow, mMozCommandLineAtom, XA_STRING, 8,
PropModeReplace, (unsigned char *) buffer,
bufend - ((char*) buffer));
if (!WaitForResponse(aWindow, aResponse, aDestroyed, mMozCommandLineAtom))
return NS_ERROR_FAILURE;
return NS_OK;
}
PRBool
XRemoteClient::WaitForResponse(Window aWindow, char **aResponse,
PRBool *aDestroyed, Atom aCommandAtom)
{
PRBool done = PR_FALSE;
PRBool accepted = PR_FALSE;
while (!done) {
XEvent event;
XNextEvent (mDisplay, &event);
if (event.xany.type == DestroyNotify &&
event.xdestroywindow.window == aWindow) {
event.xdestroywindow.window == aWindow) {
/* Print to warn user...*/
PR_LOG(sRemoteLm, PR_LOG_DEBUG,
("window 0x%x was destroyed.\n",
(unsigned int) aWindow));
("window 0x%x was destroyed.\n",
(unsigned int) aWindow));
*aResponse = strdup("Window was destroyed while reading response.");
*aDestroyed = PR_TRUE;
goto DONE;
return PR_FALSE;
}
else if (event.xany.type == PropertyNotify &&
event.xproperty.state == PropertyNewValue &&
event.xproperty.window == aWindow &&
event.xproperty.atom == mMozResponseAtom) {
event.xproperty.state == PropertyNewValue &&
event.xproperty.window == aWindow &&
event.xproperty.atom == mMozResponseAtom) {
Atom actual_type;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char *data = 0;
Bool result;
result = XGetWindowProperty (mDisplay, aWindow, mMozResponseAtom,
0, (65536 / sizeof (long)),
True, /* atomic delete after */
XA_STRING,
&actual_type, &actual_format,
&nitems, &bytes_after,
&data);
0, (65536 / sizeof (long)),
True, /* atomic delete after */
XA_STRING,
&actual_type, &actual_format,
&nitems, &bytes_after,
&data);
if (result != Success) {
PR_LOG(sRemoteLm, PR_LOG_DEBUG,
("failed reading " MOZILLA_RESPONSE_PROP
" from window 0x%0x.\n",
(unsigned int) aWindow));
*aResponse = strdup("Internal error reading response from window.");
done = PR_TRUE;
PR_LOG(sRemoteLm, PR_LOG_DEBUG,
("failed reading " MOZILLA_RESPONSE_PROP
" from window 0x%0x.\n",
(unsigned int) aWindow));
*aResponse = strdup("Internal error reading response from window.");
done = PR_TRUE;
}
else if (!data || strlen((char *) data) < 5) {
PR_LOG(sRemoteLm, PR_LOG_DEBUG,
("invalid data on " MOZILLA_RESPONSE_PROP
" property of window 0x%0x.\n",
(unsigned int) aWindow));
*aResponse = strdup("Server returned invalid data in response.");
done = PR_TRUE;
PR_LOG(sRemoteLm, PR_LOG_DEBUG,
("invalid data on " MOZILLA_RESPONSE_PROP
" property of window 0x%0x.\n",
(unsigned int) aWindow));
*aResponse = strdup("Server returned invalid data in response.");
done = PR_TRUE;
}
else if (*data == '1') { /* positive preliminary reply */
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("%s\n", data + 4));
/* keep going */
done = PR_FALSE;
else if (*data == '1') { /* positive preliminary reply */
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("%s\n", data + 4));
/* keep going */
done = PR_FALSE;
}
else if (!strncmp ((char *)data, "200", 3)) { /* positive completion */
*aResponse = strdup((char *)data);
accepted = PR_TRUE;
done = PR_TRUE;
*aResponse = strdup((char *)data);
accepted = PR_TRUE;
done = PR_TRUE;
}
else if (*data == '2') { /* positive completion */
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("%s\n", data + 4));
*aResponse = strdup((char *)data);
accepted = PR_TRUE;
done = PR_TRUE;
else if (*data == '2') { /* positive completion */
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("%s\n", data + 4));
*aResponse = strdup((char *)data);
accepted = PR_TRUE;
done = PR_TRUE;
}
else if (*data == '3') { /* positive intermediate reply */
PR_LOG(sRemoteLm, PR_LOG_DEBUG,
("internal error: "
"server wants more information? (%s)\n",
data));
*aResponse = strdup((char *)data);
done = PR_TRUE;
else if (*data == '3') { /* positive intermediate reply */
PR_LOG(sRemoteLm, PR_LOG_DEBUG,
("internal error: "
"server wants more information? (%s)\n",
data));
*aResponse = strdup((char *)data);
done = PR_TRUE;
}
else if (*data == '4' || /* transient negative completion */
*data == '5') { /* permanent negative completion */
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("%s\n", data + 4));
*aResponse = strdup((char *)data);
done = PR_TRUE;
else if (*data == '4' || /* transient negative completion */
*data == '5') { /* permanent negative completion */
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("%s\n", data + 4));
*aResponse = strdup((char *)data);
done = PR_TRUE;
}
else {
PR_LOG(sRemoteLm, PR_LOG_DEBUG,
("unrecognised " MOZILLA_RESPONSE_PROP
" from window 0x%x: %s\n",
(unsigned int) aWindow, data));
*aResponse = strdup((char *)data);
done = PR_TRUE;
PR_LOG(sRemoteLm, PR_LOG_DEBUG,
("unrecognised " MOZILLA_RESPONSE_PROP
" from window 0x%x: %s\n",
(unsigned int) aWindow, data));
*aResponse = strdup((char *)data);
done = PR_TRUE;
}
if (data)
XFree(data);
XFree(data);
}
else if (event.xany.type == PropertyNotify &&
event.xproperty.window == aWindow &&
event.xproperty.state == PropertyDelete &&
event.xproperty.atom == mMozCommandAtom) {
event.xproperty.window == aWindow &&
event.xproperty.state == PropertyDelete &&
event.xproperty.atom == aCommandAtom) {
PR_LOG(sRemoteLm, PR_LOG_DEBUG,
("(server 0x%x has accepted "
MOZILLA_COMMAND_PROP ".)\n",
(unsigned int) aWindow));
("(server 0x%x has accepted "
MOZILLA_COMMAND_PROP ".)\n",
(unsigned int) aWindow));
}
}
DONE:
if (!accepted)
return NS_ERROR_FAILURE;
return NS_OK;
return accepted;
}

Просмотреть файл

@ -37,24 +37,23 @@
#include <X11/X.h>
#include <X11/Xlib.h>
#include "nsIXRemoteClient.h"
#include "nsRemoteClient.h"
class XRemoteClient
#ifndef XREMOTE_STANDALONE
: public nsIXRemoteClient
#endif
class XRemoteClient : public nsRemoteClient
{
public:
public:
XRemoteClient();
virtual ~XRemoteClient();
~XRemoteClient();
#ifndef XREMOTE_STANDALONE
// nsISupports
NS_DECL_ISUPPORTS
#endif
// nsIXRemoteClient
NS_DECL_NSIXREMOTECLIENT
virtual nsresult Init();
virtual nsresult SendCommand(const char *aProgram, const char *aUsername,
const char *aProfile, const char *aCommand,
char **aResponse, PRBool *aSucceeded);
virtual nsresult SendCommandLine(const char *aProgram, const char *aUsername,
const char *aProfile,
PRInt32 argc, char **argv,
char **aResponse, PRBool *aSucceeded);
void Shutdown();
private:
@ -62,23 +61,33 @@ private:
Window CheckChildren (Window aWindow);
nsresult GetLock (Window aWindow, PRBool *aDestroyed);
nsresult FreeLock (Window aWindow);
Window FindBestWindow (const char *aProgram, const char *aUsername,
const char *aProfile);
Window FindBestWindow (const char *aProgram,
const char *aUsername,
const char *aProfile,
PRBool aSupportsCommandLine);
nsresult DoSendCommand (Window aWindow,
const char *aCommand,
char **aResponse,
PRBool *aDestroyed);
const char *aCommand,
char **aResponse,
PRBool *aDestroyed);
nsresult DoSendCommandLine(Window aWindow,
PRInt32 argc, char **argv,
char **aResponse,
PRBool *aDestroyed);
PRBool WaitForResponse (Window aWindow, char **aResponse,
PRBool *aDestroyed, Atom aCommandAtom);
Display *mDisplay;
Atom mMozVersionAtom;
Atom mMozLockAtom;
Atom mMozCommandAtom;
Atom mMozCommandLineAtom;
Atom mMozResponseAtom;
Atom mMozWMStateAtom;
Atom mMozUserAtom;
Atom mMozProfileAtom;
Atom mMozProgramAtom;
Atom mMozSupportsCLAtom;
char *mLockData;

Просмотреть файл

@ -38,6 +38,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <plgetopt.h>
#ifdef MOZ_WIDGET_PHOTON
#include "PhRemoteClient.h"

Просмотреть файл

@ -0,0 +1,103 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Christopher Blizzard.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsRemoteClient_h__
#define nsRemoteClient_h__
#include "nscore.h"
/**
* Pure-virtual common base class for remoting implementations.
*/
class nsRemoteClient
{
public:
/**
* Initializes the client
*/
virtual nsresult Init() = 0;
/**
* Sends a command to a running instance.
*
* @param aProgram This is the preferred program that we want to use
* for this particular command.
*
* @param aNoProgramFallback This boolean attribute tells the client
* code that if the preferred program isn't found that it should
* fail not send the command to another server.
*
* @param aUsername This allows someone to only talk to an instance
* of the server that's running under a particular username. If
* this isn't specified here it's pulled from the LOGNAME
* environmental variable if it's set.
*
* @param aProfile This allows you to specify a particular server
* running under a named profile. If it is not specified the
* profile is not checked.
*
* @param aCommand This is the command that is passed to the server.
* Please see the additional information located at:
* http://www.mozilla.org/unix/remote.html
*
* @param aResponse If there is a response, it will be here. This
* includes error messages. The string is allocated using stdlib
* string functions, so free it with free().
*
* @retun true if succeeded, false if no running instance was found.
*/
virtual nsresult SendCommand(const char *aProgram, const char *aUsername,
const char *aProfile, const char *aCommand,
char **aResponse, PRBool *aSucceeded) = 0;
/**
* Send a complete command line to a running instance.
*
* @see sendCommand
* @param argc The number of command-line arguments.
*
*/
virtual nsresult SendCommandLine(const char *aProgram, const char *aUsername,
const char *aProfile,
PRInt32 argc, char **argv,
char **aResponse, PRBool *aSucceeded) = 0;
};
#endif // nsRemoteClient_h__

Просмотреть файл

Просмотреть файл

@ -82,6 +82,7 @@ REQUIRES = xpcom \
content \
pref \
appshell \
toolkitcomps \
appcomps \
gfx \
xpinstall \
@ -92,6 +93,7 @@ REQUIRES = xpcom \
locale \
profile \
chrome \
xremoteclient \
$(NULL)
# for jprof
REQUIRES += jprof
@ -344,6 +346,11 @@ ifneq (,$(filter-out OS2 WINNT,$(OS_ARCH)))
GARBAGE += $(STACKWALK_SRC_LCSRCS) $(wildcard *.$(OBJ_SUFFIX))
endif
ifdef MOZ_ENABLE_XREMOTE
LIBS += $(DEPTH)/widget/src/xremoteclient/$(LIB_PREFIX)xremote_client_s.$(LIB_SUFFIX)
LOCAL_INCLUDES += -I$(topsrcdir)/widget/src/xremoteclient
endif
include $(topsrcdir)/config/rules.mk
ifneq (,$(filter-out OS2 WINNT,$(OS_ARCH)))
@ -384,7 +391,7 @@ endif
CXXFLAGS += $(MOZ_TOOLKIT_REGISTRY_CFLAGS)
LOCAL_INCLUDES = -I$(srcdir) -I.
LOCAL_INCLUDES += -I$(srcdir) -I.
ifneq (,$(filter-out OS2 WINNT,$(OS_ARCH)))
$(MOZ_APP_NAME).1: mozilla.man.in Makefile.in Makefile $(DEPTH)/config/autoconf.mk

Просмотреть файл

@ -103,9 +103,12 @@
// for X remote support
#ifdef MOZ_ENABLE_XREMOTE
#include "nsXRemoteClientCID.h"
#include "nsIXRemoteClient.h"
#include "nsIXRemoteService.h"
#ifdef MOZ_WIDGET_PHOTON
#include "PhRemoteClient.h"
#else
#include "XRemoteClient.h"
#endif
#include "nsIRemoteService.h"
#endif
// see DoOnShutdown()
@ -1297,10 +1300,23 @@ static nsresult main1(int argc, char* argv[], nsISupports *nativeApp )
// if we have X remote support and we have our one window up and
// running start listening for requests on the proxy window.
// It will shut itself down before the event queue stops processing events.
nsCOMPtr<nsIXRemoteService> remoteService;
remoteService = do_GetService(NS_IXREMOTESERVICE_CONTRACTID);
if (remoteService)
remoteService->Startup(MOZ_APP_NAME);
nsCOMPtr<nsIRemoteService> remoteService
(do_GetService("@mozilla.org/toolkit/remote-service;1"));
NS_ASSERTION(remoteService, "Couldn't create remote service?");
if (remoteService) {
nsCAutoString pname;
nsCOMPtr<nsIProfile> pm (do_GetService(NS_PROFILE_CONTRACTID));
if (pm) {
nsXPIDLString name;
pm->GetCurrentProfile(getter_Copies(name));
if (name) {
CopyUTF16toUTF8(name, pname);
}
}
remoteService->Startup(MOZ_APP_NAME, pname.IsEmpty() ? nsnull : pname.get());
}
#endif /* MOZ_ENABLE_XREMOTE */
// remove the nativeApp as an XPCOM autoreg observer
@ -1493,13 +1509,11 @@ static int HandleRemoteArguments(int argc, char* argv[], PRBool *aArgUsed)
return 0; // No remote argument == success
// try to get the X remote client
nsCOMPtr<nsIXRemoteClient> client (do_CreateInstance(NS_XREMOTECLIENT_CONTRACTID));
if (!client)
return 1;
XRemoteClient client;
nsresult rv;
// try to init - connects to the X server and stuff
rv = client->Init();
rv = client.Init();
if (NS_FAILED(rv)) {
PR_fprintf(PR_STDERR, "Error: Failed to connect to X server.\n");
return 1;
@ -1517,8 +1531,8 @@ static int HandleRemoteArguments(int argc, char* argv[], PRBool *aArgUsed)
char *response = NULL;
PRBool success = PR_FALSE;
rv = client->SendCommand(program, username, profile, remote,
&response, &success);
rv = client.SendCommand(program, username, profile, remote,
&response, &success);
// did the command fail?
if (NS_FAILED(rv)) {
@ -1540,7 +1554,6 @@ static int HandleRemoteArguments(int argc, char* argv[], PRBool *aArgUsed)
return 2;
}
client->Shutdown();
// success
return 0;
}

Просмотреть файл

@ -95,6 +95,12 @@ NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
NS_UTF16ToCString(input, NS_CSTRING_ENCODING_NATIVE_FILESYSTEM, output);
}
inline void
CopyUTF16toUTF8(const nsAString &input, nsACString &output)
{
NS_UTF16ToCString(input, NS_CSTRING_ENCODING_UTF8, output);
}
typedef nsCString nsCAutoString;
typedef nsString nsAutoString;
typedef nsCString nsXPIDLCString;
@ -104,6 +110,7 @@ typedef nsString nsXPIDLString;
#include "nsString.h"
#include "nsNativeCharsetUtils.h"
#include "nsReadableUtils.h"
inline void
AppendIntToString(nsCString &str, PRInt32 value)

Просмотреть файл

@ -38,7 +38,7 @@
*
* ***** END LICENSE BLOCK ***** */
const XREMOTESERVICE_CONTRACTID = "@mozilla.org/browser/xremoteservice;1";
const REMOTESERVICE_CONTRACTID = "@mozilla.org/toolkit/remote-service;1";
const XUL_NAMESPACE = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var gURLBar = null;
var gProxyButton = null;
@ -695,11 +695,11 @@ function Startup()
window.browserDOMWindow = new nsBrowserAccess();
// hook up remote support
if (XREMOTESERVICE_CONTRACTID in Components.classes) {
var remoteService;
remoteService = Components.classes[XREMOTESERVICE_CONTRACTID]
.getService(Components.interfaces.nsIXRemoteService);
remoteService.addBrowserInstance(window);
if (REMOTESERVICE_CONTRACTID in Components.classes) {
var remoteService =
Components.classes[REMOTESERVICE_CONTRACTID]
.getService(Components.interfaces.nsIRemoteService);
remoteService.registerWindow(window);
var observerService = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);

Просмотреть файл

@ -138,9 +138,11 @@ endif
endif
ifndef MOZ_XUL_APP
ifdef MOZ_ENABLE_XREMOTE
TOOL_DIRS += xremote
endif
endif
ifdef MOZ_HAVE_BROWSER
DIRS += build

Просмотреть файл

@ -43,6 +43,6 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = xremoteservice
DIRS = src
DIRS = public src
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -42,11 +42,11 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = xremoteservice
MODULE = appcomps
XPIDL_MODULE = xremoteservice
XPIDLSRCS = \
nsIXRemoteService.idl \
nsISuiteRemoteService.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,61 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Christopher Blizzard <blizzard@mozilla.org>.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIDOMWindow;
/**
* Responds to incoming xremote requests for the mozilla suite.
*/
[scriptable, uuid(52add212-2067-4575-8d26-edd5165179b1)]
interface nsISuiteRemoteService : nsISupports
{
/**
* Parse the command given.
*
* @param aCommand The command string, e.g. "openURL(http://www.foo.com/)"
* @param aContext The domwindow to target the command at. May be null, and
* may be ignored.
*/
void parseCommand (in string aCommand, in nsIDOMWindow aContext);
};
%{C++
#define NS_SUITEREMOTESERVICE_CONTRACTID "@mozilla.org/browser/xremoteservice;2"
%}

Просмотреть файл

Просмотреть файл

@ -42,7 +42,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = xremoteservice
MODULE = appcomps
LIBRARY_NAME = xremoteservice
EXPORT_LIBRARY = 1
IS_COMPONENT = 1
@ -54,7 +54,6 @@ REQUIRES = xpcom \
string \
dom \
widget \
gfx \
uriloader \
docshell \
pref \
@ -74,5 +73,6 @@ CPPSRCS = \
include $(topsrcdir)/config/rules.mk
EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
EXTRA_DSO_LDOPTS += \
$(MOZ_COMPONENT_LIBS) \
$(NULL)

Просмотреть файл

@ -48,11 +48,7 @@
#include <nsIDocShell.h>
#include <nsIScriptGlobalObject.h>
#include <nsIBaseWindow.h>
#include <nsWidgetsCID.h>
#include <nsIXRemoteWidgetHelper.h>
#include <nsIServiceManager.h>
#include <nsIObserverService.h>
#include <nsRect.h>
#include <nsString.h>
#include <nsCRT.h>
#include <nsIPref.h>
@ -74,117 +70,41 @@
#include <nsIExternalProtocolService.h>
#include <nsIProfile.h>
#ifdef MOZ_XUL_APP
#include "nsICommandLineRunner.h"
#else
#include "nsICmdLineHandler.h"
#endif
NS_DEFINE_CID(kWindowCID, NS_WINDOW_CID);
// protocol strings
static const char s200ExecutedCommand[] = "200 executed command:";
static const char s500ParseCommand[] = "500 command not parsable:";
static const char s501UnrecognizedCommand[] = "501 unrecognized command:";
// not used
//static const char s502NoWindow[] = "502 no appropriate window for:";
static const char s509InternalError[] = "509 internal error";
XRemoteService::XRemoteService()
{
mNumWindows = 0;
mRunning = PR_FALSE;
}
XRemoteService::~XRemoteService()
{
Shutdown();
}
NS_IMPL_ISUPPORTS2(XRemoteService, nsIXRemoteService, nsIObserver)
NS_IMPL_ISUPPORTS1(XRemoteService, nsISuiteRemoteService)
NS_IMETHODIMP
XRemoteService::Startup(const char *aProgram)
XRemoteService::ParseCommand(const char *aCommand, nsIDOMWindow* aWindow)
{
// We have to destroy the proxy window before the event loop stops running.
nsCOMPtr<nsIObserverService> obsServ =
do_GetService("@mozilla.org/observer-service;1");
obsServ->AddObserver(this, "quit-application", PR_FALSE);
obsServ->AddObserver(this, "profile-after-change", PR_FALSE);
mProgram.Assign(aProgram);
// Normalize program names to lowercase.
ToLowerCase(mProgram);
mRunning = PR_TRUE;
if (mNumWindows == 0)
CreateProxyWindow();
return NS_OK;
}
NS_IMETHODIMP
XRemoteService::Shutdown(void)
{
DestroyProxyWindow();
mRunning = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
XRemoteService::Observe(nsISupports *aSubject, const char *aTopic,
const PRUnichar *aData)
{
if (!strcmp(aTopic, "quit-application")) {
Shutdown();
} else {
NS_NOTREACHED("unexpected topic");
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
NS_IMETHODIMP
XRemoteService::ParseCommand(nsIWidget *aWidget,
const char *aCommand, char **aResponse)
{
if (!aCommand || !aResponse)
return NS_ERROR_INVALID_ARG;
// is there no command?
if (aCommand[0] == '\0') {
*aResponse = nsCRT::strdup(s509InternalError);
return NS_OK;
}
*aResponse = nsnull;
NS_ASSERTION(aCommand, "Tell me what to do, or shut up!");
// begin our parse
nsCString tempString;
PRInt32 begin_arg = 0;
PRInt32 end_arg = 0;
nsCString tempString(aCommand);
tempString.Append(aCommand);
// find the () in the command
begin_arg = tempString.FindChar('(');
end_arg = tempString.RFindChar(')');
PRInt32 begin_arg = tempString.FindChar('(');
PRInt32 end_arg = tempString.RFindChar(')');
// make sure that both were found, the string doesn't start with '('
// and that the ')' follows the '('
if (begin_arg == kNotFound || end_arg == kNotFound ||
begin_arg == 0 || end_arg < begin_arg) {
*aResponse = BuildResponse(s500ParseCommand, aCommand);
return NS_OK;
}
begin_arg == 0 || end_arg < begin_arg)
return NS_ERROR_INVALID_ARG;
// truncate the closing paren and anything following it
tempString.Truncate(end_arg);
// save the argument and trim whitespace off of it
nsCString argument;
argument.Append(tempString);
nsCString argument(tempString);
argument.Cut(0, begin_arg + 1);
argument.Trim(" ", PR_TRUE, PR_TRUE);
@ -192,8 +112,7 @@ XRemoteService::ParseCommand(nsIWidget *aWidget,
tempString.Truncate(begin_arg);
// get the action, strip off whitespace and convert to lower case
nsCString action;
action.Append(tempString);
nsCString action(tempString);
action.Trim(" ", PR_TRUE, PR_TRUE);
ToLowerCase(action);
@ -210,17 +129,6 @@ XRemoteService::ParseCommand(nsIWidget *aWidget,
nsresult rv = NS_OK;
// find the DOM window for the passed in parameter
nsVoidKey *key;
key = new nsVoidKey(aWidget);
if (!key)
return NS_ERROR_FAILURE;
// If this fails it's OK since it just means that we got a request
// on an unknown window. We can handle that case.
nsIDOMWindowInternal *domWindow = NS_STATIC_CAST(nsIDOMWindowInternal *,
mWindowList.Get(key));
delete key;
/*
openURL ( )
Prompts for a URL with a dialog box.
@ -240,9 +148,9 @@ XRemoteService::ParseCommand(nsIWidget *aWidget,
if (action.Equals("openurl") || action.Equals("openfile")) {
if (argument.IsEmpty())
rv = OpenURLDialog(domWindow);
rv = OpenURLDialog(aWindow);
else
rv = OpenURL(argument, domWindow, PR_TRUE);
rv = OpenURL(argument, aWindow, PR_TRUE);
}
/*
@ -296,7 +204,7 @@ XRemoteService::ParseCommand(nsIWidget *aWidget,
// and openurl should work fine.
nsCString tempArg("mailto:");
tempArg.Append(argument);
rv = OpenURL(tempArg, domWindow, PR_FALSE);
rv = OpenURL(tempArg, aWindow, PR_FALSE);
}
/*
@ -310,21 +218,7 @@ XRemoteService::ParseCommand(nsIWidget *aWidget,
*/
else if (action.Equals("addbookmark")) {
if (argument.IsEmpty()) {
rv = NS_ERROR_NOT_IMPLEMENTED;
}
else {
index = 0;
FindLastInList(argument, lastArgument, &index);
if (!lastArgument.IsEmpty()) {
nsCString title(lastArgument);
argument.Truncate(index);
rv = NS_ERROR_NOT_IMPLEMENTED;
}
else {
rv = NS_ERROR_NOT_IMPLEMENTED;
}
}
rv = NS_ERROR_NOT_IMPLEMENTED;
}
/* some extensions! */
@ -346,227 +240,17 @@ XRemoteService::ParseCommand(nsIWidget *aWidget,
*/
else if (action.Equals("xfedocommand")) {
rv = XfeDoCommand(argument, domWindow);
rv = XfeDoCommand(argument, aWindow);
}
// bad command
else {
rv = NS_ERROR_FAILURE;
*aResponse = BuildResponse(s501UnrecognizedCommand, aCommand);
}
// if we failed and *aResponse isn't already filled in, fill it in
// with a generic internal error message.
if (NS_FAILED(rv)) {
if (!*aResponse) {
if (rv == NS_ERROR_NOT_IMPLEMENTED)
*aResponse = BuildResponse(s501UnrecognizedCommand, aCommand);
else
*aResponse = nsCRT::strdup(s509InternalError);
}
}
// if we got this far then everything worked.
if (!*aResponse)
*aResponse = BuildResponse(s200ExecutedCommand, aCommand);
return rv;
}
NS_IMETHODIMP
XRemoteService::AddBrowserInstance(nsIDOMWindowInternal *aBrowser)
{
// get the native window for this instance
nsCOMPtr<nsIScriptGlobalObject> scriptObject;
scriptObject = do_QueryInterface(aBrowser);
if (!scriptObject) {
NS_WARNING("Failed to get script object for browser instance");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIBaseWindow> baseWindow;
baseWindow = do_QueryInterface(scriptObject->GetDocShell());
if (!baseWindow) {
NS_WARNING("Failed to get base window for browser instance");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIWidget> mainWidget;
baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
if (!mainWidget) {
NS_WARNING("Failed to get main widget for browser instance");
return NS_ERROR_FAILURE;
}
// walk up the widget tree and find the toplevel window in the
// hierarchy
nsCOMPtr<nsIWidget> tempWidget;
tempWidget = getter_AddRefs(mainWidget->GetParent());
while (tempWidget) {
tempWidget = getter_AddRefs(tempWidget->GetParent());
if (tempWidget)
mainWidget = tempWidget;
}
// Tell the widget code to set up X remote for this window
nsCOMPtr<nsIXRemoteWidgetHelper> widgetHelper =
do_GetService(NS_IXREMOTEWIDGETHELPER_CONTRACTID);
if (!widgetHelper) {
NS_WARNING("couldn't get widget helper service");
return NS_ERROR_FAILURE;
}
nsCAutoString profile;
GetProfileName(profile);
// Make sure that the profile is actually set to something.
const char *profileTmp = NULL;
if (profile.Length())
profileTmp = profile.get();
// Make sure we actually have a name.
const char *programTmp = NULL;
if (!mProgram.IsEmpty())
programTmp = mProgram.get();
nsresult rv;
rv = widgetHelper->EnableXRemoteCommands(mainWidget, profileTmp,
programTmp);
if (NS_FAILED(rv)) {
NS_WARNING("failed to enable x remote commands for widget");
return rv;
}
// It's assumed that someone will call RemoveBrowserInstance before
// this DOM window is destroyed so we don't addref or release or
// keep a weak ptr or anything.
nsVoidKey *key;
key = new nsVoidKey (mainWidget.get());
if (!key)
return NS_ERROR_FAILURE;
mWindowList.Put(key, aBrowser);
delete key;
// ...and the reverse lookup
key = new nsVoidKey (aBrowser);
if (!key)
return NS_ERROR_FAILURE;
mBrowserList.Put(key, mainWidget.get());
delete key;
// now that we have a real browser window listening to requests
// destroy the proxy window.
DestroyProxyWindow();
mNumWindows++;
return NS_OK;
}
NS_IMETHODIMP
XRemoteService::RemoveBrowserInstance(nsIDOMWindowInternal *aBrowser)
{
mNumWindows--;
if (mNumWindows == 0 && mRunning)
CreateProxyWindow();
// remove our keys
nsVoidKey *key;
key = new nsVoidKey(aBrowser);
if (!key)
return NS_ERROR_FAILURE;
nsIWidget *widget = NS_STATIC_CAST(nsIWidget *,
mBrowserList.Remove(key));
delete key;
key = new nsVoidKey(widget);
if (!key)
return NS_ERROR_FAILURE;
mWindowList.Remove(key);
delete key;
return NS_OK;
}
void
XRemoteService::CreateProxyWindow(void)
{
if (mProxyWindow)
return;
mProxyWindow = do_CreateInstance(kWindowCID);
if (!mProxyWindow)
return;
nsWidgetInitData initData;
initData.mWindowType = eWindowType_toplevel;
initData.mContentType = eContentTypeUI;
// create the window as a new toplevel
nsRect rect(0,0,100,100);
nsresult rv;
rv = mProxyWindow->Create(NS_STATIC_CAST(nsIWidget *, nsnull),
rect,
nsnull, nsnull, nsnull, nsnull,
&initData);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to create proxy window");
return;
}
// Tell the widget code to set up X remote for this window
nsCOMPtr<nsIXRemoteWidgetHelper> widgetHelper =
do_GetService(NS_IXREMOTEWIDGETHELPER_CONTRACTID);
if (!widgetHelper) {
NS_WARNING("couldn't get widget helper service");
return;
}
nsCAutoString profile;
GetProfileName(profile);
rv = widgetHelper->EnableXRemoteCommands(mProxyWindow, profile.get(),
mProgram.get());
if (NS_FAILED(rv)) {
NS_WARNING("failed to enable x remote commands for proxy window");
return;
}
}
void
XRemoteService::DestroyProxyWindow(void)
{
if (!mProxyWindow)
return;
mProxyWindow->Destroy();
mProxyWindow = nsnull;
}
char *
XRemoteService::BuildResponse(const char *aError, const char *aMessage)
{
nsCString retvalString;
char *retval;
// check to make sure that we have the minimum for allocating this
// buffer
if (!aError || !aMessage)
return nsnull;
retvalString.Append(aError);
retvalString.Append(" ");
retvalString.Append(aMessage);
retval = ToNewCString(retvalString);
return retval;
}
void
XRemoteService::FindRestInList(nsCString &aString, nsCString &retString,
PRUint32 *aIndexRet)
@ -760,11 +444,11 @@ XRemoteService::MayOpenURL(const nsCString &aURL)
nsresult
XRemoteService::OpenURL(nsCString &aArgument,
nsIDOMWindowInternal *aParent,
nsIDOMWindow *aParent,
PRBool aOpenBrowser)
{
// the eventual toplevel target of the load
nsCOMPtr<nsIDOMWindowInternal> finalWindow = aParent;
nsCOMPtr<nsIDOMWindowInternal> finalWindow = do_QueryInterface(aParent);
// see if there's a new-window or new-tab argument on the end
nsCString lastArgument;
@ -794,10 +478,6 @@ XRemoteService::OpenURL(nsCString &aArgument,
// If we're trying to open a new tab, we'll fall back to opening
// a new window if there's no browser window open, so look for it
// here.
#ifdef MOZ_THUNDERBIRD
newWindow = PR_FALSE;
finalWindow = nsnull; // always use the URILoader code below
#else
if (aOpenBrowser && (!newWindow || newTab)) {
nsCOMPtr<nsIDOMWindowInternal> lastUsedWindow;
FindWindow(NS_LITERAL_STRING("navigator:browser").get(),
@ -819,7 +499,6 @@ XRemoteService::OpenURL(nsCString &aArgument,
if (!finalWindow || !bwin)
newWindow = PR_TRUE;
}
#endif
// check if we can handle this type of URL
if (!MayOpenURL(aArgument))
@ -966,7 +645,7 @@ XRemoteService::OpenURL(nsCString &aArgument,
}
nsresult
XRemoteService::OpenURLDialog(nsIDOMWindowInternal *aParent)
XRemoteService::OpenURLDialog(nsIDOMWindow *aParent)
{
nsresult rv;
@ -1002,7 +681,7 @@ XRemoteService::OpenURLDialog(nsIDOMWindowInternal *aParent)
nsresult
XRemoteService::XfeDoCommand(nsCString &aArgument,
nsIDOMWindowInternal *aParent)
nsIDOMWindow *aParent)
{
nsresult rv = NS_OK;
@ -1029,7 +708,7 @@ XRemoteService::XfeDoCommand(nsCString &aArgument,
nsCOMPtr<nsIDOMWindowInternal> domWindow;
rv = FindWindow(NS_LITERAL_STRING("mail:3pane").get(),
getter_AddRefs(domWindow));
getter_AddRefs(domWindow));
if (NS_FAILED(rv))
return rv;
@ -1055,19 +734,6 @@ XRemoteService::XfeDoCommand(nsCString &aArgument,
// open a new browser window
else if (aArgument.LowerCaseEqualsLiteral("openbrowser")) {
#ifdef MOZ_XUL_APP
char* argc = "-browser";
nsCOMPtr<nsICommandLineRunner> cmdLine
(do_GetService("@mozilla.org/toolkit/command-line;1"));
NS_ENSURE_TRUE(cmdLine, NS_ERROR_FAILURE);
rv = cmdLine->Init(1, &argc, nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT);
NS_ENSURE_SUCCESS(rv, rv);
rv = cmdLine->Run();
#else
// Get the browser URL and the default start page URL.
nsCOMPtr<nsICmdLineHandler> browserHandler =
do_GetService("@mozilla.org/commandlinehandler/general-startup;1?type=browser");
@ -1086,7 +752,6 @@ XRemoteService::XfeDoCommand(nsCString &aArgument,
nsCOMPtr<nsIDOMWindow> newWindow;
rv = OpenChromeWindow(0, browserLocation, "chrome,all,dialog=no",
arg, getter_AddRefs(newWindow));
#endif
}
// open a new compose window
@ -1109,17 +774,17 @@ XRemoteService::XfeDoCommand(nsCString &aArgument,
else if (aArgument.LowerCaseEqualsLiteral("opencalendar")) {
// check to see if it's already running
nsCOMPtr<nsIDOMWindowInternal> domWindow;
nsCOMPtr<nsIDOMWindowInternal> aWindow;
rv = FindWindow(NS_LITERAL_STRING("calendarMainWindow").get(),
getter_AddRefs(domWindow));
getter_AddRefs(aWindow));
if (NS_FAILED(rv))
return rv;
// focus the window if it was found
if (domWindow) {
domWindow->Focus();
if (aWindow) {
aWindow->Focus();
}
// otherwise open a new calendar window
@ -1151,28 +816,12 @@ XRemoteService::FindWindow(const PRUnichar *aType,
return mediator->GetMostRecentWindow(aType, _retval);
}
void
XRemoteService::GetProfileName(nsACString &aProfile)
{
// Get the current profile name and save it.
nsresult rv;
nsCOMPtr<nsIProfile> profileMgr;
profileMgr = do_GetService(NS_PROFILE_CONTRACTID, &rv);
if (!profileMgr)
return;
nsXPIDLString name;
rv = profileMgr->GetCurrentProfile(getter_Copies(name));
if (NS_SUCCEEDED(rv))
LossyCopyUTF16toASCII(name, aProfile);
}
NS_GENERIC_FACTORY_CONSTRUCTOR(XRemoteService)
static const nsModuleComponentInfo components[] = {
{ NS_IXREMOTESERVICE_CLASSNAME,
{ "XRemoteService",
NS_XREMOTESERVICE_CID,
NS_IXREMOTESERVICE_CONTRACTID,
"@mozilla.org/browser/xremoteservice;2",
XRemoteServiceConstructor }
};

Просмотреть файл

@ -19,6 +19,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -34,12 +35,12 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsIXRemoteService.h"
#include "nsHashtable.h"
#include "nsIDOMWindow.h"
#include "nsIWidget.h"
#include "nsISuiteRemoteService.h"
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "nsString.h"
class nsIDOMWindowInternal;
// {3dfe7324-1dd2-11b2-9ff2-8853f91e8a20}
@ -47,7 +48,8 @@
{ 0x3dfe7324, 0x1dd2, 0x11b2, \
{ 0x9f, 0xf2, 0x88, 0x53, 0xf9, 0x1e, 0x8a, 0x20 } }
class XRemoteService : public nsIXRemoteService, public nsIObserver {
class XRemoteService : public nsISuiteRemoteService
{
public:
XRemoteService();
virtual ~XRemoteService();
@ -56,18 +58,9 @@ class XRemoteService : public nsIXRemoteService, public nsIObserver {
NS_DECL_ISUPPORTS
NS_DECL_NSIXREMOTESERVICE
NS_DECL_NSIOBSERVER
NS_DECL_NSISUITEREMOTESERVICE
private:
// create and destroy the proxy window
void CreateProxyWindow();
void DestroyProxyWindow();
// this builds a response for any parsing
char *BuildResponse(const char *aError, const char *aMessage);
// find the last argument in an argument string
void FindLastInList(nsCString &aString, nsCString &retString,
PRUint32 *aIndexRet);
@ -94,36 +87,16 @@ class XRemoteService : public nsIXRemoteService, public nsIObserver {
// remote command handlers
nsresult OpenURL(nsCString &aArgument,
nsIDOMWindowInternal *aParent,
PRBool aOpenBrowser);
nsIDOMWindow* aParent,
PRBool aOpenBrowser);
nsresult OpenURLDialog(nsIDOMWindowInternal *aParent);
nsresult OpenURLDialog(nsIDOMWindow* aParent);
// handle xfe commands
nsresult XfeDoCommand(nsCString &aArgument,
nsIDOMWindowInternal *aParent);
nsIDOMWindow* aParent);
// find the most recent window of a certain type
nsresult FindWindow(const PRUnichar *aType,
nsIDOMWindowInternal **_retval);
// Save the profile name
void GetProfileName(nsACString &aProfile);
// hidden window for proxy requests
nsCOMPtr<nsIWidget> mProxyWindow;
// native window to internal dom window map
nsHashtable mWindowList;
// internal dom window to native window map
nsHashtable mBrowserList;
// the number of non-proxy windows that are set up for X Remote
PRUint32 mNumWindows;
// have we been started up from the main loop yet?
PRBool mRunning;
// Name of our program
nsCString mProgram;
nsIDOMWindowInternal **_retval);
};