1# OverlayPresenter
2
3OverlayPresenter is used to schedule the display of UI alongside the content
4area of a WebState.
5
6## Classes of note:
7
8##### OverlayRequest
9
10OverlayRequests are model objects that are used to schedule the display of
11UI alongside a WebState's content area.  They are created with an
12OverlayUserData subclass containing the information necessary to configure the
13requested UI.
14
15##### OverlayResponse
16
17OverlayResponses are provided to each OverlayRequest to describe the user's
18interaction with the overlay UI.  Clients should create OverlayResponses with
19OverlayUserData subclasses with the overlay UI user interaction information
20necessary to execute the callback for that overlay.
21
22##### OverlayCallbackManager
23
24Each OverlayRequest owns an OverlayCallbackManager, which is used to communicate
25user interaction events from the overlay UI to the requesting site.  It supports
26two types of callbacks: completion callbacks and dispatch callbacks.  Completion
27callbacks are executed when the overlay UI is dismissed or the OverlayRequest is
28cancelled.  These callbacks are executed with a completion OverlayResponse.  In
29order to handle model updates for user interaction events for ongoing overlay
30UI, the callback manager also supports callbacks for OverlayResponses dispatched
31before overlay completion.  OverlayPresenter clients can register callbacks to
32be executed upon every dispatch of an OverlayResponse created with a specific
33type of response info type.
34
35##### OverlayRequestQueue
36
37Each WebState has an OverlayRequestQueue at each OverlayModality that stores the
38OverlayRequests for overlays to be displayed alongside that WebState's content
39area.  When a client wishes to schedule the display of an overlay, it should
40add an OverlayRequest to the desired WebState's queue.  This will trigger the
41scheduling logic for that request's corresponding overlay UI.
42
43##### OverlayPresenter
44
45OverlayPresenter drives the presentation of the UI for OverlayRequests added to
46queues for WebStates in a Browser.
47
48##### OverlayPresentationContext
49
50Clients must provide a presentation context to a Browser's OverlayPresenter that
51handles the presentation of overlay UI for that presenter's modality and
52Browser.
53
54##### OverlayPresenterObserver
55
56Objects that care about the presentation and dismissal of overlay UI by the
57presenter should add themselves as observers to the presenter.  This can be used
58to respond to update UI for UI presentation, for example to update the location
59bar text while a dialog is displayed.  Additionally, observers can use these
60hook points to add additional callbacks to the request.
61
62## Setting up OverlayPresenter:
63
64Multiple OverlayPresenters may be active for a single Browser to manage overlay
65UI at different levels of modality (i.e. modal over WebState content area, modal
66over entire browser, etc).
67
68Each instance of OverlayPresenter must be provided with an OverlayPresenter::
69UIDelegate that manages the overlay UI at the modality associated with the
70presenter.
71
72## Example usage of presenter:
73
74### Showing an alert with a title, message, an OK button, and a Cancel button
75
76##### 1. Create OverlayUserData subclasses for the requests and responses:
77
78A request configuration user data should be created with the information
79necessary to set up the overlay UI being requested.
80
81    class AlertConfig : public OverlayUserData<AlertConfig> {
82     public:
83      const std::string& title() const;
84      const std::string& message() const;
85      const std::vector<std::string>& button_titles() const;
86     private:
87      OVERLAY_USER_DATA_SETUP(AlertConfig);
88      AlertConfig(const std::string& title, const std::string& message);
89    };
90
91A response ino user data should be created with the information necessary to
92execute the callback for the overlay.
93
94    class AlertInfo : public OverlayUserData<AlertInfo> {
95     public:
96      const size_t tapped_button_index() const;
97     private:
98      OVERLAY_USER_DATA_SETUP(AlertInfo);
99      AlertInfo(size_t tapped_button_index);
100    };
101
102##### 2. Request an overlay using the request config user data.
103
104An OverlayRequest for the alert can be created using:
105
106    OverlayRequest::CreateWithConfig<AlertConfig>(
107        "alert title", "message text");
108
109A callback can be added to the request to use the response info:
110
111    OverlayCompletionCallback callback =
112        base::BindOnce(base::RetainBlock(^(OverlayResponse* response) {
113      if (!response)
114        return;
115      AlertInfo* info = response->GetInfo<AlertInfo>();
116      /* Handle button tap at info->tapped_button_index() */
117    }));
118    request->GetCallbackManager()->AddCompletionCallback(std::move(callback));
119
120Clients can then supply this request to the OverlayRequestQueue corresponding
121with the WebState alongside which the overlay should be shown:
122
123    OverlayModality modality =
124        OverlayModality::kWebContentArea;
125    OverlayRequestQueue::FromWebState(web_state, modality)->
126        AddRequest(std::move(request));
127
128##### 3. Supply a response to the request.
129
130Upon the user tapping a button on the alert, say at index 0, a response can be
131created and supplied to that request.
132
133    OverlayRequestQueue::FromWebState(web_state, modality)
134        ->front_request()
135        ->GetCallbackManager()
136        ->SetCompletionResponse(OverlayResponse::CreateWithInfo<AlertInfo>(0));
137
138### Dispatching responses for ongoing overlays
139
140This section documents how to update model objects for user interaction events
141in overlay UI that has not been dismissed yet.  As an example situation, let's
142say that there's a non-modal account picking screen.  When the user taps on an
143account, we want to update the username text in a separate view without
144dismissing the overlay UI.  This can be accomplished by dispatching responses
145through the callback manager.
146
147##### 1. Create OverlayUserData subclasses for the dispatched response:
148
149OverlayRequests configured with AccountChooserUserInfos will be dispatched via
150the OverlayRequest's callback manager in order to update the username label in
151a browser view.
152
153    class AccountChooserUserInfo :
154        public OverlayUserData<AccountChooserUserInfo> {
155     public:
156      const std::string& username() const;
157     private:
158      OVERLAY_USER_DATA_SETUP(AccountChooserUserInfo);
159      AccountChooserUserInfo(const std::string& username);
160    };
161
162##### 2. Use OverlayPresenterObserver to add a dispatch callback:
163
164The mediator for the UI showing the username label should register itself as an
165OverlayPresenterObserver so that it can be aware of the presentation of UI.
166
167    @interface UsernameLabelMediator ()<OverlayPresenterObserving>
168    @end
169
170    @implementation UsernameLabelMediator
171
172    - (void)overlayPresenter:(OverlayPresenter\*)presenter
173        willShowOverlayForRequest:(OverlayRequest*)request {
174      // Only add the dispatch callback for requests created with the desired
175      // config.  This mediator only cares about requests for the account
176      // chooser UI (AccountChooserRequestConfig definition not shown).
177      if (!request->GetConfig<AccountChooserRequestConfig>())
178        return;
179      __weak __typeof__(self) weakSelf = self;
180      OverlayDispatchCallback callback =
181          base::BindRepeating(^(OverlayResponse* response) {
182        weakSelf.consumer.usernameText = base::SysUTF8ToNSString(
183            response->GetInfo<AccountChooserUserInfo>()->username());
184      });
185      request->GetCallbackManager()->AddDispatchCallback(std::move(callback));
186    }
187
188    @end
189
190##### 3. Dispatch OverlayResponses for non-dismissing UI events
191
192When the user taps on a row in the account chooser overlay UI, the overlay's
193mediator would handle this event by dispatching an OverlayRequest created with
194an AccountChooserUserInfo in order to trigger callbacks for that type of
195response.
196
197    @implementation AccountChooserOverlayMediator
198
199    - (void)didTapOnAccountWithUsername:(NSString\*)username {
200      self.request->GetCallbackManager()->DispatchResponse(
201          OverlayResponse::CreateWithInfo<AccountChooserUserInfo>(
202          base::SysNSStringToUTF8(username)));
203    }
204
205    @end
206
207
208