void C_AwesomiumBrowserManager::DispatchJavaScriptMethods(C_AwesomiumBrowserInstance* pBrowserInstance)
{
	//WebView* pWebView = m_webViews[pWebTab];

	std::string previousObjectName = "-1";

	JSValue response;
	JSObject responseObject;
	std::vector<JavaScriptMethodCall_t*>& methodCalls = pBrowserInstance->GetJavaScriptMethodCalls();
	for (auto pJavaScriptMethodCall : methodCalls)
	{
		if (previousObjectName != pJavaScriptMethodCall->objectName)
		{
			previousObjectName = pJavaScriptMethodCall->objectName;
			response = pBrowserInstance->GetWebView()->ExecuteJavascriptWithResult(WSLit(pJavaScriptMethodCall->objectName.c_str()), WSLit(""));
			if (!response.IsObject())
				continue;

			responseObject = response.ToObject();
		}

		JSArray arguments;
		for (auto argument : pJavaScriptMethodCall->methodArguments)
			arguments.Push(WSLit(argument.c_str()));

		responseObject.InvokeAsync(WSLit(pJavaScriptMethodCall->methodName.c_str()), arguments);
	}

	//m_pWebBrowser->DispatchJavaScriptMethods(pWebTab);
}
optional<Function<T>> parseFunction(const char* name, const JSValue& value) {
    if (!value.IsObject()) {
        auto constant = parseProperty<T>(name, value);
        if (!constant) {
            return {};
        }
        return { Function<T>(*constant) };
    }

    if (!value.HasMember("stops")) {
        Log::Warning(Event::ParseStyle, "function must specify a function type");
        return {};
    }

    float base = 1.0f;

    if (value.HasMember("base")) {
        const JSValue& value_base = value["base"];

        if (!value_base.IsNumber()) {
            Log::Warning(Event::ParseStyle, "base must be numeric");
            return {};
        }

        base = value_base.GetDouble();
    }

    auto stops = parseStops<T>(name, value["stops"]);

    if (!stops) {
        return {};
    }

    return { Function<T>(*stops, base) };
}
	JSValue GlobalObject::requireModule(const JSObject& parent, const std::string& moduleId)
	{
		TITANIUM_GLOBALOBJECT_LOCK_GUARD;

		const auto js_context = parent.get_context();

		// check if we have special module such as ti.map
		if (requiredBuiltinModuleExists(js_context, moduleId)) {
			return requireBuiltinModule(js_context, moduleId);
		}

		// check if we have native module
		if (requiredNativeModuleExists(js_context, moduleId)) {
			return requireNativeModule(js_context, moduleId);
		}

		auto module_path = requestResolveModule(parent, moduleId);
		if (module_path.empty()) {
			// Fall back to assuming equivalent of "/" + moduleId?
			module_path = requestResolveModule(parent, "/" + moduleId);
			if (module_path.empty()) {
				detail::ThrowRuntimeError("require", "Could not load module " + moduleId);
			}
		}

		// check if we have already loaded the module
		if (module_cache__.find(module_path) != module_cache__.end()) {
			return module_cache__.at(module_path);
		}

		const auto module_js = readRequiredModule(parent, module_path);

		if (module_js.empty()) {
			detail::ThrowRuntimeError("require", "Could not load module " + moduleId);
		}

		try {
			JSValue result = js_context.CreateUndefined();
			if (boost::ends_with(module_path, ".json")){
				result = js_context.CreateValueFromJSON(module_js);
			} else if (js_context.JSCheckScriptSyntax(module_js, moduleId)) {
				const std::vector<JSValue> args = { js_context.CreateString(moduleId), js_context.CreateString(module_js) };
				result = require_function__(args, js_context.get_global_object());
			} else {
				detail::ThrowRuntimeError("require", "Could not load module "+moduleId);
			}
			if (!result.IsObject()) {
				TITANIUM_LOG_WARN("GlobalObject::require: module '", moduleId, "' replaced 'exports' with a non-object: ", to_string(result));
			}
			// cache it so that we can reuse it
			module_cache__.insert({module_path, result});
			return result;
		} catch (const std::exception& exception) {
			detail::ThrowRuntimeError("require", "Error while require("+moduleId+") "+static_cast<std::string>(exception.what()));
		} catch (...) {
			detail::ThrowRuntimeError("require", "Unknown error while require("+moduleId+")");
		}
		return js_context.CreateUndefined();
	}
optional<Function<Faded<std::string>>> parseProperty(const char* name, const JSValue& value) {
    if (value.IsObject()) {
        return parseFadedFunction<std::string>(value);
    }

    auto constant = parseProperty<std::string>(name, value);
    if (!constant) {
        return {};
    }
    return Function<Faded<std::string>>(*constant);
}
		MediaQueryInfoType js_to_MediaQueryInfoType(const JSValue& js_info)
		{
			const auto ctx = js_info.get_context();
			
			if (js_info.IsObject()) {
				const auto js_info_obj = static_cast<JSObject>(js_info);
				const auto exact = static_cast<bool>(js_info_obj.GetProperty("exact"));
				const auto value = js_info_obj.GetProperty("value");
				return { exact, value };
			}
			return { true, js_info };
		};
		TITANIUM_FUNCTION(DB, remove)
		{
			close();

			// Now we grab the file object and call deleteFile on it
			JSValue file = get_file();
			TITANIUM_ASSERT(file.IsObject());  // precondition
			JSObject FileObject = static_cast<JSObject>(file);

			const auto file_ptr = FileObject.GetPrivate<Titanium::Filesystem::File>();

			if (file_ptr != nullptr && file_ptr->exists()) {
				file_ptr->deleteFile();
			}

			return get_context().CreateUndefined();
		}
