зеркало из https://github.com/mozilla/gecko-dev.git
This checkin adds API to cleanly destroy a BrowserControl instance. It
also modifies EmbeddedMozilla so this code is exercised. I have changed EmbeddedMozilla to be a stub-like class that simply displays a Frame with a single Button, titled "New Window". Pressing this button causes an EMWindow to be created and displayed. EMWindow is basically the former EmbeddedMozilla renamed, with modifications to the WindowListener implementation to call the BrowserControl deallocation method. I've added a delete() method to ImplObect: * I know Java has automatic garbage collection and all, but explicitly * adding a delete method helps the gc algorithm out. <P> * Subclasses should override this and call super.delete() at the end of * their overridden delete() method. * @see org.mozilla.webclient.wrapper_native.ImplObjectNative#delete and ImplObjectNative: * Note how we call super.delete() at the end. THIS IS VERY IMPORTANT. <P> * Also, note how we don't de-allocate nativeWebShell, that is done in * the class that owns the nativeWebShell reference, WindowControlImpl. * ImplObjectNative subclasses that further override delete() are <P> <CODE><PRE> BookmarksImpl.java EventRegistrationImpl.java NativeEventThread.java WindowControlImpl.java </PRE><CODE> <P> * All other ImplObject subclasses don't have any local Ivars and thus * don't need to override delete(). I've added a delete() method to BrowserControlImpl: * Called from BrowserControlFactory.deleteBrowserControl() <P> * The order of deletion of objects is very important! <P> * We don't allow deletion if the Canvas is showing. <P> In BrowserControlImpl's delete(), the important delete()s is for WindowControlImpl: * First, we delete our eventThread, which causes the eventThread to * stop running. Then we call nativeDestroyInitContext(), which * deallocates native resources for this window. As stated above, NativeEventThread.delete() is called: * This is a very delicate method, and possibly subject to race * condition problems. To combat this, our first step is to set our * browserControlCanvas to null, within a synchronized block which * synchronizes on the same object used in the run() method's event * loop. By setting the browserControlCanvas ivar to null, we cause the * run method to return. After all of this deleting, we return from BrowserControlFactory.delete().
This commit is contained in:
Родитель
068e84c7d4
Коммит
2b80283ff3
|
@ -43,7 +43,7 @@ import java.io.FileNotFoundException;
|
|||
* This is a static class, it is neven instantiated.
|
||||
|
||||
*
|
||||
* @version $Id: BrowserControlFactory.java,v 1.1 2000/03/04 01:10:51 edburns%acm.org Exp $
|
||||
* @version $Id: BrowserControlFactory.java,v 1.2 2000/03/13 18:41:36 edburns%acm.org Exp $
|
||||
*
|
||||
* @see org.mozilla.webclient.test.EmbeddedMozilla
|
||||
|
||||
|
@ -157,7 +157,7 @@ public static void setAppData(String absolutePathToNativeBrowserBinDir) throws F
|
|||
}
|
||||
|
||||
try {
|
||||
BrowserControlImpl.initialize(absolutePathToNativeBrowserBinDir);
|
||||
BrowserControlImpl.appInitialize(absolutePathToNativeBrowserBinDir);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new ClassNotFoundException("Can't initialize native browser: " +
|
||||
|
@ -185,6 +185,25 @@ public static BrowserControl newBrowserControl() throws InstantiationException,
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* BrowserControlFactory.deleteBrowserControl is called with a
|
||||
* BrowserControl instance obtained from
|
||||
* BrowserControlFactory.newBrowserControl. This method renders the
|
||||
* argument instance completely un-usable. It should be called when the
|
||||
* BrowserControl instance is no longer needed. This method simply
|
||||
* calls through to the non-public BrowserControlImpl.delete() method.
|
||||
|
||||
* @see org.mozilla.webclient.ImplObject#delete
|
||||
|
||||
*/
|
||||
|
||||
public static void deleteBrowserControl(BrowserControl toDelete)
|
||||
{
|
||||
ParameterCheck.nonNull(toDelete);
|
||||
((BrowserControlImpl)toDelete).delete();
|
||||
}
|
||||
|
||||
//
|
||||
// General Methods
|
||||
//
|
||||
|
@ -201,7 +220,7 @@ public static void main(String [] args)
|
|||
Assert.setEnabled(true);
|
||||
Log.setApplicationName("BrowserControlFactory");
|
||||
Log.setApplicationVersion("0.0");
|
||||
Log.setApplicationVersionDate("$Id: BrowserControlFactory.java,v 1.1 2000/03/04 01:10:51 edburns%acm.org Exp $");
|
||||
Log.setApplicationVersionDate("$Id: BrowserControlFactory.java,v 1.2 2000/03/13 18:41:36 edburns%acm.org Exp $");
|
||||
|
||||
BrowserControlCanvas canvas = null;
|
||||
BrowserControl control = null;
|
||||
|
|
|
@ -82,12 +82,60 @@ public BrowserControlImpl(BrowserControlCanvas yourCanvas)
|
|||
myCanvas = yourCanvas;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Called from BrowserControlFactory.deleteBrowserControl() <P>
|
||||
|
||||
* The order of deletion of objects is very important! <P>
|
||||
|
||||
* We don't allow deletion if the Canvas is showing. <P>
|
||||
|
||||
*/
|
||||
|
||||
void delete()
|
||||
{
|
||||
Assert.assert(null != myCanvas);
|
||||
|
||||
// Make sure we're not showing.
|
||||
if (myCanvas.isShowing()) {
|
||||
throw new IllegalStateException("Can't delete a browser control while its canvas is showing");
|
||||
}
|
||||
myCanvas = null;
|
||||
|
||||
if (null != eventRegistration) {
|
||||
((ImplObject)eventRegistration).delete();
|
||||
eventRegistration = null;
|
||||
}
|
||||
|
||||
if (null != navigation) {
|
||||
((ImplObject)navigation).delete();
|
||||
navigation = null;
|
||||
}
|
||||
|
||||
if (null != history) {
|
||||
((ImplObject)history).delete();
|
||||
history = null;
|
||||
}
|
||||
|
||||
if (null != currentPage) {
|
||||
((ImplObject)currentPage).delete();
|
||||
currentPage = null;
|
||||
}
|
||||
|
||||
Assert.assert(null != windowControl);
|
||||
((ImplObject)windowControl).delete();
|
||||
windowControl = null;
|
||||
|
||||
// since bookmarks is static, we must not deallocate it here. That
|
||||
// is done in the static method appTerminate
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Class methods
|
||||
//
|
||||
|
||||
static void initialize(String verifiedBinDirAbsolutePath) throws Exception
|
||||
static void appInitialize(String verifiedBinDirAbsolutePath) throws Exception
|
||||
{
|
||||
if (null == wrapperFactory) {
|
||||
wrapperFactory = createWrapperFactory();
|
||||
|
@ -95,10 +143,15 @@ static void initialize(String verifiedBinDirAbsolutePath) throws Exception
|
|||
wrapperFactory.initialize(verifiedBinDirAbsolutePath);
|
||||
}
|
||||
|
||||
static void terminate() throws Exception
|
||||
static void appTerminate() throws Exception
|
||||
{
|
||||
Assert.assert(null != wrapperFactory);
|
||||
|
||||
if (null != bookmarks) {
|
||||
((ImplObject)bookmarks).delete();
|
||||
bookmarks = null;
|
||||
}
|
||||
|
||||
wrapperFactory.terminate();
|
||||
}
|
||||
|
||||
|
@ -230,7 +283,7 @@ public static void main(String [] args)
|
|||
Assert.setEnabled(true);
|
||||
Log.setApplicationName("BrowserControlImpl");
|
||||
Log.setApplicationVersion("0.0");
|
||||
Log.setApplicationVersionDate("$Id: BrowserControlImpl.java,v 1.1 2000/03/04 01:10:51 edburns%acm.org Exp $");
|
||||
Log.setApplicationVersionDate("$Id: BrowserControlImpl.java,v 1.2 2000/03/13 18:41:46 edburns%acm.org Exp $");
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -110,4 +110,22 @@ public ImplObject(WrapperFactory yourFactory,
|
|||
myBrowserControl = yourBrowserControl;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* I know Java has automatic garbage collection and all, but explicitly
|
||||
* adding a delete method helps the gc algorithm out. <P>
|
||||
|
||||
* Subclasses should override this and call super.delete() at the end of
|
||||
* their overridden delete() method.
|
||||
|
||||
* @see org.mozilla.webclient.wrapper_native.ImplObjectNative#delete
|
||||
|
||||
*/
|
||||
|
||||
public void delete()
|
||||
{
|
||||
myFactory = null;
|
||||
myBrowserControl = null;
|
||||
}
|
||||
|
||||
} // end of class ImplObject
|
||||
|
|
|
@ -0,0 +1,329 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 RaptorCanvas.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Kirk Baker and
|
||||
* Ian Wilkinson. Portions created by Kirk Baker and Ian Wilkinson are
|
||||
* Copyright (C) 1999 Kirk Baker and Ian Wilkinson. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Kirk Baker <kbaker@eb.com>
|
||||
* Ian Wilkinson <iw@ennoble.com>
|
||||
* Mark Goddard
|
||||
* Ed Burns <edburns@acm.org>
|
||||
*/
|
||||
|
||||
package org.mozilla.webclient.test;
|
||||
|
||||
/*
|
||||
* EMWindow.java
|
||||
*/
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
import javax.swing.tree.TreeModel;
|
||||
import javax.swing.tree.TreeNode;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.mozilla.webclient.*;
|
||||
import org.mozilla.util.Assert;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
* This is a test application for using the BrowserControl.
|
||||
|
||||
*
|
||||
* @version $Id: EMWindow.java,v 1.1 2000/03/13 18:41:51 edburns%acm.org Exp $
|
||||
*
|
||||
* @see org.mozilla.webclient.BrowserControlFactory
|
||||
|
||||
*/
|
||||
|
||||
public class EMWindow extends Frame implements ActionListener, DocumentLoadListener {
|
||||
static final int defaultWidth = 640;
|
||||
static final int defaultHeight = 480;
|
||||
|
||||
private TextField urlField;
|
||||
private BrowserControl browserControl;
|
||||
private BrowserControlCanvas browserCanvas;
|
||||
|
||||
private CurrentPage currentPage;
|
||||
private Bookmarks bookmarks;
|
||||
private BookmarksFrame bookmarksFrame = null;
|
||||
private TreeModel bookmarksTree;
|
||||
private Panel controlPanel;
|
||||
private Panel buttonsPanel;
|
||||
|
||||
public static void main (String[] arg) {
|
||||
} // main()
|
||||
|
||||
public EMWindow (String title, String binDir, String url)
|
||||
{
|
||||
super(title);
|
||||
System.out.println("constructed with binDir: " + binDir + " url: " +
|
||||
url);
|
||||
setLocation(0, EmbeddedMozilla.height);
|
||||
setSize(defaultWidth, defaultHeight);
|
||||
|
||||
// Create the URL field
|
||||
urlField = new TextField("", 30);
|
||||
urlField.addActionListener(this);
|
||||
|
||||
// Create the buttons sub panel
|
||||
buttonsPanel = new Panel();
|
||||
buttonsPanel.setLayout(new GridBagLayout());
|
||||
|
||||
// Add the buttons
|
||||
makeItem(buttonsPanel, "Back", 0, 0, 1, 1, 0.0, 0.0);
|
||||
makeItem(buttonsPanel, "Forward", 1, 0, 1, 1, 0.0, 0.0);
|
||||
makeItem(buttonsPanel, "Stop", 2, 0, 1, 1, 0.0, 0.0);
|
||||
makeItem(buttonsPanel, "Refresh", 3, 0, 1, 1, 0.0, 0.0);
|
||||
makeItem(buttonsPanel, "Bookmarks", 4, 0, 1, 1, 0.0, 0.0);
|
||||
|
||||
// Create the control panel
|
||||
controlPanel = new Panel();
|
||||
controlPanel.setLayout(new BorderLayout());
|
||||
|
||||
// Add the URL field, and the buttons panel
|
||||
controlPanel.add(urlField, BorderLayout.CENTER);
|
||||
controlPanel.add(buttonsPanel, BorderLayout.WEST);
|
||||
|
||||
// Create the browser
|
||||
try {
|
||||
BrowserControlFactory.setAppData(binDir);
|
||||
browserControl = BrowserControlFactory.newBrowserControl();
|
||||
browserCanvas =
|
||||
(BrowserControlCanvas)
|
||||
browserControl.queryInterface(BrowserControl.BROWSER_CONTROL_CANVAS_NAME);
|
||||
|
||||
}
|
||||
catch(Exception e) {
|
||||
System.out.println("Can't create BrowserControl: " +
|
||||
e.getMessage());
|
||||
}
|
||||
Assert.assert(null != browserCanvas);
|
||||
browserCanvas.setSize(defaultWidth, defaultHeight);
|
||||
|
||||
// Add the control panel and the browserCanvas
|
||||
add(controlPanel, BorderLayout.NORTH);
|
||||
add(browserCanvas, BorderLayout.CENTER);
|
||||
|
||||
addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
System.out.println("Got windowClosing");
|
||||
System.out.println("destroying the BrowserControl");
|
||||
EMWindow.this.delete();
|
||||
// should close the BrowserControlCanvas
|
||||
}
|
||||
|
||||
public void windowClosed(WindowEvent e) {
|
||||
System.out.println("Got windowClosed");
|
||||
}
|
||||
});
|
||||
|
||||
pack();
|
||||
show();
|
||||
toFront();
|
||||
|
||||
Navigation navigation = null;
|
||||
|
||||
try {
|
||||
navigation = (Navigation)
|
||||
browserControl.queryInterface(BrowserControl.NAVIGATION_NAME);
|
||||
currentPage = (CurrentPage)
|
||||
browserControl.queryInterface(BrowserControl.CURRENT_PAGE_NAME);
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
|
||||
try {
|
||||
EventRegistration eventRegistration =
|
||||
(EventRegistration)
|
||||
browserControl.queryInterface(BrowserControl.EVENT_REGISTRATION_NAME);
|
||||
System.out.println("debug: edburns: adding DocumentLoadListener");
|
||||
eventRegistration.addDocumentLoadListener(this);
|
||||
|
||||
|
||||
// PENDING(edburns): test code, replace with production code
|
||||
bookmarks =
|
||||
(Bookmarks)
|
||||
browserControl.queryInterface(BrowserControl.BOOKMARKS_NAME);
|
||||
System.out.println("debug: edburns: got Bookmarks instance");
|
||||
|
||||
bookmarksTree = bookmarks.getBookmarks();
|
||||
TreeNode bookmarksRoot = (TreeNode) bookmarksTree.getRoot();
|
||||
|
||||
System.out.println("debug: edburns: testing the Enumeration");
|
||||
int childCount = bookmarksRoot.getChildCount();
|
||||
System.out.println("debug: edburns: root has " + childCount +
|
||||
" children.");
|
||||
|
||||
Enumeration rootChildren = bookmarksRoot.children();
|
||||
TreeNode currentChild;
|
||||
|
||||
int i = 0, childIndex;
|
||||
while (rootChildren.hasMoreElements()) {
|
||||
currentChild = (TreeNode) rootChildren.nextElement();
|
||||
System.out.println("debug: edburns: bookmarks root has children! child: " + i + " name: " + currentChild.toString());
|
||||
i++;
|
||||
}
|
||||
|
||||
System.out.println("debug: edburns: testing getChildAt(" + --i + "): ");
|
||||
currentChild = bookmarksRoot.getChildAt(i);
|
||||
System.out.println("debug: edburns: testing getIndex(Child " +
|
||||
i + "): index should be " + i + ".");
|
||||
childIndex = bookmarksRoot.getIndex(currentChild);
|
||||
System.out.println("debug: edburns: index is: " + childIndex);
|
||||
|
||||
/**********
|
||||
BookmarkEntry folder = bookmarks.newBookmarkFolder("newFolder");
|
||||
|
||||
bookmarks.addBookmark(null, folder);
|
||||
|
||||
BookmarkEntry entry = bookmarks.newBookmarkEntry("http://yoyo.com");
|
||||
System.out.println("debug: edburns: got new entry");
|
||||
|
||||
Properties entryProps = entry.getProperties();
|
||||
|
||||
System.out.println("debug: edburns: entry url: " +
|
||||
entryProps.getProperty(BookmarkEntry.URL));
|
||||
bookmarks.addBookmark(folder, entry);
|
||||
**********/
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
|
||||
if (null != navigation) {
|
||||
navigation.loadURL(url);
|
||||
}
|
||||
} // EMWindow() ctor
|
||||
|
||||
public void delete()
|
||||
{
|
||||
browserCanvas.setVisible(false);
|
||||
if (null != bookmarksFrame) {
|
||||
bookmarksFrame.setVisible(false);
|
||||
bookmarksFrame.dispose();
|
||||
bookmarksFrame = null;
|
||||
}
|
||||
BrowserControlFactory.deleteBrowserControl(browserControl);
|
||||
browserControl = null;
|
||||
System.out.println("debug: edburns: about to hide");
|
||||
this.hide();
|
||||
System.out.println("debug: edburns: about to dispose");
|
||||
this.dispose();
|
||||
urlField = null;
|
||||
browserCanvas = null;
|
||||
currentPage = null;
|
||||
bookmarks = null;
|
||||
bookmarksTree = null;
|
||||
controlPanel = null;
|
||||
buttonsPanel = null;
|
||||
}
|
||||
|
||||
|
||||
public void actionPerformed (ActionEvent evt) {
|
||||
String command = evt.getActionCommand();
|
||||
|
||||
|
||||
try {
|
||||
Navigation navigation = (Navigation)
|
||||
browserControl.queryInterface(BrowserControl.NAVIGATION_NAME);
|
||||
CurrentPage currentPage = (CurrentPage)
|
||||
browserControl.queryInterface(BrowserControl.CURRENT_PAGE_NAME);
|
||||
History history = (History)
|
||||
browserControl.queryInterface(BrowserControl.HISTORY_NAME);
|
||||
if (command.equals("Stop")) {
|
||||
navigation.stop();
|
||||
}
|
||||
else if (command.equals("Refresh")) {
|
||||
navigation.refresh(Navigation.LOAD_NORMAL);
|
||||
}
|
||||
else if (command.equals("Bookmarks")) {
|
||||
if (null == bookmarksTree) {
|
||||
bookmarksTree = bookmarks.getBookmarks();
|
||||
}
|
||||
if (null == bookmarksFrame) {
|
||||
bookmarksFrame = new BookmarksFrame(bookmarksTree);
|
||||
bookmarksFrame.setSize(new Dimension(320,480));
|
||||
}
|
||||
bookmarksFrame.setVisible(true);
|
||||
}
|
||||
else if (command.equals("Back")) {
|
||||
if (history.canBack()) {
|
||||
history.back();
|
||||
}
|
||||
}
|
||||
else if (command.equals("Forward")) {
|
||||
if (history.canForward()) {
|
||||
history.forward();
|
||||
}
|
||||
}
|
||||
else {
|
||||
navigation.loadURL(urlField.getText());
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
} // actionPerformed()
|
||||
|
||||
|
||||
private void makeItem (Panel p, Object arg, int x, int y, int w, int h, double weightx, double weighty) {
|
||||
GridBagLayout gbl = (GridBagLayout) p.getLayout();
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
Component comp;
|
||||
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.gridx = x;
|
||||
c.gridy = y;
|
||||
c.gridwidth = w;
|
||||
c.gridheight = h;
|
||||
c.weightx = weightx;
|
||||
c.weighty = weighty;
|
||||
if (arg instanceof String) {
|
||||
Button b;
|
||||
|
||||
comp = b = new Button((String) arg);
|
||||
b.addActionListener(this);
|
||||
|
||||
p.add(comp);
|
||||
gbl.setConstraints(comp, c);
|
||||
}
|
||||
} // makeItem()
|
||||
|
||||
|
||||
//
|
||||
// From DocumentLoadListener
|
||||
//
|
||||
|
||||
public void eventDispatched(WebclientEvent event)
|
||||
{
|
||||
if (event instanceof DocumentLoadEvent) {
|
||||
String currentURL = currentPage.getCurrentURL();
|
||||
System.out.println("debug: edburns: Currently Viewing: " +
|
||||
currentURL);
|
||||
urlField.setText(currentURL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -32,12 +32,6 @@ package org.mozilla.webclient.test;
|
|||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
import javax.swing.tree.TreeModel;
|
||||
import javax.swing.tree.TreeNode;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.mozilla.webclient.*;
|
||||
import org.mozilla.util.Assert;
|
||||
|
||||
|
@ -47,271 +41,113 @@ import org.mozilla.util.Assert;
|
|||
* This is a test application for using the BrowserControl.
|
||||
|
||||
*
|
||||
* @version $Id: EmbeddedMozilla.java,v 1.1 2000/03/04 01:10:54 edburns%acm.org Exp $
|
||||
* @version $Id: EmbeddedMozilla.java,v 1.2 2000/03/13 18:42:02 edburns%acm.org Exp $
|
||||
*
|
||||
* @see org.mozilla.webclient.BrowserControlFactory
|
||||
|
||||
*/
|
||||
|
||||
public class EmbeddedMozilla extends Frame implements ActionListener, DocumentLoadListener {
|
||||
static final int defaultWidth = 640;
|
||||
static final int defaultHeight = 480;
|
||||
public class EmbeddedMozilla extends Frame implements ActionListener
|
||||
{
|
||||
|
||||
private TextField urlField;
|
||||
private BrowserControl browserControl;
|
||||
private CurrentPage currentPage;
|
||||
private Bookmarks bookmarks;
|
||||
private TreeModel bookmarksTree;
|
||||
private Panel controlPanel;
|
||||
private Panel buttonsPanel;
|
||||
public static String binDir;
|
||||
public static String url;
|
||||
public static int winCount = 0;
|
||||
public static String NEW_BUTTON_LABEL = "New Window";
|
||||
|
||||
public static int width = 200;
|
||||
public static int height = 100;
|
||||
|
||||
private Panel buttonPanel;
|
||||
|
||||
public static void printUsage()
|
||||
{
|
||||
System.out.println("usage: java org.mozilla.webclient.test.EmbeddedMozilla <path> [url]");
|
||||
System.out.println("usage: java org.mozilla.webclient.test.EMWindow <path> [url]");
|
||||
System.out.println(" <path> is the absolute path to the native browser bin directory, ");
|
||||
System.out.println(" including the bin.");
|
||||
}
|
||||
|
||||
|
||||
public static void main (String[] arg) {
|
||||
if (1 > arg.length) {
|
||||
printUsage();
|
||||
System.exit(-1);
|
||||
}
|
||||
String urlArg =(2 == arg.length) ? arg[1] : "file:///E|/Projects/tmp/5105.html";
|
||||
|
||||
EmbeddedMozilla gecko =
|
||||
new EmbeddedMozilla("Embedded Mozilla", arg[0], urlArg);
|
||||
} // main()
|
||||
|
||||
public EmbeddedMozilla (String title, String binDir, String url)
|
||||
{
|
||||
super(title);
|
||||
System.out.println("constructed with binDir: " + binDir + " url: " +
|
||||
url);
|
||||
|
||||
setSize(defaultWidth, defaultHeight);
|
||||
|
||||
// Create the URL field
|
||||
urlField = new TextField("", 30);
|
||||
urlField.addActionListener(this);
|
||||
|
||||
// Create the buttons sub panel
|
||||
buttonsPanel = new Panel();
|
||||
buttonsPanel.setLayout(new GridBagLayout());
|
||||
|
||||
// Add the buttons
|
||||
makeItem(buttonsPanel, "Back", 0, 0, 1, 1, 0.0, 0.0);
|
||||
makeItem(buttonsPanel, "Forward", 1, 0, 1, 1, 0.0, 0.0);
|
||||
makeItem(buttonsPanel, "Stop", 2, 0, 1, 1, 0.0, 0.0);
|
||||
makeItem(buttonsPanel, "Refresh", 3, 0, 1, 1, 0.0, 0.0);
|
||||
makeItem(buttonsPanel, "Bookmarks", 4, 0, 1, 1, 0.0, 0.0);
|
||||
|
||||
// Create the control panel
|
||||
controlPanel = new Panel();
|
||||
controlPanel.setLayout(new BorderLayout());
|
||||
|
||||
// Add the URL field, and the buttons panel
|
||||
controlPanel.add(urlField, BorderLayout.CENTER);
|
||||
controlPanel.add(buttonsPanel, BorderLayout.WEST);
|
||||
|
||||
// Create the browser
|
||||
BrowserControlCanvas browserCanvas = null;
|
||||
|
||||
try {
|
||||
BrowserControlFactory.setAppData(binDir);
|
||||
browserControl = BrowserControlFactory.newBrowserControl();
|
||||
browserCanvas =
|
||||
(BrowserControlCanvas)
|
||||
browserControl.queryInterface(BrowserControl.BROWSER_CONTROL_CANVAS_NAME);
|
||||
|
||||
}
|
||||
catch(Exception e) {
|
||||
System.out.println("Can't create BrowserControl: " +
|
||||
e.getMessage());
|
||||
}
|
||||
Assert.assert(null != browserCanvas);
|
||||
browserCanvas.setSize(defaultWidth, defaultHeight);
|
||||
|
||||
// Add the control panel and the browserCanvas
|
||||
add(controlPanel, BorderLayout.NORTH);
|
||||
add(browserCanvas, BorderLayout.CENTER);
|
||||
|
||||
addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
dispose();
|
||||
System.out.println("Got windowClosing");
|
||||
// should close the BrowserControlCanvas
|
||||
}
|
||||
|
||||
public void windowClosed(WindowEvent e) {
|
||||
System.out.println("Got windowClosed");
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
pack();
|
||||
show();
|
||||
toFront();
|
||||
|
||||
Navigation navigation = null;
|
||||
|
||||
try {
|
||||
navigation = (Navigation)
|
||||
browserControl.queryInterface(BrowserControl.NAVIGATION_NAME);
|
||||
currentPage = (CurrentPage)
|
||||
browserControl.queryInterface(BrowserControl.CURRENT_PAGE_NAME);
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
|
||||
try {
|
||||
EventRegistration eventRegistration =
|
||||
(EventRegistration)
|
||||
browserControl.queryInterface(BrowserControl.EVENT_REGISTRATION_NAME);
|
||||
System.out.println("debug: edburns: adding DocumentLoadListener");
|
||||
eventRegistration.addDocumentLoadListener(this);
|
||||
|
||||
|
||||
// PENDING(edburns): test code, replace with production code
|
||||
bookmarks =
|
||||
(Bookmarks)
|
||||
browserControl.queryInterface(BrowserControl.BOOKMARKS_NAME);
|
||||
System.out.println("debug: edburns: got Bookmarks instance");
|
||||
|
||||
bookmarksTree = bookmarks.getBookmarks();
|
||||
TreeNode bookmarksRoot = (TreeNode) bookmarksTree.getRoot();
|
||||
|
||||
System.out.println("debug: edburns: testing the Enumeration");
|
||||
int childCount = bookmarksRoot.getChildCount();
|
||||
System.out.println("debug: edburns: root has " + childCount +
|
||||
" children.");
|
||||
|
||||
Enumeration rootChildren = bookmarksRoot.children();
|
||||
TreeNode currentChild;
|
||||
|
||||
int i = 0, childIndex;
|
||||
while (rootChildren.hasMoreElements()) {
|
||||
currentChild = (TreeNode) rootChildren.nextElement();
|
||||
System.out.println("debug: edburns: bookmarks root has children! child: " + i + " name: " + currentChild.toString());
|
||||
i++;
|
||||
}
|
||||
|
||||
System.out.println("debug: edburns: testing getChildAt(" + --i + "): ");
|
||||
currentChild = bookmarksRoot.getChildAt(i);
|
||||
System.out.println("debug: edburns: testing getIndex(Child " +
|
||||
i + "): index should be " + i + ".");
|
||||
childIndex = bookmarksRoot.getIndex(currentChild);
|
||||
System.out.println("debug: edburns: index is: " + childIndex);
|
||||
|
||||
/**********
|
||||
BookmarkEntry folder = bookmarks.newBookmarkFolder("newFolder");
|
||||
|
||||
bookmarks.addBookmark(null, folder);
|
||||
|
||||
BookmarkEntry entry = bookmarks.newBookmarkEntry("http://yoyo.com");
|
||||
System.out.println("debug: edburns: got new entry");
|
||||
|
||||
Properties entryProps = entry.getProperties();
|
||||
|
||||
System.out.println("debug: edburns: entry url: " +
|
||||
entryProps.getProperty(BookmarkEntry.URL));
|
||||
bookmarks.addBookmark(folder, entry);
|
||||
**********/
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
|
||||
if (null != navigation) {
|
||||
navigation.loadURL(url);
|
||||
}
|
||||
} // EmbeddedMozilla() ctor
|
||||
|
||||
|
||||
public void actionPerformed (ActionEvent evt) {
|
||||
String command = evt.getActionCommand();
|
||||
|
||||
|
||||
try {
|
||||
Navigation navigation = (Navigation)
|
||||
browserControl.queryInterface(BrowserControl.NAVIGATION_NAME);
|
||||
CurrentPage currentPage = (CurrentPage)
|
||||
browserControl.queryInterface(BrowserControl.CURRENT_PAGE_NAME);
|
||||
History history = (History)
|
||||
browserControl.queryInterface(BrowserControl.HISTORY_NAME);
|
||||
if (command.equals("Stop")) {
|
||||
navigation.stop();
|
||||
}
|
||||
else if (command.equals("Refresh")) {
|
||||
navigation.refresh(Navigation.LOAD_NORMAL);
|
||||
}
|
||||
else if (command.equals("Bookmarks")) {
|
||||
if (null == bookmarksTree) {
|
||||
bookmarksTree = bookmarks.getBookmarks();
|
||||
}
|
||||
BookmarksFrame frame = new BookmarksFrame(bookmarksTree);
|
||||
frame.setSize(new Dimension(320,480));
|
||||
frame.setVisible(true);
|
||||
}
|
||||
else if (command.equals("Back")) {
|
||||
if (history.canBack()) {
|
||||
history.back();
|
||||
}
|
||||
}
|
||||
else if (command.equals("Forward")) {
|
||||
if (history.canForward()) {
|
||||
history.forward();
|
||||
}
|
||||
}
|
||||
else {
|
||||
navigation.loadURL(urlField.getText());
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
} // actionPerformed()
|
||||
|
||||
|
||||
private void makeItem (Panel p, Object arg, int x, int y, int w, int h, double weightx, double weighty) {
|
||||
GridBagLayout gbl = (GridBagLayout) p.getLayout();
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
Component comp;
|
||||
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.gridx = x;
|
||||
c.gridy = y;
|
||||
c.gridwidth = w;
|
||||
c.gridheight = h;
|
||||
c.weightx = weightx;
|
||||
c.weighty = weighty;
|
||||
if (arg instanceof String) {
|
||||
Button b;
|
||||
|
||||
comp = b = new Button((String) arg);
|
||||
b.addActionListener(this);
|
||||
|
||||
p.add(comp);
|
||||
gbl.setConstraints(comp, c);
|
||||
}
|
||||
} // makeItem()
|
||||
|
||||
|
||||
//
|
||||
// From DocumentLoadListener
|
||||
//
|
||||
|
||||
public void eventDispatched(WebclientEvent event)
|
||||
public EmbeddedMozilla()
|
||||
{
|
||||
if (event instanceof DocumentLoadEvent) {
|
||||
String currentURL = currentPage.getCurrentURL();
|
||||
System.out.println("debug: edburns: Currently Viewing: " +
|
||||
currentURL);
|
||||
urlField.setText(currentURL);
|
||||
super("EmbeddedMozilla Launcher");
|
||||
setSize(200, 100);
|
||||
buttonPanel = new Panel();
|
||||
buttonPanel.setLayout(new GridBagLayout());
|
||||
|
||||
// Add the buttons
|
||||
makeItem(buttonPanel, NEW_BUTTON_LABEL, 0, 0, 1, 1, 0.0, 0.0);
|
||||
add(buttonPanel, BorderLayout.CENTER);
|
||||
|
||||
addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
System.out.println("Got windowClosing");
|
||||
System.out.println("bye");
|
||||
System.exit(0);
|
||||
// should close the BrowserControlCanvas
|
||||
}
|
||||
|
||||
public void windowClosed(WindowEvent e) {
|
||||
System.out.println("Got windowClosed");
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
pack();
|
||||
show();
|
||||
toFront();
|
||||
}
|
||||
|
||||
public void actionPerformed (ActionEvent evt)
|
||||
{
|
||||
String command = evt.getActionCommand();
|
||||
EMWindow newWindow;
|
||||
|
||||
if (command.equals(NEW_BUTTON_LABEL)) {
|
||||
System.out.println("Creating new EmbeddedMozilla window");
|
||||
newWindow = new EMWindow("EmbeddedMozila#" + winCount++,
|
||||
binDir, url);
|
||||
}
|
||||
} // actionPerformed()
|
||||
|
||||
|
||||
private void makeItem (Panel p, Object arg, int x, int y, int w,
|
||||
int h, double weightx, double weighty)
|
||||
{
|
||||
GridBagLayout gbl = (GridBagLayout) p.getLayout();
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
Component comp;
|
||||
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.gridx = x;
|
||||
c.gridy = y;
|
||||
c.gridwidth = w;
|
||||
c.gridheight = h;
|
||||
c.weightx = weightx;
|
||||
c.weighty = weighty;
|
||||
if (arg instanceof String) {
|
||||
Button b;
|
||||
|
||||
comp = b = new Button((String) arg);
|
||||
b.addActionListener(this);
|
||||
|
||||
p.add(comp);
|
||||
gbl.setConstraints(comp, c);
|
||||
}
|
||||
} // makeItem()
|
||||
|
||||
|
||||
public static void main(String [] arg)
|
||||
{
|
||||
if (1 > arg.length) {
|
||||
printUsage();
|
||||
System.exit(-1);
|
||||
}
|
||||
String urlArg =(2 == arg.length) ? arg[1] : "file:///E|/Projects/tmp/5105.html";
|
||||
|
||||
// set class vars used in EmbeddedMozilla ctor
|
||||
binDir = arg[0];
|
||||
url = urlArg;
|
||||
EmbeddedMozilla em = new EmbeddedMozilla();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -73,6 +73,26 @@ public BookmarksImpl(WrapperFactory yourFactory,
|
|||
super(yourFactory, yourBrowserControl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Since this class is a singleton, we don't expect this method to be
|
||||
* called until the app is done with bookmarks for a considerable amount
|
||||
* of time.
|
||||
|
||||
// PENDING(): Write test case to see that a cycle of Bookmarks
|
||||
// allocation/destruction/new instance allocation works correctly.
|
||||
|
||||
*/
|
||||
|
||||
public void delete()
|
||||
{
|
||||
// we rely on the individual BookmarkEntryImpl instances' finalize
|
||||
// methods to be called to correctly de-allocate the native RDF
|
||||
// references.
|
||||
|
||||
bookmarksTree = null;
|
||||
}
|
||||
|
||||
//
|
||||
// Class methods
|
||||
//
|
||||
|
@ -199,7 +219,7 @@ public static void main(String [] args)
|
|||
|
||||
Log.setApplicationName("BookmarksImpl");
|
||||
Log.setApplicationVersion("0.0");
|
||||
Log.setApplicationVersionDate("$Id: BookmarksImpl.java,v 1.2 2000/03/09 23:22:50 edburns%acm.org Exp $");
|
||||
Log.setApplicationVersionDate("$Id: BookmarksImpl.java,v 1.3 2000/03/13 18:42:08 edburns%acm.org Exp $");
|
||||
|
||||
try {
|
||||
org.mozilla.webclient.BrowserControlFactory.setAppData(args[0]);
|
||||
|
|
|
@ -85,6 +85,16 @@ public EventRegistrationImpl(WrapperFactory yourFactory,
|
|||
}
|
||||
}
|
||||
|
||||
public void delete()
|
||||
{
|
||||
// PENDING(ashuk): remove all listeners, making sure to set
|
||||
// references to null
|
||||
|
||||
nativeEventThread = null;
|
||||
|
||||
super.delete();
|
||||
}
|
||||
|
||||
//
|
||||
// Class methods
|
||||
//
|
||||
|
@ -117,14 +127,6 @@ public void removeDocumentLoadListener(DocumentLoadListener listener)
|
|||
}
|
||||
}
|
||||
|
||||
public void testListenerSubclass(WebclientEventListener listener)
|
||||
{
|
||||
if (listener instanceof DocumentLoadListener) {
|
||||
System.out.println("debug: edburns: EventRegistrationImpl.testListenerSubclass: DocumentLoadListener");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----VERTIGO_TEST_START
|
||||
|
||||
//
|
||||
|
@ -137,7 +139,7 @@ public static void main(String [] args)
|
|||
|
||||
Log.setApplicationName("EventRegistrationImpl");
|
||||
Log.setApplicationVersion("0.0");
|
||||
Log.setApplicationVersionDate("$Id: EventRegistrationImpl.java,v 1.2 2000/03/09 23:22:50 edburns%acm.org Exp $");
|
||||
Log.setApplicationVersionDate("$Id: EventRegistrationImpl.java,v 1.3 2000/03/13 18:42:23 edburns%acm.org Exp $");
|
||||
|
||||
try {
|
||||
org.mozilla.webclient.BrowserControlFactory.setAppData(args[0]);
|
||||
|
|
|
@ -76,7 +76,8 @@ public abstract class ImplObjectNative extends ImplObject
|
|||
|
||||
/**
|
||||
|
||||
* a handle to the actual mozilla webShell, obtained from WindowControl
|
||||
* a handle to the actual mozilla webShell, owned, allocated, and
|
||||
* released by WindowControl
|
||||
|
||||
*/
|
||||
|
||||
|
@ -121,4 +122,33 @@ public ImplObjectNative(WrapperFactory yourFactory,
|
|||
super(yourFactory, yourBrowserControl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Note how we call super.delete() at the end. THIS IS VERY IMPORTANT. <P>
|
||||
|
||||
* Also, note how we don't de-allocate nativeWebShell, that is done in
|
||||
* the class that owns the nativeWebShell reference, WindowControlImpl. <P>
|
||||
|
||||
* ImplObjectNative subclasses that further override delete() are <P>
|
||||
|
||||
<CODE><PRE>
|
||||
BookmarksImpl.java
|
||||
EventRegistrationImpl.java
|
||||
NativeEventThread.java
|
||||
WindowControlImpl.java
|
||||
</PRE><CODE> <P>
|
||||
|
||||
* All other ImplObject subclasses don't have any local Ivars and thus
|
||||
* don't need to override delete().
|
||||
|
||||
*/
|
||||
|
||||
public void delete()
|
||||
{
|
||||
nativeWebShell = -1;
|
||||
System.out.println("debug: edburns: ImplObjectNative.delete()");
|
||||
super.delete();
|
||||
}
|
||||
|
||||
|
||||
} // end of class ImplObject
|
||||
|
|
|
@ -122,6 +122,32 @@ public NativeEventThread(String threadName, BrowserControl yourBrowserControl)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* This is a very delicate method, and possibly subject to race
|
||||
* condition problems. To combat this, our first step is to set our
|
||||
* browserControlCanvas to null, within a synchronized block which
|
||||
* synchronizes on the same object used in the run() method's event
|
||||
* loop. By setting the browserControlCanvas ivar to null, we cause the
|
||||
* run method to return.
|
||||
|
||||
*/
|
||||
|
||||
public void delete()
|
||||
{
|
||||
// setting this to null causes the run thread to exit
|
||||
synchronized(this.browserControlCanvas.getTreeLock()) {
|
||||
browserControlCanvas = null;
|
||||
}
|
||||
// PENDING(ashuk): do any necessary cleanup.
|
||||
listenersToAdd = null;
|
||||
listenersToRemove = null;
|
||||
nativeWebShell = -1;
|
||||
windowControl = null;
|
||||
browserControl = null;
|
||||
tempEnum = null;
|
||||
}
|
||||
|
||||
//
|
||||
// Methods from Thread
|
||||
//
|
||||
|
@ -162,7 +188,7 @@ public void run()
|
|||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
while (null != this.browserControlCanvas) {
|
||||
synchronized (this.browserControlCanvas.getTreeLock()) {
|
||||
nativeProcessEvents(nativeWebShell);
|
||||
|
||||
|
|
|
@ -62,6 +62,23 @@ public WindowControlImpl(WrapperFactory yourFactory,
|
|||
super(yourFactory, yourBrowserControl, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* First, we delete our eventThread, which causes the eventThread to
|
||||
* stop running. Then we call nativeDestroyInitContext(), which
|
||||
* deallocates native resources for this window.
|
||||
|
||||
*/
|
||||
|
||||
public void delete()
|
||||
{
|
||||
Assert.assert(null != eventThread, "eventThread shouldn't be null at delete time");
|
||||
eventThread.delete();
|
||||
eventThread = null;
|
||||
nativeDestroyInitContext(nativeWebShell);
|
||||
nativeWebShell = -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Class methods
|
||||
//
|
||||
|
@ -201,6 +218,8 @@ public native void nativeSetBounds(int webShellPtr, int x, int y,
|
|||
public native int nativeCreateInitContext(int nativeWindow,
|
||||
int x, int y, int width, int height, BrowserControl myBrowserControlImpl);
|
||||
|
||||
public native void nativeDestroyInitContext(int nativeWindow);
|
||||
|
||||
public native void nativeMoveWindowTo(int webShellPtr, int x, int y);
|
||||
|
||||
public native void nativeRemoveFocus(int webShellPtr);
|
||||
|
@ -224,7 +243,7 @@ public static void main(String [] args)
|
|||
|
||||
Log.setApplicationName("WindowControlImpl");
|
||||
Log.setApplicationVersion("0.0");
|
||||
Log.setApplicationVersionDate("$Id: WindowControlImpl.java,v 1.3 2000/03/09 23:22:52 edburns%acm.org Exp $");
|
||||
Log.setApplicationVersionDate("$Id: WindowControlImpl.java,v 1.4 2000/03/13 18:42:31 edburns%acm.org Exp $");
|
||||
|
||||
try {
|
||||
org.mozilla.webclient.BrowserControlFactory.setAppData(args[0]);
|
||||
|
|
|
@ -387,7 +387,7 @@ nsresult InitMozillaStuff (WebShellInitContext * initContext)
|
|||
printf("InitMozillaStuff(%lx): Create the WebShell...\n", initContext);
|
||||
#endif
|
||||
// Create the WebShell.
|
||||
rv = nsRepository::CreateInstance(kWebShellCID, nsnull, kIWebShellIID, (void**)&initContext->webShell);
|
||||
rv = nsRepository::CreateInstance(kWebShellCID, nsnull, kIWebShellIID, getter_AddRefs(initContext->webShell));
|
||||
if (NS_FAILED(rv)) {
|
||||
initContext->initFailCode = kCreateWebShellError;
|
||||
return rv;
|
||||
|
|
|
@ -133,6 +133,44 @@ JNIEXPORT jint JNICALL Java_org_mozilla_webclient_wrapper_1native_WindowControlI
|
|||
return (jint) initContext;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_mozilla_webclient_wrapper_1native_WindowControlImpl_nativeDestroyInitContext
|
||||
(JNIEnv *env, jobject obj, jint webShellPtr)
|
||||
{
|
||||
WebShellInitContext* initContext = (WebShellInitContext *) webShellPtr;
|
||||
|
||||
if (initContext == nsnull) {
|
||||
::util_ThrowExceptionToJava(env, "Exception: null webShellPtr passed to nativeDestroyInitContext");
|
||||
return;
|
||||
}
|
||||
|
||||
initContext->parentHWnd = nsnull;
|
||||
// ((nsISupports *)initContext->docShell)->Release();
|
||||
initContext->docShell = nsnull;
|
||||
// ((nsISupports *)initContext->webShell)->Release();
|
||||
initContext->webShell = nsnull;
|
||||
|
||||
//NOTE we don't de-allocate the global session history here.
|
||||
initContext->sessionHistory = nsnull;
|
||||
|
||||
// PENDING(edburns): not sure if these need to be deleted
|
||||
initContext->actionQueue = nsnull;
|
||||
initContext->embeddedThread = nsnull;
|
||||
initContext->env = nsnull;
|
||||
initContext->nativeEventThread = nsnull;
|
||||
initContext->stopThread = -1;
|
||||
initContext->initComplete = FALSE;
|
||||
initContext->initFailCode = 0;
|
||||
initContext->x = -1;
|
||||
initContext->y = -1;
|
||||
initContext->w = -1;
|
||||
initContext->h = -1;
|
||||
initContext->gtkWinPtr = nsnull;
|
||||
|
||||
delete initContext;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_mozilla_webclient_wrapper_1native_WindowControlImpl_nativeMoveWindowTo
|
||||
(JNIEnv *env, jobject obj, jint webShellPtr, jint x, jint y)
|
||||
{
|
||||
|
|
|
@ -65,7 +65,7 @@ struct WebShellInitContext {
|
|||
// PENDING(mark): Don't we need something for Mac?
|
||||
HWND parentHWnd;
|
||||
#endif
|
||||
nsIWebShell * webShell;
|
||||
nsCOMPtr<nsIWebShell> webShell;
|
||||
nsCOMPtr<nsIDocShell> docShell;
|
||||
nsISessionHistory* sessionHistory;
|
||||
PLEventQueue * actionQueue;
|
||||
|
|
Загрузка…
Ссылка в новой задаче