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