blob: ef64775ca25157462cc6b8007dbfaf49781c05d8 [file]
// <copyright file="ScriptModule.cs" company="Selenium Committers">
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you 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 License for the
// specific language governing permissions and limitations
// under the License.
// </copyright>
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
using static OpenQA.Selenium.BiDi.Script.ScriptJsonSerializerContext;
namespace OpenQA.Selenium.BiDi.Script;
internal sealed class ScriptModule : Module, IScriptModule
{
private static readonly Command<EvaluateParameters, EvaluateResult> EvaluateCommand = new(
"script.evaluate", Default.EvaluateParameters, Default.EvaluateResult);
private static readonly Command<CallFunctionParameters, EvaluateResult> CallFunctionCommand = new(
"script.callFunction", Default.CallFunctionParameters, Default.EvaluateResult);
private static readonly Command<DisownParameters, DisownResult> DisownCommand = new(
"script.disown", Default.DisownParameters, Default.DisownResult);
private static readonly Command<GetRealmsParameters, GetRealmsResult> GetRealmsCommand = new(
"script.getRealms", Default.GetRealmsParameters, Default.GetRealmsResult);
private static readonly Command<AddPreloadScriptParameters, AddPreloadScriptResult> AddPreloadScriptCommand = new(
"script.addPreloadScript", Default.AddPreloadScriptParameters, Default.AddPreloadScriptResult);
private static readonly Command<RemovePreloadScriptParameters, RemovePreloadScriptResult> RemovePreloadScriptCommand = new(
"script.removePreloadScript", Default.RemovePreloadScriptParameters, Default.RemovePreloadScriptResult);
private static readonly Event<MessageEventArgs, MessageParameters> MessageEvent = new(
"script.message",
static (bidi, p) => new MessageEventArgs(bidi, p.Channel, p.Data, p.Source),
Default.MessageParameters);
private static readonly Event<RealmCreatedEventArgs, RealmInfo> RealmCreatedEvent = new(
"script.realmCreated",
static (bidi, p) => p switch
{
WindowRealmInfo w => new WindowRealmCreatedEventArgs(bidi, w.Realm, w.Origin, w.Context, w.UserContext, w.Sandbox),
DedicatedWorkerRealmInfo d => new DedicatedWorkerRealmCreatedEventArgs(bidi, d.Realm, d.Origin, d.Owners),
SharedWorkerRealmInfo s => new SharedWorkerRealmCreatedEventArgs(bidi, s.Realm, s.Origin),
ServiceWorkerRealmInfo s => new ServiceWorkerRealmCreatedEventArgs(bidi, s.Realm, s.Origin),
WorkerRealmInfo w => new WorkerRealmCreatedEventArgs(bidi, w.Realm, w.Origin),
PaintWorkletRealmInfo p2 => new PaintWorkletRealmCreatedEventArgs(bidi, p2.Realm, p2.Origin),
AudioWorkletRealmInfo a => new AudioWorkletRealmCreatedEventArgs(bidi, a.Realm, a.Origin),
WorkletRealmInfo w => new WorkletRealmCreatedEventArgs(bidi, w.Realm, w.Origin),
_ => throw new BiDiException($"Unknown {nameof(RealmInfo)} type: {p.GetType()}")
},
Default.RealmInfo);
private static readonly Event<RealmDestroyedEventArgs, RealmDestroyedParameters> RealmDestroyedEvent = new(
"script.realmDestroyed",
static (bidi, p) => new RealmDestroyedEventArgs(bidi, p.Realm),
Default.RealmDestroyedParameters);
public async Task<EvaluateResult> EvaluateAsync([StringSyntax(StringSyntaxConstants.JavaScript)] string expression, bool awaitPromise, Target target, EvaluateOptions? options = null, CancellationToken cancellationToken = default)
{
var @params = new EvaluateParameters(expression, target, awaitPromise, options?.ResultOwnership, options?.SerializationOptions, options?.UserActivation);
return await ExecuteAsync(EvaluateCommand, @params, options, cancellationToken).ConfigureAwait(false);
}
public async Task<TResult?> EvaluateAsync<TResult>([StringSyntax(StringSyntaxConstants.JavaScript)] string expression, bool awaitPromise, Target target, EvaluateOptions? options = null, CancellationToken cancellationToken = default)
{
var result = await EvaluateAsync(expression, awaitPromise, target, options, cancellationToken).ConfigureAwait(false);
return result.AsSuccessResult().ConvertTo<TResult>();
}
public async Task<EvaluateResult> CallFunctionAsync([StringSyntax(StringSyntaxConstants.JavaScript)] string functionDeclaration, bool awaitPromise, Target target, CallFunctionOptions? options = null, CancellationToken cancellationToken = default)
{
var @params = new CallFunctionParameters(functionDeclaration, awaitPromise, target, options?.Arguments, options?.ResultOwnership, options?.SerializationOptions, options?.This, options?.UserActivation);
return await ExecuteAsync(CallFunctionCommand, @params, options, cancellationToken).ConfigureAwait(false);
}
public async Task<TResult?> CallFunctionAsync<TResult>([StringSyntax(StringSyntaxConstants.JavaScript)] string functionDeclaration, bool awaitPromise, Target target, CallFunctionOptions? options = null, CancellationToken cancellationToken = default)
{
var result = await CallFunctionAsync(functionDeclaration, awaitPromise, target, options, cancellationToken).ConfigureAwait(false);
return result.AsSuccessResult().ConvertTo<TResult>();
}
public async Task<DisownResult> DisownAsync(IEnumerable<Handle> handles, Target target, DisownOptions? options = null, CancellationToken cancellationToken = default)
{
var @params = new DisownParameters(handles, target);
return await ExecuteAsync(DisownCommand, @params, options, cancellationToken).ConfigureAwait(false);
}
public async Task<GetRealmsResult> GetRealmsAsync(GetRealmsOptions? options = null, CancellationToken cancellationToken = default)
{
var @params = new GetRealmsParameters(options?.Context, options?.Type);
return await ExecuteAsync(GetRealmsCommand, @params, options, cancellationToken).ConfigureAwait(false);
}
public async Task<AddPreloadScriptResult> AddPreloadScriptAsync([StringSyntax(StringSyntaxConstants.JavaScript)] string functionDeclaration, AddPreloadScriptOptions? options = null, CancellationToken cancellationToken = default)
{
var @params = new AddPreloadScriptParameters(functionDeclaration, options?.Arguments, options?.Contexts, options?.UserContexts, options?.Sandbox);
return await ExecuteAsync(AddPreloadScriptCommand, @params, options, cancellationToken).ConfigureAwait(false);
}
public async Task<RemovePreloadScriptResult> RemovePreloadScriptAsync(PreloadScript script, RemovePreloadScriptOptions? options = null, CancellationToken cancellationToken = default)
{
var @params = new RemovePreloadScriptParameters(script);
return await ExecuteAsync(RemovePreloadScriptCommand, @params, options, cancellationToken).ConfigureAwait(false);
}
public async Task<Subscription> OnMessageAsync(Func<MessageEventArgs, Task> handler, SubscriptionOptions? options = null, CancellationToken cancellationToken = default)
{
return await SubscribeAsync(MessageEvent, handler, options, cancellationToken).ConfigureAwait(false);
}
public async Task<Subscription> OnMessageAsync(Action<MessageEventArgs> handler, SubscriptionOptions? options = null, CancellationToken cancellationToken = default)
{
return await SubscribeAsync(MessageEvent, handler, options, cancellationToken).ConfigureAwait(false);
}
public async Task<Subscription> OnRealmCreatedAsync(Func<RealmCreatedEventArgs, Task> handler, SubscriptionOptions? options = null, CancellationToken cancellationToken = default)
{
return await SubscribeAsync(RealmCreatedEvent, handler, options, cancellationToken).ConfigureAwait(false);
}
public async Task<Subscription> OnRealmCreatedAsync(Action<RealmCreatedEventArgs> handler, SubscriptionOptions? options = null, CancellationToken cancellationToken = default)
{
return await SubscribeAsync(RealmCreatedEvent, handler, options, cancellationToken).ConfigureAwait(false);
}
public async Task<Subscription> OnRealmDestroyedAsync(Func<RealmDestroyedEventArgs, Task> handler, SubscriptionOptions? options = null, CancellationToken cancellationToken = default)
{
return await SubscribeAsync(RealmDestroyedEvent, handler, options, cancellationToken).ConfigureAwait(false);
}
public async Task<Subscription> OnRealmDestroyedAsync(Action<RealmDestroyedEventArgs> handler, SubscriptionOptions? options = null, CancellationToken cancellationToken = default)
{
return await SubscribeAsync(RealmDestroyedEvent, handler, options, cancellationToken).ConfigureAwait(false);
}
}
#region https://github.com/dotnet/runtime/issues/72604
[JsonSerializable(typeof(EvaluateResultSuccess))]
[JsonSerializable(typeof(EvaluateResultException))]
[JsonSerializable(typeof(NumberRemoteValue))]
[JsonSerializable(typeof(BooleanRemoteValue))]
[JsonSerializable(typeof(BigIntRemoteValue))]
[JsonSerializable(typeof(StringRemoteValue))]
[JsonSerializable(typeof(NullRemoteValue))]
[JsonSerializable(typeof(UndefinedRemoteValue))]
[JsonSerializable(typeof(SymbolRemoteValue))]
[JsonSerializable(typeof(ArrayRemoteValue))]
[JsonSerializable(typeof(ObjectRemoteValue))]
[JsonSerializable(typeof(FunctionRemoteValue))]
[JsonSerializable(typeof(RegExpRemoteValue))]
[JsonSerializable(typeof(DateRemoteValue))]
[JsonSerializable(typeof(MapRemoteValue))]
[JsonSerializable(typeof(SetRemoteValue))]
[JsonSerializable(typeof(WeakMapRemoteValue))]
[JsonSerializable(typeof(WeakSetRemoteValue))]
[JsonSerializable(typeof(GeneratorRemoteValue))]
[JsonSerializable(typeof(ErrorRemoteValue))]
[JsonSerializable(typeof(ProxyRemoteValue))]
[JsonSerializable(typeof(PromiseRemoteValue))]
[JsonSerializable(typeof(TypedArrayRemoteValue))]
[JsonSerializable(typeof(ArrayBufferRemoteValue))]
[JsonSerializable(typeof(NodeListRemoteValue))]
[JsonSerializable(typeof(HtmlCollectionRemoteValue))]
[JsonSerializable(typeof(NodeRemoteValue))]
[JsonSerializable(typeof(WindowProxyRemoteValue))]
[JsonSerializable(typeof(WindowRealmInfo))]
[JsonSerializable(typeof(DedicatedWorkerRealmInfo))]
[JsonSerializable(typeof(SharedWorkerRealmInfo))]
[JsonSerializable(typeof(ServiceWorkerRealmInfo))]
[JsonSerializable(typeof(WorkerRealmInfo))]
[JsonSerializable(typeof(PaintWorkletRealmInfo))]
[JsonSerializable(typeof(AudioWorkletRealmInfo))]
[JsonSerializable(typeof(WorkletRealmInfo))]
#endregion
[JsonSerializable(typeof(AddPreloadScriptParameters))]
[JsonSerializable(typeof(AddPreloadScriptResult))]
[JsonSerializable(typeof(DisownParameters))]
[JsonSerializable(typeof(DisownResult))]
[JsonSerializable(typeof(CallFunctionParameters))]
[JsonSerializable(typeof(EvaluateResult))]
[JsonSerializable(typeof(EvaluateParameters))]
[JsonSerializable(typeof(EvaluateResult))]
[JsonSerializable(typeof(GetRealmsParameters))]
[JsonSerializable(typeof(GetRealmsResult))]
[JsonSerializable(typeof(RemovePreloadScriptParameters))]
[JsonSerializable(typeof(RemovePreloadScriptResult))]
[JsonSerializable(typeof(MessageParameters))]
[JsonSerializable(typeof(RealmDestroyedParameters))]
[JsonSourceGenerationOptions(
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
internal partial class ScriptJsonSerializerContext : JsonSerializerContext;