Пример #1
0
bool JsObjectWrapper::invokeDefault(const NPVariant* args, unsigned argCount, NPVariant* result) {
	if(argCount < 1) {
		Debug::println("JsObjectWrapper::invokeDefault> argCount < 1: %d", argCount);
		return false;
	}

	if(!NPVARIANT_IS_OBJECT(args[0])) {
		Debug::println("JsObjectWrapper::invokeDefault> args[0] not an object");
		return false;
	}

	NPObject* pArray = NPVARIANT_TO_OBJECT(args[0]);
	Variant varRet;
	if(!NPN_GetProperty(getNPP(), pArray, m_agent->methods.length, varRet.ptr())) {
		Debug::println("JsObjectWrapper::invokeDefault> get length failed");
		return false;
	}

	if(!NPVARIANT_IS_INT32(varRet.get())) {
		Debug::println("JsObjectWrapper::invokeDefault> length did not return an int");
		return false;
	}

	int len = NPVARIANT_TO_INT32(varRet.get());
	VariantArray varArgs(len);

	for(int i = 0; i < len; i++) {
		NPIdentifier id = NPN_GetIntIdentifier(i);
		Variant varItem;
		if(!NPN_GetProperty(getNPP(), pArray, id, varArgs[i].ptr())) {
			Debug::println("JsObjectWrapper::invokeDefault> get [%d] failed", i);
			return false;
		}
	}

	Debug::println("JsObjectWrapper::invokeDefault");
	if(!m_agent->invokeRemoteDelegate(m_targetId, varArgs.get(), len, result)) {
		Debug::println("JsObjectWrapper::invokeDefault> invokeRemoteDelegate() failed");
		return false;
	}

	return true;
}
Пример #2
0
STDMETHODIMP CJavaObject::InvokeEx(DISPID dispidMember, LCID lcid, WORD wFlags,
                                   DISPPARAMS* pdispparams, VARIANT* pvarResult,
                                   EXCEPINFO* pexcepinfo,
                                   IServiceProvider* pspCaller)
{
  Debug::log(Debug::Debugging) << "Invoking " << dispidMember << " on Java object " << objId << Debug::flush;

  if (!sessionData) {
    // Prevent errors if the object is retained post-disconnect
    Debug::log(Debug::Warning) << "JavaObject retained beyound session shutdown" << Debug::flush;
    return DISP_E_MEMBERNOTFOUND;
  }

  HostChannel* channel = sessionData->getHostChannel();
  Value thisRef = Value();
  thisRef.setJavaObject(objId);

  if ((wFlags & DISPATCH_PROPERTYGET) && dispidMember == DISPID_VALUE &&
    pdispparams->cArgs - pdispparams->cNamedArgs == 0) {
      // This is an expression like ('' + obj)
      // raw toString();
      wFlags = DISPATCH_METHOD;
      dispidMember = DISPID_TOSTRING;
  }

  if (wFlags & DISPATCH_METHOD) {
    Debug::log(Debug::Spam) << "Dispatching method " << dispidMember << " on " << objId << Debug::flush;

    if (!(dispidMember == DISPID_VALUE || dispidMember == DISPID_TOSTRING)) {
      Debug::log(Debug::Error) << "Cannot dispatch for non-default id: " << dispidMember << Debug::flush;
      return E_FAIL;
    }
    scoped_array<Value> args;
    Value javaDispatchId;
    int numArgs;

    if (dispidMember == DISPID_VALUE) {
      numArgs = pdispparams->cArgs - pdispparams->cNamedArgs - 2;
      if (numArgs < 0) {
        // Indicates an error in JSNI rewriting or dispatch code
        Debug::log(Debug::Error) << "Insufficient number of arguments" << Debug::flush;
        return E_FAIL;
      }
      args.reset(new Value[numArgs]);
      // The dispatch parameters are backwards
      sessionData->makeValue(javaDispatchId, pdispparams->rgvarg[pdispparams->cArgs - 1]);
      sessionData->makeValue(thisRef, pdispparams->rgvarg[pdispparams->cArgs - 2]);
      for (int i = 0; i < numArgs; i++) {
        int index = pdispparams->cArgs - 3 - i;
        VARIANTARG element = pdispparams->rgvarg[index];
        sessionData->makeValue(args[i], element);
      }
    } else if (dispidMember == DISPID_TOSTRING) {
      // raw toString();
      numArgs = 0;
      javaDispatchId.setInt(0);
    }

    bool isException = false;
    Value returnValue;
    if (!InvokeMessage::send(*channel, thisRef, javaDispatchId.getInt(), numArgs, args.get())) {
      Debug::log(Debug::Error) << "Unable to send method invocation" << Debug::flush;
    } else {
      scoped_ptr<ReturnMessage> m(channel->reactToMessagesWhileWaitingForReturn(
      sessionData->getSessionHandler()));

      if (!m.get()) {
        Debug::log(Debug::Error) << "Did not receive ReturnMessage" << Debug::flush;
      } else {
        if (dispidMember == DISPID_TOSTRING) {
          // raw toString();
          if (pvarResult) {
            // This will be NULL when the caller doesn't care about the return value
            _variant_t returnVariant;
            sessionData->makeValueRef(returnVariant, m->getReturnValue());
            *pvarResult = returnVariant.Detach();
          }
          return m->isException() ? E_FAIL : S_OK;
        }
        isException = m->isException();
        returnValue = m->getReturnValue();
      }
    }

    DISPID dispId;

    HRESULT hr = IEUtils::resolveName(sessionData->getWindow(), Constants::__gwt_makeResult, &dispId);
    if (FAILED(hr)) {
        Debug::log(Debug::Error) << "Unable to get dispId for __gwt_makeResult" << Debug::flush;
        return E_FAIL;
    }

    // Call __gwt_makeResult(isException, returnValue)
    scoped_array<_variant_t> varArgs(new _variant_t[2]);
    // Args go backwards.
    varArgs[1] = (isException ? 1 : 0);
    sessionData->makeValueRef(varArgs[0], returnValue);
    DISPPARAMS dispParams = {varArgs.get(), NULL, 2, 0};
    CComPtr<IDispatchEx> dispEx;
    sessionData->getWindow()->QueryInterface(&dispEx);
    return dispEx->InvokeEx(dispId, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
      &dispParams, pvarResult, pexcepinfo, pspCaller);

  } else if (wFlags & DISPATCH_PROPERTYGET) {
    Debug::log(Debug::Spam) << "Getting property " << dispidMember << " on " << objId << Debug::flush;

    if (dispidMember == DISPID_VALUE) {
      this->QueryInterface(IID_IDispatch, (void**)&pvarResult->pdispVal);
      pvarResult->vt = VT_DISPATCH;

    } else if (dispidMember == DISPID_TOSTRING) {
      // Asking for a tear-off of the .toString function
      Debug::log(Debug::Spam) << "Making .toString tearoff" << Debug::flush;

      // Get a reference to __gwt_makeTearOff
      DISPID tearOffDispid;
      HRESULT hr = IEUtils::resolveName(sessionData->getWindow(), Constants::__gwt_makeTearOff, &tearOffDispid);
      if (FAILED(hr)) {
        Debug::log(Debug::Error) << "Unable to find __gwt_makeTearOff" << Debug::flush;
        return E_FAIL;
      }

      scoped_array<_variant_t> tearOffArgs(new _variant_t[3]);
      // Parameters are backwards:
      // __gwt_makeTearOff(proxy, dispId, argCount);
      tearOffArgs[2] = this; // proxy
      tearOffArgs[1] = 0; // dispId
      tearOffArgs[0] = 0; // argCount
      DISPPARAMS tearOffParams = {tearOffArgs.get(), NULL, 3, 0};

      // Invoke __gwt_makeTearOff
      hr = IEUtils::Invoke(sessionData->getWindow(), tearOffDispid,DISPATCH_METHOD,
          &tearOffParams, pvarResult, NULL, 0);
      if (FAILED(hr)) {
        Debug::log(Debug::Error) << "Unable to invoke __gwt_makeTearOff" << Debug::flush;
        return E_FAIL;
      }

    } else {
      Value ret = ServerMethods::getProperty(*channel,
        sessionData->getSessionHandler(), objId, dispidMember);

      if (ret.isUndefined()) {
        Debug::log(Debug::Error) << "Undefined get from Java object" << Debug::flush;
        return E_FAIL;
      }

      _variant_t returnVariant;
      sessionData->makeValueRef(returnVariant, ret);
      *pvarResult = returnVariant.Detach();
    }

  } else if (wFlags & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF)) {
    Debug::log(Debug::Spam) << "Setting property " << dispidMember << " on " << objId << Debug::flush;

    Value value;
    sessionData->makeValue(value, pdispparams->rgvarg[0]);

    ServerMethods::setProperty(*channel, sessionData->getSessionHandler(),
      objId, dispidMember, value);

  } else {
    Debug::log(Debug::Error) << "Unsupported invocation " << wFlags << Debug::flush;
    return DISP_E_MEMBERNOTFOUND;
  }

  return S_OK;
}