001: /*
002: * Copyright 2006 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.dev.shell.ie;
017:
018: import com.google.gwt.dev.shell.CompilingClassLoader;
019: import com.google.gwt.dev.shell.JsValueGlue;
020: import com.google.gwt.dev.shell.LowLevel;
021:
022: import org.eclipse.swt.browser.Browser;
023: import org.eclipse.swt.internal.ole.win32.COM;
024: import org.eclipse.swt.internal.ole.win32.COMObject;
025: import org.eclipse.swt.internal.win32.OS;
026: import org.eclipse.swt.ole.win32.Variant;
027:
028: /**
029: * A bag of static helper methods for mucking about with low-level SWT and COM
030: * constructs. Much of this is necessary simply to do things that the SWT
031: * implementers weren't really thinking about when they wrote the COM layer.
032: */
033: class SwtOleGlue {
034:
035: /**
036: * Converts a java object to its equivalent variant. A ClassLoader is passed
037: * here so that Handles can be manipulated properly.
038: */
039: public static Variant convertObjectToVariant(
040: CompilingClassLoader cl, Class<?> type, Object o) {
041: if (type.equals(Variant.class)) {
042: return (Variant) o;
043: }
044: JsValueIE6 jsValue = new JsValueIE6();
045: JsValueGlue.set(jsValue, cl, type, o);
046: return jsValue.getVariant();
047: }
048:
049: /**
050: * Converts an array of variants to their equivalent java objects.
051: */
052: public static Object[] convertVariantsToObjects(
053: Class<?>[] argTypes, Variant[] varArgs, String msgPrefix) {
054: Object[] javaArgs = new Object[Math.min(varArgs.length,
055: argTypes.length)];
056: for (int i = 0; i < javaArgs.length; i++) {
057: try {
058: Object javaArg = JsValueGlue.get(new JsValueIE6(
059: varArgs[i]), argTypes[i], msgPrefix);
060: javaArgs[i] = javaArg;
061: } catch (IllegalArgumentException e) {
062: throw new IllegalArgumentException(
063: "Error converting argument " + (i + 1) + ": "
064: + e.getMessage());
065: }
066: }
067:
068: return javaArgs;
069: }
070:
071: /**
072: * Extracts an array of strings from an (OLECHAR**) type (useful for
073: * implementing GetIDsOfNames()).
074: */
075: public static String[] extractStringArrayFromOleCharPtrPtr(
076: int ppchar, int count) {
077: String[] strings = new String[count];
078: for (int i = 0; i < count; ++i) {
079: int[] pchar = new int[1];
080: OS.MoveMemory(pchar, ppchar + 4 * i, 4);
081: strings[i] = extractStringFromOleCharPtr(pchar[0]);
082: }
083: return strings;
084: }
085:
086: /**
087: * Extracts a string from an (OLECHAR*) type.
088: */
089: public static String extractStringFromOleCharPtr(int pOleChar) {
090: // TODO: double-check the encoding (is it UTF-16?, what)
091: int size = COM.SysStringByteLen(pOleChar);
092: if (size > 8192) {
093: size = 8192;
094: }
095: char[] buffer = new char[(size + 1) / 2];
096: OS.MoveMemory(buffer, pOleChar, size);
097:
098: String s = new String(buffer);
099: if (s.indexOf('\0') != -1) {
100: return s.substring(0, s.indexOf('\0'));
101: } else {
102: return s;
103: }
104: }
105:
106: /**
107: * Injects an object into the Browser class that resolves to IE's
108: * 'window.external' object.
109: */
110: public static void injectBrowserScriptExternalObject(
111: Browser browser, final IDispatchImpl external) {
112: // Grab the browser's 'site.iDocHostUIHandler' field.
113: //
114: Object webSite = LowLevel.snatchFieldObjectValue(browser,
115: "site");
116: COMObject iDocHostUIHandler = (COMObject) LowLevel
117: .snatchFieldObjectValue(webSite, "iDocHostUIHandler");
118:
119: // Create a COMObjectProxy that will override GetExternal().
120: //
121: COMObjectProxy webSiteProxy = new COMObjectProxy(new int[] { 2,
122: 0, 0, 4, 1, 5, 0, 0, 1, 1, 1, 3, 3, 2, 2, 1, 3, 2 }) {
123:
124: {
125: // make sure we hold onto a ref on the external object
126: external.AddRef();
127: }
128:
129: @Override
130: public int method15(int[] args) {
131: // GetExternal() is method 15.
132: //
133: return GetExternal(args[0]);
134: }
135:
136: @Override
137: public int method2(int[] args) {
138: int result = super .method2(args);
139: if (result == 0) {
140: external.Release();
141: }
142: return result;
143: }
144:
145: // CHECKSTYLE_OFF
146: int GetExternal(int ppDispatch) {
147: // CHECKSTYLE_ON
148: if (ppDispatch != 0) {
149: try {
150: // Return the 'external' object.
151: //
152: external.AddRef();
153: OS.MoveMemory(ppDispatch, new int[] { external
154: .getAddress() }, 4);
155: return COM.S_OK;
156: } catch (Throwable e) {
157: e.printStackTrace();
158: return COM.E_FAIL;
159: }
160: } else {
161: OS.MoveMemory(ppDispatch, new int[] { 0 }, 4);
162: return COM.E_NOTIMPL;
163: }
164: }
165:
166: };
167:
168: // Interpose the proxy in front of the browser's iDocHostUiHandler.
169: //
170: webSiteProxy.interpose(iDocHostUIHandler);
171: }
172:
173: /**
174: * Convert a Java string to a COM BSTR.
175: *
176: * Wrapper for the OS' SysAllocStringLen(), since SysAllocString() is not
177: * safe for embedded nulls.
178: */
179: public static int sysAllocString(String s) {
180: return COM.SysAllocStringLen(s.toCharArray(), s.length());
181: }
182:
183: }
|