blob: 71d4904b0649525f76cadbc12a68e4f4ce2b06f0 [file] [log] [blame]
// 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.weblayer_private;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.ContextThemeWrapper;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.components.browser_ui.styles.R;
import org.chromium.components.embedder_support.application.ClassLoaderContextWrapperFactory;
import org.chromium.weblayer_private.interfaces.BrowserFragmentArgs;
import org.chromium.weblayer_private.interfaces.IBrowser;
import org.chromium.weblayer_private.interfaces.IBrowserFragment;
import org.chromium.weblayer_private.interfaces.IRemoteFragment;
import org.chromium.weblayer_private.interfaces.IRemoteFragmentClient;
import org.chromium.weblayer_private.interfaces.StrictModeWorkaround;
/**
* Implementation of RemoteFragmentImpl which forwards logic to BrowserImpl.
*/
public class BrowserFragmentImpl extends FragmentHostingRemoteFragmentImpl {
private static int sResumedCount;
private static long sSessionStartTimeMs;
private final ProfileImpl mProfile;
private final String mPersistenceId;
private BrowserImpl mBrowser;
// The embedder's original context object. Only use this to resolve resource IDs provided by the
// embedder.
private Context mEmbedderActivityContext;
public BrowserFragmentImpl(
ProfileManager profileManager, IRemoteFragmentClient client, Bundle fragmentArgs) {
super(client);
mPersistenceId = fragmentArgs.getString(BrowserFragmentArgs.PERSISTENCE_ID);
String name = fragmentArgs.getString(BrowserFragmentArgs.PROFILE_NAME);
boolean isIncognito;
if (fragmentArgs.containsKey(BrowserFragmentArgs.IS_INCOGNITO)) {
isIncognito = fragmentArgs.getBoolean(BrowserFragmentArgs.IS_INCOGNITO, false);
} else {
isIncognito = "".equals(name);
}
mProfile = profileManager.getProfile(name, isIncognito);
}
@Override
public void onAttach(Context context) {
StrictModeWorkaround.apply();
super.onAttach(context);
mEmbedderActivityContext = context;
if (mBrowser != null) { // On first creation, onAttach is called before onCreate
mBrowser.onFragmentAttached(mEmbedderActivityContext,
new FragmentWindowAndroid(getWebLayerContext(), this));
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
StrictModeWorkaround.apply();
super.onCreate(savedInstanceState);
// onCreate() is only called once
assert mBrowser == null;
// onCreate() is always called after onAttach(). onAttach() sets |getWebLayerContext()| and
// |mEmbedderContext|.
assert getWebLayerContext() != null;
assert mEmbedderActivityContext != null;
mBrowser = new BrowserImpl(mEmbedderActivityContext, mProfile, mPersistenceId,
savedInstanceState, new FragmentWindowAndroid(getWebLayerContext(), this));
}
@Override
public View onCreateView(ViewGroup container, Bundle savedInstanceState) {
StrictModeWorkaround.apply();
return mBrowser.getFragmentView();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
StrictModeWorkaround.apply();
mBrowser.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onRequestPermissionsResult(
int requestCode, String[] permissions, int[] grantResults) {
StrictModeWorkaround.apply();
mBrowser.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public void onDestroy() {
StrictModeWorkaround.apply();
super.onDestroy();
mBrowser.destroy();
mBrowser = null;
}
@Override
public void onDetach() {
StrictModeWorkaround.apply();
super.onDetach();
// mBrowser != null if fragment is retained, otherwise onDestroy is called first.
if (mBrowser != null) {
mBrowser.onFragmentDetached();
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
StrictModeWorkaround.apply();
mBrowser.onSaveInstanceState(outState);
super.onSaveInstanceState(outState);
}
@Override
public void onStart() {
super.onStart();
mBrowser.onFragmentStart();
}
@Override
public void onStop() {
super.onStop();
Activity activity = getActivity();
mBrowser.onFragmentStop(activity != null && activity.getChangingConfigurations() != 0);
}
@Override
public void onResume() {
super.onResume();
sResumedCount++;
if (sResumedCount == 1) sSessionStartTimeMs = SystemClock.uptimeMillis();
mBrowser.onFragmentResume();
}
@Override
public void onPause() {
super.onPause();
sResumedCount--;
if (sResumedCount == 0) {
long deltaMs = SystemClock.uptimeMillis() - sSessionStartTimeMs;
RecordHistogram.recordLongTimesHistogram("Session.TotalDuration", deltaMs);
}
mBrowser.onFragmentPause();
}
@Nullable
public BrowserImpl getBrowser() {
return mBrowser;
}
public IBrowserFragment asIBrowserFragment() {
return new IBrowserFragment.Stub() {
@Override
public IRemoteFragment asRemoteFragment() {
StrictModeWorkaround.apply();
return BrowserFragmentImpl.this;
}
@Override
public IBrowser getBrowser() {
StrictModeWorkaround.apply();
if (mBrowser == null) {
throw new RuntimeException("Browser is available only between"
+ " BrowserFragment's onCreate() and onDestroy().");
}
return mBrowser;
}
};
}
@Override
protected FragmentHostingRemoteFragmentImpl.RemoteFragmentContext createRemoteFragmentContext(
Context embedderContext) {
Context wrappedContext = ClassLoaderContextWrapperFactory.get(embedderContext);
Context themedContext = new ContextThemeWrapper(wrappedContext, R.style.Theme_BrowserUI);
return new FragmentHostingRemoteFragmentImpl.RemoteFragmentContext(themedContext);
}
}