Skip to content

Commit

Permalink
Support for IE9 GWT Developer Mode plugin.
Browse files Browse the repository at this point in the history
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9599 8db76d5a-ed1c-0410-87a9-c151d255dfc7
  • Loading branch information
fabiomfv@google.com committed Jan 24, 2011
1 parent e0fbdff commit 2006164
Show file tree
Hide file tree
Showing 20 changed files with 746 additions and 277 deletions.
18 changes: 10 additions & 8 deletions common/Socket.cpp
@@ -1,12 +1,12 @@
/*
* Copyright 2008 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
Expand Down Expand Up @@ -80,10 +80,12 @@ bool Socket::connect(const char* host, int port) {
if (::connect(fd, (struct sockaddr*) &sockAddr, sizeof(sockAddr)) < 0) {
#ifdef _WINDOWS
char buf[256];
strerror_s(buf, sizeof(buf), errno);
Debug::log(Debug::Error) << "Can't connect to " << host << ":" << port << " -- "
<< buf << Debug::flush;
DWORD dwLastError = ::GetLastError();
strerror_s(buf, sizeof(buf), dwLastError);
Debug::log(Debug::Error) << "Failed to connect to " << host << ":" << port << " -- error code "
<< dwLastError << Debug::flush;
closesocket(fd);
::SetLastError(dwLastError);
#else
Debug::log(Debug::Error) << "Can't connect to " << host << ":" << port << " -- "
<< strerror(errno) << Debug::flush;
Expand Down Expand Up @@ -119,7 +121,7 @@ bool Socket::disconnect(bool doFlush) {
}
return true;
}

bool Socket::emptyWriteBuf() {
size_t len = writeBufPtr - writeBuf;
Debug::log(Debug::Spam) << "Socket::emptyWriteBuf: len=" << len << Debug::flush;
Expand All @@ -146,7 +148,7 @@ bool Socket::emptyWriteBuf() {
writeBufPtr = writeBuf;
return true;
}

bool Socket::fillReadBuf() {
readBufPtr = readBuf;
errno = 0;
Expand Down
4 changes: 2 additions & 2 deletions ie/installer/oophm.wxs
Expand Up @@ -12,7 +12,7 @@
</Fragment>
<Fragment>
<ComponentGroup Id="oophmDll">
<Component Win64="$(var.win64Flag)" Id="cmpC5076456A3EE2DC3FC2683246BE38AD6" Directory="dir315E0C50682DFB472927FE1254A22F6A" Guid="76483594-CBB8-438C-B777-5ABF473A90F0">
<Component Win64="$(var.win64Flag)" Id="cmpC5076456A3EE2DC3FC2683246BE38AD6" Directory="dir315E0C50682DFB472927FE1254A22F6A" Guid="FA1A9445-6468-4AF2-9132-8089DBE4AA91">
<File Id="filEF78EFE99C26E3436EC9C8852A85BE88" KeyPath="yes" Source="$(var.binDir)\oophm.dll">
<TypeLib Id="{9259F105-BE55-4BF6-B7CE-D0AA878C1BA6}" Description="oophm 1.0 Type Library" HelpDirectory="dir315E0C50682DFB472927FE1254A22F6A" Language="0" MajorVersion="1" MinorVersion="0">
<AppId Description="oophm" Id="{F9365E53-5A14-47F3-BF1D-10CAAB815309}">
Expand Down Expand Up @@ -41,7 +41,7 @@
<RegistryValue Root="HKMU" Key="AppID\oophm.DLL" Name="AppID" Value="{F9365E53-5A14-47F3-BF1D-10CAAB815309}" Type="string" Action="write" />
<RegistryValue Root="HKMU" Key="CLSID\{1D6156B6-002B-49E7-B5CA-C138FB843B4E}\MiscStatus\1" Value="131473" Type="string" Action="write" />
<RegistryValue Root="HKMU" Key="CLSID\{1D6156B6-002B-49E7-B5CA-C138FB843B4E}\MiscStatus" Value="0" Type="string" Action="write" />
<RegistryValue Root="HKMU" Key="CLSID\{1D6156B6-002B-49E7-B5CA-C138FB843B4E}\ToolboxBitmap32" Value="[!filEF78EFE99C26E3436EC9C8852A85BE88], 102" Type="string" Action="write" />
<RegistryValue Root="HKMU" Key="CLSID\{1D6156B6-002B-49E7-B5CA-C138FB843B4E}\ToolboxBitmap32" Value="[#filEF78EFE99C26E3436EC9C8852A85BE88], 102" Type="string" Action="write" />
</Component>
</ComponentGroup>
</Fragment>
Expand Down
22 changes: 22 additions & 0 deletions ie/oophm/oophm/Constants.h
@@ -0,0 +1,22 @@
#pragma once

#include "stdafx.h"

class Constants
{
public:
const static LPOLESTR __gwt_disconnected;
const static LPOLESTR valueOf;
const static LPOLESTR Error;
const static _bstr_t JavaScript;
const static LPOLESTR __gwt_makeResult;
const static LPOLESTR __gwt_makeTearOff;
};

__declspec(selectany) const LPOLESTR Constants::__gwt_disconnected = L"__gwt_disconnected";
__declspec(selectany) const LPOLESTR Constants::valueOf = L"valueOf";
__declspec(selectany) const LPOLESTR Constants::Error = L"Error";
__declspec(selectany) const _bstr_t Constants::JavaScript = _bstr_t(L"JavaScript");
__declspec(selectany) const LPOLESTR Constants::__gwt_makeResult = L"__gwt_makeResult";
__declspec(selectany) const LPOLESTR Constants::__gwt_makeTearOff = L"__gwt_makeTearOff";

119 changes: 65 additions & 54 deletions ie/oophm/oophm/IESessionHandler.cpp
Expand Up @@ -21,49 +21,54 @@
#include "IESessionHandler.h"
#include "ServerMethods.h"
#include "scoped_ptr/scoped_ptr.h"
#include "IEUtils.h"
#include "Constants.h"


IESessionHandler::IESessionHandler(HostChannel* channel,
IHTMLWindow2* window) : SessionData(channel, window, this), jsObjectId(1)
{
// window->put_defaultStatus(L"GWT Developer Plugin active");
IEUtils::resetResolver();
}

IESessionHandler::~IESessionHandler(void) {
Debug::log(Debug::Debugging) << "Destroying session handler" << Debug::flush;

Debug::log(Debug::Spam) << jsObjectsById.size() << " active JS object referances" << Debug::flush;

// Put any remaining JavaObject references into zombie-mode in case
// of lingering references
Debug::log(Debug::Spam) << javaObjectsById.size() << " active Java object referances" << Debug::flush;
Debug::log(Debug::Spam) << javaObjectsById.size() << " active Java object references" << Debug::flush;

IEUtils::resetResolver();
std::map<int, IUnknown*>::iterator it = javaObjectsById.begin();
while (it != javaObjectsById.end()) {
((CJavaObject*)it->second)->shutdown();
it++;
}

channel->disconnectFromHost();
}

void IESessionHandler::disconnectDetectedImpl() {
DISPID dispId;
LPOLESTR gwtDisconnectedName = L"__gwt_disconnected";
if (!SUCCEEDED(getWindow()->GetIDsOfNames(IID_NULL, &gwtDisconnectedName, 1,
LOCALE_SYSTEM_DEFAULT, &dispId))) {
Debug::log(Debug::Error) << "Unable to get dispId for __gwt_disconnected" << Debug::flush;
return;

HRESULT hr = IEUtils::resolveName(window, Constants::__gwt_disconnected, &dispId);
if(FAILED(hr)) {
Debug::log(Debug::Error) << "Unable to get dispId for __gwt_disconnected" << Debug::flush;
return;
}

DISPPARAMS dispParams = {NULL, NULL, 0, 0};
CComPtr<IDispatchEx> dispEx;
getWindow()->QueryInterface(&dispEx);
dispEx->InvokeEx(dispId, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
&dispParams, NULL, NULL, NULL);
hr = IEUtils::Invoke(getWindow(), dispId, DISPATCH_METHOD, &dispParams, NULL, NULL, NULL);
if (FAILED(hr)) {
Debug::log(Debug::Error) << "Unable to invoke __gwt_disconnected" << Debug::flush;
SYSLOGERROR(L"failed to invoke __gwt_disconnected", L"hr=0x%08x", hr);
}
}

void IESessionHandler::fatalError(HostChannel& channel,
const std::string& message) {
// TODO: better way of reporting error?
SYSLOGERROR(L"IESessionHandler::fatalError()", L"%S", message.c_str());
Debug::log(Debug::Error) << "Fatal error: " << message << Debug::flush;
}

Expand Down Expand Up @@ -92,6 +97,7 @@ void IESessionHandler::sendFreeValues(HostChannel& channel) {
if (!ServerMethods::freeJava(channel, this, idCount, ids.get())) {
Debug::log(Debug::Error) << "Unable to free Java ids on server" << Debug::flush;
}

javaObjectsToFree.clear();
}

Expand All @@ -113,17 +119,17 @@ bool IESessionHandler::invoke(HostChannel& channel, const Value& thisObj,
const std::string& methodName, int numArgs,
const Value* const args, Value* returnValue)
{
Debug::log(Debug::Debugging) << "Executing method " << methodName << " on object " << thisObj.toString() << Debug::flush;
Debug::log(Debug::Debugging) << "Executing method " << methodName <<
" on object " << thisObj.toString() << Debug::flush;

HRESULT res;

// Get the function off of the window
DISPID methodDispId;
_bstr_t methodNameBstr = UTF8ToBSTR(methodName.length(), methodName.c_str());
res = window->GetIDsOfNames(IID_NULL, &methodNameBstr.GetBSTR(), 1,
LOCALE_SYSTEM_DEFAULT, &methodDispId);
if (res) {
Debug::log(Debug::Error) << "Unable to find method " << methodName << " on the window object" <<Debug::flush;
HRESULT hr = IEUtils::resolveName(window, methodName, &methodDispId);
if (FAILED(hr)) {
SYSLOGERROR(L"Failed to resolve name to DISPID",
L"IESessionHandler::invoke(thisObj=%S, methodName=%S)",
thisObj.toString().c_str(), methodName.c_str());
Debug::log(Debug::Error) << "Unable to find method " << methodName
<< " on the window object" <<Debug::flush;
makeExceptionValue(*returnValue, "Unable to find named method on window");
return true;
}
Expand All @@ -132,14 +138,16 @@ bool IESessionHandler::invoke(HostChannel& channel, const Value& thisObj,
// TODO try PROPERTYGET|EXECUTE instead?
_variant_t functionObject;
DISPPARAMS disparamsNoArgs = {NULL, NULL, 0, 0};
res = window->Invoke(methodDispId, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET, &disparamsNoArgs, functionObject.GetAddress(), NULL, NULL);
if (res) {
Debug::log(Debug::Error) << "Unable to get method " << methodName << Debug::flush;
hr = IEUtils::Invoke(window, methodDispId, DISPATCH_PROPERTYGET, &disparamsNoArgs,
functionObject.GetAddress(), NULL, NULL);
if (FAILED(hr)) {
Debug::log(Debug::Error) << "Unable to get method " << methodName
<< Debug::flush;
makeExceptionValue(*returnValue, "Unable to get method from window");
return true;
} else if (functionObject.vt != VT_DISPATCH) {
Debug::log(Debug::Error) << "Did not get a VT_DISPATCH, got " << functionObject.vt << Debug::flush;
Debug::log(Debug::Error) << "Did not get a VT_DISPATCH, got " <<
functionObject.vt << Debug::flush;
makeExceptionValue(*returnValue, "Did not get a VT_DISPATCH");
return true;
}
Expand All @@ -148,7 +156,8 @@ bool IESessionHandler::invoke(HostChannel& channel, const Value& thisObj,
CComPtr<IDispatchEx> ex;
if (functionObject.pdispVal->QueryInterface(&ex)) {
// Probably not a function
Debug::log(Debug::Error) << "Failed to invoke " << methodName << " which is not an IDispatchEx" << Debug::flush;
Debug::log(Debug::Error) << "Failed to invoke " << methodName <<
" which is not an IDispatchEx" << Debug::flush;
makeExceptionValue(*returnValue, "Unable to invoke method");
return true;
}
Expand All @@ -171,7 +180,7 @@ bool IESessionHandler::invoke(HostChannel& channel, const Value& thisObj,

CComPtr<IServiceProvider> serviceProvider;
catcher->QueryInterface(&serviceProvider);
res = ex->InvokeEx(DISPID_VALUE, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
hr = ex->InvokeEx(DISPID_VALUE, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
&callDispParams, retVal.GetAddress(), &excepInfo, serviceProvider);

// There are cases where an exception was thrown and we've caught it, but
Expand All @@ -187,7 +196,7 @@ bool IESessionHandler::invoke(HostChannel& channel, const Value& thisObj,
makeValue(*returnValue, exception);
exceptionFlag = true;

} else if (!SUCCEEDED(res)) {
} else if (!SUCCEEDED(hr)) {
makeExceptionValue(*returnValue, "Unknown failure");
exceptionFlag = true;

Expand All @@ -206,50 +215,53 @@ bool IESessionHandler::invokeSpecial(HostChannel& channel, SpecialMethodId metho
return true;
}

void IESessionHandler::loadJsni(HostChannel& channel, const std::string& js) {
Debug::log(Debug::Spam) << "loadJsni " << js << Debug::flush;

_bstr_t code = UTF8ToBSTR(js.length(), js.c_str());
_bstr_t language = UTF8ToBSTR(10, "JavaScript");
_variant_t retVal;
Value toReturn;
void IESessionHandler::loadJsni(HostChannel& channel, const std::string& js) {
Debug::log(Debug::Spam) << ">>> loadJsni\n" << js << "\n<<< loadJsni" << Debug::flush;

HRESULT res = window->execScript(code, language, retVal.GetAddress());
if (!SUCCEEDED(res)) {
Debug::log(Debug::Error) << "Unable to evaluate JSNI code" << Debug::flush;
}
_variant_t retVal;
HRESULT hr = window->execScript(UTF8ToBSTR(js.length(), js.c_str()),
Constants::JavaScript, retVal.GetAddress());
if (FAILED(hr)) {
Debug::log(Debug::Error) << "Unable to evaluate JSNI code" << Debug::flush;
}
}

void IESessionHandler::makeException(_variant_t& in, const char* message) {
Debug::log(Debug::Debugging) << "Creating exception variant " << std::string(message) << Debug::flush;
HRESULT res;
Debug::log(Debug::Debugging) << "Creating exception variant " <<
std::string(message) << Debug::flush;

SYSLOGERROR(L"IESessionHandler::makeException()", L"exception: %S", message);
DISPID dispId;
LPOLESTR error = L"Error";
res = window->GetIDsOfNames(IID_NULL, &error, 1, LOCALE_SYSTEM_DEFAULT, &dispId);
HRESULT hr = IEUtils::resolveName(window, Constants::Error, &dispId);
if (FAILED(hr)) {
SYSLOGERROR(L"failed to resolve Error object", L"hr=0x%08x", hr);
return;
}

DISPPARAMS emptyParams = {NULL, NULL, 0, 0};
_variant_t errorConstructor;
res = window->Invoke(dispId, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET,
&emptyParams, errorConstructor.GetAddress(), NULL, NULL);
if (res) {
hr = IEUtils::Invoke(window, dispId, DISPATCH_PROPERTYGET, &emptyParams,
errorConstructor.GetAddress(), NULL, NULL);
if (FAILED(hr)) {
Debug::log(Debug::Error) << "Unable to get Error constructor" << Debug::flush;
in.SetString("Unable to get Error constructor");
}

CComPtr<IDispatchEx> ex;
res = errorConstructor.pdispVal->QueryInterface(&ex);
if (res) {
hr = errorConstructor.pdispVal->QueryInterface(&ex);
if (FAILED(hr)) {
Debug::log(Debug::Error) << "Error constructor not IDispatchEx" << Debug::flush;
in.SetString("Error constructor not IDispatchEx");
}

_variant_t param = _variant_t(message);
DISPPARAMS dispParams = {&param, NULL, 1, 0};

res = ex->InvokeEx(DISPID_VALUE, LOCALE_SYSTEM_DEFAULT, DISPATCH_CONSTRUCT,
hr = ex->InvokeEx(DISPID_VALUE, LOCALE_SYSTEM_DEFAULT, DISPATCH_CONSTRUCT,
&dispParams, in.GetAddress(), NULL, NULL);

if (res) {
if (FAILED(hr)) {
Debug::log(Debug::Error) << "Unable to invoke Error constructor" << Debug::flush;
in.SetString("Unable to invoke Error constructor");
}
Expand Down Expand Up @@ -315,10 +327,9 @@ void IESessionHandler::makeValue(Value& retVal, const _variant_t& value) {
_variant_t stringValue;
DISPPARAMS emptyParams = {NULL, NULL, 0, 0};
DISPID valueOfDispId = -1;
LPOLESTR valueOfString = L"valueOf";

dispObj->GetIDsOfNames(IID_NULL, &valueOfString, 1, LOCALE_SYSTEM_DEFAULT, &valueOfDispId);
// See if it's a wrapped String object by invoking valueOf()
HRESULT hr = dispObj->GetIDsOfNames(IID_NULL, (LPOLESTR*)&Constants::valueOf, 1,
LOCALE_SYSTEM_DEFAULT, &valueOfDispId);
if ((valueOfDispId != -1) &&
SUCCEEDED(dispObj->Invoke(valueOfDispId, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, &emptyParams, stringValue.GetAddress(),
Expand Down

0 comments on commit 2006164

Please sign in to comment.