1717
1818import android .graphics .Bitmap ;
1919import android .os .Build ;
20+ import android .os .ConditionVariable ;
2021import android .text .TextUtils ;
2122import android .webkit .WebView ;
2223import android .webkit .WebViewClient ;
2324
24- import com .facebook .catalyst .views .webview .events .TopLoadingErrorEvent ;
25- import com .facebook .catalyst .views .webview .events .TopLoadingFinishEvent ;
26- import com .facebook .catalyst .views .webview .events .TopLoadingStartEvent ;
25+ import com .facebook .react .views .webview .events .TopLoadingErrorEvent ;
26+ import com .facebook .react .views .webview .events .TopLoadingFinishEvent ;
27+ import com .facebook .react .views .webview .events .TopLoadingStartEvent ;
28+ import com .facebook .react .views .webview .events .ShouldOverrideUrlLoadingEvent ;
2729import com .facebook .react .bridge .Arguments ;
2830import com .facebook .react .bridge .LifecycleEventListener ;
2931import com .facebook .react .bridge .ReactContext ;
4042import com .facebook .react .uimanager .annotations .ReactProp ;
4143import com .facebook .react .uimanager .events .Event ;
4244import com .facebook .react .uimanager .events .EventDispatcher ;
45+ import com .facebook .react .common .MapBuilder ;
4346
4447/**
4548 * Manages instances of {@link WebView}
5356 * - topLoadingFinish
5457 * - topLoadingStart
5558 * - topLoadingError
59+ * - topShouldOverrideUrlLoading
5660 *
5761 * Each event will carry the following properties:
5862 * - target - view's react tag
@@ -74,6 +78,7 @@ public class ReactWebViewManager extends SimpleViewManager<WebView> {
7478 public static final int COMMAND_GO_BACK = 1 ;
7579 public static final int COMMAND_GO_FORWARD = 2 ;
7680 public static final int COMMAND_RELOAD = 3 ;
81+ public static final int COMMAND_SHOULD_OVERRIDE_WITH_RESULT = 4 ;
7782
7883 // Use `webView.loadUrl("about:blank")` to reliably reset the view
7984 // state and release page resources (including any running JavaScript).
@@ -143,6 +148,23 @@ public void doUpdateVisitedHistory(WebView webView, String url, boolean isReload
143148 createWebViewEvent (webView , url )));
144149 }
145150
151+ @ Override
152+ public boolean shouldOverrideUrlLoading (WebView webView , String url ) {
153+ ReactWebView view = ((ReactWebView )webView );
154+ view .mShouldOverrideUrlLoadingResult = false ;
155+ dispatchEvent (
156+ webView ,
157+ new ShouldOverrideUrlLoadingEvent (
158+ webView .getId (),
159+ SystemClock .nanoTime (),
160+ createWebViewEvent (webView , url )));
161+
162+ view .mShouldOverrideUrlLoadingConditionVariable .close ();
163+ view .mShouldOverrideUrlLoadingConditionVariable .block (250 );
164+
165+ return view .mShouldOverrideUrlLoadingResult ;
166+ }
167+
146168 private void emitFinishEvent (WebView webView , String url ) {
147169 dispatchEvent (
148170 webView ,
@@ -180,6 +202,9 @@ private WritableMap createWebViewEvent(WebView webView, String url) {
180202 private static class ReactWebView extends WebView implements LifecycleEventListener {
181203 private @ Nullable String injectedJS ;
182204
205+ protected ConditionVariable mShouldOverrideUrlLoadingConditionVariable ;
206+ protected boolean mShouldOverrideUrlLoadingResult ;
207+
183208 /**
184209 * WebView must be created with an context of the current activity
185210 *
@@ -189,6 +214,7 @@ private static class ReactWebView extends WebView implements LifecycleEventListe
189214 */
190215 public ReactWebView (ThemedReactContext reactContext ) {
191216 super (reactContext );
217+ mShouldOverrideUrlLoadingConditionVariable = new ConditionVariable ();
192218 }
193219
194220 @ Override
@@ -222,6 +248,11 @@ private void cleanupCallbacksAndDestroy() {
222248 setWebViewClient (null );
223249 destroy ();
224250 }
251+
252+ private void shouldOverrideWithResult (ReadableArray args ) {
253+ this .mShouldOverrideUrlLoadingResult = args .getBoolean (0 );
254+ this .mShouldOverrideUrlLoadingConditionVariable .open ();
255+ }
225256 }
226257
227258 public ReactWebViewManager () {
@@ -342,7 +373,8 @@ protected void addEventEmitters(ThemedReactContext reactContext, WebView view) {
342373 return MapBuilder .of (
343374 "goBack" , COMMAND_GO_BACK ,
344375 "goForward" , COMMAND_GO_FORWARD ,
345- "reload" , COMMAND_RELOAD );
376+ "reload" , COMMAND_RELOAD ,
377+ "shouldOverrideWithResult" , COMMAND_SHOULD_OVERRIDE_WITH_RESULT );
346378 }
347379
348380 @ Override
@@ -357,6 +389,9 @@ public void receiveCommand(WebView root, int commandId, @Nullable ReadableArray
357389 case COMMAND_RELOAD :
358390 root .reload ();
359391 break ;
392+ case COMMAND_SHOULD_OVERRIDE_WITH_RESULT :
393+ ((ReactWebView ) root ).shouldOverrideWithResult (args );
394+ break ;
360395 }
361396 }
362397
@@ -366,4 +401,11 @@ public void onDropViewInstance(WebView webView) {
366401 ((ThemedReactContext ) webView .getContext ()).removeLifecycleEventListener ((ReactWebView ) webView );
367402 ((ReactWebView ) webView ).cleanupCallbacksAndDestroy ();
368403 }
404+
405+ @ Override
406+ public @ Nullable Map getExportedCustomDirectEventTypeConstants () {
407+ return MapBuilder .builder ()
408+ .put ("topShouldOverrideUrlLoading" , MapBuilder .of ("registrationName" , "onShouldOverrideUrlLoading" ))
409+ .build ();
410+ }
369411}
0 commit comments