playwright/imp/core/
remote_object.rs

1use crate::imp::{core::*, impl_future::*, prelude::*};
2use serde_json::value::Value;
3use std::{fmt::Debug, future::Future, pin::Pin, sync::TryLockError, task::Waker};
4
5pub(crate) fn upgrade<T>(w: &Weak<T>) -> Result<Arc<T>, Error> {
6    w.upgrade().ok_or(Error::ObjectNotFound)
7}
8
9pub(crate) fn weak_and_then<T, U, F>(w: &Weak<T>, f: F) -> Weak<U>
10where
11    F: FnOnce(Arc<T>) -> Weak<U>
12{
13    let rc = match w.upgrade() {
14        None => return Weak::new(),
15        Some(rc) => rc
16    };
17    f(rc)
18}
19
20#[derive(Debug)]
21pub(crate) struct ChannelOwner {
22    pub(crate) ctx: Weak<Mutex<Context>>,
23    pub(crate) parent: Option<RemoteWeak>,
24    pub(crate) typ: Str<ObjectType>,
25    pub(crate) guid: Str<Guid>,
26    pub(crate) initializer: Value,
27    children: Mutex<Vec<RemoteWeak>>
28}
29
30impl ChannelOwner {
31    pub(crate) fn new(
32        ctx: Weak<Mutex<Context>>,
33        parent: RemoteWeak,
34        typ: Str<ObjectType>,
35        guid: Str<Guid>,
36        initializer: Value
37    ) -> Self {
38        Self {
39            ctx,
40            parent: Some(parent),
41            typ,
42            guid,
43            initializer,
44            children: Mutex::new(Vec::new())
45        }
46    }
47
48    pub(crate) fn new_root() -> Self {
49        Self {
50            ctx: Weak::new(),
51            parent: None,
52            typ: Str::validate("".into()).unwrap(),
53            guid: Str::validate("".into()).unwrap(),
54            initializer: Value::default(),
55            children: Mutex::default()
56        }
57    }
58
59    pub(crate) fn create_request(&self, method: Str<Method>) -> RequestBody {
60        RequestBody::new(self.guid.clone(), method)
61    }
62
63    pub(crate) async fn send_message(
64        &self,
65        r: RequestBody
66    ) -> Result<WaitData<WaitMessageResult>, Error> {
67        let wait = WaitData::new();
68        let r = r.set_wait(&wait);
69        let ctx = upgrade(&self.ctx)?;
70        ctx.lock().unwrap().send_message(r)?;
71        Ok(wait)
72    }
73
74    pub(crate) fn children(&self) -> Vec<RemoteWeak> { self.children.lock().unwrap().to_vec() }
75
76    pub(crate) fn push_child(&self, c: RemoteWeak) {
77        let children = &mut self.children.lock().unwrap();
78        children.push(c);
79    }
80}
81
82#[derive(Debug)]
83pub(crate) struct DummyObject {
84    channel: ChannelOwner
85}
86
87impl DummyObject {
88    pub(crate) fn new(channel: ChannelOwner) -> Self { DummyObject { channel } }
89}
90
91impl RemoteObject for DummyObject {
92    fn channel(&self) -> &ChannelOwner { &self.channel }
93    fn channel_mut(&mut self) -> &mut ChannelOwner { &mut self.channel }
94}
95
96#[derive(Debug)]
97pub(crate) struct RootObject {
98    channel: ChannelOwner
99}
100
101impl RootObject {
102    pub(crate) fn new() -> Self {
103        Self {
104            channel: ChannelOwner::new_root()
105        }
106    }
107}
108
109impl Default for RootObject {
110    fn default() -> Self { Self::new() }
111}
112
113impl RemoteObject for RootObject {
114    fn channel(&self) -> &ChannelOwner { &self.channel }
115    fn channel_mut(&mut self) -> &mut ChannelOwner { &mut self.channel }
116}
117
118pub(crate) trait RemoteObject: Debug {
119    fn channel(&self) -> &ChannelOwner;
120    fn channel_mut(&mut self) -> &mut ChannelOwner;
121
122    fn guid(&self) -> &S<Guid> { &self.channel().guid }
123    fn context(&self) -> Result<Arc<Mutex<Context>>, Error> { upgrade(&self.channel().ctx) }
124
125    fn handle_event(
126        &self,
127        _ctx: &Context,
128        _method: Str<Method>,
129        _params: Map<String, Value>
130    ) -> Result<(), Error> {
131        Ok(())
132    }
133}
134
135mod remote_enum {
136    use super::{DummyObject as Dummy, RootObject as Root, *};
137    use crate::imp::{
138        artifact::Artifact, binding_call::BindingCall, browser::Browser,
139        browser_context::BrowserContext, browser_type::BrowserType,
140        console_message::ConsoleMessage, dialog::Dialog, element_handle::ElementHandle,
141        frame::Frame, js_handle::JsHandle, page::Page, playwright::Playwright, request::Request,
142        response::Response, route::Route, selectors::Selectors, stream::Stream,
143        websocket::WebSocket, worker::Worker
144    };
145
146    macro_rules! upgrade {
147        ($($t:ident),*) => {
148            pub(crate) fn upgrade(&self) -> Option<RemoteArc> {
149                match self {
150                    $(
151                        Self::$t(x) => x.upgrade().map(RemoteArc::$t)
152                    ),*
153                }
154            }
155        }
156    }
157
158    macro_rules! downgrade {
159        ($($t:ident),*) => {
160            pub(crate) fn downgrade(&self) -> RemoteWeak {
161                match self {
162                    $(
163                        Self::$t(x) => RemoteWeak::$t(Arc::downgrade(x))
164                    ),*
165                }
166            }
167        }
168    }
169
170    macro_rules! handle_event {
171        ($($t:ident),*) => {
172            pub(crate) fn handle_event(
173                &self, ctx: &Context, method: Str<Method>, params: Map<String, Value>
174            ) -> Result<(), Error> {
175                match self {
176                    $(
177                        Self::$t(x) => x.handle_event(ctx, method, params)
178                    ),*
179                }
180            }
181        }
182    }
183
184    macro_rules! channel {
185        ($($t:ident),*) => {
186            pub(crate) fn channel(&self) -> &ChannelOwner {
187                match self {
188                    $(
189                        Self::$t(x) => x.channel()
190                    ),*
191                }
192            }
193        }
194    }
195
196    macro_rules! remote_enum {
197        ($($t:ident),*) => {
198            #[derive(Debug, Clone)]
199            pub(crate) enum RemoteArc {
200                $($t(Arc<$t>)),*
201            }
202
203            #[derive(Debug, Clone)]
204            pub(crate) enum RemoteWeak {
205                $($t(Weak<$t>)),*
206            }
207
208            impl RemoteWeak {
209                upgrade!{$($t),*}
210            }
211
212            impl RemoteArc {
213                downgrade!{$($t),*}
214                handle_event!{$($t),*}
215                channel!{$($t),*}
216            }
217        }
218    }
219
220    remote_enum! {
221        Dummy,
222        Root,
223        // Android
224        // AndroidSocket
225        // AndroidDevice
226        Artifact,
227        BindingCall,
228        Browser,
229        BrowserContext,
230        BrowserType,
231        // CdpSession
232        ConsoleMessage,
233        Dialog,
234        // Electron
235        // ElectronApplication
236        ElementHandle,
237        Frame,
238        JsHandle,
239        Page,
240        Playwright,
241        Request,
242        Response,
243        Route,
244        Stream,
245        Selectors,
246        WebSocket,
247        Worker
248    }
249
250    impl RemoteArc {
251        pub(crate) fn try_new(
252            typ: &S<ObjectType>,
253            ctx: &Context,
254            c: ChannelOwner
255        ) -> Result<RemoteArc, Error> {
256            let r = match typ.as_str() {
257                "Artifact" => RemoteArc::Artifact(Arc::new(Artifact::try_new(c)?)),
258                "BindingCall" => RemoteArc::BindingCall(Arc::new(BindingCall::new(c))),
259                "Browser" => RemoteArc::Browser(Arc::new(Browser::try_new(c)?)),
260                "BrowserContext" => {
261                    RemoteArc::BrowserContext(Arc::new(BrowserContext::try_new(c)?))
262                }
263                "BrowserType" => RemoteArc::BrowserType(Arc::new(BrowserType::try_new(c)?)),
264                "ConsoleMessage" => {
265                    RemoteArc::ConsoleMessage(Arc::new(ConsoleMessage::try_new(ctx, c)?))
266                }
267                "Dialog" => RemoteArc::Dialog(Arc::new(Dialog::new(c))),
268                "ElementHandle" => RemoteArc::ElementHandle(Arc::new(ElementHandle::new(c))),
269                "Frame" => RemoteArc::Frame(Arc::new(Frame::try_new(ctx, c)?)),
270                "JSHandle" => RemoteArc::JsHandle(Arc::new(JsHandle::try_new(c)?)),
271                "Page" => RemoteArc::Page(Arc::new(Page::try_new(ctx, c)?)),
272                "Playwright" => RemoteArc::Playwright(Arc::new(Playwright::try_new(ctx, c)?)),
273                "Request" => RemoteArc::Request(Request::try_new(ctx, c)?),
274                "Response" => RemoteArc::Response(Arc::new(Response::try_new(ctx, c)?)),
275                "Route" => RemoteArc::Route(Arc::new(Route::try_new(ctx, c)?)),
276                "Stream" => RemoteArc::Stream(Arc::new(Stream::new(c))),
277                "Selectors" => RemoteArc::Selectors(Arc::new(Selectors::new(c))),
278                "WebSocket" => RemoteArc::WebSocket(Arc::new(WebSocket::try_new(c)?)),
279                "Worker" => RemoteArc::Worker(Arc::new(Worker::try_new(c)?)),
280                _ => RemoteArc::Dummy(Arc::new(DummyObject::new(c)))
281            };
282            Ok(r)
283        }
284    }
285}
286
287pub(crate) use remote_enum::{RemoteArc, RemoteWeak};
288
289pub(crate) struct RequestBody {
290    pub(crate) guid: Str<Guid>,
291    pub(crate) method: Str<Method>,
292    pub(crate) params: Map<String, Value>,
293    pub(crate) place: WaitPlaces<WaitMessageResult>
294}
295
296impl RequestBody {
297    pub(crate) fn new(guid: Str<Guid>, method: Str<Method>) -> RequestBody {
298        RequestBody {
299            guid,
300            method,
301            params: Map::default(),
302            place: WaitPlaces::new_empty()
303        }
304    }
305
306    // pub(crate) fn set_method(mut self, method: Str<Method>) -> Self {
307    //    self.method = method;
308    //    self
309    //}
310
311    pub(crate) fn set_params(mut self, params: Map<String, Value>) -> Self {
312        self.params = params;
313        self
314    }
315
316    pub(crate) fn set_args<T: Serialize>(self, body: T) -> Result<Self, Error> {
317        let v = serde_json::value::to_value(body).map_err(Error::Serde)?;
318        let p = match v {
319            Value::Object(m) => m,
320            _ => return Err(Error::NotObject)
321        };
322        Ok(self.set_params(p))
323    }
324
325    pub(crate) fn set_wait(mut self, wait: &WaitData<WaitMessageResult>) -> Self {
326        self.place = wait.place();
327        self
328    }
329
330    // pub(crate) fn set_guid(mut self, guid: Str<Guid>) -> Self {
331    //    self.guid = guid;
332    //    self
333    //}
334}
335
336pub(crate) type WaitMessageResult = Result<Result<Arc<Value>, Arc<ErrorMessage>>, Arc<Error>>;
337
338#[derive(Debug, Clone)]
339pub(crate) struct WaitPlaces<T> {
340    pub(crate) value: Wm<Option<T>>,
341    pub(crate) waker: Wm<Option<Waker>>
342}
343
344pub(crate) struct WaitData<T> {
345    place: Arc<Mutex<Option<T>>>,
346    waker: Arc<Mutex<Option<Waker>>>
347}
348
349impl<T> WaitPlaces<T> {
350    pub(crate) fn new_empty() -> Self {
351        Self {
352            value: Weak::new(),
353            waker: Weak::new()
354        }
355    }
356}
357
358impl<T> WaitData<T> {
359    pub(crate) fn new() -> Self {
360        let place = Arc::new(Mutex::new(None));
361        let waker = Arc::new(Mutex::new(None));
362        Self { place, waker }
363    }
364
365    pub(crate) fn place(&self) -> WaitPlaces<T> {
366        let wp = Arc::downgrade(&self.place);
367        let ww = Arc::downgrade(&self.waker);
368        WaitPlaces {
369            value: wp,
370            waker: ww
371        }
372    }
373}
374
375impl<T> Future for WaitData<T>
376where
377    T: Clone
378{
379    type Output = T;
380
381    fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
382        let this = self.get_mut();
383        log::trace!("poll WaitData");
384        macro_rules! pending {
385            () => {{
386                cx.waker().wake_by_ref();
387                return Poll::Pending;
388            }};
389        }
390        {
391            let x = match this.place.try_lock() {
392                Ok(x) => x,
393                Err(TryLockError::WouldBlock) => pending!(),
394                Err(e) => Err(e).unwrap()
395            };
396            if let Some(x) = &*x {
397                return Poll::Ready(x.clone());
398            }
399        }
400        {
401            let mut x = match this.waker.try_lock() {
402                Ok(x) => x,
403                Err(TryLockError::WouldBlock) => pending!(),
404                Err(e) => Err(e).unwrap()
405            };
406            if x.is_none() {
407                *x = Some(cx.waker().clone());
408            }
409        }
410        Poll::Pending
411    }
412}