FB::variant FB::JSFunction::exec( const std::vector<variant>& args ) { FB::JSAPIPtr api = m_apiWeak.lock(); if (!api) throw new FB::script_error("Invalid JSAPI object"); // Force calls to use the zone this function was created with FB::scoped_zonelock _l(api, getZone()); return api->Invoke(m_methodName, args); }
// Methods to manage methods on the API FB::variant NPObjectAPI::Invoke(const std::string& methodName, const std::vector<FB::variant>& args) { if (m_browser.expired()) return false; NpapiBrowserHostPtr browser(getHost()); if (!browser->isMainThread()) { return browser->CallOnMainThread(boost::bind((FB::InvokeType)&NPObjectAPI::Invoke, this, methodName, args)); } if (is_JSAPI) { FB::JSAPIPtr tmp = inner.lock(); if (tmp) return tmp->Invoke(methodName, args); else return false; } NPVariant retVal; // Convert the arguments to NPVariants boost::scoped_array<NPVariant> npargs(new NPVariant[args.size()]); for (unsigned int i = 0; i < args.size(); i++) { browser->getNPVariant(&npargs[i], args[i]); } bool res = false; // Invoke the method ("" means invoke default method) if (methodName.size() > 0) { res = browser->Invoke(obj, browser->GetStringIdentifier(methodName.c_str()), npargs.get(), args.size(), &retVal); } else { res = browser->InvokeDefault(obj, npargs.get(), args.size(), &retVal); } // Free the NPVariants that we earlier allocated for (unsigned int i = 0; i < args.size(); i++) { browser->ReleaseVariantValue(&npargs[i]); } if (!res) { // If the method call failed, throw an exception browser->ReleaseVariantValue(&retVal); // Always release the return value! throw script_error(methodName.c_str()); } else { FB::variant ret = browser->getVariant(&retVal); browser->ReleaseVariantValue(&retVal); // Always release the return value! return ret; } }
void FB::Npapi::NPObjectAPI::callMultipleFunctions( const std::string& name, const FB::VariantList& args, const std::vector<JSObjectPtr>& direct, const std::vector<JSObjectPtr>& ifaces ) { if (!isValid()) throw FB::script_error("Error calling handlers"); NpapiBrowserHostPtr browser(getHost()); if (!browser->isMainThread()) { return browser->ScheduleOnMainThread(shared_from_this(), boost::bind(&NPObjectAPI::callMultipleFunctions, this, name, args, direct, ifaces)); } NPVariant retVal; // We make these calls through a delegate javascript function that is injected into // the page on startup. The reason we do this is to prevent some weird reentrance bugs // particularly in FF4. NPObjectAPIPtr d = static_pointer_cast<NPObjectAPI>(browser->getDelayedInvokeDelegate()); NPObject* delegate(d->getNPObject()); // Allocate the arguments boost::scoped_array<NPVariant> npargs(new NPVariant[4]); browser->getNPVariant(&npargs[0], 0); browser->getNPVariant(&npargs[2], args); browser->getNPVariant(&npargs[3], name); bool res = false; std::vector<JSObjectPtr>::const_iterator it(direct.begin()); std::vector<JSObjectPtr>::const_iterator end(direct.end()); for (; it != end; ++it) { NPObjectAPIPtr ptr(boost::static_pointer_cast<NPObjectAPI>(*it)); if (ptr->is_JSAPI) { FB::JSAPIPtr tmp = ptr->inner.lock(); if (tmp) { tmp->Invoke("", args); continue; } } browser->getNPVariant(&npargs[1], ptr); res = browser->InvokeDefault(delegate, npargs.get(), 3, &retVal); browser->ReleaseVariantValue(&retVal); browser->ReleaseVariantValue(&npargs[1]); } it = ifaces.begin(); end = ifaces.end(); for (; it != end; ++it) { NPObjectAPIPtr ptr(boost::static_pointer_cast<NPObjectAPI>(*it)); if (ptr->is_JSAPI) { FB::JSAPIPtr tmp = ptr->inner.lock(); if (tmp) { tmp->Invoke("", args); continue; } } browser->getNPVariant(&npargs[1], ptr); res = browser->InvokeDefault(delegate, npargs.get(), 4, &retVal); browser->ReleaseVariantValue(&retVal); browser->ReleaseVariantValue(&npargs[1]); } browser->ReleaseVariantValue(&npargs[2]); browser->ReleaseVariantValue(&npargs[3]); }