Commit fe32dfb3 authored by Jinsuk Kim's avatar Jinsuk Kim Committed by Commit Bot

Android: Factor Tab reparenting job out of Tab

Tab reparenting task is used for custom tab or in multi window mode
to move a Tab object from an activity to another. This CL refactors
it into its own per-tab class to drive the task.

Bug: 995903

Change-Id: I5d9565765902a5669fdd9cb2c3b7439228a53598
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1829618
Commit-Queue: Jinsuk Kim <jinsukkim@chromium.org>
Reviewed-by: default avatarYusuf Ozuysal <yusufo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#707160}
parent 8cc5a4d4
...@@ -2707,6 +2707,7 @@ generate_jni("chrome_jni_headers") { ...@@ -2707,6 +2707,7 @@ generate_jni("chrome_jni_headers") {
"java/src/org/chromium/chrome/browser/tab/TabState.java", "java/src/org/chromium/chrome/browser/tab/TabState.java",
"java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java", "java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java",
"java/src/org/chromium/chrome/browser/tab/TrustedCdn.java", "java/src/org/chromium/chrome/browser/tab/TrustedCdn.java",
"java/src/org/chromium/chrome/browser/tab_activity_glue/ReparentingTask.java",
"java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java", "java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java",
"java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java", "java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java",
"java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java", "java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java",
......
...@@ -402,6 +402,7 @@ chrome_java_sources = [ ...@@ -402,6 +402,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/customtabs/NavigationInfoCaptureTrigger.java", "java/src/org/chromium/chrome/browser/customtabs/NavigationInfoCaptureTrigger.java",
"java/src/org/chromium/chrome/browser/customtabs/PageLoadMetricsObserver.java", "java/src/org/chromium/chrome/browser/customtabs/PageLoadMetricsObserver.java",
"java/src/org/chromium/chrome/browser/customtabs/PaymentHandlerActivity.java", "java/src/org/chromium/chrome/browser/customtabs/PaymentHandlerActivity.java",
"java/src/org/chromium/chrome/browser/customtabs/ReparentingTaskProvider.java",
"java/src/org/chromium/chrome/browser/customtabs/RequestThrottler.java", "java/src/org/chromium/chrome/browser/customtabs/RequestThrottler.java",
"java/src/org/chromium/chrome/browser/customtabs/SeparateTaskCustomTabActivity.java", "java/src/org/chromium/chrome/browser/customtabs/SeparateTaskCustomTabActivity.java",
"java/src/org/chromium/chrome/browser/customtabs/SeparateTaskCustomTabActivity0.java", "java/src/org/chromium/chrome/browser/customtabs/SeparateTaskCustomTabActivity0.java",
...@@ -1616,6 +1617,7 @@ chrome_java_sources = [ ...@@ -1616,6 +1617,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/tabmodel/document/AsyncTabCreationParams.java", "java/src/org/chromium/chrome/browser/tabmodel/document/AsyncTabCreationParams.java",
"java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java", "java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java",
"java/src/org/chromium/chrome/browser/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java", "java/src/org/chromium/chrome/browser/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java",
"java/src/org/chromium/chrome/browser/tab_activity_glue/ReparentingTask.java",
"java/src/org/chromium/chrome/browser/tab_activity_glue/TabDelegateFactoryImpl.java", "java/src/org/chromium/chrome/browser/tab_activity_glue/TabDelegateFactoryImpl.java",
"java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java", "java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java",
"java/src/org/chromium/chrome/browser/tasks/EngagementTimeUtil.java", "java/src/org/chromium/chrome/browser/tasks/EngagementTimeUtil.java",
......
...@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.tab.EmptyTabObserver; ...@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.tab.EmptyTabObserver;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabBuilder; import org.chromium.chrome.browser.tab.TabBuilder;
import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.tab.TabObserver;
import org.chromium.chrome.browser.tab_activity_glue.ReparentingTask;
import org.chromium.chrome.browser.tabmodel.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabLaunchType;
import org.chromium.chrome.browser.util.UrlUtilities; import org.chromium.chrome.browser.util.UrlUtilities;
import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.LoadUrlParams;
...@@ -126,7 +127,7 @@ public class HiddenTabHolder { ...@@ -126,7 +127,7 @@ public class HiddenTabHolder {
int width = bounds.right - bounds.left; int width = bounds.right - bounds.left;
int height = bounds.bottom - bounds.top; int height = bounds.bottom - bounds.top;
tab.getWebContents().setSize(width, height); tab.getWebContents().setSize(width, height);
tab.detach(); ReparentingTask.detach(tab);
return tab; return tab;
} }
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.customtabs;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab_activity_glue.ReparentingTask;
import javax.inject.Inject;
/**
* Provides {@link ReparentingTask} object to CustomTabActivityController.
* Makes the target class test-friendly by allowing for mock injection.
*/
public class ReparentingTaskProvider {
@Inject
public ReparentingTaskProvider() {}
public ReparentingTask get(Tab tab) {
return ReparentingTask.from(tab);
}
}
...@@ -33,6 +33,7 @@ import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy; ...@@ -33,6 +33,7 @@ import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy;
import org.chromium.chrome.browser.customtabs.CustomTabsConnection; import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
import org.chromium.chrome.browser.customtabs.FirstMeaningfulPaintObserver; import org.chromium.chrome.browser.customtabs.FirstMeaningfulPaintObserver;
import org.chromium.chrome.browser.customtabs.PageLoadMetricsObserver; import org.chromium.chrome.browser.customtabs.PageLoadMetricsObserver;
import org.chromium.chrome.browser.customtabs.ReparentingTaskProvider;
import org.chromium.chrome.browser.dependency_injection.ActivityScope; import org.chromium.chrome.browser.dependency_injection.ActivityScope;
import org.chromium.chrome.browser.init.StartupTabPreloader; import org.chromium.chrome.browser.init.StartupTabPreloader;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
...@@ -97,6 +98,7 @@ public class CustomTabActivityTabController implements InflationObserver, Native ...@@ -97,6 +98,7 @@ public class CustomTabActivityTabController implements InflationObserver, Native
private final ActivityTabProvider mActivityTabProvider; private final ActivityTabProvider mActivityTabProvider;
private final CustomTabActivityTabProvider mTabProvider; private final CustomTabActivityTabProvider mTabProvider;
private final StartupTabPreloader mStartupTabPreloader; private final StartupTabPreloader mStartupTabPreloader;
private final ReparentingTaskProvider mReparentingTaskProvider;
@Nullable @Nullable
private final CustomTabsSessionToken mSession; private final CustomTabsSessionToken mSession;
...@@ -120,7 +122,8 @@ public class CustomTabActivityTabController implements InflationObserver, Native ...@@ -120,7 +122,8 @@ public class CustomTabActivityTabController implements InflationObserver, Native
CustomTabTabPersistencePolicy persistencePolicy, CustomTabActivityTabFactory tabFactory, CustomTabTabPersistencePolicy persistencePolicy, CustomTabActivityTabFactory tabFactory,
Lazy<CustomTabObserver> customTabObserver, WebContentsFactory webContentsFactory, Lazy<CustomTabObserver> customTabObserver, WebContentsFactory webContentsFactory,
CustomTabNavigationEventObserver tabNavigationEventObserver, CustomTabNavigationEventObserver tabNavigationEventObserver,
CustomTabActivityTabProvider tabProvider, StartupTabPreloader startupTabPreloader) { CustomTabActivityTabProvider tabProvider, StartupTabPreloader startupTabPreloader,
ReparentingTaskProvider reparentingTaskProvider) {
mCustomTabDelegateFactory = customTabDelegateFactory; mCustomTabDelegateFactory = customTabDelegateFactory;
mActivity = activity; mActivity = activity;
mConnection = connection; mConnection = connection;
...@@ -136,6 +139,7 @@ public class CustomTabActivityTabController implements InflationObserver, Native ...@@ -136,6 +139,7 @@ public class CustomTabActivityTabController implements InflationObserver, Native
mActivityTabProvider = activityTabProvider; mActivityTabProvider = activityTabProvider;
mTabProvider = tabProvider; mTabProvider = tabProvider;
mStartupTabPreloader = startupTabPreloader; mStartupTabPreloader = startupTabPreloader;
mReparentingTaskProvider = reparentingTaskProvider;
mSession = mIntentDataProvider.getSession(); mSession = mIntentDataProvider.getSession();
mIntent = mIntentDataProvider.getIntent(); mIntent = mIntentDataProvider.getIntent();
...@@ -166,7 +170,8 @@ public class CustomTabActivityTabController implements InflationObserver, Native ...@@ -166,7 +170,8 @@ public class CustomTabActivityTabController implements InflationObserver, Native
return; return;
} }
mTabProvider.removeTab(); mTabProvider.removeTab();
tab.detachAndStartReparenting(intent, startActivityOptions, finishCallback); mReparentingTaskProvider.get(tab).begin(
mActivity, intent, startActivityOptions, finishCallback);
} }
/** /**
...@@ -311,7 +316,7 @@ public class CustomTabActivityTabController implements InflationObserver, Native ...@@ -311,7 +316,7 @@ public class CustomTabActivityTabController implements InflationObserver, Native
if (mode == TabCreationMode.HIDDEN) { if (mode == TabCreationMode.HIDDEN) {
TabReparentingParams params = TabReparentingParams params =
(TabReparentingParams) AsyncTabParamsManager.remove(tab.getId()); (TabReparentingParams) AsyncTabParamsManager.remove(tab.getId());
tab.attachAndFinishReparenting(mActivity, mCustomTabDelegateFactory.get(), mReparentingTaskProvider.get(tab).finish(mActivity, mCustomTabDelegateFactory.get(),
(params == null ? null : params.getFinalizeCallback())); (params == null ? null : params.getFinalizeCallback()));
} }
......
...@@ -5,14 +5,15 @@ ...@@ -5,14 +5,15 @@
package org.chromium.chrome.browser.customtabs.dependency_injection; package org.chromium.chrome.browser.customtabs.dependency_injection;
import org.chromium.chrome.browser.browserservices.trustedwebactivityui.TrustedWebActivityCoordinator; import org.chromium.chrome.browser.browserservices.trustedwebactivityui.TrustedWebActivityCoordinator;
import org.chromium.chrome.browser.customtabs.CustomTabActivityClientConnectionKeeper;
import org.chromium.chrome.browser.browserservices.trustedwebactivityui.TwaFinishHandler; import org.chromium.chrome.browser.browserservices.trustedwebactivityui.TwaFinishHandler;
import org.chromium.chrome.browser.customtabs.CustomTabActivityClientConnectionKeeper;
import org.chromium.chrome.browser.customtabs.CustomTabActivityLifecycleUmaTracker; import org.chromium.chrome.browser.customtabs.CustomTabActivityLifecycleUmaTracker;
import org.chromium.chrome.browser.customtabs.CustomTabBottomBarDelegate; import org.chromium.chrome.browser.customtabs.CustomTabBottomBarDelegate;
import org.chromium.chrome.browser.customtabs.CustomTabCompositorContentInitializer; import org.chromium.chrome.browser.customtabs.CustomTabCompositorContentInitializer;
import org.chromium.chrome.browser.customtabs.CustomTabSessionHandler; import org.chromium.chrome.browser.customtabs.CustomTabSessionHandler;
import org.chromium.chrome.browser.customtabs.CustomTabStatusBarColorProvider; import org.chromium.chrome.browser.customtabs.CustomTabStatusBarColorProvider;
import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy; import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy;
import org.chromium.chrome.browser.customtabs.ReparentingTaskProvider;
import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController;
import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabController; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabController;
import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabFactory; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabFactory;
...@@ -54,5 +55,7 @@ public interface CustomTabActivityComponent extends ChromeActivityComponent { ...@@ -54,5 +55,7 @@ public interface CustomTabActivityComponent extends ChromeActivityComponent {
TwaFinishHandler resolveTwaFinishHandler(); TwaFinishHandler resolveTwaFinishHandler();
ImmersiveModeController resolveImmersiveModeController(); ImmersiveModeController resolveImmersiveModeController();
CustomTabTabPersistencePolicy resolveTabPersistencePolicy(); // For testing // For testing
CustomTabTabPersistencePolicy resolveTabPersistencePolicy();
ReparentingTaskProvider resolveReparentingTaskProvider();
} }
...@@ -26,6 +26,7 @@ import org.chromium.chrome.browser.lifecycle.Destroyable; ...@@ -26,6 +26,7 @@ import org.chromium.chrome.browser.lifecycle.Destroyable;
import org.chromium.chrome.browser.lifecycle.NativeInitObserver; import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver; import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab_activity_glue.ReparentingTask;
import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.util.AndroidTaskUtils; import org.chromium.chrome.browser.util.AndroidTaskUtils;
import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.util.FeatureUtilities;
...@@ -314,7 +315,7 @@ public class MultiInstanceManager ...@@ -314,7 +315,7 @@ public class MultiInstanceManager
if (intent == null) return; if (intent == null) return;
onMultiInstanceModeStarted(); onMultiInstanceModeStarted();
tab.detachAndStartReparenting(intent, ReparentingTask.from(tab).begin(mContext, intent,
mMultiWindowModeStateDispatcher.getOpenInOtherWindowActivityOptions(), null); mMultiWindowModeStateDispatcher.getOpenInOtherWindowActivityOptions(), null);
} }
} }
...@@ -7,11 +7,7 @@ package org.chromium.chrome.browser.tab; ...@@ -7,11 +7,7 @@ package org.chromium.chrome.browser.tab;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.graphics.Rect; import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Browser;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.View.OnAttachStateChangeListener; import android.view.View.OnAttachStateChangeListener;
...@@ -33,14 +29,11 @@ import org.chromium.base.annotations.CalledByNative; ...@@ -33,14 +29,11 @@ import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.ChromeVersionInfo;
import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.WarmupManager; import org.chromium.chrome.browser.WarmupManager;
import org.chromium.chrome.browser.WebContentsFactory; import org.chromium.chrome.browser.WebContentsFactory;
import org.chromium.chrome.browser.content.ContentUtils; import org.chromium.chrome.browser.content.ContentUtils;
import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator; import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator;
import org.chromium.chrome.browser.document.ChromeLauncherActivity;
import org.chromium.chrome.browser.fullscreen.FullscreenOptions; import org.chromium.chrome.browser.fullscreen.FullscreenOptions;
import org.chromium.chrome.browser.native_page.FrozenNativePage; import org.chromium.chrome.browser.native_page.FrozenNativePage;
import org.chromium.chrome.browser.native_page.NativePage; import org.chromium.chrome.browser.native_page.NativePage;
...@@ -55,9 +48,7 @@ import org.chromium.chrome.browser.rlz.RevenueStats; ...@@ -55,9 +48,7 @@ import org.chromium.chrome.browser.rlz.RevenueStats;
import org.chromium.chrome.browser.ssl.SecurityStateModel; import org.chromium.chrome.browser.ssl.SecurityStateModel;
import org.chromium.chrome.browser.tab.TabState.WebContentsState; import org.chromium.chrome.browser.tab.TabState.WebContentsState;
import org.chromium.chrome.browser.tab.TabUma.TabCreationState; import org.chromium.chrome.browser.tab.TabUma.TabCreationState;
import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
import org.chromium.chrome.browser.tabmodel.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabLaunchType;
import org.chromium.chrome.browser.tabmodel.TabReparentingParams;
import org.chromium.chrome.browser.tabmodel.TabSelectionType; import org.chromium.chrome.browser.tabmodel.TabSelectionType;
import org.chromium.chrome.browser.util.UrlConstants; import org.chromium.chrome.browser.util.UrlConstants;
import org.chromium.chrome.browser.vr.VrModuleProvider; import org.chromium.chrome.browser.vr.VrModuleProvider;
...@@ -900,125 +891,30 @@ public class Tab { ...@@ -900,125 +891,30 @@ public class Tab {
} }
/** /**
* Begins the tab reparenting process. Detaches the tab from its current activity and fires * Set {@link TabDelegateFactory} instance and updates the references.
* an Intent to reparent the tab into its new host activity. * @param factory TabDelegateFactory instance.
*
* @param intent An optional intent with the desired component, flags, or extras to use when
* launching the new host activity. This intent's URI and action will be
* overriden. This may be null if no intent customization is needed.
* @param startActivityOptions Options to pass to {@link Activity#startActivity(Intent, Bundle)}
* @param finalizeCallback A callback that will be called after the tab is attached to the new
* host activity in {@link #attachAndFinishReparenting}.
* @return Whether reparenting succeeded. If false, the tab was not removed and the intent was
* not fired.
*/
public boolean detachAndStartReparenting(Intent intent, Bundle startActivityOptions,
Runnable finalizeCallback) {
ChromeActivity activity = getActivity();
if (activity == null) return false;
if (intent == null) intent = new Intent();
if (intent.getComponent() == null) {
intent.setClass(mThemedApplicationContext, ChromeLauncherActivity.class);
}
intent.setAction(Intent.ACTION_VIEW);
if (TextUtils.isEmpty(intent.getDataString())) intent.setData(Uri.parse(getUrl()));
if (isIncognito()) {
intent.putExtra(Browser.EXTRA_APPLICATION_ID,
ContextUtils.getApplicationContext().getPackageName());
intent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true);
}
IntentHandler.addTrustedIntentExtras(intent);
if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_REPARENTING)) {
// Add the tab to AsyncTabParamsManager before removing it from the current model to
// ensure the global count of tabs is correct. See https://crbug.com/611806.
intent.putExtra(IntentHandler.EXTRA_TAB_ID, mId);
AsyncTabParamsManager.add(
mId, new TabReparentingParams(this, intent, finalizeCallback));
detach();
}
activity.startActivity(intent, startActivityOptions);
return true;
}
/**
* Detaches a tab from its current activity if any.
*
* In details, this function:
* - Removes the tab from its current {@link TabModelSelector}, effectively severing
* the {@link Activity} to {@link Tab} link.
*/
public void detach() {
// TODO(yusufo): We can't call updateWindowAndroid here and set mWindowAndroid to null
// because many code paths (including navigation) expect the tab to always be associated
// with an activity, and will crash. crbug.com/657007
WebContents webContents = getWebContents();
if (webContents != null) webContents.setTopLevelNativeWindow(null);
// TabModelSelector of this Tab, if present, gets notified to remove the tab from
// the TabModel it belonged to.
for (TabObserver observer : mObservers) {
observer.onActivityAttachmentChanged(this, false);
}
}
/**
* Finishes the tab reparenting process. Attaches the tab to the new activity, and updates the
* tab and related objects to reference the new activity. This updates many delegates inside the
* tab and {@link WebContents} both on java and native sides.
*
* @param activity The new activity this tab should be associated with.
* @param tabDelegateFactory The new delegate factory this tab should be using.
* @param finalizeCallback A Callback to be called after the Tab has been reparented.
*/
public void attachAndFinishReparenting(ChromeActivity activity,
TabDelegateFactory tabDelegateFactory,
@Nullable Runnable finalizeCallback) {
// TODO(yusufo): Share these calls with the construction related calls.
// crbug.com/590281
activity.getCompositorViewHolder().prepareForTabReparenting();
attach(activity, tabDelegateFactory);
mIsTabStateDirty = true;
if (finalizeCallback != null) finalizeCallback.run();
}
/**
* Attaches the tab to the new activity and updates the tab and related objects to reference the
* new activity. This updates many delegates inside the tab and {@link WebContents} both on
* java and native sides.
* TODO(ltian:) explore calling this for all types of tabs.
*
* @param activity The new activity this tab should be associated with.
* @param tabDelegateFactory The new delegate factory this tab should be using.
*/ */
public void attach(ChromeActivity activity, TabDelegateFactory tabDelegateFactory) { public void setDelegateFactory(TabDelegateFactory factory) {
assert isDetached();
updateWindowAndroid(activity.getWindowAndroid());
// Update the delegate factory, then recreate and propagate all delegates. // Update the delegate factory, then recreate and propagate all delegates.
mDelegateFactory = tabDelegateFactory; mDelegateFactory = factory;
mWebContentsDelegate = mDelegateFactory.createWebContentsDelegate(this);
// Reload the NativePage (if any), since the old NativePage has a reference to the old
// activity.
maybeShowNativePage(getUrl(), true);
assert mNativeTabAndroid != 0; mWebContentsDelegate = mDelegateFactory.createWebContentsDelegate(this);
TabJni.get().attachDetachedTab(mNativeTabAndroid, Tab.this);
if (getWebContents() != null) { if (getWebContents() != null) {
TabJni.get().updateDelegates(mNativeTabAndroid, Tab.this, mWebContentsDelegate, TabJni.get().updateDelegates(mNativeTabAndroid, Tab.this, mWebContentsDelegate,
new TabContextMenuPopulator( new TabContextMenuPopulator(
mDelegateFactory.createContextMenuPopulator(this), this)); mDelegateFactory.createContextMenuPopulator(this), this));
} }
}
for (TabObserver observer : mObservers) observer.onActivityAttachmentChanged(this, true); /**
* Notify observers of the new attachment state to activity.
* @param attached {@code true} if the tab gets attached.
*/
public void notifyActivityAttachmentChanged(boolean attached) {
for (TabObserver observer : mObservers) {
observer.onActivityAttachmentChanged(this, attached);
}
} }
/** /**
...@@ -1037,15 +933,16 @@ public class Tab { ...@@ -1037,15 +933,16 @@ public class Tab {
} }
/** /**
* @param tab {@link Tab} instance being checked.
* @return Whether the tab is detached from any Activity and its {@link WindowAndroid}. * @return Whether the tab is detached from any Activity and its {@link WindowAndroid}.
* Certain functionalities will not work until it is attached to an activity * Certain functionalities will not work until it is attached to an activity
* with {@link Tab#attachAndFinishReparenting}. * with {@link ReparentingTask#finish}.
*/ */
public boolean isDetached() { public static boolean isDetached(Tab tab) {
if (getWebContents() == null) return true; if (tab.getWebContents() == null) return true;
// Should get WindowAndroid from WebContents since the one from |getWindowAndroid()| // Should get WindowAndroid from WebContents since the one from |getWindowAndroid()|
// is always non-null even when the tab is in detached state. See the comment in |detach()|. // is always non-null even when the tab is in detached state. See the comment in |detach()|.
WindowAndroid window = getWebContents().getTopLevelNativeWindow(); WindowAndroid window = tab.getWebContents().getTopLevelNativeWindow();
if (window == null) return true; if (window == null) return true;
Activity activity = ContextUtils.activityFromContext(window.getContext().get()); Activity activity = ContextUtils.activityFromContext(window.getContext().get());
return !(activity instanceof ChromeActivity); return !(activity instanceof ChromeActivity);
...@@ -1170,7 +1067,7 @@ public class Tab { ...@@ -1170,7 +1067,7 @@ public class Tab {
mWebContentsDelegate = mDelegateFactory.createWebContentsDelegate(this); mWebContentsDelegate = mDelegateFactory.createWebContentsDelegate(this);
assert mNativeTabAndroid != 0; assert mNativeTabAndroid != 0;
TabJni.get().initWebContents(mNativeTabAndroid, Tab.this, mIncognito, isDetached(), TabJni.get().initWebContents(mNativeTabAndroid, Tab.this, mIncognito, isDetached(this),
webContents, mSourceTabId, mWebContentsDelegate, webContents, mSourceTabId, mWebContentsDelegate,
new TabContextMenuPopulator( new TabContextMenuPopulator(
mDelegateFactory.createContextMenuPopulator(this), this)); mDelegateFactory.createContextMenuPopulator(this), this));
...@@ -1194,11 +1091,11 @@ public class Tab { ...@@ -1194,11 +1091,11 @@ public class Tab {
* matches the URL. * matches the URL.
* @return True, if a native page was displayed for url. * @return True, if a native page was displayed for url.
*/ */
boolean maybeShowNativePage(String url, boolean forceReload) { public boolean maybeShowNativePage(String url, boolean forceReload) {
// While detached for reparenting we don't have an owning Activity, or TabModelSelector, // While detached for reparenting we don't have an owning Activity, or TabModelSelector,
// so we can't create the native page. The native page will be created once reparenting is // so we can't create the native page. The native page will be created once reparenting is
// completed. // completed.
if (isDetached()) return false; if (isDetached(this)) return false;
NativePage candidateForReuse = forceReload ? null : getNativePage(); NativePage candidateForReuse = forceReload ? null : getNativePage();
NativePage nativePage = NativePageFactory.createNativePageForURL( NativePage nativePage = NativePageFactory.createNativePageForURL(
url, candidateForReuse, this, getActivity()); url, candidateForReuse, this, getActivity());
...@@ -1883,6 +1780,5 @@ public class Tab { ...@@ -1883,6 +1780,5 @@ public class Tab {
void setActiveNavigationEntryTitleForUrl( void setActiveNavigationEntryTitleForUrl(
long nativeTabAndroid, Tab caller, String url, String title); long nativeTabAndroid, Tab caller, String url, String title);
void loadOriginalImage(long nativeTabAndroid, Tab caller); void loadOriginalImage(long nativeTabAndroid, Tab caller);
void attachDetachedTab(long nativeTabAndroid, Tab caller);
} }
} }
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.tab_activity_glue;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Browser;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import org.chromium.base.ContextUtils;
import org.chromium.base.UserData;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.document.ChromeLauncherActivity;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabDelegateFactory;
import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
import org.chromium.chrome.browser.tabmodel.TabReparentingParams;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.WindowAndroid;
/**
* Takes care of reparenting a Tab object from one Activity to another.
*/
public class ReparentingTask implements UserData {
private static final Class<ReparentingTask> USER_DATA_KEY = ReparentingTask.class;
private final Tab mTab;
/**
* @param tab {@link Tab} object.
* @return {@link ReparentingTask} object for a given {@link Tab}. Creates one
* if not present.
*/
public static ReparentingTask from(Tab tab) {
ReparentingTask reparentingTask = get(tab);
if (reparentingTask == null) {
reparentingTask =
tab.getUserDataHost().setUserData(USER_DATA_KEY, new ReparentingTask(tab));
}
return reparentingTask;
}
@Nullable
private static ReparentingTask get(Tab tab) {
return tab.getUserDataHost().getUserData(USER_DATA_KEY);
}
private ReparentingTask(Tab tab) {
mTab = tab;
}
/**
* Begins the tab reparenting process. Detaches the tab from its current activity and fires
* an Intent to reparent the tab into its new host activity.
*
* @param context {@link Context} object used to start a new activity.
* @param intent An optional intent with the desired component, flags, or extras to use when
* launching the new host activity. This intent's URI and action will be
* overridden. This may be null if no intent customization is needed.
* @param startActivityOptions Options to pass to {@link Activity#startActivity(Intent, Bundle)}
* @param finalizeCallback A callback that will be called after the tab is attached to the new
* host activity in {@link #attachAndFinishReparenting}.
* @return Whether reparenting succeeded. If false, the tab was not removed and the intent was
* not fired.
*/
public boolean begin(Context context, Intent intent, Bundle startActivityOptions,
Runnable finalizeCallback) {
if (intent == null) intent = new Intent();
if (intent.getComponent() == null) {
intent.setClass(mTab.getThemedApplicationContext(), ChromeLauncherActivity.class);
}
intent.setAction(Intent.ACTION_VIEW);
if (TextUtils.isEmpty(intent.getDataString())) intent.setData(Uri.parse(mTab.getUrl()));
if (mTab.isIncognito()) {
intent.putExtra(Browser.EXTRA_APPLICATION_ID,
ContextUtils.getApplicationContext().getPackageName());
intent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true);
}
IntentHandler.addTrustedIntentExtras(intent);
if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_REPARENTING)) {
// Add the tab to AsyncTabParamsManager before removing it from the current model to
// ensure the global count of tabs is correct. See https://crbug.com/611806.
intent.putExtra(IntentHandler.EXTRA_TAB_ID, mTab.getId());
AsyncTabParamsManager.add(
mTab.getId(), new TabReparentingParams(mTab, intent, finalizeCallback));
detach(mTab);
}
context.startActivity(intent, startActivityOptions);
return true;
}
/**
* Detaches a tab from its current activity if any.
*
* In details, this function:
* - Removes the tab from its current {@link TabModelSelector}, effectively severing
* the {@link Activity} to {@link Tab} link.
*/
public static void detach(Tab tab) {
// TODO(yusufo): We can't call tab.updateWindowAndroid that sets |mWindowAndroid| to null
// because many code paths (including navigation) expect the tab to always be associated
// with an activity, and will crash. crbug.com/657007
WebContents webContents = tab.getWebContents();
if (webContents != null) webContents.setTopLevelNativeWindow(null);
// TabModelSelector of this Tab, if present, gets notified to remove the tab from
// the TabModel it belonged to.
tab.notifyActivityAttachmentChanged(false);
}
/**
* Finishes the tab reparenting process. Attaches this tab to a new activity, and updates
* the tab and related objects to reference it. This updates many delegates inside the tab
* and {@link WebContents} both on java and native sides.
*
* @param activity A new {@link ChromeActivity} to attach this Tab instance to.
* @param tabDelegateFactory The new delegate factory this tab should be using.
* @param finalizeCallback A Callback to be called after the Tab has been reparented.
*/
public void finish(ChromeActivity activity, TabDelegateFactory tabDelegateFactory,
@Nullable Runnable finalizeCallback) {
activity.getCompositorViewHolder().prepareForTabReparenting();
attach(activity.getWindowAndroid(), tabDelegateFactory);
mTab.setIsTabStateDirty(true);
if (finalizeCallback != null) finalizeCallback.run();
}
/**
* Attaches the tab to the new activity and updates the tab and related objects to reference the
* new activity. This updates many delegates inside the tab and {@link WebContents} both on
* java and native sides.
*
* @param window A new {@link WindowAndroid} to attach the tab to.
* @param activity The new activity this tab should be associated with.
* @param tabDelegateFactory The new delegate factory this tab should be using.
*/
private void attach(WindowAndroid window, TabDelegateFactory tabDelegateFactory) {
assert Tab.isDetached(mTab);
mTab.updateWindowAndroid(window);
mTab.setDelegateFactory(tabDelegateFactory);
// Reload the NativePage (if any), since the old NativePage has a reference to the old
// activity.
mTab.maybeShowNativePage(mTab.getUrl(), true);
ReparentingTaskJni.get().attachTab(mTab.getWebContents());
mTab.notifyActivityAttachmentChanged(true);
}
@NativeMethods
interface Natives {
void attachTab(WebContents webContents);
}
}
...@@ -23,6 +23,7 @@ import org.chromium.chrome.browser.tab.TabDelegateFactory; ...@@ -23,6 +23,7 @@ import org.chromium.chrome.browser.tab.TabDelegateFactory;
import org.chromium.chrome.browser.tab.TabParentIntent; import org.chromium.chrome.browser.tab.TabParentIntent;
import org.chromium.chrome.browser.tab.TabRedirectHandler; import org.chromium.chrome.browser.tab.TabRedirectHandler;
import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tab.TabState;
import org.chromium.chrome.browser.tab_activity_glue.ReparentingTask;
import org.chromium.chrome.browser.tab_activity_glue.TabDelegateFactoryImpl; import org.chromium.chrome.browser.tab_activity_glue.TabDelegateFactoryImpl;
import org.chromium.chrome.browser.util.IntentUtils; import org.chromium.chrome.browser.util.IntentUtils;
import org.chromium.components.url_formatter.UrlFormatter; import org.chromium.components.url_formatter.UrlFormatter;
...@@ -122,7 +123,7 @@ public class ChromeTabCreator extends TabCreatorManager.TabCreator { ...@@ -122,7 +123,7 @@ public class ChromeTabCreator extends TabCreatorManager.TabCreator {
TabReparentingParams params = (TabReparentingParams) asyncParams; TabReparentingParams params = (TabReparentingParams) asyncParams;
tab = params.getTabToReparent(); tab = params.getTabToReparent();
tab.attachAndFinishReparenting( ReparentingTask.from(tab).finish(
mActivity, createDefaultTabDelegateFactory(), params.getFinalizeCallback()); mActivity, createDefaultTabDelegateFactory(), params.getFinalizeCallback());
} else if (asyncParams != null && asyncParams.getWebContents() != null) { } else if (asyncParams != null && asyncParams.getWebContents() != null) {
openInForeground = true; openInForeground = true;
......
...@@ -330,7 +330,7 @@ public class TabModelSelectorImpl extends TabModelSelectorBase implements TabMod ...@@ -330,7 +330,7 @@ public class TabModelSelectorImpl extends TabModelSelectorBase implements TabMod
TabModelImpl.startTabSwitchLatencyTiming(type); TabModelImpl.startTabSwitchLatencyTiming(type);
} }
if (mVisibleTab != null && mVisibleTab != tab && !mVisibleTab.needsReload()) { if (mVisibleTab != null && mVisibleTab != tab && !mVisibleTab.needsReload()) {
if (mVisibleTab.isInitialized() && !mVisibleTab.isDetached()) { if (mVisibleTab.isInitialized() && !Tab.isDetached(mVisibleTab)) {
// TODO(dtrainor): Once we figure out why we can't grab a snapshot from the current // TODO(dtrainor): Once we figure out why we can't grab a snapshot from the current
// tab when we have other tabs loading from external apps remove the checks for // tab when we have other tabs loading from external apps remove the checks for
// FROM_EXTERNAL_APP/FROM_NEW. // FROM_EXTERNAL_APP/FROM_NEW.
......
...@@ -42,6 +42,7 @@ import org.chromium.chrome.browser.customtabs.CustomTabNavigationEventObserver; ...@@ -42,6 +42,7 @@ import org.chromium.chrome.browser.customtabs.CustomTabNavigationEventObserver;
import org.chromium.chrome.browser.customtabs.CustomTabObserver; import org.chromium.chrome.browser.customtabs.CustomTabObserver;
import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy; import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy;
import org.chromium.chrome.browser.customtabs.CustomTabsConnection; import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
import org.chromium.chrome.browser.customtabs.ReparentingTaskProvider;
import org.chromium.chrome.browser.customtabs.shadows.ShadowExternalNavigationDelegateImpl; import org.chromium.chrome.browser.customtabs.shadows.ShadowExternalNavigationDelegateImpl;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
import org.chromium.chrome.browser.init.ChromeBrowserInitializer; import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
...@@ -49,6 +50,7 @@ import org.chromium.chrome.browser.init.StartupTabPreloader; ...@@ -49,6 +50,7 @@ import org.chromium.chrome.browser.init.StartupTabPreloader;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabObserverRegistrar; import org.chromium.chrome.browser.tab.TabObserverRegistrar;
import org.chromium.chrome.browser.tab_activity_glue.ReparentingTask;
import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager; import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl; import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
...@@ -69,6 +71,7 @@ public class CustomTabActivityContentTestEnvironment extends TestWatcher { ...@@ -69,6 +71,7 @@ public class CustomTabActivityContentTestEnvironment extends TestWatcher {
public final Intent intent = new Intent(); public final Intent intent = new Intent();
// clang-format off
@Mock public CustomTabDelegateFactory customTabDelegateFactory; @Mock public CustomTabDelegateFactory customTabDelegateFactory;
@Mock public ChromeActivity activity; @Mock public ChromeActivity activity;
@Mock public CustomTabsConnection connection; @Mock public CustomTabsConnection connection;
...@@ -85,13 +88,16 @@ public class CustomTabActivityContentTestEnvironment extends TestWatcher { ...@@ -85,13 +88,16 @@ public class CustomTabActivityContentTestEnvironment extends TestWatcher {
@Mock public CustomTabsSessionToken session; @Mock public CustomTabsSessionToken session;
@Mock public TabModelSelectorImpl tabModelSelector; @Mock public TabModelSelectorImpl tabModelSelector;
@Mock public TabModel tabModel; @Mock public TabModel tabModel;
@Mock public ReparentingTaskProvider reparentingTaskProvider;
@Mock public ReparentingTask reparentingTask;
@Mock public CustomTabNavigationEventObserver navigationEventObserver; @Mock public CustomTabNavigationEventObserver navigationEventObserver;
@Mock public CloseButtonNavigator closeButtonNavigator; @Mock public CloseButtonNavigator closeButtonNavigator;
@Mock public ToolbarManager toolbarManager; @Mock public ToolbarManager toolbarManager;
@Mock public ChromeBrowserInitializer browserInitializer; @Mock public ChromeBrowserInitializer browserInitializer;
@Mock public ChromeFullscreenManager fullscreenManager; @Mock public ChromeFullscreenManager fullscreenManager;
@Mock @Mock public StartupTabPreloader startupTabPreloader;
public StartupTabPreloader startupTabPreloader; // clang-format on
public final CustomTabActivityTabProvider tabProvider = new CustomTabActivityTabProvider(); public final CustomTabActivityTabProvider tabProvider = new CustomTabActivityTabProvider();
@Captor public ArgumentCaptor<ActivityTabObserver> activityTabObserverCaptor; @Captor public ArgumentCaptor<ActivityTabObserver> activityTabObserverCaptor;
...@@ -121,7 +127,7 @@ public class CustomTabActivityContentTestEnvironment extends TestWatcher { ...@@ -121,7 +127,7 @@ public class CustomTabActivityContentTestEnvironment extends TestWatcher {
when(toolbarManager.back()).thenReturn(null); when(toolbarManager.back()).thenReturn(null);
when(startupTabPreloader.takeTabIfMatchingOrDestroy(any(), anyInt())).thenReturn(null); when(startupTabPreloader.takeTabIfMatchingOrDestroy(any(), anyInt())).thenReturn(null);
when(reparentingTaskProvider.get(any())).thenReturn(reparentingTask);
doNothing().when(activityTabProvider).addObserverAndTrigger( doNothing().when(activityTabProvider).addObserverAndTrigger(
activityTabObserverCaptor.capture()); activityTabObserverCaptor.capture());
} }
...@@ -134,18 +140,15 @@ public class CustomTabActivityContentTestEnvironment extends TestWatcher { ...@@ -134,18 +140,15 @@ public class CustomTabActivityContentTestEnvironment extends TestWatcher {
ShadowExternalNavigationDelegateImpl.setWillChromeHandleIntent(false); ShadowExternalNavigationDelegateImpl.setWillChromeHandleIntent(false);
} }
// clang-format off
public CustomTabActivityTabController createTabController() { public CustomTabActivityTabController createTabController() {
return new CustomTabActivityTabController(activity, return new CustomTabActivityTabController(activity, () -> customTabDelegateFactory,
()
-> customTabDelegateFactory,
connection, intentDataProvider, activityTabProvider, tabObserverRegistrar, connection, intentDataProvider, activityTabProvider, tabObserverRegistrar,
() () -> compositorViewHolder, lifecycleDispatcher, warmupManager,
-> compositorViewHolder, tabPersistencePolicy, tabFactory, () -> customTabObserver, webContentsFactory,
lifecycleDispatcher, warmupManager, tabPersistencePolicy, tabFactory, navigationEventObserver, tabProvider, startupTabPreloader, reparentingTaskProvider);
()
-> customTabObserver,
webContentsFactory, navigationEventObserver, tabProvider, startupTabPreloader);
} }
// clang-format on
public CustomTabActivityNavigationController createNavigationController( public CustomTabActivityNavigationController createNavigationController(
CustomTabActivityTabController tabController) { CustomTabActivityTabController tabController) {
......
...@@ -126,7 +126,7 @@ public class CustomTabActivityTabControllerTest { ...@@ -126,7 +126,7 @@ public class CustomTabActivityTabControllerTest {
public void finishesReparentingHiddenTab() { public void finishesReparentingHiddenTab() {
Tab hiddenTab = env.prepareHiddenTab(); Tab hiddenTab = env.prepareHiddenTab();
env.reachNativeInit(mTabController); env.reachNativeInit(mTabController);
verify(hiddenTab).attachAndFinishReparenting(any(), any(), any()); verify(env.reparentingTaskProvider.get(hiddenTab)).finish(any(), any(), any());
} }
@Test @Test
......
...@@ -2530,6 +2530,7 @@ jumbo_static_library("browser") { ...@@ -2530,6 +2530,7 @@ jumbo_static_library("browser") {
"android/rappor/rappor_service_bridge.cc", "android/rappor/rappor_service_bridge.cc",
"android/recently_closed_tabs_bridge.cc", "android/recently_closed_tabs_bridge.cc",
"android/recently_closed_tabs_bridge.h", "android/recently_closed_tabs_bridge.h",
"android/reparenting_task.cc",
"android/resource_id.h", "android/resource_id.h",
"android/resource_mapper.cc", "android/resource_mapper.cc",
"android/resource_mapper.h", "android/resource_mapper.h",
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/android/chrome_jni_headers/ReparentingTask_jni.h"
#include "chrome/browser/android/background_tab_manager.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/web_contents.h"
using base::android::JavaParamRef;
using chrome::android::BackgroundTabManager;
using content::WebContents;
static void JNI_ReparentingTask_AttachTab(
JNIEnv* env,
const JavaParamRef<jobject>& jweb_contents) {
auto* background_tab_manager = BackgroundTabManager::GetInstance();
auto* web_contents = content::WebContents::FromJavaWebContents(jweb_contents);
if (background_tab_manager->IsBackgroundTab(web_contents)) {
Profile* profile = background_tab_manager->GetProfile();
background_tab_manager->CommitHistory(HistoryServiceFactory::GetForProfile(
profile, ServiceAccessType::IMPLICIT_ACCESS));
background_tab_manager->UnregisterBackgroundTab();
}
}
...@@ -440,19 +440,6 @@ void TabAndroid::LoadOriginalImage(JNIEnv* env, ...@@ -440,19 +440,6 @@ void TabAndroid::LoadOriginalImage(JNIEnv* env,
renderer->RequestReloadImageForContextNode(); renderer->RequestReloadImageForContextNode();
} }
void TabAndroid::AttachDetachedTab(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) {
BackgroundTabManager* background_tab_manager =
BackgroundTabManager::GetInstance();
if (background_tab_manager->IsBackgroundTab(web_contents())) {
Profile* profile = background_tab_manager->GetProfile();
background_tab_manager->CommitHistory(HistoryServiceFactory::GetForProfile(
profile, ServiceAccessType::IMPLICIT_ACCESS));
background_tab_manager->UnregisterBackgroundTab();
}
}
scoped_refptr<content::DevToolsAgentHost> TabAndroid::GetDevToolsAgentHost() { scoped_refptr<content::DevToolsAgentHost> TabAndroid::GetDevToolsAgentHost() {
return devtools_host_; return devtools_host_;
} }
......
...@@ -173,8 +173,6 @@ class TabAndroid { ...@@ -173,8 +173,6 @@ class TabAndroid {
void SetDevToolsAgentHost(scoped_refptr<content::DevToolsAgentHost> host); void SetDevToolsAgentHost(scoped_refptr<content::DevToolsAgentHost> host);
void AttachDetachedTab(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
private: private:
JavaObjectWeakGlobalRef weak_java_tab_; JavaObjectWeakGlobalRef weak_java_tab_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment