Learning documentation.

This commit is contained in:
edburns%acm.org 2001-05-10 22:24:36 +00:00
parent c136fc58fc
commit 9f3a659d37
10 changed files with 4096 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -0,0 +1,28 @@
<HTML>
<HEAD>
<TITLE>Introduction to Waterfall</TITLE>
</HEAD>
<BODY>
<PRE>
This document describes the benefits of waterfall.
This diagram illustrates the allocation of dependencies to dlls in both
the Java Plugin (JPI) and waterfall.
<IMG SRC="wf_deployment.gif"></IMG>
You can see from the above diagram that all the browser specific
dependencies are located in the wf_moz6.dll. wf_moz6.dll communicates
to the jvmp.dll through the well defined waterfall C api. jvmp.dll
communicates to the Java environment through the well defined JNI C api.
<IMG SRC="jpi_deployment.gif"></IMG>
The Java Plugin has browser specific dependencies in both npoji600.dll
and in jpins32.dll. jpins32.dll communicates with the Java environment
throug the well defined JNI C api and some additional proprietary APIs.
Thus, a change in any of the netscape interfaces impacts the java plugin
very deeply, where with waterfall, the change is isolated to one module.
</PRE> </BODY> </HTML>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,303 @@
<HTML>
<HEAD>
<TITLE>Reasearch Scratch Pad for Learning Waterfall</TITLE>
</HEAD>
<BODY>
<PRE>
This document is a scratch pad for helping me understand how waterfall
works. I will use mozilla and the debugger as a guide. I'll start by
discovering how mozilla hooks into waterfall.
Refer to this diagram:
<IMG SRC="primaryclasses.gif"></IMG>
Waterfall Metrics
=================
144 files total
76 java
3 cpp
25 c
40 h
30849 SLOC including comments.
Waterfall Bootstrapping
=======================
Mozilla hooks in to waterfall by virtue of the wf_moz6 module being an
XPCOM component.
D:\Projects\trunk\mozilla\wf_moz6\wf_moz6\src\nsCJVMFactory.cpp
This file defines the necessary macro to be an XPCOM component:
NS_IMPL_NSGETMODULE("nsCJVMModule", components);
The second argument is an array of nsModuleComponentInfo structs.
static nsModuleComponentInfo components[] =
{
{ "Waterfall API-based JVM Service",
NS_PLUGGABLEJVM_CID,
NS_INLINE_PLUGIN_CONTRACTID_PREFIX "application/x-java-vm",
nsJavaHTMLObjectFactory::Create,
},
};
nsModuleComponentInfo is defined in:
D:\Projects\trunk\mozilla\dist\include\nsIGenericFactory.h
The important elements in this struct are the third and forth:
const char* mContractID;
NSConstructorProcPtr mConstructor;
the mContractID tells XPCOM what our programmatic name is, and the
mConstructor tells XPCOM what to call to construct an instance of the
module. In waterfall's case, this is nsJavaHTMLObjectFactory::Create,
defined in
D:\Projects\trunk\mozilla\wf_moz6\wf_moz6\src\nsJavaHTMLObjectFactory.cpp
As you may know every dll in the components directory is interrogated at
mozilla startup in what is known as "auto-registration". This is how
waterfall gets picked up. The waterfall library is called
dist\win32*\bin\components\ojijvm.dll. Our Create method gets called
here:
nsJavaHTMLObjectFactory::Create(nsISupports * 0x00000000, const nsID & {...}, void * * 0x0012f8e4) line 92
nsGenericFactory::CreateInstance(nsGenericFactory * const 0x0173a2d0, nsISupports * 0x00000000, const nsID & {...}, void * * 0x0012f8e4) line 56
nsComponentManagerImpl::CreateInstance(nsComponentManagerImpl * const 0x00a96c80, const nsID & {...}, nsISupports * 0x00000000, const nsID & {...}, void * * 0x0012f8e4) line 1199 + 24 bytes
nsComponentManager::CreateInstance(const nsID & {...}, nsISupports * 0x00000000, const nsID & {...}, void * * 0x0012f8e4) line 82
nsServiceManagerImpl::GetService(nsServiceManagerImpl * const 0x00a955a0, const nsID & {...}, const nsID & {...}, nsISupports * * 0x0012f9a4, nsIShutdownListener * 0x00000000) line 344 + 19 bytes
nsServiceManagerImpl::GetService(nsServiceManagerImpl * const 0x00a955a0, const char * 0x024536d0, const nsID & {...}, nsISupports * * 0x0012f9a4, nsIShutdownListener * 0x00000000) line 492
nsServiceManager::GetService(const char * 0x024536d0, const nsID & {...}, nsISupports * * 0x0012f9a4, nsIShutdownListener * 0x00000000) line 605
nsGetServiceByContractID::operator()(const nsID & {...}, void * * 0x0012f9a4) line 64 + 22 bytes
nsCOMPtr<nsIPlugin>::assign_from_helper(const nsCOMPtr_helper & {...}, const nsID & {...}) line 970 + 18 bytes
nsCOMPtr<nsIPlugin>::nsCOMPtr<nsIPlugin>(const nsCOMPtr_helper & {...}) line 552
nsJVMManager::StartupJVM() line 605 + 30 bytes
nsJVMManager::MaybeStartupLiveConnect() line 788 + 20 bytes
nsJVMManager::StartupLiveConnect(nsJVMManager * const 0x01739118, JSRuntime * 0x00f97210, int & 0) line 128 + 11 bytes
nsJSEnvironment::nsJSEnvironment() line 1505 + 49 bytes
nsJSEnvironment::GetScriptingEnvironment() line 1446 + 27 bytes
NS_CreateScriptContext(nsIScriptGlobalObject * 0x0169c7b0, nsIScriptContext * * 0x01693680) line 1545 + 5 bytes
nsDocShell::EnsureScriptEnvironment(nsDocShell * const 0x016935d0) line 4384 + 50 bytes
nsWebShell::GetInterface(nsWebShell * const 0x016935f4, const nsID & {...}, void * * 0x0012fc00) line 327 + 19 bytes
nsGetInterface::operator()(const nsID & {...}, void * * 0x0012fc00) line 37 + 31 bytes
nsCOMPtr<nsIDOMWindowInternal>::assign_from_helper(const nsCOMPtr_helper & {...}, const nsID & {...}) line 970 + 18 bytes
nsCOMPtr<nsIDOMWindowInternal>::nsCOMPtr<nsIDOMWindowInternal>(const nsCOMPtr_helper & {...}) line 552
nsAppShellService::GetHiddenWindowAndJSContext(nsAppShellService * const 0x00b579b0, nsIDOMWindowInternal * * 0x0012fca8, JSContext * * 0x0012fcac) line 727 + 32 bytes
nsAppShellService::SetXPConnectSafeContext() line 191 + 40 bytes
nsAppShellService::CreateHiddenWindow(nsAppShellService * const 0x00b579b0) line 251
main1(int 1, char * * 0x00a95930, nsISupports * 0x00000000) line 987
main(int 1, char * * 0x00a95930) line 1298 + 37 bytes
mainCRTStartup() line 338 + 17 bytes
KERNEL32! 77f1ba3c()
Regarding nsJVMManager.cpp StartupJVM() on the stack: this is where the
first modification in the patch to bug 72708 comes into play:
NS_WITH_SERVICE(nsIPlugin, f,
NS_INLINE_PLUGIN_CONTRACTID_PREFIX NS_JVM_MIME_TYPE,
&err);
if (NS_FAILED(err) || !f) {
err = pluginHost->GetPluginFactory(NS_JVM_MIME_TYPE, &pluginFactory);
}
else {
pluginFactory = f;
}
Note that the contract ID matches the one specified in
nsCJVMFactory.cpp. Here Nikolay has modified the oji code to first
check for waterfall, then to fall back on the
pluginHost->CreatePlugin().
ns nsJavaHTMLObjectFactory::Create, we create an instance of
nsJavaHTMLObjectFactory. This has a reference to an nsIPluggableJVM
impl. We send nsJavaHTMLObjectFactory Initialize(). In Initialize(),
we send StartupJVM to nsIPluggableJVM. This calls
nsPluggableJVM::loadPluginDLL(). As far as I can tell this is where the
first call into the Waterfall plugin code occurrs. loadPluginDLL() opens
the jvmp.dll, and finds the symbol "JVMP_GetPlugin". This calls
loadJVM(), which opens the JDK's JVM dll and looks for several symbols.
Here there is ifdef'd code for each of the supported JVMS:
#ifdef _JVMP_IBMJVM
#ifdef _JVMP_SUNJVM
etc.
The symbols loaded from the JVM dll are:
JNI_GetDefaultJavaVMInitArgs
JNI_CreateJavaVM
JNI_GetCreatedJavaVMs
JVMP_GetPlugin returns a pointer to a static JVMP_RuntimeContext
instance. JVMP_RuntimeContext is defined in
d:\Projects\blackwood\eng\wf\public\jvmp.h. The RuntimeContext is a
collection pointers to functions defined in java_plugin.c.
nsPluggableJVM keeps a pointer to the JVMP_RuntimeContext.
After loading the jvmp.dll, we call nsPluggableJVM::initJVM().
nsPluggableJVM::initJVM() calls JVMP_GetRunningJVM(), in
d:\Projects\blackwood\eng\wf\src\plugin\java_plugin.c. This calls
JVMP_initJavaClasses(). Here is the first time we see JNI constructs.
We find the class sun/jvmp/generic/{motif,win32}/Plugin.java and call its
startJVM() method. This returns an instance of the java class
PluggableJVM. This is saved as the static native var
JVMP_PluginInstance. The class Plugin is saved as JVMP_PluginClass.
After returning, we call JVMP_initClassPath, which pulls in the java
classpath from the CLASSPATH env var. This results in creating an array
like this:
Java Plugin: JVM option[0]=-Djava.class.path=D:\Projects\blackwood\eng\wf\build\win32\classes;
Java Plugin: JVM option[1]=-Djava.library.path=D:\Projects\blackwood\eng\wf\build\win32;D:\Projects\blackwood\eng\wf\build\win32\java\jre\lib\win32:
Java Plugin: JVM option[2]=-Djava.home=D:\Projects\blackwood\eng\wf\build\win32/java/jre
Java Plugin: JVM option[3]=-Xbootclasspath:D:\Projects\blackwood\eng\wf\build\win32\java\jre\classes;D:\Projects\blackwood\eng\wf\build\win32\java\jre\lib\rt.jar;D:\Projects\blackwood\eng\wf\build\win32\java\jre\lib\i18n.jar
Java Plugin: JVM option[4]=-Djava.security.manager
Java Plugin: JVM option[5]=-Djvmp.home=D:\Projects\blackwood\eng\wf\build\win32
Java Plugin: JVM option[6]=-Djava.security.policy=file:D:/Projects/blackwood/eng/wf/build/win32/plugin.policy
We then try to get access to a JavaVM, using JVMP_ReuseJVM(). This uses
the JVMMethods struct, defined in java_plugin.c. This is a struct of
function pointers to JVM methods.
We then call JVMP_EnableCapabilities(). This is the first sign of
security code in waterfall. Let me step out of context to define two
terms. A Principal is an entity responsible for a script in some way.
There are several kinds of principals. A certificate principal
represents the signer of the script. A certificate principal is
responsible for proving the script is from who it says it is. Another
way of saying it is that a certificate principal is responsible for the
script's authentication. The set of principals is fixed at the time the
page is loaded. Each principal has a set of capabilities, each of which
can be enabled or disabled by the system and the user.
I don't know what a system principal is, but it represents mozilla.org?
How does a codebase principal differ from a certificate principal? They
both seem to deal with the issue of authentication.
Back to calling JVMP_EnableCapabilities(). This manipulates the
JVMP_CallingContext, a struct with function pointers for manipulating
Caps. Caps is a term bandied about by security types. It's short for
capabilities. If someone could come up with a better definition, I'd
appreciate it. At this point we call back into java for the
PluggableJVM.enableCapabilities() method, passing in the byte array for
the caps and an array of principals.
We return and pop up the java console, then return from
nsJavaHTMLObjectFactory::Create(), returning an instance of
nsJavaHTMLObjectFactory typed as a nsIPlugin. Our being typed this way
enables us to provide the necessary services to the browser. This
completes the bootstrapping process.
How an Applet is instantiated
=============================
The normal plugin instantiation and initialization proccess occurrs.
This includes scanning the plugin directory for any plugins that respond
to the applet mime type. Of course none are found since waterfall
requires that the java plugin is not installed. Then we try to
instantiate a plugin using the contract id:
"@mozilla.org/inline-plugin/application/x-java-vm". Remember that
waterfall declared itself as responding to that contractID in
D:\Projects\trunk\mozilla\wf_moz6\wf_moz6\src\nsCJVMFactory.cpp. This
happens here:
nsJavaHTMLObjectFactory::Create(nsISupports * 0x00000000, const nsID & {...}, void * * 0x0012a944) line 104
nsGenericFactory::CreateInstance(nsGenericFactory * const 0x0173beb0, nsISupports * 0x00000000, const nsID & {...}, void * * 0x0012a944) line 56
nsComponentManagerImpl::CreateInstance(nsComponentManagerImpl * const 0x00a96bc0, const nsID & {...}, nsISupports * 0x00000000, const nsID & {...}, void * * 0x0012a944) line 1199 + 24 bytes
nsComponentManagerImpl::CreateInstanceByContractID(nsComponentManagerImpl * const 0x00a96bc0, const char * 0x0012a948, nsISupports * 0x00000000, const nsID & {...}, void * * 0x0012a944) line 1239
nsComponentManager::CreateInstance(const char * 0x0012a948, nsISupports * 0x00000000, const nsID & {...}, void * * 0x0012a944) line 94
nsPluginHostImpl::SetUpPluginInstance(nsPluginHostImpl * const 0x0173a4b4, const char * 0x0b7d21ec, nsIURI * 0x0e0e6440, nsIPluginInstanceOwner * 0x0e0e6950) line 2758 + 28 bytes
nsPluginHostImpl::InstantiateEmbededPlugin(nsPluginHostImpl * const 0x0173a4b4, const char * 0x0b7d21ec, nsIURI * 0x0e0e6440, nsIPluginInstanceOwner * 0x0e0e6950) line 2461 + 24 bytes
nsObjectFrame::InstantiatePlugin(nsIPresContext * 0x0d0a3290, nsHTMLReflowMetrics & {...}, const nsHTMLReflowState & {...}, nsIPluginHost * 0x0173a4b4, const char * 0x0b7d21ec, nsIURI * 0x0e0e6440) line 1037
nsObjectFrame::Reflow(nsObjectFrame * const 0x0125596c, nsIPresContext * 0x0d0a3290, nsHTMLReflowMetrics & {...}, const nsHTMLReflowState & {...}, unsigned int & 0) line 853 + 49 bytes
The plugin is looking for an nsIPluginInstance instance, which waterfall
returns in the form of an nsAppletHTMLObject instance. This guy also
implements nsIJVMPluginInstance. It creates and has a nsIJavaHTMLObject
instance. According to the comments, the nsIJavaHTMLObject instance is
the "is instance of visible object on browser's page controlled by Java
code, like APPLET or OBJECT tag content." This eventually calls into
the java class PluggableJVM.createPeer(). The nsIJavaHTMLObject
instance creates and keeps an nsIJavaObjectInfo instance.
Comments and Questions
======================
How does the java console get hooked up to nsIJVMConsole?
nsJavaHTMLObjectFactory::Initialize()
should use do_getService() instead of nsServiceManager::GetService().
shouldn't use stock malloc, should use nsCRT.
nsPluggableJVM::StartupJVM()
shouldn't use env vars. At the very least, shouldn't use stock
getenv, should use nsCRT.
Console shouldn't be hard coded to visible.
JVMP_initClassPath(), JVMP_GetPlugin(), loadJVM(), etc
I know these classes are independent of mozilla. Is it ok to use the
stock malloc() and getenv()? Should waterfall c plugin classes use
nspr?
Is this ifdefing allowable:
#ifdef _JVMP_IBMJVM
#ifdef _JVMP_SUNJVM
In loadJVM() we have the filepaths to the jvm dll hard coded, is this
safe?
Is it safe to assume these symbols are in the jvm dll?
JNI_GetDefaultJavaVMInitArgs
JNI_CreateJavaVM
JNI_GetCreatedJavaVMs
Or do we assume we'll have a different jvmp for each released Java
plugin version? I *do* think this is a safe assumption.
* JRE 1.3.0_01 doesn't have classic vm
* when running ./plugin_host, you must start the JVM, then enable system
capabilities in order to do most anything else.
* He has inconsistent environment variables for things.
JAVA_HOME == JDK
* The documentation refers to files that aren't there. build.txt refers
to ../java/makefile.win, when it should be ../build/java/makefile.win.
* Why do you have to copy the Java directory into the build area on
win32, and link it on unix?
* Why does he have a jni.h in his tree? How does it differ from the
stock jni.h?
* Building is a mess. Each platform has unnecessarily different
conventions, many errors in build instructions.
* Can't build wf_moz6: Syntax errors.
</PRE>
</BODY>
</HTML>

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,76 @@
<?xml version = "1.0" encoding = "ISO-8859-1" ?>
<!DOCTYPE argo SYSTEM "argo.dtd" >
<argo>
<documentation>
<authorname></authorname>
<version></version>
<description>
</description>
</documentation>
<searchpath href="PROJECT_DIR" />
<member
type="pgml"
name="wf_classdiagram1.pgml"
/>
<member
type="pgml"
name="wf_usecasediagram1.pgml"
/>
<member
type="xmi"
name="wf.xmi"
/>
<member
type="pgml"
name="wf_classdiagram3.pgml"
/>
<historyfile name="" />
<stats>
<stat name="clicksInToDoPane"
value="0" />
<stat name="dblClicksInToDoPane"
value="0" />
<stat name="longestToDoList"
value="206" />
<stat name="longestAdd"
value="0" />
<stat name="longestHot"
value="0" />
<stat name="numCriticsFired"
value="47595" />
<stat name="numNotValid"
value="0" />
<stat name="numCriticsApplied"
value="0" />
<stat name="toDoPerspectivesChanged"
value="0" />
<stat name="navPerspectivesChanged"
value="2" />
<stat name="clicksInNavPane"
value="0" />
<stat name="numFinds"
value="0" />
<stat name="numJumpToRelated"
value="0" />
<stat name="numDecisionModel"
value="0" />
<stat name="numGoalsModel"
value="0" />
<stat name="numCriticBrowser"
value="0" />
<stat name="numNavConfig"
value="0" />
<stat name="numHushes"
value="0" />
<stat name="numChecks"
value="0" />
<stat name="Num_Button_Clicks"
value="0" />
<stat name="Drags_To_New"
value="0" />
<stat name="Drags_To_Existing"
value="0" />
</stats>
</argo>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE pgml SYSTEM "pgml.dtd">
<pgml description="uci.uml.visual.UMLUseCaseDiagram|-64--127-100-3-40a9f9:e56db40b1d:-8000"
name="use case diagram 1"
>
</pgml>