optional<PropertyTransition> parseProperty(const char *, const JSValue& value) {
    PropertyTransition transition;
    if (value.IsObject()) {
        bool parsed = false;
        if (value.HasMember("duration") && value["duration"].IsNumber()) {
            transition.duration.emplace(Milliseconds(value["duration"].GetUint()));
            parsed = true;
        }
        if (value.HasMember("delay") && value["delay"].IsNumber()) {
            transition.delay.emplace(Milliseconds(value["delay"].GetUint()));
            parsed = true;
        }
        if (!parsed) {
            return {};
        }
    }
    return transition;
}
Пример #8
0
void Parser::parseSources(const JSValue& value) {
    if (!value.IsObject()) {
        Log::Warning(Event::ParseStyle, "sources must be an object");
        return;
    }

    for (const auto& property : value.GetObject()) {
        std::string id = *conversion::toString(property.name);

        conversion::Result<std::unique_ptr<Source>> source =
            conversion::convert<std::unique_ptr<Source>>(property.value, id);
        if (!source) {
            Log::Warning(Event::ParseStyle, source.error().message);
            continue;
        }

        sourcesMap.emplace(id, (*source).get());
        sources.emplace_back(std::move(*source));
    }
}
Пример #9
0
void Parser::parseSources(const JSValue& value) {
    if (!value.IsObject()) {
        Log::Warning(Event::ParseStyle, "sources must be an object");
        return;
    }

    for (auto it = value.MemberBegin(); it != value.MemberEnd(); ++it) {
        std::string id = *conversion::toString(it->name);

        conversion::Result<std::unique_ptr<Source>> source
            = conversion::convert<std::unique_ptr<Source>>(it->value, id);
        if (!source) {
            Log::Warning(Event::ParseStyle, source.error().message);
            continue;
        }

        sourcesMap.emplace(id, (*source).get());
        sources.emplace_back(std::move(*source));
    }
}
optional<TransitionOptions> parseTransitionOptions(const char *, const JSValue& value) {
    if (!value.IsObject()) {
        return {};
    }

    optional<Duration> duration;
    if (value.HasMember("duration") && value["duration"].IsNumber()) {
        duration.emplace(Milliseconds(value["duration"].GetUint()));
    }

    optional<Duration> delay;
    if (value.HasMember("delay") && value["delay"].IsNumber()) {
        delay.emplace(Milliseconds(value["delay"].GetUint()));
    }

    if (!duration && !delay) {
        return {};
    }

    return TransitionOptions(duration, delay);
}
Пример #11
0
	void BindMethods(WebView* web_view) {
		// Create a global js object named 'app'
		JSValue result = web_view->CreateGlobalJavascriptObject(WSLit("app"));
		if (result.IsObject()) {
			// Bind our custom method to it.
			JSObject& app_object = result.ToObject();
			method_dispatcher_.Bind(app_object,
				WSLit("backgroundGrey"),
				JSDelegate(this, &TutorialApp::BackgroundGrey));

			method_dispatcher_.Bind(app_object,
				WSLit("backgroundWhite"),
				JSDelegate(this, &TutorialApp::BackgroundWhite));

			method_dispatcher_.Bind(app_object,
				WSLit("backgroundBluish"),
				JSDelegate(this, &TutorialApp::BackgroundBluish));
		}

		// Bind our method dispatcher to the WebView
		web_view->set_js_method_handler(&method_dispatcher_);
	}
