0001: /*******************************************************************************
0002: * Copyright (c) 2003, 2006 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.swt.browser;
0011:
0012: import org.eclipse.swt.*;
0013: import org.eclipse.swt.graphics.*;
0014: import org.eclipse.swt.internal.ole.win32.*;
0015: import org.eclipse.swt.internal.win32.*;
0016: import org.eclipse.swt.ole.win32.*;
0017: import org.eclipse.swt.widgets.*;
0018:
0019: /**
0020: * Instances of this class implement the browser user interface
0021: * metaphor. It allows the user to visualize and navigate through
0022: * HTML documents.
0023: * <p>
0024: * Note that although this class is a subclass of <code>Composite</code>,
0025: * it does not make sense to set a layout on it.
0026: * </p><p>
0027: * IMPORTANT: This class is <em>not</em> intended to be subclassed.
0028: * </p>
0029: *
0030: * @since 3.0
0031: */
0032: public class Browser extends Composite {
0033:
0034: OleFrame frame;
0035: OleControlSite site;
0036: OleAutomation auto;
0037:
0038: boolean back, forward, navigate, delaySetText, ignoreDispose;
0039: Point location;
0040: Point size;
0041: boolean addressBar = true, menuBar = true, statusBar = true,
0042: toolBar = true;
0043: int info;
0044:
0045: int globalDispatch;
0046: String html;
0047:
0048: /* External Listener management */
0049: CloseWindowListener[] closeWindowListeners = new CloseWindowListener[0];
0050: LocationListener[] locationListeners = new LocationListener[0];
0051: OpenWindowListener[] openWindowListeners = new OpenWindowListener[0];
0052: ProgressListener[] progressListeners = new ProgressListener[0];
0053: StatusTextListener[] statusTextListeners = new StatusTextListener[0];
0054: TitleListener[] titleListeners = new TitleListener[0];
0055: VisibilityWindowListener[] visibilityWindowListeners = new VisibilityWindowListener[0];
0056:
0057: static final int BeforeNavigate2 = 0xfa;
0058: static final int CommandStateChange = 0x69;
0059: static final int DocumentComplete = 0x103;
0060: static final int NavigateComplete2 = 0xfc;
0061: static final int NewWindow2 = 0xfb;
0062: static final int OnMenuBar = 0x100;
0063: static final int OnStatusBar = 0x101;
0064: static final int OnToolBar = 0xff;
0065: static final int OnVisible = 0xfe;
0066: static final int ProgressChange = 0x6c;
0067: static final int RegisterAsBrowser = 0x228;
0068: static final int StatusTextChange = 0x66;
0069: static final int TitleChange = 0x71;
0070: static final int WindowClosing = 0x107;
0071: static final int WindowSetHeight = 0x10b;
0072: static final int WindowSetLeft = 0x108;
0073: static final int WindowSetResizable = 0x106;
0074: static final int WindowSetTop = 0x109;
0075: static final int WindowSetWidth = 0x10a;
0076:
0077: static final short CSC_NAVIGATEFORWARD = 1;
0078: static final short CSC_NAVIGATEBACK = 2;
0079: static final int INET_E_DEFAULT_ACTION = 0x800C0011;
0080: static final int READYSTATE_COMPLETE = 4;
0081: static final int URLPOLICY_ALLOW = 0x00;
0082: static final int URLPOLICY_DISALLOW = 0x03;
0083: static final int URLZONE_LOCAL_MACHINE = 0;
0084: static final int URLZONE_INTRANET = 1;
0085: static final int URLACTION_ACTIVEX_MIN = 0x00001200;
0086: static final int URLACTION_ACTIVEX_MAX = 0x000013ff;
0087: static final int URLACTION_ACTIVEX_RUN = 0x00001200;
0088: static final int URLACTION_JAVA_MIN = 0x00001C00;
0089: static final int URLPOLICY_JAVA_LOW = 0x00030000;
0090: static final int URLACTION_JAVA_MAX = 0x00001Cff;
0091:
0092: static final int DISPID_AMBIENT_DLCONTROL = -5512;
0093: static final int DLCTL_DLIMAGES = 0x00000010;
0094: static final int DLCTL_VIDEOS = 0x00000020;
0095: static final int DLCTL_BGSOUNDS = 0x00000040;
0096: static final int DLCTL_NO_SCRIPTS = 0x00000080;
0097: static final int DLCTL_NO_JAVA = 0x00000100;
0098: static final int DLCTL_NO_RUNACTIVEXCTLS = 0x00000200;
0099: static final int DLCTL_NO_DLACTIVEXCTLS = 0x00000400;
0100: static final int DLCTL_DOWNLOADONLY = 0x00000800;
0101: static final int DLCTL_NO_FRAMEDOWNLOAD = 0x00001000;
0102: static final int DLCTL_RESYNCHRONIZE = 0x00002000;
0103: static final int DLCTL_PRAGMA_NO_CACHE = 0x00004000;
0104: static final int DLCTL_FORCEOFFLINE = 0x10000000;
0105: static final int DLCTL_NO_CLIENTPULL = 0x20000000;
0106: static final int DLCTL_SILENT = 0x40000000;
0107: static final int DOCHOSTUIFLAG_THEME = 0x00040000;
0108: static final int DOCHOSTUIFLAG_NO3DBORDER = 0x0000004;
0109: static final int DOCHOSTUIFLAG_NO3DOUTERBORDER = 0x00200000;
0110:
0111: static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$
0112: static final String CLSID_SHELLEXPLORER1 = "{EAB22AC3-30C1-11CF-A7EB-0000C05BAE0B}";
0113: static final String URL_DIRECTOR = "http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab"; //$NON-NLS-1$
0114:
0115: /* Package Name */
0116: static final String PACKAGE_PREFIX = "org.eclipse.swt.browser."; //$NON-NLS-1$
0117:
0118: /**
0119: * Constructs a new instance of this class given its parent
0120: * and a style value describing its behavior and appearance.
0121: * <p>
0122: * The style value is either one of the style constants defined in
0123: * class <code>SWT</code> which is applicable to instances of this
0124: * class, or must be built by <em>bitwise OR</em>'ing together
0125: * (that is, using the <code>int</code> "|" operator) two or more
0126: * of those <code>SWT</code> style constants. The class description
0127: * lists the style constants that are applicable to the class.
0128: * Style bits are also inherited from superclasses.
0129: * </p>
0130: *
0131: * @param parent a widget which will be the parent of the new instance (cannot be null)
0132: * @param style the style of widget to construct
0133: *
0134: * @exception IllegalArgumentException <ul>
0135: * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
0136: * </ul>
0137: * @exception SWTException <ul>
0138: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
0139: * </ul>
0140: * @exception SWTError <ul>
0141: * <li>ERROR_NO_HANDLES if a handle could not be obtained for browser creation</li>
0142: * </ul>
0143: *
0144: * @see Widget#getStyle
0145: *
0146: * @since 3.0
0147: */
0148: public Browser(Composite parent, int style) {
0149: super (parent, style & ~SWT.BORDER);
0150: info = Browser.DOCHOSTUIFLAG_THEME;
0151: if ((style & SWT.BORDER) == 0)
0152: info |= Browser.DOCHOSTUIFLAG_NO3DOUTERBORDER;
0153: frame = new OleFrame(this , SWT.NONE);
0154:
0155: /*
0156: * Registry entry HKEY_CLASSES_ROOT\Shell.Explorer\CLSID indicates which version of
0157: * Shell.Explorer to use by default. We usually want to use this value because it
0158: * typically points at the newest one that is available. However it is possible for
0159: * this registry entry to be changed by another application to point at some other
0160: * Shell.Explorer version.
0161: *
0162: * The Browser depends on the Shell.Explorer version being at least Shell.Explorer.2.
0163: * If it is detected in the registry to be Shell.Explorer.1 then change the progId that
0164: * will be embedded to explicitly specify Shell.Explorer.2.
0165: */
0166: String progId = "Shell.Explorer"; //$NON-NLS-1$
0167: TCHAR key = new TCHAR(0, "Shell.Explorer\\CLSID", true); //$NON-NLS-1$
0168: int[] phkResult = new int[1];
0169: if (OS.RegOpenKeyEx(OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ,
0170: phkResult) == 0) {
0171: int[] lpcbData = new int[1];
0172: int result = OS.RegQueryValueEx(phkResult[0], null, 0,
0173: null, (TCHAR) null, lpcbData);
0174: if (result == 0) {
0175: TCHAR lpData = new TCHAR(0, lpcbData[0] / TCHAR.sizeof);
0176: result = OS.RegQueryValueEx(phkResult[0], null, 0,
0177: null, lpData, lpcbData);
0178: if (result == 0) {
0179: String clsid = lpData.toString(0, lpData.strlen());
0180: if (clsid.equals(CLSID_SHELLEXPLORER1)) {
0181: /* Shell.Explorer.1 is the default, ensure that Shell.Explorer.2 is available */
0182: key = new TCHAR(0, "Shell.Explorer.2", true); //$NON-NLS-1$
0183: int[] phkResult2 = new int[1];
0184: if (OS.RegOpenKeyEx(OS.HKEY_CLASSES_ROOT, key,
0185: 0, OS.KEY_READ, phkResult2) == 0) {
0186: /* specify that Shell.Explorer.2 is to be used */
0187: OS.RegCloseKey(phkResult2[0]);
0188: progId = "Shell.Explorer.2"; //$NON-NLS-1$
0189: }
0190: }
0191: }
0192: }
0193: OS.RegCloseKey(phkResult[0]);
0194: }
0195: try {
0196: site = new WebSite(frame, SWT.NONE, progId); //$NON-NLS-1$
0197: } catch (SWTException e) {
0198: dispose();
0199: SWT.error(SWT.ERROR_NO_HANDLES);
0200: }
0201:
0202: site.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
0203: auto = new OleAutomation(site);
0204:
0205: Listener listener = new Listener() {
0206: public void handleEvent(Event e) {
0207: switch (e.type) {
0208: case SWT.Dispose: {
0209: /* make this handler run after other dispose listeners */
0210: if (ignoreDispose) {
0211: ignoreDispose = false;
0212: break;
0213: }
0214: ignoreDispose = true;
0215: notifyListeners(e.type, e);
0216: e.type = SWT.NONE;
0217: if (auto != null)
0218: auto.dispose();
0219: auto = null;
0220: break;
0221: }
0222: case SWT.Resize: {
0223: frame.setBounds(getClientArea());
0224: break;
0225: }
0226: case SWT.KeyDown:
0227: case SWT.KeyUp: {
0228: notifyListeners(e.type, e);
0229: break;
0230: }
0231: }
0232: }
0233: };
0234: addListener(SWT.Dispose, listener);
0235: addListener(SWT.Resize, listener);
0236: site.addListener(SWT.KeyDown, listener);
0237: site.addListener(SWT.KeyUp, listener);
0238:
0239: OleListener oleListener = new OleListener() {
0240: public void handleEvent(OleEvent event) {
0241: if (auto == null)
0242: return; /* receiver was disposed, callback is asynchronous */
0243: switch (event.type) {
0244: case BeforeNavigate2: {
0245: Variant varResult = event.arguments[1];
0246: String url = varResult.getString();
0247: LocationEvent newEvent = new LocationEvent(
0248: Browser.this );
0249: newEvent.display = getDisplay();
0250: newEvent.widget = Browser.this ;
0251: newEvent.location = url;
0252: newEvent.doit = true;
0253: for (int i = 0; i < locationListeners.length; i++) {
0254: locationListeners[i].changing(newEvent);
0255: }
0256: Variant cancel = event.arguments[6];
0257: if (cancel != null) {
0258: int pCancel = cancel.getByRef();
0259: COM
0260: .MoveMemory(
0261: pCancel,
0262: new short[] { newEvent.doit ? COM.VARIANT_FALSE
0263: : COM.VARIANT_TRUE }, 2);
0264: }
0265: break;
0266: }
0267: case CommandStateChange: {
0268: boolean enabled = false;
0269: Variant varResult = event.arguments[0];
0270: int command = varResult.getInt();
0271: varResult = event.arguments[1];
0272: enabled = varResult.getBoolean();
0273: switch (command) {
0274: case CSC_NAVIGATEBACK:
0275: back = enabled;
0276: break;
0277: case CSC_NAVIGATEFORWARD:
0278: forward = enabled;
0279: break;
0280: }
0281: break;
0282: }
0283: case DocumentComplete: {
0284: Variant varResult = event.arguments[0];
0285: IDispatch dispatch = varResult.getDispatch();
0286:
0287: varResult = event.arguments[1];
0288: String url = varResult.getString();
0289: if (html != null && url.equals(ABOUT_BLANK)) {
0290: Runnable runnable = new Runnable() {
0291: public void run() {
0292: if (isDisposed() || html == null)
0293: return;
0294: int charCount = html.length();
0295: char[] chars = new char[charCount];
0296: html.getChars(0, charCount, chars, 0);
0297: html = null;
0298: int byteCount = OS.WideCharToMultiByte(
0299: OS.CP_UTF8, 0, chars,
0300: charCount, null, 0, null, null);
0301: /*
0302: * Note. Internet Explorer appears to treat the data loaded with
0303: * nsIPersistStreamInit.Load as if it were encoded using the default
0304: * local charset. There does not seem to be an API to set the
0305: * desired charset explicitely in this case. The fix is to
0306: * prepend the UTF-8 Byte Order Mark signature to the data.
0307: */
0308: byte[] UTF8BOM = { (byte) 0xEF,
0309: (byte) 0xBB, (byte) 0xBF };
0310: int hGlobal = OS.GlobalAlloc(
0311: OS.GMEM_FIXED
0312: | OS.GMEM_ZEROINIT,
0313: UTF8BOM.length + byteCount);
0314: if (hGlobal != 0) {
0315: OS.MoveMemory(hGlobal, UTF8BOM,
0316: UTF8BOM.length);
0317: OS.WideCharToMultiByte(OS.CP_UTF8,
0318: 0, chars, charCount,
0319: hGlobal + UTF8BOM.length,
0320: byteCount, null, null);
0321: int[] ppstm = new int[1];
0322: /*
0323: * Note. CreateStreamOnHGlobal is called with the flag fDeleteOnRelease.
0324: * If the call succeeds the buffer hGlobal is freed automatically
0325: * when the IStream object is released. If the call fails, free the buffer
0326: * hGlobal.
0327: */
0328: if (OS.CreateStreamOnHGlobal(
0329: hGlobal, true, ppstm) == OS.S_OK) {
0330: int[] rgdispid = auto
0331: .getIDsOfNames(new String[] { "Document" }); //$NON-NLS-1$
0332: Variant pVarResult = auto
0333: .getProperty(rgdispid[0]);
0334: IDispatch dispatchDocument = pVarResult
0335: .getDispatch();
0336: int[] ppvObject = new int[1];
0337: int result = dispatchDocument
0338: .QueryInterface(
0339: COM.IIDIPersistStreamInit,
0340: ppvObject);
0341: if (result == OS.S_OK) {
0342: IPersistStreamInit persistStreamInit = new IPersistStreamInit(
0343: ppvObject[0]);
0344: if (persistStreamInit
0345: .InitNew() == OS.S_OK) {
0346: persistStreamInit
0347: .Load(ppstm[0]);
0348: }
0349: persistStreamInit.Release();
0350: }
0351: pVarResult.dispose();
0352: /*
0353: * This code is intentionally commented. The IDispatch obtained from a Variant
0354: * did not increase the reference count for the enclosed interface.
0355: */
0356: //dispatchDocument.Release();
0357: IUnknown stream = new IUnknown(
0358: ppstm[0]);
0359: stream.Release();
0360: } else {
0361: OS.GlobalFree(hGlobal);
0362: }
0363: }
0364: }
0365: };
0366: if (delaySetText) {
0367: delaySetText = false;
0368: getDisplay().asyncExec(runnable);
0369: } else {
0370: runnable.run();
0371: }
0372: } else {
0373: Variant variant = new Variant(auto);
0374: IDispatch top = variant.getDispatch();
0375: LocationEvent locationEvent = new LocationEvent(
0376: Browser.this );
0377: locationEvent.display = getDisplay();
0378: locationEvent.widget = Browser.this ;
0379: locationEvent.location = url;
0380: locationEvent.top = top.getAddress() == dispatch
0381: .getAddress();
0382: for (int i = 0; i < locationListeners.length; i++) {
0383: locationListeners[i].changed(locationEvent);
0384: }
0385: /*
0386: * This code is intentionally commented. A Variant constructed from an
0387: * OleAutomation object does not increase its reference count. The IDispatch
0388: * obtained from this Variant did not increase the reference count for the
0389: * OleAutomation instance either.
0390: */
0391: //top.Release();
0392: //variant.dispose();
0393: /*
0394: * Note. The completion of the page loading is detected as
0395: * described in the MSDN article "Determine when a page is
0396: * done loading in WebBrowser Control".
0397: */
0398: if (globalDispatch != 0
0399: && dispatch.getAddress() == globalDispatch) {
0400: /* final document complete */
0401: globalDispatch = 0;
0402: ProgressEvent progressEvent = new ProgressEvent(
0403: Browser.this );
0404: progressEvent.display = getDisplay();
0405: progressEvent.widget = Browser.this ;
0406: for (int i = 0; i < progressListeners.length; i++) {
0407: progressListeners[i]
0408: .completed(progressEvent);
0409: }
0410: }
0411: }
0412:
0413: /*
0414: * This code is intentionally commented. This IDispatch was received
0415: * as an argument from the OleEvent and it will be disposed along with
0416: * the other arguments.
0417: */
0418: //dispatch.Release();
0419: break;
0420: }
0421: case NavigateComplete2: {
0422: Variant varResult = event.arguments[0];
0423: IDispatch dispatch = varResult.getDispatch();
0424: if (globalDispatch == 0)
0425: globalDispatch = dispatch.getAddress();
0426: break;
0427: }
0428: case NewWindow2: {
0429: Variant cancel = event.arguments[1];
0430: int pCancel = cancel.getByRef();
0431: WindowEvent newEvent = new WindowEvent(Browser.this );
0432: newEvent.display = getDisplay();
0433: newEvent.widget = Browser.this ;
0434: newEvent.required = false;
0435: for (int i = 0; i < openWindowListeners.length; i++) {
0436: openWindowListeners[i].open(newEvent);
0437: }
0438: Browser browser = newEvent.browser;
0439: boolean doit = browser != null
0440: && !browser.isDisposed();
0441: if (doit) {
0442: Variant variant = new Variant(browser.auto);
0443: IDispatch iDispatch = variant.getDispatch();
0444: Variant ppDisp = event.arguments[0];
0445: int byref = ppDisp.getByRef();
0446: if (byref != 0)
0447: COM.MoveMemory(byref, new int[] { iDispatch
0448: .getAddress() }, 4);
0449: /*
0450: * This code is intentionally commented. A Variant constructed from an
0451: * OleAutomation object does not increase its reference count. The IDispatch
0452: * obtained from this Variant did not increase the reference count for the
0453: * OleAutomation instance either.
0454: */
0455: //variant.dispose();
0456: //iDispatch.Release();
0457: }
0458: if (newEvent.required) {
0459: COM.MoveMemory(pCancel,
0460: new short[] { doit ? COM.VARIANT_FALSE
0461: : COM.VARIANT_TRUE }, 2);
0462: }
0463: break;
0464: }
0465: case OnMenuBar: {
0466: Variant arg0 = event.arguments[0];
0467: menuBar = arg0.getBoolean();
0468: break;
0469: }
0470: case OnStatusBar: {
0471: Variant arg0 = event.arguments[0];
0472: statusBar = arg0.getBoolean();
0473: break;
0474: }
0475: case OnToolBar: {
0476: Variant arg0 = event.arguments[0];
0477: toolBar = arg0.getBoolean();
0478: /*
0479: * Feature in Internet Explorer. OnToolBar FALSE is emitted
0480: * when both tool bar, address bar and menu bar must not be visible.
0481: * OnToolBar TRUE is emitted when either of tool bar, address bar
0482: * or menu bar is visible.
0483: */
0484: if (!toolBar) {
0485: addressBar = false;
0486: menuBar = false;
0487: }
0488: break;
0489: }
0490: case OnVisible: {
0491: Variant arg1 = event.arguments[0];
0492: boolean visible = arg1.getBoolean();
0493: WindowEvent newEvent = new WindowEvent(Browser.this );
0494: newEvent.display = getDisplay();
0495: newEvent.widget = Browser.this ;
0496: if (visible) {
0497: if (addressBar) {
0498: /*
0499: * Bug in Internet Explorer. There is no distinct notification for
0500: * the address bar. If neither address, menu or tool bars are visible,
0501: * OnToolBar FALSE is emitted. For some reason, querying the value of
0502: * AddressBar in this case returns true even though it should not be
0503: * set visible. The workaround is to only query the value of AddressBar
0504: * when OnToolBar FALSE has not been emitted.
0505: */
0506: int[] rgdispid = auto
0507: .getIDsOfNames(new String[] { "AddressBar" }); //$NON-NLS-1$
0508: Variant pVarResult = auto
0509: .getProperty(rgdispid[0]);
0510: if (pVarResult != null
0511: && pVarResult.getType() == OLE.VT_BOOL)
0512: addressBar = pVarResult.getBoolean();
0513: }
0514: newEvent.addressBar = addressBar;
0515: newEvent.menuBar = menuBar;
0516: newEvent.statusBar = statusBar;
0517: newEvent.toolBar = toolBar;
0518: newEvent.location = location;
0519: newEvent.size = size;
0520: for (int i = 0; i < visibilityWindowListeners.length; i++) {
0521: visibilityWindowListeners[i].show(newEvent);
0522: }
0523: location = null;
0524: size = null;
0525: } else {
0526: for (int i = 0; i < visibilityWindowListeners.length; i++) {
0527: visibilityWindowListeners[i].hide(newEvent);
0528: }
0529: }
0530: break;
0531: }
0532: case ProgressChange: {
0533: Variant arg1 = event.arguments[0];
0534: int nProgress = arg1.getType() != OLE.VT_I4 ? 0
0535: : arg1.getInt(); // may be -1
0536: Variant arg2 = event.arguments[1];
0537: int nProgressMax = arg2.getType() != OLE.VT_I4 ? 0
0538: : arg2.getInt();
0539: ProgressEvent newEvent = new ProgressEvent(
0540: Browser.this );
0541: newEvent.display = getDisplay();
0542: newEvent.widget = Browser.this ;
0543: newEvent.current = nProgress;
0544: newEvent.total = nProgressMax;
0545: if (nProgress != -1) {
0546: for (int i = 0; i < progressListeners.length; i++) {
0547: progressListeners[i].changed(newEvent);
0548: }
0549: }
0550: break;
0551: }
0552: case StatusTextChange: {
0553: Variant arg1 = event.arguments[0];
0554: if (arg1.getType() == OLE.VT_BSTR) {
0555: String text = arg1.getString();
0556: StatusTextEvent newEvent = new StatusTextEvent(
0557: Browser.this );
0558: newEvent.display = getDisplay();
0559: newEvent.widget = Browser.this ;
0560: newEvent.text = text;
0561: for (int i = 0; i < statusTextListeners.length; i++) {
0562: statusTextListeners[i].changed(newEvent);
0563: }
0564: }
0565: break;
0566: }
0567: case TitleChange: {
0568: Variant arg1 = event.arguments[0];
0569: if (arg1.getType() == OLE.VT_BSTR) {
0570: String title = arg1.getString();
0571: TitleEvent newEvent = new TitleEvent(
0572: Browser.this );
0573: newEvent.display = getDisplay();
0574: newEvent.widget = Browser.this ;
0575: newEvent.title = title;
0576: for (int i = 0; i < titleListeners.length; i++) {
0577: titleListeners[i].changed(newEvent);
0578: }
0579: }
0580: break;
0581: }
0582: case WindowClosing: {
0583: WindowEvent newEvent = new WindowEvent(Browser.this );
0584: newEvent.display = getDisplay();
0585: newEvent.widget = Browser.this ;
0586: for (int i = 0; i < closeWindowListeners.length; i++) {
0587: closeWindowListeners[i].close(newEvent);
0588: }
0589: Variant cancel = event.arguments[1];
0590: int pCancel = cancel.getByRef();
0591: Variant arg1 = event.arguments[0];
0592: boolean isChildWindow = arg1.getBoolean();
0593: COM
0594: .MoveMemory(
0595: pCancel,
0596: new short[] { isChildWindow ? COM.VARIANT_FALSE
0597: : COM.VARIANT_TRUE }, 2);
0598: dispose();
0599: break;
0600: }
0601: case WindowSetHeight: {
0602: if (size == null)
0603: size = new Point(0, 0);
0604: Variant arg1 = event.arguments[0];
0605: size.y = arg1.getInt();
0606: break;
0607: }
0608: case WindowSetLeft: {
0609: if (location == null)
0610: location = new Point(0, 0);
0611: Variant arg1 = event.arguments[0];
0612: location.x = arg1.getInt();
0613: break;
0614: }
0615: case WindowSetTop: {
0616: if (location == null)
0617: location = new Point(0, 0);
0618: Variant arg1 = event.arguments[0];
0619: location.y = arg1.getInt();
0620: break;
0621: }
0622: case WindowSetWidth: {
0623: if (size == null)
0624: size = new Point(0, 0);
0625: Variant arg1 = event.arguments[0];
0626: size.x = arg1.getInt();
0627: break;
0628: }
0629: }
0630: /*
0631: * Dispose all arguments passed in the OleEvent. This must be
0632: * done to properly release any IDispatch reference that was
0633: * automatically addRef'ed when constructing the OleEvent.
0634: */
0635: Variant[] arguments = event.arguments;
0636: for (int i = 0; i < arguments.length; i++)
0637: arguments[i].dispose();
0638: }
0639: };
0640: site.addEventListener(BeforeNavigate2, oleListener);
0641: site.addEventListener(CommandStateChange, oleListener);
0642: site.addEventListener(DocumentComplete, oleListener);
0643: site.addEventListener(NavigateComplete2, oleListener);
0644: site.addEventListener(NewWindow2, oleListener);
0645: site.addEventListener(OnMenuBar, oleListener);
0646: site.addEventListener(OnStatusBar, oleListener);
0647: site.addEventListener(OnToolBar, oleListener);
0648: site.addEventListener(OnVisible, oleListener);
0649: site.addEventListener(ProgressChange, oleListener);
0650: site.addEventListener(StatusTextChange, oleListener);
0651: site.addEventListener(TitleChange, oleListener);
0652: site.addEventListener(WindowClosing, oleListener);
0653: site.addEventListener(WindowSetHeight, oleListener);
0654: site.addEventListener(WindowSetLeft, oleListener);
0655: site.addEventListener(WindowSetTop, oleListener);
0656: site.addEventListener(WindowSetWidth, oleListener);
0657:
0658: Variant variant = new Variant(true);
0659: auto.setProperty(RegisterAsBrowser, variant);
0660: variant.dispose();
0661:
0662: variant = new Variant(false);
0663: int[] rgdispid = auto
0664: .getIDsOfNames(new String[] { "RegisterAsDropTarget" }); //$NON-NLS-1$
0665: if (rgdispid != null)
0666: auto.setProperty(rgdispid[0], variant);
0667: variant.dispose();
0668:
0669: // GOOGLE: Load Google Gears if we can.
0670: ((WebSite) site).startGears();
0671: }
0672:
0673: /**
0674: * Clears all session cookies from all current Browser instances.
0675: *
0676: * @since 3.2
0677: */
0678: public static void clearSessions() {
0679: OS.InternetSetOption(0, OS.INTERNET_OPTION_END_BROWSER_SESSION,
0680: 0, 0);
0681: }
0682:
0683: /**
0684: * Adds the listener to the collection of listeners who will be
0685: * notified when the window hosting the receiver should be closed.
0686: * <p>
0687: * This notification occurs when a javascript command such as
0688: * <code>window.close</code> gets executed by a <code>Browser</code>.
0689: * </p>
0690: *
0691: * @param listener the listener which should be notified
0692: *
0693: * @exception IllegalArgumentException <ul>
0694: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
0695: * </ul>
0696: *
0697: * @exception SWTException <ul>
0698: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
0699: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
0700: * </ul>
0701: *
0702: * @since 3.0
0703: */
0704: public void addCloseWindowListener(CloseWindowListener listener) {
0705: checkWidget();
0706: if (listener == null)
0707: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0708: CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length + 1];
0709: System
0710: .arraycopy(closeWindowListeners, 0,
0711: newCloseWindowListeners, 0,
0712: closeWindowListeners.length);
0713: closeWindowListeners = newCloseWindowListeners;
0714: closeWindowListeners[closeWindowListeners.length - 1] = listener;
0715: }
0716:
0717: /**
0718: * Adds the listener to the collection of listeners who will be
0719: * notified when the current location has changed or is about to change.
0720: * <p>
0721: * This notification typically occurs when the application navigates
0722: * to a new location with {@link #setUrl(String)} or when the user
0723: * activates a hyperlink.
0724: * </p>
0725: *
0726: * @param listener the listener which should be notified
0727: *
0728: * @exception IllegalArgumentException <ul>
0729: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
0730: * </ul>
0731: *
0732: * @exception SWTException <ul>
0733: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
0734: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
0735: * </ul>
0736: *
0737: * @since 3.0
0738: */
0739: public void addLocationListener(LocationListener listener) {
0740: checkWidget();
0741: if (listener == null)
0742: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0743: LocationListener[] newLocationListeners = new LocationListener[locationListeners.length + 1];
0744: System.arraycopy(locationListeners, 0, newLocationListeners, 0,
0745: locationListeners.length);
0746: locationListeners = newLocationListeners;
0747: locationListeners[locationListeners.length - 1] = listener;
0748: }
0749:
0750: /**
0751: * Adds the listener to the collection of listeners who will be
0752: * notified when a new window needs to be created.
0753: * <p>
0754: * This notification occurs when a javascript command such as
0755: * <code>window.open</code> gets executed by a <code>Browser</code>.
0756: * </p>
0757: *
0758: * @param listener the listener which should be notified
0759: *
0760: * @exception IllegalArgumentException <ul>
0761: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
0762: * </ul>
0763: *
0764: * @exception SWTException <ul>
0765: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
0766: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
0767: * </ul>
0768: *
0769: * @since 3.0
0770: */
0771: public void addOpenWindowListener(OpenWindowListener listener) {
0772: checkWidget();
0773: if (listener == null)
0774: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0775: OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length + 1];
0776: System.arraycopy(openWindowListeners, 0,
0777: newOpenWindowListeners, 0, openWindowListeners.length);
0778: openWindowListeners = newOpenWindowListeners;
0779: openWindowListeners[openWindowListeners.length - 1] = listener;
0780: }
0781:
0782: /**
0783: * Adds the listener to the collection of listeners who will be
0784: * notified when a progress is made during the loading of the current
0785: * URL or when the loading of the current URL has been completed.
0786: *
0787: * @param listener the listener which should be notified
0788: *
0789: * @exception IllegalArgumentException <ul>
0790: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
0791: * </ul>
0792: *
0793: * @exception SWTException <ul>
0794: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
0795: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
0796: * </ul>
0797: *
0798: * @since 3.0
0799: */
0800: public void addProgressListener(ProgressListener listener) {
0801: checkWidget();
0802: if (listener == null)
0803: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0804: ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length + 1];
0805: System.arraycopy(progressListeners, 0, newProgressListeners, 0,
0806: progressListeners.length);
0807: progressListeners = newProgressListeners;
0808: progressListeners[progressListeners.length - 1] = listener;
0809: }
0810:
0811: /**
0812: * Adds the listener to the collection of listeners who will be
0813: * notified when the status text is changed.
0814: * <p>
0815: * The status text is typically displayed in the status bar of
0816: * a browser application.
0817: * </p>
0818: *
0819: * @param listener the listener which should be notified
0820: *
0821: * @exception IllegalArgumentException <ul>
0822: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
0823: * </ul>
0824: *
0825: * @exception SWTException <ul>
0826: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
0827: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
0828: * </ul>
0829: *
0830: * @since 3.0
0831: */
0832: public void addStatusTextListener(StatusTextListener listener) {
0833: checkWidget();
0834: if (listener == null)
0835: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0836: StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length + 1];
0837: System.arraycopy(statusTextListeners, 0,
0838: newStatusTextListeners, 0, statusTextListeners.length);
0839: statusTextListeners = newStatusTextListeners;
0840: statusTextListeners[statusTextListeners.length - 1] = listener;
0841: }
0842:
0843: /**
0844: * Adds the listener to the collection of listeners who will be
0845: * notified when the title of the current document is available
0846: * or has changed.
0847: *
0848: * @param listener the listener which should be notified
0849: *
0850: * @exception IllegalArgumentException <ul>
0851: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
0852: * </ul>
0853: *
0854: * @exception SWTException <ul>
0855: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
0856: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
0857: * </ul>
0858: *
0859: * @since 3.0
0860: */
0861: public void addTitleListener(TitleListener listener) {
0862: checkWidget();
0863: if (listener == null)
0864: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0865: TitleListener[] newTitleListeners = new TitleListener[titleListeners.length + 1];
0866: System.arraycopy(titleListeners, 0, newTitleListeners, 0,
0867: titleListeners.length);
0868: titleListeners = newTitleListeners;
0869: titleListeners[titleListeners.length - 1] = listener;
0870: }
0871:
0872: /**
0873: * Adds the listener to the collection of listeners who will be
0874: * notified when a window hosting the receiver needs to be displayed
0875: * or hidden.
0876: *
0877: * @param listener the listener which should be notified
0878: *
0879: * @exception IllegalArgumentException <ul>
0880: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
0881: * </ul>
0882: *
0883: * @exception SWTException <ul>
0884: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
0885: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
0886: * </ul>
0887: *
0888: * @since 3.0
0889: */
0890: public void addVisibilityWindowListener(
0891: VisibilityWindowListener listener) {
0892: checkWidget();
0893: if (listener == null)
0894: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0895: VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length + 1];
0896: System.arraycopy(visibilityWindowListeners, 0,
0897: newVisibilityWindowListeners, 0,
0898: visibilityWindowListeners.length);
0899: visibilityWindowListeners = newVisibilityWindowListeners;
0900: visibilityWindowListeners[visibilityWindowListeners.length - 1] = listener;
0901: }
0902:
0903: /**
0904: * Navigate to the previous session history item.
0905: *
0906: * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
0907: *
0908: * @exception SWTException <ul>
0909: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
0910: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
0911: * </ul>
0912: *
0913: * @see #forward
0914: *
0915: * @since 3.0
0916: */
0917: public boolean back() {
0918: checkWidget();
0919: if (!back)
0920: return false;
0921: int[] rgdispid = auto.getIDsOfNames(new String[] { "GoBack" }); //$NON-NLS-1$
0922: Variant pVarResult = auto.invoke(rgdispid[0]);
0923: return pVarResult != null
0924: && pVarResult.getType() == OLE.VT_EMPTY;
0925: }
0926:
0927: protected void checkSubclass() {
0928: String name = getClass().getName();
0929: int index = name.lastIndexOf('.');
0930: if (!name.substring(0, index + 1).equals(PACKAGE_PREFIX)) {
0931: SWT.error(SWT.ERROR_INVALID_SUBCLASS);
0932: }
0933: }
0934:
0935: /**
0936: * Execute the specified script.
0937: *
0938: * <p>
0939: * Execute a script containing javascript commands in the context of the current document.
0940: *
0941: * @param script the script with javascript commands
0942: *
0943: * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
0944: *
0945: * @exception IllegalArgumentException <ul>
0946: * <li>ERROR_NULL_ARGUMENT - if the script is null</li>
0947: * </ul>
0948: *
0949: * @exception SWTException <ul>
0950: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
0951: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
0952: * </ul>
0953: *
0954: * @since 3.1
0955: */
0956: public boolean execute(String script) {
0957: checkWidget();
0958: if (script == null)
0959: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0960:
0961: /* get IHTMLDocument2 */
0962: int[] rgdispid = auto
0963: .getIDsOfNames(new String[] { "Document" }); //$NON-NLS-1$
0964: int dispIdMember = rgdispid[0];
0965: Variant pVarResult = auto.getProperty(dispIdMember);
0966: if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY)
0967: return false;
0968: OleAutomation document = pVarResult.getAutomation();
0969: pVarResult.dispose();
0970:
0971: /* get IHTMLWindow2 */
0972: rgdispid = document
0973: .getIDsOfNames(new String[] { "parentWindow" }); //$NON-NLS-1$
0974: if (rgdispid == null) {
0975: /* implies that browser's content is not a IHTMLDocument2 (eg.- acrobat reader) */
0976: document.dispose();
0977: return false;
0978: }
0979: dispIdMember = rgdispid[0];
0980: pVarResult = document.getProperty(dispIdMember);
0981: OleAutomation ihtmlWindow2 = pVarResult.getAutomation();
0982: pVarResult.dispose();
0983: document.dispose();
0984:
0985: rgdispid = ihtmlWindow2.getIDsOfNames(new String[] {
0986: "execScript", "code" }); //$NON-NLS-1$ //$NON-NLS-2$
0987: Variant[] rgvarg = new Variant[1];
0988: rgvarg[0] = new Variant(script);
0989: int[] rgdispidNamedArgs = new int[1];
0990: rgdispidNamedArgs[0] = rgdispid[1];
0991: pVarResult = ihtmlWindow2.invoke(rgdispid[0], rgvarg,
0992: rgdispidNamedArgs);
0993: rgvarg[0].dispose();
0994: ihtmlWindow2.dispose();
0995: if (pVarResult == null)
0996: return false;
0997: pVarResult.dispose();
0998: return true;
0999: }
1000:
1001: /**
1002: * Navigate to the next session history item.
1003: *
1004: * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
1005: *
1006: * @exception SWTException <ul>
1007: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
1008: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
1009: * </ul>
1010: *
1011: * @see #back
1012: *
1013: * @since 3.0
1014: */
1015: public boolean forward() {
1016: checkWidget();
1017: if (!forward)
1018: return false;
1019: int[] rgdispid = auto
1020: .getIDsOfNames(new String[] { "GoForward" }); //$NON-NLS-1$
1021: Variant pVarResult = auto.invoke(rgdispid[0]);
1022: return pVarResult != null
1023: && pVarResult.getType() == OLE.VT_EMPTY;
1024: }
1025:
1026: /**
1027: * Returns <code>true</code> if the receiver can navigate to the
1028: * previous session history item, and <code>false</code> otherwise.
1029: *
1030: * @return the receiver's back command enabled state
1031: *
1032: * @exception SWTException <ul>
1033: * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1034: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1035: * </ul>
1036: *
1037: * @see #back
1038: */
1039: public boolean isBackEnabled() {
1040: checkWidget();
1041: return back;
1042: }
1043:
1044: /**
1045: * Returns <code>true</code> if the receiver can navigate to the
1046: * next session history item, and <code>false</code> otherwise.
1047: *
1048: * @return the receiver's forward command enabled state
1049: *
1050: * @exception SWTException <ul>
1051: * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1052: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1053: * </ul>
1054: *
1055: * @see #forward
1056: */
1057: public boolean isForwardEnabled() {
1058: checkWidget();
1059: return forward;
1060: }
1061:
1062: /**
1063: * Returns the current URL.
1064: *
1065: * @return the current URL or an empty <code>String</code> if there is no current URL
1066: *
1067: * @exception SWTException <ul>
1068: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
1069: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
1070: * </ul>
1071: *
1072: * @see #setUrl
1073: *
1074: * @since 3.0
1075: */
1076: public String getUrl() {
1077: checkWidget();
1078: int[] rgdispid = auto
1079: .getIDsOfNames(new String[] { "LocationURL" }); //$NON-NLS-1$
1080: Variant pVarResult = auto.getProperty(rgdispid[0]);
1081: if (pVarResult == null || pVarResult.getType() != OLE.VT_BSTR)
1082: return "";
1083: String result = pVarResult.getString();
1084: pVarResult.dispose();
1085: return result;
1086: }
1087:
1088: public boolean isFocusControl() {
1089: checkWidget();
1090: if (site.isFocusControl() || frame.isFocusControl())
1091: return true;
1092: return super .isFocusControl();
1093: }
1094:
1095: /**
1096: * Refresh the current page.
1097: *
1098: * @exception SWTException <ul>
1099: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
1100: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
1101: * </ul>
1102: *
1103: * @since 3.0
1104: */
1105: public void refresh() {
1106: checkWidget();
1107: int[] rgdispid = auto.getIDsOfNames(new String[] { "Refresh" }); //$NON-NLS-1$
1108: auto.invoke(rgdispid[0]);
1109: }
1110:
1111: /**
1112: * Removes the listener from the collection of listeners who will
1113: * be notified when the window hosting the receiver should be closed.
1114: *
1115: * @param listener the listener which should no longer be notified
1116: *
1117: * @exception IllegalArgumentException <ul>
1118: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1119: * </ul>
1120: *
1121: * @exception SWTException <ul>
1122: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
1123: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
1124: * </ul>
1125: *
1126: * @since 3.0
1127: */
1128: public void removeCloseWindowListener(CloseWindowListener listener) {
1129: checkWidget();
1130: if (listener == null)
1131: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1132: if (closeWindowListeners.length == 0)
1133: return;
1134: int index = -1;
1135: for (int i = 0; i < closeWindowListeners.length; i++) {
1136: if (listener == closeWindowListeners[i]) {
1137: index = i;
1138: break;
1139: }
1140: }
1141: if (index == -1)
1142: return;
1143: if (closeWindowListeners.length == 1) {
1144: closeWindowListeners = new CloseWindowListener[0];
1145: return;
1146: }
1147: CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length - 1];
1148: System.arraycopy(closeWindowListeners, 0,
1149: newCloseWindowListeners, 0, index);
1150: System.arraycopy(closeWindowListeners, index + 1,
1151: newCloseWindowListeners, index,
1152: closeWindowListeners.length - index - 1);
1153: closeWindowListeners = newCloseWindowListeners;
1154: }
1155:
1156: /**
1157: * Removes the listener from the collection of listeners who will
1158: * be notified when the current location is changed or about to be changed.
1159: *
1160: * @param listener the listener which should no longer be notified
1161: *
1162: * @exception IllegalArgumentException <ul>
1163: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1164: * </ul>
1165: *
1166: * @exception SWTException <ul>
1167: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
1168: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
1169: * </ul>
1170: *
1171: * @since 3.0
1172: */
1173: public void removeLocationListener(LocationListener listener) {
1174: checkWidget();
1175: if (listener == null)
1176: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1177: if (locationListeners.length == 0)
1178: return;
1179: int index = -1;
1180: for (int i = 0; i < locationListeners.length; i++) {
1181: if (listener == locationListeners[i]) {
1182: index = i;
1183: break;
1184: }
1185: }
1186: if (index == -1)
1187: return;
1188: if (locationListeners.length == 1) {
1189: locationListeners = new LocationListener[0];
1190: return;
1191: }
1192: LocationListener[] newLocationListeners = new LocationListener[locationListeners.length - 1];
1193: System.arraycopy(locationListeners, 0, newLocationListeners, 0,
1194: index);
1195: System.arraycopy(locationListeners, index + 1,
1196: newLocationListeners, index, locationListeners.length
1197: - index - 1);
1198: locationListeners = newLocationListeners;
1199: }
1200:
1201: /**
1202: * Removes the listener from the collection of listeners who will
1203: * be notified when a new window needs to be created.
1204: *
1205: * @param listener the listener which should no longer be notified
1206: *
1207: * @exception IllegalArgumentException <ul>
1208: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1209: * </ul>
1210: *
1211: * @exception SWTException <ul>
1212: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
1213: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
1214: * </ul>
1215: *
1216: * @since 3.0
1217: */
1218: public void removeOpenWindowListener(OpenWindowListener listener) {
1219: checkWidget();
1220: if (listener == null)
1221: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1222: if (openWindowListeners.length == 0)
1223: return;
1224: int index = -1;
1225: for (int i = 0; i < openWindowListeners.length; i++) {
1226: if (listener == openWindowListeners[i]) {
1227: index = i;
1228: break;
1229: }
1230: }
1231: if (index == -1)
1232: return;
1233: if (openWindowListeners.length == 1) {
1234: openWindowListeners = new OpenWindowListener[0];
1235: return;
1236: }
1237: OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length - 1];
1238: System.arraycopy(openWindowListeners, 0,
1239: newOpenWindowListeners, 0, index);
1240: System.arraycopy(openWindowListeners, index + 1,
1241: newOpenWindowListeners, index,
1242: openWindowListeners.length - index - 1);
1243: openWindowListeners = newOpenWindowListeners;
1244: }
1245:
1246: /**
1247: * Removes the listener from the collection of listeners who will
1248: * be notified when a progress is made during the loading of the current
1249: * URL or when the loading of the current URL has been completed.
1250: *
1251: * @param listener the listener which should no longer be notified
1252: *
1253: * @exception IllegalArgumentException <ul>
1254: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1255: * </ul>
1256: *
1257: * @exception SWTException <ul>
1258: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
1259: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
1260: * </ul>
1261: *
1262: * @since 3.0
1263: */
1264: public void removeProgressListener(ProgressListener listener) {
1265: checkWidget();
1266: if (listener == null)
1267: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1268: if (progressListeners.length == 0)
1269: return;
1270: int index = -1;
1271: for (int i = 0; i < progressListeners.length; i++) {
1272: if (listener == progressListeners[i]) {
1273: index = i;
1274: break;
1275: }
1276: }
1277: if (index == -1)
1278: return;
1279: if (progressListeners.length == 1) {
1280: progressListeners = new ProgressListener[0];
1281: return;
1282: }
1283: ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length - 1];
1284: System.arraycopy(progressListeners, 0, newProgressListeners, 0,
1285: index);
1286: System.arraycopy(progressListeners, index + 1,
1287: newProgressListeners, index, progressListeners.length
1288: - index - 1);
1289: progressListeners = newProgressListeners;
1290: }
1291:
1292: /**
1293: * Removes the listener from the collection of listeners who will
1294: * be notified when the status text is changed.
1295: *
1296: * @param listener the listener which should no longer be notified
1297: *
1298: * @exception IllegalArgumentException <ul>
1299: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1300: * </ul>
1301: *
1302: * @exception SWTException <ul>
1303: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
1304: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
1305: * </ul>
1306: *
1307: * @since 3.0
1308: */
1309: public void removeStatusTextListener(StatusTextListener listener) {
1310: checkWidget();
1311: if (listener == null)
1312: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1313: if (statusTextListeners.length == 0)
1314: return;
1315: int index = -1;
1316: for (int i = 0; i < statusTextListeners.length; i++) {
1317: if (listener == statusTextListeners[i]) {
1318: index = i;
1319: break;
1320: }
1321: }
1322: if (index == -1)
1323: return;
1324: if (statusTextListeners.length == 1) {
1325: statusTextListeners = new StatusTextListener[0];
1326: return;
1327: }
1328: StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length - 1];
1329: System.arraycopy(statusTextListeners, 0,
1330: newStatusTextListeners, 0, index);
1331: System.arraycopy(statusTextListeners, index + 1,
1332: newStatusTextListeners, index,
1333: statusTextListeners.length - index - 1);
1334: statusTextListeners = newStatusTextListeners;
1335: }
1336:
1337: /**
1338: * Removes the listener from the collection of listeners who will
1339: * be notified when the title of the current document is available
1340: * or has changed.
1341: *
1342: * @param listener the listener which should no longer be notified
1343: *
1344: * @exception IllegalArgumentException <ul>
1345: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1346: * </ul>
1347: *
1348: * @exception SWTException <ul>
1349: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
1350: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
1351: * </ul>
1352: *
1353: * @since 3.0
1354: */
1355: public void removeTitleListener(TitleListener listener) {
1356: checkWidget();
1357: if (listener == null)
1358: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1359: if (titleListeners.length == 0)
1360: return;
1361: int index = -1;
1362: for (int i = 0; i < titleListeners.length; i++) {
1363: if (listener == titleListeners[i]) {
1364: index = i;
1365: break;
1366: }
1367: }
1368: if (index == -1)
1369: return;
1370: if (titleListeners.length == 1) {
1371: titleListeners = new TitleListener[0];
1372: return;
1373: }
1374: TitleListener[] newTitleListeners = new TitleListener[titleListeners.length - 1];
1375: System
1376: .arraycopy(titleListeners, 0, newTitleListeners, 0,
1377: index);
1378: System.arraycopy(titleListeners, index + 1, newTitleListeners,
1379: index, titleListeners.length - index - 1);
1380: titleListeners = newTitleListeners;
1381: }
1382:
1383: /**
1384: * Removes the listener from the collection of listeners who will
1385: * be notified when a window hosting the receiver needs to be displayed
1386: * or hidden.
1387: *
1388: * @param listener the listener which should no longer be notified
1389: *
1390: * @exception IllegalArgumentException <ul>
1391: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1392: * </ul>
1393: *
1394: * @exception SWTException <ul>
1395: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
1396: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
1397: * </ul>
1398: *
1399: * @since 3.0
1400: */
1401: public void removeVisibilityWindowListener(
1402: VisibilityWindowListener listener) {
1403: checkWidget();
1404: if (listener == null)
1405: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1406: if (visibilityWindowListeners.length == 0)
1407: return;
1408: int index = -1;
1409: for (int i = 0; i < visibilityWindowListeners.length; i++) {
1410: if (listener == visibilityWindowListeners[i]) {
1411: index = i;
1412: break;
1413: }
1414: }
1415: if (index == -1)
1416: return;
1417: if (visibilityWindowListeners.length == 1) {
1418: visibilityWindowListeners = new VisibilityWindowListener[0];
1419: return;
1420: }
1421: VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length - 1];
1422: System.arraycopy(visibilityWindowListeners, 0,
1423: newVisibilityWindowListeners, 0, index);
1424: System.arraycopy(visibilityWindowListeners, index + 1,
1425: newVisibilityWindowListeners, index,
1426: visibilityWindowListeners.length - index - 1);
1427: visibilityWindowListeners = newVisibilityWindowListeners;
1428: }
1429:
1430: /**
1431: * Renders HTML.
1432: *
1433: * <p>
1434: * The html parameter is Unicode encoded since it is a java <code>String</code>.
1435: * As a result, the HTML meta tag charset should not be set. The charset is implied
1436: * by the <code>String</code> itself.
1437: *
1438: * @param html the HTML content to be rendered
1439: *
1440: * @return true if the operation was successful and false otherwise.
1441: *
1442: * @exception IllegalArgumentException <ul>
1443: * <li>ERROR_NULL_ARGUMENT - if the html is null</li>
1444: * </ul>
1445: *
1446: * @exception SWTException <ul>
1447: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
1448: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
1449: * </ul>
1450: *
1451: * @see #setUrl
1452: *
1453: * @since 3.0
1454: */
1455: public boolean setText(String html) {
1456: checkWidget();
1457: if (html == null)
1458: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1459:
1460: /*
1461: * If the html field is non-null then the about:blank page is already being
1462: * loaded, so no Stop or Navigate is required. Just set the html that is to
1463: * be shown.
1464: */
1465: boolean blankLoading = this .html != null;
1466: this .html = html;
1467: if (blankLoading)
1468: return true;
1469:
1470: /*
1471: * Navigate to the blank page and insert the given html when
1472: * receiving the next DocumentComplete notification. See the
1473: * MSDN article "Loading HTML content from a Stream".
1474: *
1475: * Note. Stop any pending request. This is required to avoid displaying a
1476: * blank page as a result of consecutive calls to setUrl and/or setText.
1477: * The previous request would otherwise render the new html content and
1478: * reset the html field before the browser actually navigates to the blank
1479: * page as requested below.
1480: *
1481: * Feature in Internet Explorer. Stopping pending requests when no request
1482: * is pending causes a default page 'Action cancelled' to be displayed. The
1483: * workaround is to not invoke 'stop' when no request has been set since
1484: * that instance was created.
1485: */
1486: int[] rgdispid;
1487: if (navigate) {
1488: /*
1489: * Stopping the loading of a page causes DocumentComplete events from previous
1490: * requests to be received before the DocumentComplete for this page. In such
1491: * cases we must be sure to not set the html into the browser too soon, since
1492: * doing so could result in its page being cleared out by a subsequent
1493: * DocumentComplete. The Browser's ReadyState can be used to determine whether
1494: * these extra events will be received or not.
1495: */
1496: rgdispid = auto
1497: .getIDsOfNames(new String[] { "ReadyState" }); //$NON-NLS-1$
1498: Variant pVarResult = auto.getProperty(rgdispid[0]);
1499: if (pVarResult == null)
1500: return false;
1501: delaySetText = pVarResult.getInt() != READYSTATE_COMPLETE;
1502: pVarResult.dispose();
1503: rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
1504: auto.invoke(rgdispid[0]);
1505: }
1506: rgdispid = auto
1507: .getIDsOfNames(new String[] { "Navigate", "URL" }); //$NON-NLS-1$ //$NON-NLS-2$
1508: navigate = true;
1509: Variant[] rgvarg = new Variant[1];
1510: rgvarg[0] = new Variant(ABOUT_BLANK);
1511: int[] rgdispidNamedArgs = new int[1];
1512: rgdispidNamedArgs[0] = rgdispid[1];
1513: Variant pVarResult = auto.invoke(rgdispid[0], rgvarg,
1514: rgdispidNamedArgs);
1515: rgvarg[0].dispose();
1516: if (pVarResult == null)
1517: return false;
1518: boolean result = pVarResult.getType() == OLE.VT_EMPTY;
1519: pVarResult.dispose();
1520: return result;
1521: }
1522:
1523: /**
1524: * Loads a URL.
1525: *
1526: * @param url the URL to be loaded
1527: *
1528: * @return true if the operation was successful and false otherwise.
1529: *
1530: * @exception IllegalArgumentException <ul>
1531: * <li>ERROR_NULL_ARGUMENT - if the url is null</li>
1532: * </ul>
1533: *
1534: * @exception SWTException <ul>
1535: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
1536: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
1537: * </ul>
1538: *
1539: * @see #getUrl
1540: *
1541: * @since 3.0
1542: */
1543: public boolean setUrl(String url) {
1544: checkWidget();
1545: if (url == null)
1546: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1547: html = null;
1548:
1549: /*
1550: * Bug in Internet Explorer. For some reason, Navigating to an xml document before
1551: * a previous Navigate has completed will leave the Browser in a bad state if the
1552: * Navigate to the xml document does not complete. This bad state causes a GP when
1553: * the parent window is eventually disposed. The workaround is to issue a Stop before
1554: * navigating to any xml document.
1555: */
1556: if (url.endsWith(".xml")) { //$NON-NLS-1$
1557: /*
1558: * Feature in Internet Explorer. Stopping pending requests when no request has been
1559: * issued causes a default 'Action cancelled' page to be displayed. Since Stop must
1560: * be issued here, the workaround is to first Navigate to the about:blank page before
1561: * issuing Stop so that the 'Action cancelled' page is not displayed.
1562: */
1563: if (!navigate) {
1564: int[] rgdispid = auto.getIDsOfNames(new String[] {
1565: "Navigate", "URL" }); //$NON-NLS-1$ //$NON-NLS-2$
1566: Variant[] rgvarg = new Variant[1];
1567: rgvarg[0] = new Variant(ABOUT_BLANK);
1568: int[] rgdispidNamedArgs = new int[1];
1569: rgdispidNamedArgs[0] = rgdispid[1];
1570: auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
1571: rgvarg[0].dispose();
1572: }
1573: int[] rgdispid = auto
1574: .getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
1575: auto.invoke(rgdispid[0]);
1576: }
1577:
1578: int[] rgdispid = auto.getIDsOfNames(new String[] {
1579: "Navigate", "URL" }); //$NON-NLS-1$ //$NON-NLS-2$
1580: navigate = true;
1581: Variant[] rgvarg = new Variant[1];
1582: rgvarg[0] = new Variant(url);
1583: int[] rgdispidNamedArgs = new int[1];
1584: rgdispidNamedArgs[0] = rgdispid[1];
1585: Variant pVarResult = auto.invoke(rgdispid[0], rgvarg,
1586: rgdispidNamedArgs);
1587: rgvarg[0].dispose();
1588: if (pVarResult == null)
1589: return false;
1590: boolean result = pVarResult.getType() == OLE.VT_EMPTY;
1591: pVarResult.dispose();
1592: return result;
1593: }
1594:
1595: /**
1596: * Stop any loading and rendering activity.
1597: *
1598: * @exception SWTException <ul>
1599: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
1600: * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
1601: * </ul>
1602: *
1603: * @since 3.0
1604: */
1605: public void stop() {
1606: checkWidget();
1607: int[] rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
1608: auto.invoke(rgdispid[0]);
1609: }
1610: }
|