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") {
"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/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/TabModelObserverJniBridge.java",
"java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java",
......
......@@ -402,6 +402,7 @@ chrome_java_sources = [
"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/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/SeparateTaskCustomTabActivity.java",
"java/src/org/chromium/chrome/browser/customtabs/SeparateTaskCustomTabActivity0.java",
......@@ -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/TabDelegate.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/tasks/ReturnToChromeExperimentsUtil.java",
"java/src/org/chromium/chrome/browser/tasks/EngagementTimeUtil.java",
......
......@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.tab.EmptyTabObserver;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabBuilder;
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.util.UrlUtilities;
import org.chromium.content_public.browser.LoadUrlParams;
......@@ -126,7 +127,7 @@ public class HiddenTabHolder {
int width = bounds.right - bounds.left;
int height = bounds.bottom - bounds.top;
tab.getWebContents().setSize(width, height);
tab.detach();
ReparentingTask.detach(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;
import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
import org.chromium.chrome.browser.customtabs.FirstMeaningfulPaintObserver;
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.init.StartupTabPreloader;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
......@@ -97,6 +98,7 @@ public class CustomTabActivityTabController implements InflationObserver, Native
private final ActivityTabProvider mActivityTabProvider;
private final CustomTabActivityTabProvider mTabProvider;
private final StartupTabPreloader mStartupTabPreloader;
private final ReparentingTaskProvider mReparentingTaskProvider;
@Nullable
private final CustomTabsSessionToken mSession;
......@@ -120,7 +122,8 @@ public class CustomTabActivityTabController implements InflationObserver, Native
CustomTabTabPersistencePolicy persistencePolicy, CustomTabActivityTabFactory tabFactory,
Lazy<CustomTabObserver> customTabObserver, WebContentsFactory webContentsFactory,
CustomTabNavigationEventObserver tabNavigationEventObserver,
CustomTabActivityTabProvider tabProvider, StartupTabPreloader startupTabPreloader) {
CustomTabActivityTabProvider tabProvider, StartupTabPreloader startupTabPreloader,
ReparentingTaskProvider reparentingTaskProvider) {
mCustomTabDelegateFactory = customTabDelegateFactory;
mActivity = activity;
mConnection = connection;
......@@ -136,6 +139,7 @@ public class CustomTabActivityTabController implements InflationObserver, Native
mActivityTabProvider = activityTabProvider;
mTabProvider = tabProvider;
mStartupTabPreloader = startupTabPreloader;
mReparentingTaskProvider = reparentingTaskProvider;
mSession = mIntentDataProvider.getSession();
mIntent = mIntentDataProvider.getIntent();
......@@ -166,7 +170,8 @@ public class CustomTabActivityTabController implements InflationObserver, Native
return;
}
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
if (mode == TabCreationMode.HIDDEN) {
TabReparentingParams params =
(TabReparentingParams) AsyncTabParamsManager.remove(tab.getId());
tab.attachAndFinishReparenting(mActivity, mCustomTabDelegateFactory.get(),
mReparentingTaskProvider.get(tab).finish(mActivity, mCustomTabDelegateFactory.get(),
(params == null ? null : params.getFinalizeCallback()));
}
......
......@@ -5,14 +5,15 @@
package org.chromium.chrome.browser.customtabs.dependency_injection;
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.customtabs.CustomTabActivityClientConnectionKeeper;
import org.chromium.chrome.browser.customtabs.CustomTabActivityLifecycleUmaTracker;
import org.chromium.chrome.browser.customtabs.CustomTabBottomBarDelegate;
import org.chromium.chrome.browser.customtabs.CustomTabCompositorContentInitializer;
import org.chromium.chrome.browser.customtabs.CustomTabSessionHandler;
import org.chromium.chrome.browser.customtabs.CustomTabStatusBarColorProvider;
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.CustomTabActivityTabController;
import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabFactory;
......@@ -54,5 +55,7 @@ public interface CustomTabActivityComponent extends ChromeActivityComponent {
TwaFinishHandler resolveTwaFinishHandler();
ImmersiveModeController resolveImmersiveModeController();
CustomTabTabPersistencePolicy resolveTabPersistencePolicy(); // For testing
// For testing
CustomTabTabPersistencePolicy resolveTabPersistencePolicy();
ReparentingTaskProvider resolveReparentingTaskProvider();
}
......@@ -26,6 +26,7 @@ import org.chromium.chrome.browser.lifecycle.Destroyable;
import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver;
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.util.AndroidTaskUtils;
import org.chromium.chrome.browser.util.FeatureUtilities;
......@@ -314,7 +315,7 @@ public class MultiInstanceManager
if (intent == null) return;
onMultiInstanceModeStarted();
tab.detachAndStartReparenting(intent,
ReparentingTask.from(tab).begin(mContext, intent,
mMultiWindowModeStateDispatcher.getOpenInOtherWindowActivityOptions(), null);
}
}
// 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;
import org.chromium.chrome.browser.tab.TabParentIntent;
import org.chromium.chrome.browser.tab.TabRedirectHandler;
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.util.IntentUtils;
import org.chromium.components.url_formatter.UrlFormatter;
......@@ -122,7 +123,7 @@ public class ChromeTabCreator extends TabCreatorManager.TabCreator {
TabReparentingParams params = (TabReparentingParams) asyncParams;
tab = params.getTabToReparent();
tab.attachAndFinishReparenting(
ReparentingTask.from(tab).finish(
mActivity, createDefaultTabDelegateFactory(), params.getFinalizeCallback());
} else if (asyncParams != null && asyncParams.getWebContents() != null) {
openInForeground = true;
......
......@@ -330,7 +330,7 @@ public class TabModelSelectorImpl extends TabModelSelectorBase implements TabMod
TabModelImpl.startTabSwitchLatencyTiming(type);
}
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
// tab when we have other tabs loading from external apps remove the checks for
// FROM_EXTERNAL_APP/FROM_NEW.
......
......@@ -42,6 +42,7 @@ import org.chromium.chrome.browser.customtabs.CustomTabNavigationEventObserver;
import org.chromium.chrome.browser.customtabs.CustomTabObserver;
import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy;
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.fullscreen.ChromeFullscreenManager;
import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
......@@ -49,6 +50,7 @@ import org.chromium.chrome.browser.init.StartupTabPreloader;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.tab.Tab;
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.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
......@@ -69,6 +71,7 @@ public class CustomTabActivityContentTestEnvironment extends TestWatcher {
public final Intent intent = new Intent();
// clang-format off
@Mock public CustomTabDelegateFactory customTabDelegateFactory;
@Mock public ChromeActivity activity;
@Mock public CustomTabsConnection connection;
......@@ -85,13 +88,16 @@ public class CustomTabActivityContentTestEnvironment extends TestWatcher {
@Mock public CustomTabsSessionToken session;
@Mock public TabModelSelectorImpl tabModelSelector;
@Mock public TabModel tabModel;
@Mock public ReparentingTaskProvider reparentingTaskProvider;
@Mock public ReparentingTask reparentingTask;
@Mock public CustomTabNavigationEventObserver navigationEventObserver;
@Mock public CloseButtonNavigator closeButtonNavigator;
@Mock public ToolbarManager toolbarManager;
@Mock public ChromeBrowserInitializer browserInitializer;
@Mock public ChromeFullscreenManager fullscreenManager;
@Mock
public StartupTabPreloader startupTabPreloader;
@Mock public StartupTabPreloader startupTabPreloader;
// clang-format on
public final CustomTabActivityTabProvider tabProvider = new CustomTabActivityTabProvider();
@Captor public ArgumentCaptor<ActivityTabObserver> activityTabObserverCaptor;
......@@ -121,7 +127,7 @@ public class CustomTabActivityContentTestEnvironment extends TestWatcher {
when(toolbarManager.back()).thenReturn(null);
when(startupTabPreloader.takeTabIfMatchingOrDestroy(any(), anyInt())).thenReturn(null);
when(reparentingTaskProvider.get(any())).thenReturn(reparentingTask);
doNothing().when(activityTabProvider).addObserverAndTrigger(
activityTabObserverCaptor.capture());
}
......@@ -134,18 +140,15 @@ public class CustomTabActivityContentTestEnvironment extends TestWatcher {
ShadowExternalNavigationDelegateImpl.setWillChromeHandleIntent(false);
}
// clang-format off
public CustomTabActivityTabController createTabController() {
return new CustomTabActivityTabController(activity,
()
-> customTabDelegateFactory,
return new CustomTabActivityTabController(activity, () -> customTabDelegateFactory,
connection, intentDataProvider, activityTabProvider, tabObserverRegistrar,
()
-> compositorViewHolder,
lifecycleDispatcher, warmupManager, tabPersistencePolicy, tabFactory,
()
-> customTabObserver,
webContentsFactory, navigationEventObserver, tabProvider, startupTabPreloader);
() -> compositorViewHolder, lifecycleDispatcher, warmupManager,
tabPersistencePolicy, tabFactory, () -> customTabObserver, webContentsFactory,
navigationEventObserver, tabProvider, startupTabPreloader, reparentingTaskProvider);
}
// clang-format on
public CustomTabActivityNavigationController createNavigationController(
CustomTabActivityTabController tabController) {
......
......@@ -126,7 +126,7 @@ public class CustomTabActivityTabControllerTest {
public void finishesReparentingHiddenTab() {
Tab hiddenTab = env.prepareHiddenTab();
env.reachNativeInit(mTabController);
verify(hiddenTab).attachAndFinishReparenting(any(), any(), any());
verify(env.reparentingTaskProvider.get(hiddenTab)).finish(any(), any(), any());
}
@Test
......
......@@ -2530,6 +2530,7 @@ jumbo_static_library("browser") {
"android/rappor/rappor_service_bridge.cc",
"android/recently_closed_tabs_bridge.cc",
"android/recently_closed_tabs_bridge.h",
"android/reparenting_task.cc",
"android/resource_id.h",
"android/resource_mapper.cc",
"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,
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() {
return devtools_host_;
}
......
......@@ -173,8 +173,6 @@ class TabAndroid {
void SetDevToolsAgentHost(scoped_refptr<content::DevToolsAgentHost> host);
void AttachDetachedTab(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
private:
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