Revision: 6308 Author: [email protected] Date: Tue Oct 6 15:59:35 2009 Log: Add support for getting the browser icon from the client, added tests for the new messages and to verify all supported protocol versions work properly.
http://code.google.com/p/google-web-toolkit/source/detail?r=6308 Added: /changes/jat/abstractui/dev/core/test/com/google/gwt/dev/shell/BrowserChannelServerTest.java /changes/jat/abstractui/dev/core/test/com/google/gwt/dev/shell/FailErrorLogger.java /changes/jat/abstractui/dev/core/test/com/google/gwt/dev/shell/TestBrowserChannel.java /changes/jat/abstractui/dev/core/test/com/google/gwt/dev/util/TemporaryBufferStream.java Deleted: /changes/jat/abstractui/dev/core/src/com/google/gwt/dev/util/TemporaryBufferStream.java Modified: /changes/jat/abstractui/dev/core/src/com/google/gwt/dev/shell/HostedHtmlVersion.java /changes/jat/abstractui/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannel.java /changes/jat/abstractui/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannelServer.java /changes/jat/abstractui/dev/oophm/test/com/google/gwt/dev/shell/BrowserChannelTest.java ======================================= --- /dev/null +++ /changes/jat/abstractui/dev/core/test/com/google/gwt/dev/shell/BrowserChannelServerTest.java Tue Oct 6 15:59:35 2009 @@ -0,0 +1,305 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.dev.shell; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.dev.shell.BrowserChannel.CheckVersionsMessage; +import com.google.gwt.dev.shell.BrowserChannel.LoadModuleMessage; +import com.google.gwt.dev.shell.BrowserChannel.MessageType; +import com.google.gwt.dev.shell.BrowserChannel.OldLoadModuleMessage; +import com.google.gwt.dev.shell.BrowserChannel.ProtocolVersionMessage; +import com.google.gwt.dev.shell.BrowserChannel.QuitMessage; +import com.google.gwt.dev.shell.BrowserChannel.RequestIconMessage; +import com.google.gwt.dev.shell.BrowserChannel.ReturnMessage; +import com.google.gwt.dev.shell.BrowserChannel.SessionHandler; +import com.google.gwt.dev.shell.BrowserChannel.UserAgentIconMessage; +import com.google.gwt.dev.shell.BrowserChannel.Value; + +import junit.framework.TestCase; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.util.concurrent.Semaphore; + +/** + * Test that the protocol startup of BrowserChannelworks for all supported + * protocol versions. + */ +public class BrowserChannelServerTest extends TestCase { + + /** + * A BrowserChannelServer that can notify when the connection is closed. + */ + private class TestBrowserChannelServer extends BrowserChannelServer { + + private final Semaphore finishNotify = new Semaphore(0); + + public TestBrowserChannelServer(TreeLogger logger, + InputStream inputStream, OutputStream outputStream, + SessionHandler handler) throws IOException { + super(logger, inputStream, outputStream, handler); + } + + @Override + protected void processConnection() throws IOException, + BrowserChannelException { + super.processConnection(); + finishNotify.release(); + } + + public void waitForClose() throws InterruptedException { + finishNotify.acquire(); + } + } + + /** + * Maintains a connected pair of piped streams. + */ + private class PipedStreamPair { + + private final PipedOutputStream output; + private final PipedInputStream input; + + public PipedStreamPair() { + PipedOutputStream out = null; + PipedInputStream in = null; + try { + out = new PipedOutputStream(); + in = new PipedInputStream(out); + } catch (IOException e) { + } + output = out; + input = in; + } + + public PipedInputStream getInputStream() { + return input; + } + + public PipedOutputStream getOutputStream() { + return output; + } + } + + /** + * A SessionHandler which keeps track of parameters from the LoadModule + * message, but mocks out everything else. + */ + private static class TestSessionHandler extends SessionHandler { + + private String loadedModule; + private String userAgent; + private String url; + private String tabKey; + private String sessionKey; + private byte[] userAgentIcon; + private String moduleName; + + @Override + public void freeValue(BrowserChannel channel, int[] ids) { + } + + public String getLoadedModule() { + return loadedModule; + } + + public String getModuleName() { + return moduleName; + } + + @Override + public ExceptionOrReturnValue getProperty(BrowserChannel channel, + int refId, int dispId) { + return new ExceptionOrReturnValue(false, new Value()); + } + + public String getSessionKey() { + return sessionKey; + } + + public String getTabKey() { + return tabKey; + } + + public String getUrl() { + return url; + } + + public String getUserAgent() { + return userAgent; + } + + public byte[] getUserAgentIcon() { + return userAgentIcon; + } + + @Override + public ExceptionOrReturnValue invoke(BrowserChannel channel, Value thisObj, + int dispId, Value[] args) { + return new ExceptionOrReturnValue(false, new Value()); + } + + @Override + public TreeLogger loadModule(TreeLogger logger, BrowserChannel channel, + String moduleName, String userAgent, String url, String tabKey, + String sessionKey, byte[] userAgentIcon) { + loadedModule = moduleName; + this.moduleName = moduleName; + this.userAgent = userAgent; + this.url = url; + this.tabKey = tabKey; + this.sessionKey = sessionKey; + this.userAgentIcon = userAgentIcon; + return logger; + } + + @Override + public ExceptionOrReturnValue setProperty(BrowserChannel channel, + int refId, int dispId, Value newValue) { + return new ExceptionOrReturnValue(false, new Value()); + } + + @Override + public void unloadModule(BrowserChannel channel, String moduleName) { + loadedModule = null; + } + } + + private PipedStreamPair clientToServer = new PipedStreamPair(); + private PipedStreamPair serverToClient = new PipedStreamPair(); + + /** + * Test a version 1 client interacting with the server. + * + * @throws IOException + * @throws BrowserChannelException + * @throws InterruptedException + */ + public void testVersion1() throws IOException, BrowserChannelException, + InterruptedException { + TestSessionHandler handler = new TestSessionHandler(); + TestBrowserChannelServer server = new TestBrowserChannelServer( + new FailErrorLogger(), clientToServer.getInputStream(), + serverToClient.getOutputStream(), handler); + TestBrowserChannel client = new TestBrowserChannel( + serverToClient.getInputStream(), clientToServer.getOutputStream()); + new OldLoadModuleMessage(client, 1, "testModule", "userAgent").send(); + MessageType type = client.readMessageType(); + assertEquals("testModule", handler.getModuleName()); + assertEquals("userAgent", handler.getUserAgent()); + assertNull(handler.getUrl()); + assertNull(handler.getTabKey()); + assertNull(handler.getSessionKey()); + assertNull(handler.getUserAgentIcon()); + assertEquals(MessageType.RETURN, type); + ReturnMessage returnMessage = ReturnMessage.receive(client); + QuitMessage.send(client); + server.waitForClose(); + assertNull(handler.getLoadedModule()); + } + + /** + * Test a version 2 client interacting with the server. + * + * @throws IOException + * @throws BrowserChannelException + * @throws InterruptedException + */ + public void testVersion2() throws IOException, BrowserChannelException, + InterruptedException { + TestSessionHandler handler = new TestSessionHandler(); + TestBrowserChannelServer server = new TestBrowserChannelServer( + new FailErrorLogger(), clientToServer.getInputStream(), + serverToClient.getOutputStream(), handler); + TestBrowserChannel client = new TestBrowserChannel( + serverToClient.getInputStream(), clientToServer.getOutputStream()); + new CheckVersionsMessage(client, 2, 2, + HostedHtmlVersion.EXPECTED_GWT_ONLOAD_VERSION).send(); + MessageType type = client.readMessageType(); + assertEquals(MessageType.PROTOCOL_VERSION, type); + ProtocolVersionMessage protocolMessage = ProtocolVersionMessage.receive( + client); + assertEquals(2, protocolMessage.getProtocolVersion()); + new LoadModuleMessage(client, "url", "tabkey", "session", "testModule", + "userAgent").send(); + type = client.readMessageType(); + assertEquals("testModule", handler.getModuleName()); + assertEquals("userAgent", handler.getUserAgent()); + assertEquals("url", handler.getUrl()); + assertEquals("tabkey", handler.getTabKey()); + assertEquals("session", handler.getSessionKey()); + assertNull(handler.getUserAgentIcon()); + assertEquals(MessageType.RETURN, type); + ReturnMessage returnMessage = ReturnMessage.receive(client); + QuitMessage.send(client); + server.waitForClose(); + assertNull(handler.getLoadedModule()); + } + + /** + * Test a version 3 client interacting with the server. + * + * @throws IOException + * @throws BrowserChannelException + * @throws InterruptedException + */ + public void testVersion3() throws IOException, BrowserChannelException, + InterruptedException { + TestSessionHandler handler = new TestSessionHandler(); + TestBrowserChannelServer server = new TestBrowserChannelServer( + new FailErrorLogger(), clientToServer.getInputStream(), + serverToClient.getOutputStream(), handler); + TestBrowserChannel client = new TestBrowserChannel( + serverToClient.getInputStream(), clientToServer.getOutputStream()); + new CheckVersionsMessage(client, 2, 3, + HostedHtmlVersion.EXPECTED_GWT_ONLOAD_VERSION).send(); + MessageType type = client.readMessageType(); + byte[] iconBytes = null; + if (type == MessageType.REQUEST_ICON) { + RequestIconMessage requestIconlMessage = RequestIconMessage.receive( + client); + iconBytes = new byte[] { 0, 1, 2, 3, 4, 5 }; + UserAgentIconMessage.send(client, iconBytes); + } + type = client.readMessageType(); + assertEquals(MessageType.PROTOCOL_VERSION, type); + ProtocolVersionMessage protocolMessage = ProtocolVersionMessage.receive( + client); + assertEquals(3, protocolMessage.getProtocolVersion()); + new LoadModuleMessage(client, "url", "tabkey", "session", "testModule", + "userAgent").send(); + type = client.readMessageType(); + assertEquals("testModule", handler.getModuleName()); + assertEquals("userAgent", handler.getUserAgent()); + assertEquals("url", handler.getUrl()); + assertEquals("tabkey", handler.getTabKey()); + assertEquals("session", handler.getSessionKey()); + byte[] receivedIcon = handler.getUserAgentIcon(); + assertNotNull(receivedIcon); + assertEquals(iconBytes.length, receivedIcon.length); + for (int i = 0; i < iconBytes.length; ++i) { + assertEquals(iconBytes[i], receivedIcon[i]); + } + assertEquals(MessageType.RETURN, type); + ReturnMessage returnMessage = ReturnMessage.receive(client); + QuitMessage.send(client); + server.waitForClose(); + assertNull(handler.getLoadedModule()); + } +} ======================================= --- /dev/null +++ /changes/jat/abstractui/dev/core/test/com/google/gwt/dev/shell/FailErrorLogger.java Tue Oct 6 15:59:35 2009 @@ -0,0 +1,49 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.dev.shell; + +import com.google.gwt.core.ext.TreeLogger; + +/** + * A TreeLogger which throws an assertion failure if any error is logged. + */ +public class FailErrorLogger extends TreeLogger { + + @Override + public TreeLogger branch(Type type, String msg, Throwable caught, + HelpInfo helpInfo) { + if (type == TreeLogger.ERROR) { + AssertionError error = new AssertionError(msg); + error.initCause(caught); + throw error; + } + return this; + } + + @Override + public boolean isLoggable(Type type) { + return true; + } + + @Override + public void log(Type type, String msg, Throwable caught, HelpInfo helpInfo) { + if (type == TreeLogger.ERROR) { + AssertionError error = new AssertionError(msg); + error.initCause(caught); + throw error; + } + } +} ======================================= --- /dev/null +++ /changes/jat/abstractui/dev/core/test/com/google/gwt/dev/shell/TestBrowserChannel.java Tue Oct 6 15:59:35 2009 @@ -0,0 +1,50 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.dev.shell; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collections; +import java.util.Set; + +/** + * A test channel that mocks out Java/JS object references. + */ +class TestBrowserChannel extends BrowserChannel { + public TestBrowserChannel(InputStream inputStream, + OutputStream outputStream) throws IOException { + super(inputStream, outputStream, new ObjectRefFactory() { + public JavaObjectRef getJavaObjectRef(int refId) { + return new JavaObjectRef(refId); + } + + public JsObjectRef getJsObjectRef(int refId) { + return new JsObjectRef(refId); + } + + public Set<Integer> getRefIdsForCleanup() { + return Collections.emptySet(); + } + }); + } + + public MessageType readMessageType() throws IOException, + BrowserChannelException { + getStreamToOtherSide().flush(); + return Message.readMessageType(getStreamFromOtherSide()); + } +} ======================================= --- /dev/null +++ /changes/jat/abstractui/dev/core/test/com/google/gwt/dev/util/TemporaryBufferStream.java Tue Oct 6 15:59:35 2009 @@ -0,0 +1,56 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.dev.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; + +/** + * A utility for tests that allow writing to a temporary buffer and reading + * from the same buffer to verify that serialization/deserialization works. + */ +public class TemporaryBufferStream { + + private ArrayList<Byte> buf = new ArrayList<Byte>(); + + private InputStream inputStream = new InputStream() { + @Override + public int read() throws IOException { + try { + return buf.remove(0) & 255; + } catch (IndexOutOfBoundsException e) { + return -1; + } + } + }; + + private OutputStream outputStream = new OutputStream() { + @Override + public void write(int b) throws IOException { + buf.add(Byte.valueOf((byte) b)); + } + }; + + public InputStream getInputStream() { + return inputStream; + } + + public OutputStream getOutputStream() { + return outputStream; + } +} ======================================= --- /changes/jat/abstractui/dev/core/src/com/google/gwt/dev/util/TemporaryBufferStream.java Thu Aug 6 18:57:54 2009 +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.gwt.dev.util; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; - -/** - * A utility for tests that allow writing to a temporary buffer and reading - * from the same buffer to verify that serialization/deserialization works. - */ -public class TemporaryBufferStream { - - private ArrayList<Byte> buf = new ArrayList<Byte>(); - - private InputStream inputStream = new InputStream() { - @Override - public int read() throws IOException { - try { - return buf.remove(0) & 255; - } catch (IndexOutOfBoundsException e) { - return -1; - } - } - }; - - private OutputStream outputStream = new OutputStream() { - @Override - public void write(int b) throws IOException { - buf.add(Byte.valueOf((byte) b)); - } - }; - - public InputStream getInputStream() { - return inputStream; - } - - public OutputStream getOutputStream() { - return outputStream; - } -} ======================================= --- /changes/jat/abstractui/dev/core/src/com/google/gwt/dev/shell/HostedHtmlVersion.java Mon Aug 24 10:11:55 2009 +++ /changes/jat/abstractui/dev/core/src/com/google/gwt/dev/shell/HostedHtmlVersion.java Tue Oct 6 15:59:35 2009 @@ -27,7 +27,7 @@ * The version number that should be passed into gwtOnLoad. Must match the * version in hosted.html. */ - private static final String EXPECTED_GWT_ONLOAD_VERSION = "2.0"; + public static final String EXPECTED_GWT_ONLOAD_VERSION = "2.0"; /** * Validate that the supplied hosted.html version matches. ======================================= --- /changes/jat/abstractui/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannel.java Tue Oct 6 09:29:34 2009 +++ /changes/jat/abstractui/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannel.java Tue Oct 6 15:59:35 2009 @@ -1273,7 +1273,7 @@ /** * A message asking the client to send an icon suitable for use in the UI. - * @see {...@link UserAgentIconMessage}. + * <p>See {...@link UserAgentIconMessage}. */ protected static class RequestIconMessage extends Message { public static RequestIconMessage receive(BrowserChannel channel) @@ -1401,7 +1401,7 @@ /** * A message supplying an icon, which fits in 24x24 and in a standard image * format such as PNG or GIF, suitable for use in the UI. - * @see {...@link RequestIconMessage}. + * <p>See {...@link RequestIconMessage}. */ protected static class UserAgentIconMessage extends Message { public static UserAgentIconMessage receive(BrowserChannel channel) ======================================= --- /changes/jat/abstractui/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannelServer.java Tue Oct 6 09:29:34 2009 +++ /changes/jat/abstractui/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannelServer.java Tue Oct 6 15:59:35 2009 @@ -19,15 +19,17 @@ import com.google.gwt.dev.shell.JsValue.DispatchObject; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.net.Socket; import java.util.HashMap; import java.util.Map; import java.util.Set; /** - * + * Server-side of the browser channel protocol. */ -public final class BrowserChannelServer extends BrowserChannel +public class BrowserChannelServer extends BrowserChannel implements Runnable { private static class ServerObjectRefFactory implements ObjectRefFactory { @@ -84,6 +86,18 @@ thread.setName("Hosted mode worker"); thread.start(); } + + // @VisibleForTesting + BrowserChannelServer(TreeLogger initialLogger, InputStream inputStream, + OutputStream outputStream, SessionHandler handler) throws IOException { + super(inputStream, outputStream, new ServerObjectRefFactory()); + this.handler = handler; + this.logger = initialLogger; + Thread thread = new Thread(this); + thread.setDaemon(true); + thread.setName("Hosted mode worker"); + thread.start(); + } public void freeJsValue(int[] ids) { try { @@ -199,6 +213,124 @@ public void shutdown() throws IOException { QuitMessage.send(this); } + + // @VisibleForTesting + protected void processConnection() throws IOException, BrowserChannelException { + MessageType type = Message.readMessageType(getStreamFromOtherSide()); + // TODO(jat): add support for getting the a shim plugin downloading the + // real plugin via a GetRealPlugin message before CheckVersions + String url = null; + String tabKey = null; + String sessionKey = null; + byte[] iconBytes = null; + switch (type) { + case OLD_LOAD_MODULE: + // v1 client + OldLoadModuleMessage oldLoadModule = OldLoadModuleMessage.receive(this); + if (oldLoadModule.getProtoVersion() != 1) { + // This message type was only used in v1, so something is really + // broken here. + throw new BrowserChannelException( + "Old LoadModule message used, but not v1 protocol"); + } + moduleName = oldLoadModule.getModuleName(); + userAgent = oldLoadModule.getUserAgent(); + protocolVersion = 1; + logger.log(TreeLogger.WARN, "Connection from old browser plugin -- " + + "please upgrade to a later version for full functionality"); + break; + case CHECK_VERSIONS: + String connectError = null; + CheckVersionsMessage hello = CheckVersionsMessage.receive(this); + int minVersion = hello.getMinVersion(); + int maxVersion = hello.getMaxVersion(); + String hostedHtmlVersion = hello.getHostedHtmlVersion(); + if (minVersion > PROTOCOL_VERSION_CURRENT + || maxVersion < PROTOCOL_VERSION_OLDEST) { + connectError = "No supported protocol version in range " + minVersion + + " - " + maxVersion; + } else { + if (!HostedHtmlVersion.validHostedHtmlVersion(logger, + hostedHtmlVersion)) { + new FatalErrorMessage(this, + "Invalid hosted.html version - check log window").send(); + return; + } + } + protocolVersion = Math.min(PROTOCOL_VERSION_CURRENT, maxVersion); + if (connectError != null) { + logger.log(TreeLogger.ERROR, "Connection error: " + connectError, + null); + new FatalErrorMessage(this, connectError).send(); + return; + } + if (protocolVersion >= PROTOCOL_VERSION_GET_ICON) { + synchronized (cacheLock) { + if (iconCache.containsKey(userAgent)) { + iconBytes = iconCache.get(userAgent); + } else { + RequestIconMessage.send(this); + type = Message.readMessageType(getStreamFromOtherSide()); + if (type != MessageType.USER_AGENT_ICON) { + logger.log(TreeLogger.ERROR, "Unexpected message type " + type + + "; expecting UserAgentIcon"); + return; + } + UserAgentIconMessage uaIconMessage = UserAgentIconMessage.receive( + this); + iconBytes = uaIconMessage.getIconBytes(); + iconCache.put(userAgent, iconBytes); + } + } + } + new ProtocolVersionMessage(this, protocolVersion).send(); + type = Message.readMessageType(getStreamFromOtherSide()); + + // Optionally allow client to request switch of transports. Inband is + // always supported, so a return of an empty transport string requires + // the client to stay in this channel. + if (type == MessageType.CHOOSE_TRANSPORT) { + ChooseTransportMessage chooseTransport = ChooseTransportMessage.receive(this); + String transport = selectTransport(chooseTransport.getTransports()); + String transportArgs = null; + if (transport != null) { + transportArgs = createTransport(transport); + } + new SwitchTransportMessage(this, transport, transportArgs).send(); + type = Message.readMessageType(getStreamFromOtherSide()); + } + + // Now we expect a LoadModule message to load a GWT module. + if (type != MessageType.LOAD_MODULE) { + logger.log(TreeLogger.ERROR, "Unexpected message type " + type + + "; expecting LoadModule"); + return; + } + LoadModuleMessage loadModule = LoadModuleMessage.receive(this); + url = loadModule.getUrl(); + tabKey = loadModule.getTabKey(); + sessionKey = loadModule.getSessionKey(); + moduleName = loadModule.getModuleName(); + userAgent = loadModule.getUserAgent(); + break; + default: + logger.log(TreeLogger.ERROR, "Unexpected message type " + type + + "; expecting CheckVersions"); + return; + } + Thread.currentThread().setName( + "Hosting " + moduleName + " for " + userAgent + " on " + url + " @ " + + sessionKey); + logger = handler.loadModule(logger, this, moduleName, userAgent, url, + tabKey, sessionKey, iconBytes); + try { + // send LoadModule response + ReturnMessage.send(this, false, new Value()); + reactToMessages(handler); + } finally { + handler.unloadModule(this, moduleName); + } + } /** * Convert a JsValue into a BrowserChannel Value. @@ -307,120 +439,6 @@ throw new UnsupportedOperationException( "No alternate transports supported"); } - - private void processConnection() throws IOException, BrowserChannelException { - MessageType type = Message.readMessageType(getStreamFromOtherSide()); - // TODO(jat): add support for getting the a shim plugin downloading the - // real plugin via a GetRealPlugin message before CheckVersions - String url = null; - String tabKey = null; - String sessionKey = null; - switch (type) { - case OLD_LOAD_MODULE: - // v1 client - OldLoadModuleMessage oldLoadModule = OldLoadModuleMessage.receive(this); - if (oldLoadModule.getProtoVersion() != 1) { - // This message type was only used in v1, so something is really - // broken here. - throw new BrowserChannelException( - "Old LoadModule message used, but not v1 protocol"); - } - moduleName = oldLoadModule.getModuleName(); - userAgent = oldLoadModule.getUserAgent(); - protocolVersion = 1; - logger.log(TreeLogger.WARN, "Connection from old browser plugin -- " - + "please upgrade to a later version for full functionality"); - break; - case CHECK_VERSIONS: - String connectError = null; - CheckVersionsMessage hello = CheckVersionsMessage.receive(this); - int minVersion = hello.getMinVersion(); - int maxVersion = hello.getMaxVersion(); - String hostedHtmlVersion = hello.getHostedHtmlVersion(); - if (minVersion > PROTOCOL_VERSION_CURRENT - || maxVersion < PROTOCOL_VERSION_OLDEST) { - connectError = "No supported protocol version in range " + minVersion - + " - " + maxVersion; - } else { - if (!HostedHtmlVersion.validHostedHtmlVersion(logger, - hostedHtmlVersion)) { - new FatalErrorMessage(this, - "Invalid hosted.html version - check log window").send(); - return; - } - } - protocolVersion = Math.min(PROTOCOL_VERSION_CURRENT, maxVersion); - if (connectError != null) { - logger.log(TreeLogger.ERROR, "Connection error: " + connectError, - null); - new FatalErrorMessage(this, connectError).send(); - return; - } - new ProtocolVersionMessage(this, protocolVersion).send(); - type = Message.readMessageType(getStreamFromOtherSide()); - - // Optionally allow client to request switch of transports. Inband is - // always supported, so a return of an empty transport string requires - // the client to stay in this channel. - if (type == MessageType.CHOOSE_TRANSPORT) { - ChooseTransportMessage chooseTransport = ChooseTransportMessage.receive(this); - String transport = selectTransport(chooseTransport.getTransports()); - String transportArgs = null; - if (transport != null) { - transportArgs = createTransport(transport); - } - new SwitchTransportMessage(this, transport, transportArgs).send(); - type = Message.readMessageType(getStreamFromOtherSide()); - } - - // Now we expect a LoadModule message to load a GWT module. - if (type != MessageType.LOAD_MODULE) { - logger.log(TreeLogger.ERROR, "Unexpected message type " + type - + "; expecting LoadModule"); - return; - } - LoadModuleMessage loadModule = LoadModuleMessage.receive(this); - url = loadModule.getUrl(); - tabKey = loadModule.getTabKey(); - sessionKey = loadModule.getSessionKey(); - moduleName = loadModule.getModuleName(); - userAgent = loadModule.getUserAgent(); - break; - default: - logger.log(TreeLogger.ERROR, "Unexpected message type " + type - + "; expecting CheckVersions"); - return; - } - Thread.currentThread().setName( - "Hosting " + moduleName + " for " + userAgent + " on " + url + " @ " - + sessionKey); - byte[] iconBytes = null; - synchronized (cacheLock) { - if (iconCache.containsKey(userAgent)) { - iconBytes = iconCache.get(userAgent); - } else { - RequestIconMessage.send(this); - type = Message.readMessageType(getStreamFromOtherSide()); - if (type != MessageType.USER_AGENT_ICON) { - logger.log(TreeLogger.ERROR, "Unexpected message type " + type - + "; expecting UserAgentIcon"); - return; - } - UserAgentIconMessage uaIconMessage = UserAgentIconMessage.receive(this); - iconBytes = uaIconMessage.getIconBytes(); - iconCache.put(userAgent, iconBytes); - } - } - logger = handler.loadModule(logger, this, moduleName, userAgent, url, - tabKey, sessionKey, iconBytes); - try { - // send LoadModule response - ReturnMessage.send(this, false, new Value()); - reactToMessages(handler); - } finally { - handler.unloadModule(this, moduleName); - } - } /** * Select a transport from those provided by the client. ======================================= --- /changes/jat/abstractui/dev/oophm/test/com/google/gwt/dev/shell/BrowserChannelTest.java Tue Oct 6 09:29:34 2009 +++ /changes/jat/abstractui/dev/oophm/test/com/google/gwt/dev/shell/BrowserChannelTest.java Tue Oct 6 15:59:35 2009 @@ -43,10 +43,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.util.Arrays; -import java.util.Set; /** * Test for {...@link BrowserChannel}. @@ -55,32 +52,6 @@ private TemporaryBufferStream bufferStream = new TemporaryBufferStream(); - private class TestBrowserChannel extends BrowserChannel { - public TestBrowserChannel(InputStream inputStream, - OutputStream outputStream) throws IOException { - super(inputStream, outputStream, new ObjectRefFactory() { - public JavaObjectRef getJavaObjectRef(int refId) { - return new JavaObjectRef(refId); - } - - public JsObjectRef getJsObjectRef(int refId) { - return new JsObjectRef(refId); - } - - public Set<Integer> getRefIdsForCleanup() { - fail("getRefIdsForCleanup mocked"); - return null; - } - }); - } - - public MessageType readMessageType() throws IOException, - BrowserChannelException { - getStreamToOtherSide().flush(); - return Message.readMessageType(getStreamFromOtherSide()); - } - } - private DataInputStream iStr = new DataInputStream( bufferStream.getInputStream()); private DataOutputStream oStr = new DataOutputStream( @@ -392,15 +363,14 @@ assertEquals(MessageType.USER_AGENT_ICON, type); UserAgentIconMessage message = UserAgentIconMessage.receive(channel); assertFalse(message.isAsynchronous()); - byte[] receivedBytes = message.getIconBytes(); - assertNull(receivedBytes); + assertNull(message.getIconBytes()); UserAgentIconMessage.send(channel, new byte[0]); type = channel.readMessageType(); assertEquals(MessageType.USER_AGENT_ICON, type); message = UserAgentIconMessage.receive(channel); assertFalse(message.isAsynchronous()); - assertNull(receivedBytes); + assertNull(message.getIconBytes()); byte[] bytes = new byte[] { 0, 1, 2, 3, 4 }; UserAgentIconMessage.send(channel, bytes); @@ -408,10 +378,11 @@ assertEquals(MessageType.USER_AGENT_ICON, type); message = UserAgentIconMessage.receive(channel); assertFalse(message.isAsynchronous()); + byte[] receivedBytes = message.getIconBytes(); assertNotNull(receivedBytes); - assertEquals(5, receivedBytes.length); - for (int i = 0; i < 5; ++i) { - assertEquals(i, receivedBytes[i]); + assertEquals(bytes.length, receivedBytes.length); + for (int i = 0; i < bytes.length; ++i) { + assertEquals(bytes[i], receivedBytes[i]); } } } --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---
