1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.chrome.browser.gesturenav;
6 
7 import android.os.Handler;
8 
9 import org.chromium.base.Function;
10 import org.chromium.chrome.browser.tab.Tab;
11 import org.chromium.chrome.browser.tab.TabAssociatedApp;
12 
13 /**
14  * Implementation of {@link NavigationHandler#ActionDelegate} that works with
15  * native/rendered pages in tabbed mode. Uses interface methods of {@link Tab}
16  * to implement navigation.
17  */
18 public class TabbedActionDelegate implements NavigationHandler.ActionDelegate {
19     private final Tab mTab;
20     private final Handler mHandler = new Handler();
21     private final Function<Tab, Boolean> mBackShouldCloseTab;
22     private final Runnable mOnBackPressed;
23 
TabbedActionDelegate( Tab tab, Function<Tab, Boolean> backShouldCloseTab, Runnable onBackPressed)24     public TabbedActionDelegate(
25             Tab tab, Function<Tab, Boolean> backShouldCloseTab, Runnable onBackPressed) {
26         mTab = tab;
27         mBackShouldCloseTab = backShouldCloseTab;
28         mOnBackPressed = onBackPressed;
29     }
30 
31     @Override
canNavigate(boolean forward)32     public boolean canNavigate(boolean forward) {
33         return forward ? mTab.canGoForward() : true;
34     }
35 
36     @Override
navigate(boolean forward)37     public void navigate(boolean forward) {
38         if (forward) {
39             mTab.goForward();
40         } else {
41             // Perform back action at the next UI thread execution. The back action can
42             // potentially close the tab we're running on, which causes use-after-destroy
43             // exception if the closing operation is performed synchronously.
44             mHandler.post(mOnBackPressed);
45         }
46     }
47 
48     @Override
willBackCloseTab()49     public boolean willBackCloseTab() {
50         return !mTab.canGoBack() && mBackShouldCloseTab.apply(mTab);
51     }
52 
53     @Override
willBackExitApp()54     public boolean willBackExitApp() {
55         return !mTab.canGoBack()
56                 && (!mBackShouldCloseTab.apply(mTab)
57                         || TabAssociatedApp.isOpenedFromExternalApp(mTab));
58     }
59 }
60