1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    fidl_fuchsia_ui_test_conformance::{
        PuppetEmbedRemoteViewResponse, PuppetFactoryCreateResponse, PuppetFactoryRequest,
        PuppetFactoryRequestStream, PuppetRequest, PuppetRequestStream,
        PuppetSetEmbeddedViewPropertiesResponse, Result_,
    },
    futures::TryStreamExt,
    std::{cell::RefCell, rc::Rc},
    tracing::info,
};

mod presentation_loop;
mod view;

async fn run_puppet(request_stream: PuppetRequestStream, puppet_view: Rc<RefCell<view::View>>) {
    info!("Starting puppet instance");

    request_stream
        .try_for_each(|request| async {
            match request {
                PuppetRequest::EmbedRemoteView { payload, responder, .. } => {
                    let viewport_id = payload.id.expect("missing viewport id");
                    let properties = payload.properties.expect("missing embedded view properties");

                    let view_creation_token =
                        puppet_view.borrow_mut().embed_remote_view(viewport_id, properties).await;

                    responder
                        .send(PuppetEmbedRemoteViewResponse {
                            result: Some(Result_::Success),
                            view_creation_token: Some(view_creation_token),
                            ..Default::default()
                        })
                        .expect("failed to respond to EmbedRemoteView request");
                }
                PuppetRequest::SetEmbeddedViewProperties { payload, responder, .. } => {
                    let viewport_id = payload.id.expect("missing viewport id");
                    let properties = payload.properties.expect("missing embedded view properties");

                    puppet_view
                        .borrow_mut()
                        .set_embedded_view_properties(viewport_id, properties)
                        .await;

                    responder
                        .send(&PuppetSetEmbeddedViewPropertiesResponse {
                            result: Some(Result_::Success),
                            ..Default::default()
                        })
                        .expect("failed to respond to SetEmbeddedViewProperties request");
                }
                _ => {
                    panic!("unsupported operation");
                }
            }

            Ok(())
        })
        .await
        .expect("failed to serve puppet stream");

    info!("reached end of puppet request stream; closing connection");
}

pub async fn run_puppet_factory(request_stream: PuppetFactoryRequestStream) {
    info!("handling client connection to puppet factory service");

    request_stream
        .try_for_each_concurrent(None, |request| async {
            match request {
                PuppetFactoryRequest::Create { payload, responder, .. } => {
                    info!("create puppet");
                    let flatland = payload
                        .flatland_client
                        .expect("missing flatland client")
                        .into_proxy()
                        .expect("failed to generate proxy");
                    let keyboard = payload
                        .keyboard_client
                        .expect("missing keyboard client")
                        .into_proxy()
                        .expect("failed to generate proxy");
                    let view_token =
                        payload.view_token.expect("missing puppet viewport creation token");
                    let puppet_server = payload.server_end.expect("missing puppet server endpoint");
                    let touch_listener = match payload.touch_listener {
                        None => None,
                        Some(touch_listener) => {
                            Some(touch_listener.into_proxy().expect("failed to generate proxy"))
                        }
                    };
                    let mouse_listener = match payload.mouse_listener {
                        None => None,
                        Some(mouse_listener) => {
                            Some(mouse_listener.into_proxy().expect("failed to generate proxy"))
                        }
                    };
                    let keyboard_listener = match payload.keyboard_listener {
                        None => None,
                        Some(keyboard_listener) => {
                            Some(keyboard_listener.into_proxy().expect("failed to generate proxy"))
                        }
                    };
                    let device_pixel_ratio =
                        payload.device_pixel_ratio.expect("missing device_pixel_ratio");

                    let (view, view_ref) = view::View::new(
                        flatland,
                        keyboard,
                        view_token,
                        touch_listener,
                        mouse_listener,
                        keyboard_listener,
                        device_pixel_ratio,
                        payload.focuser,
                    )
                    .await;

                    responder
                        .send(PuppetFactoryCreateResponse {
                            result: Some(Result_::Success),
                            view_ref: Some(view_ref),
                            ..Default::default()
                        })
                        .expect("failed to respond to PuppetFactoryRequest::Create");

                    run_puppet(
                        puppet_server.into_stream().expect("failed to bind puppet server endpoint"),
                        view,
                    )
                    .await;
                }
            }

            Ok(())
        })
        .await
        .expect("failed to serve puppet factory stream");

    info!("reached end of puppet factory request stream; closing connection");
}