void C_AwesomiumBrowserManager::DispatchJavaScriptMethod(C_AwesomiumBrowserInstance* pBrowserInstance, std::string objectName, std::string objectMethod, std::vector<std::string> methodArguments)
{
	//WebView* pWebView = m_webViews[pWebTab];

	JSValue response = pBrowserInstance->GetWebView()->ExecuteJavascriptWithResult(WSLit(objectName.c_str()), WSLit(""));
	if (response.IsObject())
	{
		JSObject object = response.ToObject();
		JSArray arguments;

		for (auto argument : methodArguments)
			arguments.Push(WSLit(argument.c_str()));

		object.InvokeAsync(WSLit(objectMethod.c_str()), arguments);
	}

	//m_pWebBrowser->DispatchJavaScriptMethod(pWebTab, objectName, objectMethod, methodArguments);
	/*
	for (auto arg : args)
	{
	DevMsg("Argument: %s\n", arg->text.c_str());
	}
	*/
}
TEST_F(ModuleTests, properties)
{
	JSContext js_context = js_context_group.CreateContext(JSExport<Titanium::GlobalObject>::Class());
	auto global_object = js_context.get_global_object();

	XCTAssertFalse(global_object.HasProperty("Titanium"));
	auto Titanium = js_context.CreateObject();
	global_object.SetProperty("Titanium", Titanium, {JSPropertyAttribute::ReadOnly, JSPropertyAttribute::DontDelete});
	XCTAssertTrue(global_object.HasProperty("Titanium"));

	// Make the alias "Ti" for the "Titanium" property.
	XCTAssertFalse(global_object.HasProperty("Ti"));
	global_object.SetProperty("Ti", Titanium, {JSPropertyAttribute::ReadOnly, JSPropertyAttribute::DontDelete});
	XCTAssertTrue(global_object.HasProperty("Ti"));

	XCTAssertFalse(Titanium.HasProperty("Module"));
	auto Module = js_context.CreateObject(JSExport<Titanium::Module>::Class());
	Titanium.SetProperty("Module", Module, {JSPropertyAttribute::ReadOnly, JSPropertyAttribute::DontDelete});
	XCTAssertTrue(Titanium.HasProperty("Module"));

	XCTAssertTrue(Module.HasProperty("addEventListener"));
	XCTAssertTrue(Module.HasProperty("applyProperties"));
	XCTAssertTrue(Module.HasProperty("fireEvent"));

	auto nativeModuleExample = js_context.CreateObject(JSExport<NativeModuleExample>::Class());
	global_object.SetProperty("NativeModuleExample", nativeModuleExample, {JSPropertyAttribute::ReadOnly, JSPropertyAttribute::DontDelete});
	XCTAssertTrue(global_object.HasProperty("NativeModuleExample"));

	JSValue result = js_context.CreateNull();
	XCTAssertNoThrow(result = js_context.JSEvaluateScript("var module = new NativeModuleExample(); module;"));
	XCTAssertTrue(result.IsObject());

	JSObject module = static_cast<JSObject>(result);
	auto module_ptr = module.GetPrivate<NativeModuleExample>();
	XCTAssertNotEqual(nullptr, module_ptr);

	// Set the name of the event that "enables" the native module. This could be
	// the 'update' event for the Titanium.Accelerometer that turns on the
	// device's battery-consuming accelerometer measurements.
	module_ptr->set_event_name("foo");
	XCTAssertEqual("foo", module_ptr->get_event_name());

	// The native module should be disabled since there are no 'foo' event
	// listeners registered yet.
	XCTAssertNoThrow(result = js_context.JSEvaluateScript("module.enabled;"));
	XCTAssertTrue(result.IsBoolean());
	XCTAssertFalse(static_cast<bool>(result));

	// Create a listener interested in 'foo' events.
	XCTAssertNoThrow(result = js_context.JSEvaluateScript("function fooEventListener(event){};"));
	XCTAssertTrue(result.IsUndefined());

	// Add the event listener to the native module.
	XCTAssertNoThrow(js_context.JSEvaluateScript("module.addEventListener('foo', fooEventListener);"));

	// The native module should now be enabled since there is a 'foo' event
	// listeners registered.
	XCTAssertNoThrow(result = js_context.JSEvaluateScript("module.enabled;"));
	XCTAssertTrue(result.IsBoolean());
	XCTAssertTrue(static_cast<bool>(result));

	// Now remove the event listener.
	XCTAssertNoThrow(js_context.JSEvaluateScript("module.removeEventListener('foo', fooEventListener);"));

	// The native module should now be disabled since there are no more 'foo'
	// event listeners registered.
	XCTAssertNoThrow(result = js_context.JSEvaluateScript("module.enabled;"));
	XCTAssertTrue(result.IsBoolean());
	XCTAssertFalse(static_cast<bool>(result));

	auto json_result = js_context.JSEvaluateScript("JSON.stringify(Ti.Module);");
	XCTAssertEqual("{}", static_cast<std::string>(json_result));

	json_result = js_context.JSEvaluateScript("JSON.stringify(module);");
	XCTAssertEqual("{\"enabled\":false}", static_cast<std::string>(json_result));
}
void MenuListener::OnShowPopupMenu(WebView *caller, const WebPopupMenuInfo &menu_info)
{
//	DevMsg("DISABLED FOR TESTING!\n");
//	return;

	//C_WebTab* pWebTab = g_pAnarchyManager->GetWebManager()->GetWebBrowser()->FindWebTab(caller);
	//C_WebTab* pHudWebTab = g_pAnarchyManager->GetWebManager()->GetHudWebTab();
	//WebView* pHudWebView = g_pAnarchyManager->GetWebManager()->GetWebBrowser()->FindWebView(pHudWebTab);

	C_AwesomiumBrowserInstance* pAwesomiumBrowserInstance = g_pAnarchyManager->GetAwesomiumBrowserManager()->FindAwesomiumBrowserInstance(caller);	// FIXME: This should be a general EmbeddedInstance of any type.
	C_AwesomiumBrowserInstance* pHudBrowserInstance = g_pAnarchyManager->GetAwesomiumBrowserManager()->FindAwesomiumBrowserInstance("hud");
	WebView* pHudWebView = pHudBrowserInstance->GetWebView();

	DevMsg("Pop menu detected!\n");

	std::vector<std::string> methodArguments;
	methodArguments.push_back(pAwesomiumBrowserInstance->GetId());
	methodArguments.push_back(VarArgs("%i", menu_info.bounds.x));
	methodArguments.push_back(VarArgs("%i", menu_info.bounds.y));
	methodArguments.push_back(VarArgs("%i", menu_info.bounds.width));
	methodArguments.push_back(VarArgs("%i", menu_info.bounds.height));
	methodArguments.push_back(VarArgs("%i", menu_info.item_height));
	methodArguments.push_back(VarArgs("%f", menu_info.item_font_size));
	methodArguments.push_back(VarArgs("%i", menu_info.selected_item));
	methodArguments.push_back(VarArgs("%i", menu_info.right_aligned));

	for (int i = 0; i < menu_info.items.size(); i++)
	{
		if (menu_info.items[i].type == kWebMenuItemType_Option)
			methodArguments.push_back("Option");
		else if (menu_info.items[i].type == kWebMenuItemType_CheckableOption)
			methodArguments.push_back("CheckableOption");
		else if (menu_info.items[i].type == kWebMenuItemType_Group)
			methodArguments.push_back("Group");
		else if (menu_info.items[i].type == kWebMenuItemType_Separator)
			methodArguments.push_back("Separator");

		methodArguments.push_back(WebStringToCharString(menu_info.items[i].label));
		methodArguments.push_back(WebStringToCharString(menu_info.items[i].tooltip));
		methodArguments.push_back(VarArgs("%i", menu_info.items[i].action));
		methodArguments.push_back(VarArgs("%i", menu_info.items[i].right_to_left));
		methodArguments.push_back(VarArgs("%i", menu_info.items[i].has_directional_override));
		methodArguments.push_back(VarArgs("%i", menu_info.items[i].enabled));
		methodArguments.push_back(VarArgs("%i", menu_info.items[i].checked));
	}
	
	std::string objectName = "window.arcadeHud";
	std::string objectMethod = "showPopupMenu";

	JSValue response = pHudWebView->ExecuteJavascriptWithResult(WSLit(objectName.c_str()), WSLit(""));
	if (response.IsObject())
	{
		JSObject object = response.ToObject();
		JSArray arguments;

		for (auto argument : methodArguments)
			arguments.Push(WSLit(argument.c_str()));

		object.InvokeAsync(WSLit(objectMethod.c_str()), arguments);
	}
}
TEST_F(FileTests, logging)
{
	JSContext js_context = js_context_group.CreateContext(JSExport<Titanium::GlobalObject>::Class());
	auto global_object = js_context.get_global_object();

	XCTAssertFalse(global_object.HasProperty("Titanium"));
	auto Titanium = js_context.CreateObject();
	global_object.SetProperty("Titanium", Titanium, {JSPropertyAttribute::ReadOnly, JSPropertyAttribute::DontDelete});
	XCTAssertTrue(global_object.HasProperty("Titanium"));

	// Make the alias "Ti" for the "Titanium" property.
	XCTAssertFalse(global_object.HasProperty("Ti"));
	global_object.SetProperty("Ti", Titanium, {JSPropertyAttribute::ReadOnly, JSPropertyAttribute::DontDelete});
	XCTAssertTrue(global_object.HasProperty("Ti"));

	XCTAssertFalse(Titanium.HasProperty("Filesystem"));
	auto Filesystem = js_context.CreateObject(JSExport<Titanium::FilesystemModule>::Class());
	Titanium.SetProperty("Filesystem", Filesystem, {JSPropertyAttribute::ReadOnly, JSPropertyAttribute::DontDelete});
	XCTAssertTrue(Titanium.HasProperty("Filesystem"));

	XCTAssertFalse(Filesystem.HasProperty("File"));
	auto File = js_context.CreateObject(JSExport<NativeFileExample>::Class());
	Filesystem.SetProperty("File", File, {JSPropertyAttribute::ReadOnly, JSPropertyAttribute::DontDelete});
	XCTAssertTrue(Filesystem.HasProperty("File"));

	XCTAssertTrue(Filesystem.HasProperty("createTempDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("createTempFile"));
	XCTAssertTrue(Filesystem.HasProperty("getFile"));
	XCTAssertTrue(Filesystem.HasProperty("isExternalStoragePresent"));
	XCTAssertTrue(Filesystem.HasProperty("openStream"));

	XCTAssertTrue(Filesystem.HasProperty("separator"));
	XCTAssertTrue(Filesystem.HasProperty("applicationCacheDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("applicationDataDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("applicationDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("applicationSupportDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("externalStorageDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("lineEnding"));
	XCTAssertTrue(Filesystem.HasProperty("resourcesDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("tempDirectory"));

	XCTAssertTrue(Filesystem.HasProperty("getSeparator"));
	XCTAssertTrue(Filesystem.HasProperty("getApplicationCacheDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("getApplicationDataDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("getApplicationDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("getApplicationSupportDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("getExternalStorageDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("getLineEnding"));
	XCTAssertTrue(Filesystem.HasProperty("getResourcesDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("getTempDirectory"));

	auto File_ptr = File.GetPrivate<NativeFileExample>();
	XCTAssertNotEqual(nullptr, File_ptr);

	JSValue result = js_context.CreateNull();
	XCTAssertNoThrow(result = File.CallAsConstructor(js_context.CreateNull()));
	XCTAssertTrue(result.IsObject());

	JSObject file = static_cast<JSObject>(result);

	XCTAssertTrue(file.HasProperty("executable"));
	XCTAssertTrue(file.HasProperty("hidden"));
	XCTAssertTrue(file.HasProperty("name"));
	XCTAssertTrue(file.HasProperty("nativePath"));
	XCTAssertTrue(file.HasProperty("parent"));
	XCTAssertTrue(file.HasProperty("readonly"));
	XCTAssertTrue(file.HasProperty("remoteBackup"));
	XCTAssertTrue(file.HasProperty("size"));
	XCTAssertTrue(file.HasProperty("symbolicLink"));
	XCTAssertTrue(file.HasProperty("writable"));
	XCTAssertTrue(file.HasProperty("getExecutable"));
	XCTAssertTrue(file.HasProperty("getHidden"));
	XCTAssertTrue(file.HasProperty("getName"));
	XCTAssertTrue(file.HasProperty("getNativePath"));
	XCTAssertTrue(file.HasProperty("getParent"));
	XCTAssertTrue(file.HasProperty("getReadonly"));
	XCTAssertTrue(file.HasProperty("getRemoteBackup"));
	XCTAssertTrue(file.HasProperty("getSize"));
	XCTAssertTrue(file.HasProperty("getSymbolicLink"));
	XCTAssertTrue(file.HasProperty("getWritable"));
	XCTAssertTrue(file.HasProperty("append"));
	XCTAssertTrue(file.HasProperty("copy"));
	XCTAssertTrue(file.HasProperty("createDirectory"));
	XCTAssertTrue(file.HasProperty("createFile"));
	XCTAssertTrue(file.HasProperty("createTimestamp"));
	XCTAssertTrue(file.HasProperty("deleteDirectory"));
	XCTAssertTrue(file.HasProperty("deleteFile"));
	XCTAssertTrue(file.HasProperty("exists"));
	XCTAssertTrue(file.HasProperty("extension"));
	XCTAssertTrue(file.HasProperty("getDirectoryListing"));
	XCTAssertTrue(file.HasProperty("isDirectory"));
	XCTAssertTrue(file.HasProperty("isFile"));
	XCTAssertTrue(file.HasProperty("modificationTimestamp"));
	XCTAssertTrue(file.HasProperty("move"));
	XCTAssertTrue(file.HasProperty("open"));
	XCTAssertTrue(file.HasProperty("read"));
	XCTAssertTrue(file.HasProperty("rename"));
	XCTAssertTrue(file.HasProperty("resolve"));
	XCTAssertTrue(file.HasProperty("spaceAvailable"));
	XCTAssertTrue(file.HasProperty("write"));
}
TEST_F(FileTests, logging)
{
	JSContext js_context = js_context_group.CreateContext(JSExport<Titanium::GlobalObject>::Class());
	auto global_object = js_context.get_global_object();

	auto Filesystem = js_context.CreateObject(JSExport<Titanium::FilesystemModule>::Class());
	auto File = js_context.CreateObject(JSExport<NativeFileExample>::Class());

	Filesystem.SetProperty("File", File);
	global_object.SetProperty("Filesystem", Filesystem);

	XCTAssertTrue(Filesystem.HasProperty("createTempDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("createTempFile"));
	XCTAssertTrue(Filesystem.HasProperty("getFile"));
	XCTAssertTrue(Filesystem.HasProperty("isExternalStoragePresent"));
	XCTAssertTrue(Filesystem.HasProperty("openStream"));

	XCTAssertTrue(Filesystem.HasProperty("separator"));
	XCTAssertTrue(Filesystem.HasProperty("applicationCacheDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("applicationDataDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("applicationDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("applicationSupportDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("externalStorageDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("lineEnding"));
	XCTAssertTrue(Filesystem.HasProperty("resourcesDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("tempDirectory"));

	XCTAssertTrue(Filesystem.HasProperty("getSeparator"));
	XCTAssertTrue(Filesystem.HasProperty("getApplicationCacheDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("getApplicationDataDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("getApplicationDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("getApplicationSupportDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("getExternalStorageDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("getLineEnding"));
	XCTAssertTrue(Filesystem.HasProperty("getResourcesDirectory"));
	XCTAssertTrue(Filesystem.HasProperty("getTempDirectory"));

	auto json_result = js_context.JSEvaluateScript("JSON.stringify(Filesystem);");
	XCTAssertTrue(static_cast<std::string>(json_result).find("\"separator\":") != std::string::npos);

	auto File_ptr = File.GetPrivate<NativeFileExample>();
	XCTAssertNotEqual(nullptr, File_ptr);

	JSValue result = js_context.CreateNull();
	XCTAssertNoThrow(result = File.CallAsConstructor(js_context.CreateNull()));
	XCTAssertTrue(result.IsObject());

	JSObject file = static_cast<JSObject>(result);

	XCTAssertTrue(file.HasProperty("executable"));
	XCTAssertTrue(file.HasProperty("hidden"));
	XCTAssertTrue(file.HasProperty("name"));
	XCTAssertTrue(file.HasProperty("nativePath"));
	XCTAssertTrue(file.HasProperty("parent"));
	XCTAssertTrue(file.HasProperty("readonly"));
	XCTAssertTrue(file.HasProperty("remoteBackup"));
	XCTAssertTrue(file.HasProperty("size"));
	XCTAssertTrue(file.HasProperty("symbolicLink"));
	XCTAssertTrue(file.HasProperty("writable"));
	XCTAssertTrue(file.HasProperty("getExecutable"));
	XCTAssertTrue(file.HasProperty("getHidden"));
	XCTAssertTrue(file.HasProperty("getName"));
	XCTAssertTrue(file.HasProperty("getNativePath"));
	XCTAssertTrue(file.HasProperty("getParent"));
	XCTAssertTrue(file.HasProperty("getReadonly"));
	XCTAssertTrue(file.HasProperty("getRemoteBackup"));
	XCTAssertTrue(file.HasProperty("getSize"));
	XCTAssertTrue(file.HasProperty("getSymbolicLink"));
	XCTAssertTrue(file.HasProperty("getWritable"));
	XCTAssertTrue(file.HasProperty("append"));
	XCTAssertTrue(file.HasProperty("copy"));
	XCTAssertTrue(file.HasProperty("createDirectory"));
	XCTAssertTrue(file.HasProperty("createFile"));
	XCTAssertTrue(file.HasProperty("createTimestamp"));
	XCTAssertTrue(file.HasProperty("deleteDirectory"));
	XCTAssertTrue(file.HasProperty("deleteFile"));
	XCTAssertTrue(file.HasProperty("exists"));
	XCTAssertTrue(file.HasProperty("extension"));
	XCTAssertTrue(file.HasProperty("getDirectoryListing"));
	XCTAssertTrue(file.HasProperty("isDirectory"));
	XCTAssertTrue(file.HasProperty("isFile"));
	XCTAssertTrue(file.HasProperty("modificationTimestamp"));
	XCTAssertTrue(file.HasProperty("move"));
	XCTAssertTrue(file.HasProperty("open"));
	XCTAssertTrue(file.HasProperty("read"));
	XCTAssertTrue(file.HasProperty("rename"));
	XCTAssertTrue(file.HasProperty("resolve"));
	XCTAssertTrue(file.HasProperty("spaceAvailable"));
	XCTAssertTrue(file.HasProperty("write"));

	global_object.SetProperty("file", file);
	json_result = js_context.JSEvaluateScript("JSON.stringify(file);");
	XCTAssertTrue(static_cast<std::string>(json_result).find("\"symbolicLink\":") != std::string::npos);
}
void C_AwesomiumBrowserManager::CreateAaApi(WebView* pWebView)
{
	DevMsg("Adding AAAPI...\n");

	JSValue result = pWebView->CreateGlobalJavascriptObject(WSLit("aaapi"));
	if (!result.IsObject())
	{
		DevMsg("Failed to create AAAPI.\n");
		g_pAnarchyManager->ThrowEarlyError("Anarchy Arcade cannot detect its UI process.\nPlease adjust your anti-virus software to allow\nAArcade to communicate with its UI and try again.");
		return;
	}

	JSObject& aaapiObject = result.ToObject();

	// SYSTEM
	result = pWebView->CreateGlobalJavascriptObject(WSLit("aaapi.system"));
	if (!result.IsObject())
		return;

	JSObject& systemObject = result.ToObject();
	systemObject.SetCustomMethod(WSLit("quit"), false);
	systemObject.SetCustomMethod(WSLit("launchItem"), false);
	systemObject.SetCustomMethod(WSLit("spawnItem"), false);	// OBSOLETE!!
	systemObject.SetCustomMethod(WSLit("spawnEntry"), false);
	systemObject.SetCustomMethod(WSLit("setLibraryBrowserContext"), false);
	systemObject.SetCustomMethod(WSLit("getLibraryBrowserContext"), true);
	systemObject.SetCustomMethod(WSLit("didSelectPopupMenuItem"), true);
	systemObject.SetCustomMethod(WSLit("didCancelPopupMenu"), true);
	systemObject.SetCustomMethod(WSLit("loadFirstLocalApp"), false);
	systemObject.SetCustomMethod(WSLit("loadNextLocalApp"), false);
	systemObject.SetCustomMethod(WSLit("loadLocalAppClose"), false);
	systemObject.SetCustomMethod(WSLit("detectAllMaps"), false);
	systemObject.SetCustomMethod(WSLit("detectAllModels"), false);
	systemObject.SetCustomMethod(WSLit("detectAllMapScreenshots"), true);
	systemObject.SetCustomMethod(WSLit("getAllMapScreenshots"), true);
	systemObject.SetCustomMethod(WSLit("getScreenshot"), true);
	systemObject.SetCustomMethod(WSLit("getAllMaps"), true);
	systemObject.SetCustomMethod(WSLit("getMap"), true);
	systemObject.SetCustomMethod(WSLit("loadMap"), false);
	systemObject.SetCustomMethod(WSLit("loadMapNow"), false);
	systemObject.SetCustomMethod(WSLit("deactivateInputMode"), false);
	systemObject.SetCustomMethod(WSLit("forceInputMode"), false);
	systemObject.SetCustomMethod(WSLit("hudMouseDown"), false);
	systemObject.SetCustomMethod(WSLit("hudMouseUp"), false);
	systemObject.SetCustomMethod(WSLit("getSelectedWebTab"), true);
	systemObject.SetCustomMethod(WSLit("requestActivateInputMode"), false);
	systemObject.SetCustomMethod(WSLit("simpleImageReady"), false);
	systemObject.SetCustomMethod(WSLit("importSteamGames"), true);
	systemObject.SetCustomMethod(WSLit("saveLibretroKeybind"), false);
	systemObject.SetCustomMethod(WSLit("getLibretroKeybinds"), true);
	//systemObject.SetCustomMethod(WSLit("getLibretroOptions"), true);
	systemObject.SetCustomMethod(WSLit("generateUniqueId"), true);
	systemObject.SetCustomMethod(WSLit("removeAppFilepath"), false);
	systemObject.SetCustomMethod(WSLit("getMapInstances"), true);
	systemObject.SetCustomMethod(WSLit("getInstance"), true);
	systemObject.SetCustomMethod(WSLit("getDefaultLibretroInputDevices"), true);
	systemObject.SetCustomMethod(WSLit("saveLibretroOption"), false);
	systemObject.SetCustomMethod(WSLit("getLibretroOptions"), true);
	systemObject.SetCustomMethod(WSLit("spawnNearestObject"), false);
	systemObject.SetCustomMethod(WSLit("setNearestObjectDist"), true);
	systemObject.SetCustomMethod(WSLit("isInGame"), true);
	systemObject.SetCustomMethod(WSLit("fileBrowse"), false);
	systemObject.SetCustomMethod(WSLit("metaSearch"), false);
	systemObject.SetCustomMethod(WSLit("getDOM"), false);
	systemObject.SetCustomMethod(WSLit("clearAwesomiumCache"), false);
	systemObject.SetCustomMethod(WSLit("disconnect"), false);
	systemObject.SetCustomMethod(WSLit("viewStream"), false);
	systemObject.SetCustomMethod(WSLit("autoInspect"), false);
	systemObject.SetCustomMethod(WSLit("viewPreview"), false);
	systemObject.SetCustomMethod(WSLit("runLibretro"), false);
	systemObject.SetCustomMethod(WSLit("popout"), false);
	systemObject.SetCustomMethod(WSLit("cabinetSelected"), false);
	systemObject.SetCustomMethod(WSLit("modelSelected"), false);
	systemObject.SetCustomMethod(WSLit("objectHover"), false);
	systemObject.SetCustomMethod(WSLit("objectSelected"), false);
	systemObject.SetCustomMethod(WSLit("moveObject"), false);
	systemObject.SetCustomMethod(WSLit("deleteObject"), false);
	systemObject.SetCustomMethod(WSLit("beginImportSteamGames"), false);	// this loads the profile page
	systemObject.SetCustomMethod(WSLit("startImportSteamGames"), false);	// this actually starts adding stuff to the library
	systemObject.SetCustomMethod(WSLit("showEngineOptionsMenu"), false);
	systemObject.SetCustomMethod(WSLit("setSlaveScreen"), false);
	systemObject.SetCustomMethod(WSLit("navigateToURI"), false);
	systemObject.SetCustomMethod(WSLit("getWorldInfo"), true);
	systemObject.SetCustomMethod(WSLit("getDbSize"), true);
	systemObject.SetCustomMethod(WSLit("createDbBackup"), true);
	systemObject.SetCustomMethod(WSLit("viewObjectInfo"), false);
	systemObject.SetCustomMethod(WSLit("getEntityInfo"), true);
	systemObject.SetCustomMethod(WSLit("getObjectInfo"), true);
	systemObject.SetCustomMethod(WSLit("getObject"), true);
	systemObject.SetCustomMethod(WSLit("getAllObjectInfos"), true);
	systemObject.SetCustomMethod(WSLit("getTransformInfo"), true);
	systemObject.SetCustomMethod(WSLit("adjustObjectOffset"), false);
	systemObject.SetCustomMethod(WSLit("adjustObjectRot"), false);
	systemObject.SetCustomMethod(WSLit("adjustObjectScale"), false);
	systemObject.SetCustomMethod(WSLit("goBack"), false);
	systemObject.SetCustomMethod(WSLit("doCopy"), false);
	systemObject.SetCustomMethod(WSLit("goForward"), false);
	systemObject.SetCustomMethod(WSLit("reload"), false);
	systemObject.SetCustomMethod(WSLit("goHome"), false);
	systemObject.SetCustomMethod(WSLit("playSound"), false);
	systemObject.SetCustomMethod(WSLit("libretroPause"), false);
	systemObject.SetCustomMethod(WSLit("libretroReset"), false);
	systemObject.SetCustomMethod(WSLit("libretroSetOverlay"), false);
	systemObject.SetCustomMethod(WSLit("acquire"), false);
	systemObject.SetCustomMethod(WSLit("libretroClearOverlay"), false);
	systemObject.SetCustomMethod(WSLit("libretroSaveOverlay"), false);
	systemObject.SetCustomMethod(WSLit("libretroUpdateDLL"), true);
	systemObject.SetCustomMethod(WSLit("setStartWithWindows"), false);
	systemObject.SetCustomMethod(WSLit("checkStartWithWindows"), true);
	systemObject.SetCustomMethod(WSLit("libretroGetAllDLLs"), true);
	systemObject.SetCustomMethod(WSLit("getLibretroActiveOverlay"), true);
	systemObject.SetCustomMethod(WSLit("getLibretroOverlays"), true);
	systemObject.SetCustomMethod(WSLit("getLibretroGUIGamepadEnabled"), true);
	systemObject.SetCustomMethod(WSLit("setLibretroGUIGamepadEnabled"), false);
	systemObject.SetCustomMethod(WSLit("setLibretroGUIGamepadButtonState"), false);
	systemObject.SetCustomMethod(WSLit("clearLibretroGUIGamepadButtonStates"), false);
	systemObject.SetCustomMethod(WSLit("taskClear"), false);
	systemObject.SetCustomMethod(WSLit("closeTask"), false);
	systemObject.SetCustomMethod(WSLit("hideTask"), false);
	systemObject.SetCustomMethod(WSLit("unhideTask"), false);
	systemObject.SetCustomMethod(WSLit("switchToTask"), false);
	systemObject.SetCustomMethod(WSLit("setTabMenuFile"), false);
	systemObject.SetCustomMethod(WSLit("displayTask"), false);
	systemObject.SetCustomMethod(WSLit("takeScreenshot"), false);
	systemObject.SetCustomMethod(WSLit("deleteScreenshot"), false);
	systemObject.SetCustomMethod(WSLit("teleportScreenshot"), false);
	systemObject.SetCustomMethod(WSLit("saveNewNode"), false);
	systemObject.SetCustomMethod(WSLit("addToastMessage"), false);
	systemObject.SetCustomMethod(WSLit("clearNodeSpace"), false);
	systemObject.SetCustomMethod(WSLit("feedback"), false);
	systemObject.SetCustomMethod(WSLit("doPause"), false);
	systemObject.SetCustomMethod(WSLit("consoleCommand"), false);
	systemObject.SetCustomMethod(WSLit("specialReady"), false);
	systemObject.SetCustomMethod(WSLit("selectTaskObject"), false);
	systemObject.SetCustomMethod(WSLit("alphabetSafe"), true);
	systemObject.SetCustomMethod(WSLit("getConVarValue"), true);
	systemObject.SetCustomMethod(WSLit("getAllMounts"), true);
	systemObject.SetCustomMethod(WSLit("getMount"), true);
	systemObject.SetCustomMethod(WSLit("getAllTasks"), true);
	systemObject.SetCustomMethod(WSLit("getAllWorkshopSubscriptions"), true);
	systemObject.SetCustomMethod(WSLit("getRelativeAssetPath"), true);
	systemObject.SetCustomMethod(WSLit("getAllBackpacks"), true);
	systemObject.SetCustomMethod(WSLit("getBackpack"), true);
	systemObject.SetCustomMethod(WSLit("getNearestObjectToPlayerLook"), true);
	systemObject.SetCustomMethod(WSLit("getNextNearestObjectToPlayerLook"), true);
	systemObject.SetCustomMethod(WSLit("getNodeSetupInfo"), true);


	// LIBRARY
	result = pWebView->CreateGlobalJavascriptObject(WSLit("aaapi.library"));
	if (!result.IsObject())
		return;

	JSObject& libraryObject = result.ToObject();

	// SUPER DUPER LIBRARY QUERY IN GENERALIZED ORDINARY GUY FORM
	libraryObject.SetCustomMethod(WSLit("hasLibraryEntry"), true);
	libraryObject.SetCustomMethod(WSLit("getFirstLibraryEntry"), true);
	libraryObject.SetCustomMethod(WSLit("getNextLibraryEntry"), true);
	libraryObject.SetCustomMethod(WSLit("findFirstLibraryEntry"), true);
	libraryObject.SetCustomMethod(WSLit("findNextLibraryEntry"), true);
	// EACH QUERY HANDLE IS CLEARED WHEN IT IS USED TO EXHAUSTION
	// *ALL* QUERY HANDLES ARE CLEARED ON MAP TRANSITION FOR GARBAGE COLLECTION OF UNCLOSED HANDLES

	libraryObject.SetCustomMethod(WSLit("getAllLibraryTypes"), true);
	libraryObject.SetCustomMethod(WSLit("getLibraryType"), true);
	libraryObject.SetCustomMethod(WSLit("getAllLibraryApps"), true);
	libraryObject.SetCustomMethod(WSLit("getLibraryApp"), true);
	libraryObject.SetCustomMethod(WSLit("getFirstLibraryItem"), true);	// OBSOLETE!
	libraryObject.SetCustomMethod(WSLit("getNextLibraryItem"), true);	// OBSOLETE!
	libraryObject.SetCustomMethod(WSLit("getLibraryItem"), true);
	libraryObject.SetCustomMethod(WSLit("getLibraryModel"), true);
	libraryObject.SetCustomMethod(WSLit("getSelectedLibraryItem"), true);
	libraryObject.SetCustomMethod(WSLit("findFirstLibraryItem"), true);	// OBSOLETE!
	libraryObject.SetCustomMethod(WSLit("findNextLibraryItem"), true);	// OBSOLETE!
	libraryObject.SetCustomMethod(WSLit("findLibraryItem"), true);
	libraryObject.SetCustomMethod(WSLit("findLibraryModel"), true);
	libraryObject.SetCustomMethod(WSLit("findLibraryApp"), true);
	libraryObject.SetCustomMethod(WSLit("findLibraryType"), true);
	libraryObject.SetCustomMethod(WSLit("updateItem"), true);
	libraryObject.SetCustomMethod(WSLit("updateApp"), true);
	libraryObject.SetCustomMethod(WSLit("updateInstance"), true);
	libraryObject.SetCustomMethod(WSLit("deleteInstance"), true);
	libraryObject.SetCustomMethod(WSLit("updateModel"), true);
	libraryObject.SetCustomMethod(WSLit("updateType"), true);
	libraryObject.SetCustomMethod(WSLit("createItem"), true);
	libraryObject.SetCustomMethod(WSLit("createApp"), true);
	libraryObject.SetCustomMethod(WSLit("createType"), true);
	libraryObject.SetCustomMethod(WSLit("createModel"), true);
	libraryObject.SetCustomMethod(WSLit("saveItem"), true);
	libraryObject.SetCustomMethod(WSLit("deleteApp"), false);

	libraryObject.SetCustomMethod(WSLit("getFirstLibraryModel"), true);	// OBSOLETE!
	libraryObject.SetCustomMethod(WSLit("getNextLibraryModel"), true);	// OBSOLETE!
	libraryObject.SetCustomMethod(WSLit("findFirstLibraryModel"), true);	// OBSOLETE!
	libraryObject.SetCustomMethod(WSLit("findNextLibraryModel"), true);	// OBSOLETE!

	// CALLBACKS
	result = pWebView->CreateGlobalJavascriptObject(WSLit("aaapi.callbacks"));
	if (!result.IsObject())
		return;

	JSObject& callbacksObject = result.ToObject();
	//callbacksObject.SetCustomMethod(WSLit("loadNextLocalAppCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("startupCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("defaultLibraryReadyCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("mountNextWorkshopCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("loadNextLocalItemLegacyCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("detectNextMapCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("spawnNextObjectCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("addNextDefaultLibraryCallback"), false);
	//callbacksObject.SetCustomMethod(WSLit("defaultLibraryReadyCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("updateLibraryVersionCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("readyToLoadUserLibraryCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("rebuildSoundCacheCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("processAllModelsCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("processNextModelCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("addNextModelCallback"), false);
	callbacksObject.SetCustomMethod(WSLit("importNextSteamGameCallback"), false);

	// NETWORK
	result = pWebView->CreateGlobalJavascriptObject(WSLit("aaapi.network"));
	if (!result.IsObject())
		return;

	JSObject& networkObject = result.ToObject();
	networkObject.SetCustomMethod(WSLit("getConnectedSession"), true);
	networkObject.SetCustomMethod(WSLit("getAllUserChat"), true);
	networkObject.SetCustomMethod(WSLit("getAllUsers"), true);
	networkObject.SetCustomMethod(WSLit("getNumUsers"), true);
	networkObject.SetCustomMethod(WSLit("getSyncOverview"), true);
	networkObject.SetCustomMethod(WSLit("hostSession"), false);
	networkObject.SetCustomMethod(WSLit("objectUpdateReceived"), false);
	networkObject.SetCustomMethod(WSLit("restartNetwork"), false);
	networkObject.SetCustomMethod(WSLit("disconnected"), false);
	networkObject.SetCustomMethod(WSLit("networkEvent"), false);
	networkObject.SetCustomMethod(WSLit("followPlayer"), false);
	networkObject.SetCustomMethod(WSLit("joinLobby"), false);
	networkObject.SetCustomMethod(WSLit("banPlayer"), false);
	networkObject.SetCustomMethod(WSLit("syncPano"), false);
	networkObject.SetCustomMethod(WSLit("unbanPlayer"), false);
	networkObject.SetCustomMethod(WSLit("sendEntryUpdate"), false);
	networkObject.SetCustomMethod(WSLit("sendLocalChatMsg"), false);
	//networkObject.SetCustomMethod(WSLit("extractOverviewTGA"), false);

	/*
	result = pWebView->CreateGlobalJavascriptObject(WSLit("aaapi.metaverse"));
	if (!result.IsObject())
	return;

	JSObject& metaverseObject = result.ToObject();
	metaverseObject.SetCustomMethod(WSLit("OnSelectItem"), false);
	*/
}