int to_erl_object(emonk_buf_t* buf, JSContext* cx, JSObject* obj) { JSObject* iter; JSString* key; jsid idp; jsval val; jschar* keyname; size_t keylen; int count = 0; int lengthpos; REQUEST(7); BUFPTR[0] = SMALL_TUPLE; BUFPTR[1] = (char) 1; BUFPTR[2] = LIST; // Remember the byte offset where length goes so we can write it // after enumerating the properties. lengthpos = buf->used + 3; buf->used += 7; iter = JS_NewPropertyIterator(cx, obj); if(iter == NULL) return ERROR; while(JS_NextProperty(cx, iter, &idp)) { // Done iterating, write length and bail. if(idp == JSVAL_VOID) { count = htonl(count); memcpy(buf->buf+lengthpos, &count, 4); REQUEST(1); BUFPTR[0] = NIL; buf->used += 1; return OK; } REQUEST(2); BUFPTR[0] = SMALL_TUPLE; BUFPTR[1] = 2; buf->used += 2; if(!JS_IdToValue(cx, idp, &val)) return ERROR; if(!to_erl_string(buf, cx, val)) return ERROR; key = JS_ValueToString(cx, val); keyname = JS_GetStringChars(key); keylen = JS_GetStringLength(key); if(!JS_GetUCProperty(cx, obj, keyname, keylen, &val)) return ERROR; if(!to_erl_intern(buf, cx, val)) return ERROR; count += 1; } return ERROR; }
/* * Class: netscape_javascript_JSObject * Method: getMember * Signature: (Ljava/lang/String;)Ljava/lang/Object; */ JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getMember(JNIEnv *jEnv, jobject java_wrapper_obj, jstring property_name_jstr) { JSContext *cx = NULL; JSObject *js_obj; jsval js_val; int dummy_cost; JSBool dummy_bool; const jchar *property_name_ucs2; jsize property_name_len; JSErrorReporter saved_reporter; jobject member; jboolean is_copy; JSJavaThreadState *jsj_env; jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); if (!jsj_env) return NULL; property_name_ucs2 = NULL; if (!property_name_jstr) { JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_NULL_MEMBER_NAME); member = NULL; goto done; } /* Get the Unicode string for the JS property name */ property_name_ucs2 = (*jEnv)->GetStringChars(jEnv, property_name_jstr, &is_copy); if (!property_name_ucs2) { JS_ASSERT(0); goto done; } property_name_len = (*jEnv)->GetStringLength(jEnv, property_name_jstr); if (!JS_GetUCProperty(cx, js_obj, property_name_ucs2, property_name_len, &js_val)) goto done; jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &member, &dummy_bool); done: if (property_name_ucs2) (*jEnv)->ReleaseStringChars(jEnv, property_name_jstr, property_name_ucs2); if (!jsj_exit_js(cx, jsj_env, saved_reporter)) return NULL; return member; }
XPCDispJSPropertyInfo::XPCDispJSPropertyInfo(JSContext* cx, PRUint32 memid, JSObject* obj, jsval val) : mPropertyType(INVALID), mMemID(memid) { PRUint32 len; jschar * chars = xpc_JSString2String(cx, val, &len); if(!chars) return; mName = nsString(reinterpret_cast<const PRUnichar *>(chars), len); JSBool found; uintN attr; // Get the property's attributes, and make sure it's found and enumerable if(!JS_GetUCPropertyAttributes(cx, obj, chars, len, &attr, &found) || !found || (attr & JSPROP_ENUMERATE) == 0) return; // Retrieve the property if(!chars || !JS_GetUCProperty(cx, obj, chars, len, &mProperty) || JSVAL_IS_NULL(mProperty)) return; // If this is a function if(JSVAL_IS_OBJECT(mProperty) && JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(mProperty))) { mPropertyType = FUNCTION; JSObject * funcObj = JSVAL_TO_OBJECT(mProperty); JSIdArray * funcObjArray = JS_Enumerate(cx, funcObj); if(funcObjArray) { mParamCount = funcObjArray->length; } } else // It's a property { mParamCount = 0; if((attr & JSPROP_READONLY) != 0) { mPropertyType = READONLY_PROPERTY; } else { mPropertyType = PROPERTY; } } }
NS_METHOD abpScriptable::GetProperty(nsIXPConnectWrappedNative* wrapper, JSContext* cx, JSObject* obj, jsval id, jsval* vp, PRBool* _retval) { nsresult rv = NS_OK; JSString* property = JS_ValueToString(cx, id); if (property == nsnull) return NS_ERROR_FAILURE; nsCOMPtr<nsISupports> native; rv = wrapper->GetNative(getter_AddRefs(native)); if (NS_FAILED(rv)) return rv; JSObject* innerObj = UnwrapJSObject(native); if (innerObj == nsnull) return NS_ERROR_FAILURE; *_retval = JS_GetUCProperty(cx, innerObj, JS_GetStringChars(property), JS_GetStringLength(property), vp); return rv; }
JSDProperty* jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name) { JSContext* cx = jsdc->dumbContext; JSDProperty* jsdprop; JSDProperty* iter = NULL; JSObject* obj; uintN attrs = 0; JSBool found; JSPropertyDesc pd; const jschar * nameChars; size_t nameLen; jsval val, nameval; jsid nameid; JSCrossCompartmentCall *call = NULL; if(!jsd_IsValueObject(jsdc, jsdval)) return NULL; /* If we already have the prop, then return it */ while(NULL != (jsdprop = jsd_IterateProperties(jsdc, jsdval, &iter))) { JSString* propName = jsd_GetValueString(jsdc, jsdprop->name); if(propName) { intN result; if (JS_CompareStrings(cx, propName, name, &result) && !result) return jsdprop; } JSD_DropProperty(jsdc, jsdprop); } /* Not found in property list, look it up explicitly */ if(!(obj = JSVAL_TO_OBJECT(jsdval->val))) return NULL; if (!(nameChars = JS_GetStringCharsZAndLength(cx, name, &nameLen))) return NULL; JS_BeginRequest(cx); call = JS_EnterCrossCompartmentCall(cx, obj); if(!call) { JS_EndRequest(cx); return NULL; } JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found); if (!found) { JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); return NULL; } JS_ClearPendingException(cx); if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, &val)) { if (JS_IsExceptionPending(cx)) { if (!JS_GetPendingException(cx, &pd.value)) { JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); return NULL; } pd.flags = JSPD_EXCEPTION; } else { pd.flags = JSPD_ERROR; pd.value = JSVAL_VOID; } } else { pd.value = val; } JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); nameval = STRING_TO_JSVAL(name); if (!JS_ValueToId(cx, nameval, &nameid) || !JS_IdToValue(cx, nameid, &pd.id)) { return NULL; } pd.slot = pd.spare = 0; pd.alias = JSVAL_NULL; pd.flags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0 | (attrs & JSPROP_READONLY) ? JSPD_READONLY : 0 | (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0; return _newProperty(jsdc, &pd, JSDPD_HINTED); }
/* * Class: netscape_javascript_JSObject * Method: call * Signature: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object; */ JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_call(JNIEnv *jEnv, jobject java_wrapper_obj, jstring function_name_jstr, jobjectArray java_args) { int i, argc, arg_num; jsval *argv; JSContext *cx = NULL; JSObject *js_obj; jsval js_val, function_val; int dummy_cost; JSBool dummy_bool; const jchar *function_name_ucs2; jsize function_name_len; JSErrorReporter saved_reporter; jboolean is_copy; jobject result; JSJavaThreadState *jsj_env; jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); if (!jsj_env) return NULL; function_name_ucs2 = NULL; result = NULL; if (!function_name_jstr) { JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_NULL_FUNCTION_NAME); goto done; } /* Get the function name to eval as raw Unicode characters */ function_name_ucs2 = (*jEnv)->GetStringChars(jEnv, function_name_jstr, &is_copy); if (!function_name_ucs2) { JS_ASSERT(0); goto done; } function_name_len = (*jEnv)->GetStringLength(jEnv, function_name_jstr); /* Allocate space for JS arguments */ if (java_args) { argc = (*jEnv)->GetArrayLength(jEnv, java_args); argv = (jsval*)JS_malloc(cx, argc * sizeof(jsval)); } else { argc = 0; argv = 0; } /* Convert arguments from Java to JS values */ for (arg_num = 0; arg_num < argc; arg_num++) { jobject arg = (*jEnv)->GetObjectArrayElement(jEnv, java_args, arg_num); if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, arg, &argv[arg_num])) goto cleanup_argv; JS_AddNamedRoot(cx, &argv[arg_num], "&argv[arg_num]"); } if (!JS_GetUCProperty(cx, js_obj, function_name_ucs2, function_name_len, &function_val)) goto cleanup_argv; if (!JS_CallFunctionValue(cx, js_obj, function_val, argc, argv, &js_val)) goto cleanup_argv; jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &result, &dummy_bool); cleanup_argv: if (argv) { for (i = 0; i < arg_num; i++) JS_RemoveRoot(cx, &argv[i]); JS_free(cx, argv); } done: if (function_name_ucs2) (*jEnv)->ReleaseStringChars(jEnv, function_name_jstr, function_name_ucs2); if (!jsj_exit_js(cx, jsj_env, saved_reporter)) return NULL; return result; }
JSBool js_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, JSONWriteCallback callback, void *data, uint32 depth) { if (depth > JSON_MAX_DEPTH) return JS_FALSE; /* encoding error */ JSBool ok = JS_TRUE; JSObject *obj = JSVAL_TO_OBJECT(*vp); JSBool isArray = JS_IsArrayObject(cx, obj); jschar output = jschar(isArray ? '[' : '{'); if (!callback(&output, 1, data)) return JS_FALSE; JSObject *iterObj = NULL; jsint i = 0; jsuint length = 0; if (isArray) { if (!JS_GetArrayLength(cx, obj, &length)) return JS_FALSE; } else { if (!js_ValueToIterator(cx, JSITER_ENUMERATE, vp)) return JS_FALSE; iterObj = JSVAL_TO_OBJECT(*vp); } jsval outputValue = JSVAL_VOID; JSAutoTempValueRooter tvr(cx, 1, &outputValue); jsval key; JSBool memberWritten = JS_FALSE; do { outputValue = JSVAL_VOID; if (isArray) { if ((jsuint)i >= length) break; ok = JS_GetElement(cx, obj, i++, &outputValue); } else { ok = js_CallIteratorNext(cx, iterObj, &key); if (!ok) break; if (key == JSVAL_HOLE) break; JSString *ks; if (JSVAL_IS_STRING(key)) { ks = JSVAL_TO_STRING(key); } else { ks = JS_ValueToString(cx, key); if (!ks) { ok = JS_FALSE; break; } } ok = JS_GetUCProperty(cx, obj, JS_GetStringChars(ks), JS_GetStringLength(ks), &outputValue); } if (!ok) break; // if this is an array, holes are transmitted as null if (isArray && outputValue == JSVAL_VOID) { outputValue = JSVAL_NULL; } else if (JSVAL_IS_OBJECT(outputValue)) { ok = js_TryJSON(cx, &outputValue); if (!ok) break; } // elide undefined values if (outputValue == JSVAL_VOID) continue; // output a comma unless this is the first member to write if (memberWritten) { output = jschar(','); ok = callback(&output, 1, data); if (!ok) break; } memberWritten = JS_TRUE; JSType type = JS_TypeOfValue(cx, outputValue); // Can't encode these types, so drop them if (type == JSTYPE_FUNCTION || type == JSTYPE_XML) break; // Be careful below, this string is weakly rooted. JSString *s; // If this isn't an array, we need to output a key if (!isArray) { s = JS_ValueToString(cx, key); if (!s) { ok = JS_FALSE; break; } ok = write_string(cx, callback, data, JS_GetStringChars(s), JS_GetStringLength(s)); if (!ok) break; output = jschar(':'); ok = callback(&output, 1, data); if (!ok) break; } if (!JSVAL_IS_PRIMITIVE(outputValue)) { // recurse ok = js_Stringify(cx, &outputValue, replacer, callback, data, depth + 1); } else { JSString *outputString; s = JS_ValueToString(cx, outputValue); if (!s) { ok = JS_FALSE; break; } if (type == JSTYPE_STRING) { ok = write_string(cx, callback, data, JS_GetStringChars(s), JS_GetStringLength(s)); if (!ok) break; continue; } if (type == JSTYPE_NUMBER) { if (JSVAL_IS_DOUBLE(outputValue)) { jsdouble d = *JSVAL_TO_DOUBLE(outputValue); if (!JSDOUBLE_IS_FINITE(d)) outputString = JS_NewStringCopyN(cx, "null", 4); else outputString = s; } else { outputString = s; } } else if (type == JSTYPE_BOOLEAN) { outputString = s; } else if (JSVAL_IS_NULL(outputValue)) { outputString = JS_NewStringCopyN(cx, "null", 4); } else { ok = JS_FALSE; // encoding error break; } ok = callback(JS_GetStringChars(outputString), JS_GetStringLength(outputString), data); } } while (ok); if (iterObj) { // Always close the iterator, but make sure not to stomp on OK js_CloseIteratorState(cx, iterObj); // encoding error or propagate? FIXME: Bug 408838. } if (!ok) { JS_ReportError(cx, "Error during JSON encoding."); return JS_FALSE; } output = jschar(isArray ? ']' : '}'); ok = callback(&output, 1, data); return ok; }
NS_IMETHODIMP IDBCursor::Update(const jsval &aValue, JSContext* aCx, nsIIDBRequest** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); if (mType != OBJECTSTORE) { NS_NOTYETIMPLEMENTED("Implement me!"); return NS_ERROR_NOT_IMPLEMENTED; } if (!mObjectStore->TransactionIsOpen()) { return NS_ERROR_UNEXPECTED; } if (!mObjectStore->IsWriteAllowed()) { return NS_ERROR_OBJECT_IS_IMMUTABLE; } const Key& key = mData[mDataIndex].key; NS_ASSERTION(!key.IsUnset() && !key.IsNull(), "Bad key!"); JSAutoRequest ar(aCx); js::AutoValueRooter clone(aCx); nsresult rv = nsContentUtils::CreateStructuredClone(aCx, aValue, clone.jsval_addr()); if (NS_FAILED(rv)) { return rv; } if (!mObjectStore->KeyPath().IsEmpty()) { // Make sure the object given has the correct keyPath value set on it or // we will add it. const nsString& keyPath = mObjectStore->KeyPath(); const jschar* keyPathChars = reinterpret_cast<const jschar*>(keyPath.get()); const size_t keyPathLen = keyPath.Length(); js::AutoValueRooter prop(aCx); JSBool ok = JS_GetUCProperty(aCx, JSVAL_TO_OBJECT(clone.jsval_value()), keyPathChars, keyPathLen, prop.jsval_addr()); NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE); if (JSVAL_IS_VOID(prop.jsval_value())) { rv = IDBObjectStore::GetJSValFromKey(key, aCx, prop.jsval_addr()); NS_ENSURE_SUCCESS(rv, rv); ok = JS_DefineUCProperty(aCx, JSVAL_TO_OBJECT(clone.jsval_value()), keyPathChars, keyPathLen, prop.jsval_value(), nsnull, nsnull, JSPROP_ENUMERATE); NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE); } else { Key newKey; rv = IDBObjectStore::GetKeyFromJSVal(prop.jsval_value(), newKey); NS_ENSURE_SUCCESS(rv, rv); if (newKey.IsUnset() || newKey.IsNull() || newKey != key) { return NS_ERROR_INVALID_ARG; } } } nsTArray<IndexUpdateInfo> indexUpdateInfo; rv = IDBObjectStore::GetIndexUpdateInfo(mObjectStore->GetObjectStoreInfo(), aCx, clone.jsval_value(), indexUpdateInfo); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIJSON> json(new nsJSON()); nsString jsonValue; rv = json->EncodeFromJSVal(clone.jsval_addr(), aCx, jsonValue); NS_ENSURE_SUCCESS(rv, rv); nsRefPtr<IDBRequest> request = GenerateWriteRequest(mTransaction->ScriptContext(), mTransaction->Owner()); NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); nsRefPtr<UpdateHelper> helper = new UpdateHelper(mTransaction, request, mObjectStore->Id(), jsonValue, key, mObjectStore->IsAutoIncrement(), indexUpdateInfo); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, rv); request.forget(_retval); return NS_OK; }
/** * call a method of Native JSObject. * * @param jEnv - JNIEnv on which the call is being made. * @param obj - A Native JS Object. * @param name - Name of a method. * @param jobjArr - Array of jobjects representing parameters of method being caled. * @param pjobj - return value. */ NS_METHOD nsCLiveconnect::Call(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobjectArray java_args, void* principalsArray[], int numPrincipals, nsISupports *securitySupports, jobject *pjobj) { if(jEnv == NULL || obj == 0) { return NS_ERROR_FAILURE; } int i = 0; int argc = 0; int arg_num = 0; jsval *argv = 0; JSJavaThreadState *jsj_env = NULL; JSObjectHandle *handle = (JSObjectHandle*)obj; JSObject *js_obj = handle->js_obj; JSContext *cx = NULL; jsval js_val; jsval function_val = 0; int dummy_cost = 0; JSBool dummy_bool = PR_FALSE; JSErrorReporter saved_state = NULL; jobject result = NULL; jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); if (!jsj_env) return NS_ERROR_FAILURE; result = NULL; AutoPushJSContext autopush(securitySupports, cx); if (NS_FAILED(autopush.ResultOfPush())) goto done; if (!name) { JS_ReportError(cx, "illegal null JavaScript function name"); goto done; } /* Allocate space for JS arguments */ argc = java_args ? jEnv->GetArrayLength(java_args) : 0; if (argc) { argv = (jsval*)JS_malloc(cx, argc * sizeof(jsval)); if (!argv) goto done; } else { argv = 0; } /* Convert arguments from Java to JS values */ for (arg_num = 0; arg_num < argc; arg_num++) { jobject arg = jEnv->GetObjectArrayElement(java_args, arg_num); JSBool ret = jsj_ConvertJavaObjectToJSValue(cx, jEnv, arg, &argv[arg_num]); jEnv->DeleteLocalRef(arg); if (!ret) goto cleanup_argv; JS_AddRoot(cx, &argv[arg_num]); } if (!JS_GetUCProperty(cx, js_obj, name, length, &function_val)) goto cleanup_argv; if (!JS_CallFunctionValue(cx, js_obj, function_val, argc, argv, &js_val)) goto cleanup_argv; jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &result, &dummy_bool); cleanup_argv: if (argv) { for (i = 0; i < arg_num; i++) JS_RemoveRoot(cx, &argv[i]); JS_free(cx, argv); } done: if (!jsj_exit_js(cx, jsj_env, saved_state)) return NS_ERROR_FAILURE; *pjobj = result; return NS_OK; }
NS_INTERFACE_MAP_END //////////////////////////////////////////////////////////////////////////// // from nsILiveconnect: /** * get member of a Native JSObject for a given name. * * @param jEnv - JNIEnv on which the call is being made. * @param obj - A Native JS Object. * @param name - Name of a member. * @param pjobj - return parameter as a java object representing * the member. If it is a basic data type it is converted to * a corresponding java type. If it is a NJSObject, then it is * wrapped up as java wrapper netscape.javascript.JSObject. */ NS_METHOD nsCLiveconnect::GetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, void* principalsArray[], int numPrincipals, nsISupports *securitySupports, jobject *pjobj) { if(jEnv == NULL || obj == 0) { return NS_ERROR_FAILURE; } JSJavaThreadState *jsj_env = NULL; JSObjectHandle *handle = (JSObjectHandle*)obj; JSObject *js_obj = handle->js_obj; JSContext *cx = NULL; jobject member = NULL; jsval js_val; int dummy_cost = 0; JSBool dummy_bool = PR_FALSE; JSErrorReporter saved_state = NULL; jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); if (!jsj_env) return NS_ERROR_FAILURE; AutoPushJSContext autopush(securitySupports, cx); if (NS_FAILED(autopush.ResultOfPush())) goto done; if (!name) { JS_ReportError(cx, "illegal null member name"); member = NULL; goto done; } if (!JS_GetUCProperty(cx, js_obj, name, length, &js_val)) goto done; jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &member, &dummy_bool); done: if (!jsj_exit_js(cx, jsj_env, saved_state)) return NS_ERROR_FAILURE; *pjobj = member; return NS_OK; }
// // Native method Install // static JSBool InstallTriggerGlobalInstall(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { nsIDOMInstallTriggerGlobal *nativeThis = getTriggerNative(cx, obj); if (!nativeThis) return JS_FALSE; *rval = JSVAL_FALSE; // make sure XPInstall is enabled, return false if not nsIScriptGlobalObject *globalObject = nsnull; nsIScriptContext *scriptContext = GetScriptContextFromJSContext(cx); if (scriptContext) globalObject = scriptContext->GetGlobalObject(); if (!globalObject) return JS_TRUE; nsCOMPtr<nsIScriptSecurityManager> secman(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID)); if (!secman) { JS_ReportError(cx, "Could not the script security manager service."); return JS_FALSE; } // get the principal. if it doesn't exist, die. nsCOMPtr<nsIPrincipal> principal; secman->GetSubjectPrincipal(getter_AddRefs(principal)); if (!principal) { JS_ReportError(cx, "Could not get the Subject Principal during InstallTrigger.Install()"); return JS_FALSE; } // get window.location to construct relative URLs nsCOMPtr<nsIURI> baseURL; JSObject* global = JS_GetGlobalObject(cx); if (global) { jsval v; if (JS_GetProperty(cx,global,"location",&v)) { nsAutoString location; ConvertJSValToStr( location, cx, v ); NS_NewURI(getter_AddRefs(baseURL), location); } } PRBool abortLoad = PR_FALSE; // parse associative array of installs if ( argc >= 1 && JSVAL_IS_OBJECT(argv[0]) && JSVAL_TO_OBJECT(argv[0]) ) { nsXPITriggerInfo *trigger = new nsXPITriggerInfo(); if (!trigger) return JS_FALSE; trigger->SetPrincipal(principal); JSIdArray *ida = JS_Enumerate( cx, JSVAL_TO_OBJECT(argv[0]) ); if ( ida ) { jsval v; const PRUnichar *name, *URL; const PRUnichar *iconURL = nsnull; for (int i = 0; i < ida->length && !abortLoad; i++ ) { JS_IdToValue( cx, ida->vector[i], &v ); JSString * str = JS_ValueToString( cx, v ); if (!str) { abortLoad = PR_TRUE; break; } name = reinterpret_cast<const PRUnichar*>(JS_GetStringChars( str )); URL = iconURL = nsnull; JSAutoByteString hash; JS_GetUCProperty( cx, JSVAL_TO_OBJECT(argv[0]), reinterpret_cast<const jschar*>(name), nsCRT::strlen(name), &v ); if ( JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) ) { jsval v2; if (JS_GetProperty( cx, JSVAL_TO_OBJECT(v), "URL", &v2 ) && !JSVAL_IS_VOID(v2)) { JSString *str = JS_ValueToString(cx, v2); if (!str) { abortLoad = PR_TRUE; break; } URL = reinterpret_cast<const PRUnichar*>(JS_GetStringChars(str)); } if (JS_GetProperty( cx, JSVAL_TO_OBJECT(v), "IconURL", &v2 ) && !JSVAL_IS_VOID(v2)) { JSString *str = JS_ValueToString(cx, v2); if (!str) { abortLoad = PR_TRUE; break; } iconURL = reinterpret_cast<const PRUnichar*>(JS_GetStringChars(str)); } if (JS_GetProperty( cx, JSVAL_TO_OBJECT(v), "Hash", &v2) && !JSVAL_IS_VOID(v2)) { JSString *str = JS_ValueToString(cx, v2); if (!str || !hash.encode(cx, str)) { abortLoad = PR_TRUE; break; } } } else { JSString *str = JS_ValueToString(cx, v); if (!str) { abortLoad = PR_TRUE; break; } URL = reinterpret_cast<const PRUnichar*>(JS_GetStringChars(str)); } if ( URL ) { // Get relative URL to load nsAutoString xpiURL(URL); if (baseURL) { nsCAutoString resolvedURL; baseURL->Resolve(NS_ConvertUTF16toUTF8(xpiURL), resolvedURL); xpiURL = NS_ConvertUTF8toUTF16(resolvedURL); } nsAutoString icon(iconURL); if (iconURL && baseURL) { nsCAutoString resolvedIcon; baseURL->Resolve(NS_ConvertUTF16toUTF8(icon), resolvedIcon); icon = NS_ConvertUTF8toUTF16(resolvedIcon); } // Make sure we're allowed to load this URL and the icon URL nsresult rv = InstallTriggerCheckLoadURIFromScript(cx, xpiURL); if (NS_FAILED(rv)) abortLoad = PR_TRUE; if (!abortLoad && iconURL) { rv = InstallTriggerCheckLoadURIFromScript(cx, icon); if (NS_FAILED(rv)) abortLoad = PR_TRUE; } if (!abortLoad) { // Add the install item to the trigger collection nsXPITriggerItem *item = new nsXPITriggerItem( name, xpiURL.get(), icon.get(), hash ); if ( item ) { trigger->Add( item ); } else abortLoad = PR_TRUE; } } else abortLoad = PR_TRUE; } JS_DestroyIdArray( cx, ida ); } // pass on only if good stuff found if (!abortLoad && trigger->Size() > 0) { nsCOMPtr<nsIURI> checkuri; nsresult rv = nativeThis->GetOriginatingURI(globalObject, getter_AddRefs(checkuri)); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(globalObject)); nsCOMPtr<nsIXPIInstallInfo> installInfo = new nsXPIInstallInfo(win, checkuri, trigger, 0); if (installInfo) { // installInfo now owns triggers PRBool enabled = PR_FALSE; nativeThis->UpdateEnabled(checkuri, XPI_WHITELIST, &enabled); if (!enabled) { nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); if (os) os->NotifyObservers(installInfo, "xpinstall-install-blocked", nsnull); } else { // save callback function if any (ignore bad args for now) if ( argc >= 2 && JS_TypeOfValue(cx,argv[1]) == JSTYPE_FUNCTION ) { trigger->SaveCallback( cx, argv[1] ); } PRBool result; nativeThis->StartInstall(installInfo, &result); *rval = BOOLEAN_TO_JSVAL(result); } return JS_TRUE; } } } // didn't pass it on so we must delete trigger delete trigger; } JS_ReportError(cx, "Incorrect arguments to InstallTrigger.Install()"); return JS_FALSE; }