[This local archive copy is from the official and canonical URL, http://www.mozilla.org/xpfe/appCore/appcores.html; please refer to the canonical source document if possible.]
|
NOTE: There is already a notion of a Service Manager
in the Mozilla code base. So there is no confusion, throughout the
rest of this document the term "Application Core" or AppCore will be
used in the place of Application Service. As stated earlier, the AppRunner has no application specific
knowledge, it merely loads a XUL file and one or associated AppCores,
then "hooks" them together and an application specific instance is
born. An AppCore is one more objects that implements a set of
functionality required for a specific type of application. For
example, the mail application would conceivably have an
MailAppCore that is capable of grabbing the data out of the UI
and sending a message. The AppCore may be written entirely in
JavaScript (JS), entirely in C++, or combination of the two (see
Figure #1). An AppCore is divided into two distinct pieces, the "glue" code
and the application specific code. The "glue" code has knowledge of
the UI and sits between the static UI element and the application
specific code. The application specific code's role is to know a
little as possible about the GUI and only provide core application
functionality. Figure #1 shows a line from the XUL to the JavaScript
and then from the JS to the App. Specific Code (ASC). This path
illustrates a user manipulating a UI element which cause a UI event
to be fired. The event is process in the JavaScript and then a call
is made into the application specific code. The line between the XUL and the ASC illustrates direct calls from
the GUI into the ASC and notifications from the ASC to the UI (this
later path to UI from the ASC is discouraged). In the MailAppCore example, consider a very simple UI. Text
fields for the Address, Subject and the body of the message; and a
single "Send" button for sending the contents of the UI to the
specified address. The JS code for the XUL would contain two
functions, a MailSendMsg function and a MailSent
function. The user would fill in the message fields and then press
"Send." The Send button invokes a XULCommand that executes the
MailSendMsg function in the JS. The JS MailSendMsg
function grabs the data out of the UI and makes a call into the ASC
function called SendMail. When the ASC's SendMail completes, it makes a JS call to
invoke the MailSent function. The MailSent function can
then do any type of notification to the GUI (i.e like clearing the
form). Let's continue with the MailAppCore example. The Mail demo loads an intial XUL file MailAppShell.xml at
start up. This file defines three IFRAMEs: the toolbar area, the
"content" area, and the status bar area. In this example, the content
area will contain an HTML file defining a form for entering in a Mail
message (see figure #3) Next, we define the toolbar. The "Send" button defines a
XULCommand to be executed when the user presses it. The XULCommands
are also defined in the XUL files and they describe the JavaScript
string they are to execute.
<xul:toolbar>
<xul:commands> The XULCommand nsCmd:MailSendMsg defines a JavaScript string that is to be executed when the button is pressed. This JS function will ask the AppCoreManager for a MailAppCore by a unique name. If the MailAppCore doesn't by that name doesn't exist yet, it will create one. Then it gets the data out of the form and invokes the SendMail function on the MailAppCore object. function
SendMailMessage() Next, we will define the GUI
The MailAppCore code is as follows: NS_IMETHODIMP if (nsnull != mScriptContext)
{ Summary How do I create an Application Core?In order to create and use a native code from JavaScript we must do several things:
The C++ implementation will also be derived from the nsIDOMxxx interface that is automatically generated from the IDL compiler. Here is the C++ implementation with the new interface added: class nsMailCore : public
nsBaseAppCore,
nsMailCore();
NS_DECL_ISUPPORTS
NS_IMETHOD MailCompleteCallback(const nsString&
aScript); NS_IMETHOD SendMail(const nsString& aAddrTo, const nsString& aSubject, const nsString& aMsg); protected: nsString mScript;
nsIScriptContext *mScriptContext; The methods Init, GetId, and GetScritpableObject are defined in the IDL's base class BaseAppCore. Here is a brief description of some of the methods:
NOTE: It is important that the name of the IDL object matches the name of the implementation object (except for the "ns" prefix). The IDL compiler generates stub code for the mapping of the JS function calls to an instance of the implementation object. If the names are different you will get a compiler error. Your implementation object must have a standard facotry for
creating instances of it. Registering the JS object into the External name space The Mozilla service manager contains a service for registering the JS object into the JS script name space. The following code snipet shows how to get the service and register a new script name space:
/***************************************/
nsIScriptNameSetRegistry *registry; The nsAppCoresNameSet object implements the nsIScriptExternalNameSet interface and it provides two important functions:
Here is a small portion of the code for adding it's name to the name space: NS_IMETHODIMP result =
aScriptContext->GetNameSpaceManager(&manager);
NS_RELEASE(manager); Here is a snipet showing the initialization of the external classes: NS_IMETHODIMP result =
NS_InitMailCoreClass(aScriptContext, nsnull); The DLL containing the external object(s) has a method NSGetFactory where a CID is passed in and the appropriate factory is passed back. So each scriptable object needs it's factory. This method looks as follows: extern "C" NS_EXPORT
nsresult *aFactory =
NULL; if (
aClass.Equals(kMailCoreCID) ) { if (inst == NULL)
{ nsresult res =
inst->QueryInterface(kIFactoryIID, (void**)
aFactory); return res; } How does this all fit together? Until COMConnect is implemented, the objects that are in the external DLL must be registered into the nsRespository like all other Mozilla objects. Then the NameSet object for the objects must be added to the ScriptNameSetRegistry service. Now the application is ready to execute. When JS starts up it checks the registry and initializes all the classes (this is when the InitializeClasses method gets called.) When JS encounters the new object in the script it looks it up in the external name set registry and is then able to create an object of this kind.
ConclusionThis document provides the initial approach to providing
ApplicationCore objects to a XUL application using native code and
scriptable interfaces. There are manay unresolved issues that must be
addressed. A few of these are as follows:
|
|||||||||||||||||||||||||
Copyright © 1998 The Mozilla Organization. |