/** * Ensures correctness of the visibilityDetermined() calls, that should be always preceded by * setInForeground(). */ @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @LargeTest @Feature({"ProcessManagement"}) public void testVisibilityDetermined() throws Exception { // Create a tab in foreground and wait until it is loaded. final Tab fgTab = ChromeApplication.getDocumentTabModelSelector() .getTabById(launchViaViewIntent(false, URL_1, "Page 1")); int initialNavigationPid = fgTab.getContentViewCore().getCurrentRenderProcessId(); // Ensure the following calls happened: // - FG - setInForeground(true) - when the tab is created in the foreground // - DETERMINED - visibilityDetermined() - after the initial navigation is committed assertEquals("FG;DETERMINED;", mBindingManager.getVisibilityCalls(initialNavigationPid)); // Navigate to about:version which requires a different renderer. getInstrumentation() .runOnMainSync( new Runnable() { @Override public void run() { fgTab.loadUrl(new LoadUrlParams(ABOUT_VERSION_PATH)); } }); ChromeTabUtils.waitForTabPageLoaded(fgTab, ABOUT_VERSION_PATH); int secondNavigationPid = fgTab.getContentViewCore().getCurrentRenderProcessId(); assertTrue(secondNavigationPid != initialNavigationPid); // Ensure the following calls happened: // - BG - setInForeground(false) - when the renderer is created for uncommited frame // - FG - setInForeground(true) - when the frame is swapped in on commit // - DETERMINED - visibilityDetermined() - after the navigation is committed assertEquals("BG;FG;DETERMINED;", mBindingManager.getVisibilityCalls(secondNavigationPid)); // Open a tab in the background and load it. final Tab bgTab = ChromeApplication.getDocumentTabModelSelector() .getTabById(launchViaLaunchDocumentInstanceInBackground(false, URL_2, "Page 2")); int bgNavigationPid = bgTab.getContentViewCore().getCurrentRenderProcessId(); // Ensure the following calls happened: // - BG - setInForeground(false) - when tab is created in the background // - DETERMINED - visibilityDetermined() - after the navigation is committed assertEquals("BG;DETERMINED;", mBindingManager.getVisibilityCalls(bgNavigationPid)); }
/** * Handle application level deferred startup tasks that can be lazily done after all the necessary * initialization has been completed. Any calls requiring network access should probably go here. */ @UiThread public void onDeferredStartupForApp() { if (mDeferredStartupComplete) return; ThreadUtils.assertOnUiThread(); long startDeferredStartupTime = SystemClock.uptimeMillis(); RecordHistogram.recordLongTimesHistogram( "UMA.Debug.EnableCrashUpload.DeferredStartUptime", startDeferredStartupTime - UmaUtils.getMainEntryPointTime(), TimeUnit.MILLISECONDS); mLocaleManager.recordStartupMetrics(); // Punt all tasks that may block the UI thread off onto a background thread. new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { try { TraceEvent.begin("ChromeBrowserInitializer.onDeferredStartup.doInBackground"); long asyncTaskStartTime = SystemClock.uptimeMillis(); boolean crashDumpDisabled = CommandLine.getInstance().hasSwitch(ChromeSwitches.DISABLE_CRASH_DUMP_UPLOAD); if (!crashDumpDisabled) { RecordHistogram.recordLongTimesHistogram( "UMA.Debug.EnableCrashUpload.Uptime2", asyncTaskStartTime - UmaUtils.getMainEntryPointTime(), TimeUnit.MILLISECONDS); PrivacyPreferencesManager.getInstance().enablePotentialCrashUploading(); MinidumpUploadService.tryUploadAllCrashDumps(mAppContext); } CrashFileManager crashFileManager = new CrashFileManager(mAppContext.getCacheDir()); crashFileManager.cleanOutAllNonFreshMinidumpFiles(); MinidumpUploadService.storeBreakpadUploadStatsInUma( ChromePreferenceManager.getInstance(mAppContext)); // Force a widget refresh in order to wake up any possible zombie widgets. // This is needed to ensure the right behavior when the process is suddenly // killed. BookmarkWidgetProvider.refreshAllWidgets(mAppContext); // Initialize whether or not precaching is enabled. PrecacheLauncher.updatePrecachingEnabled(mAppContext); if (CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_WEBAPK)) { WebApkVersionManager.updateWebApksIfNeeded(); } removeSnapshotDatabase(); cacheIsChromeDefaultBrowser(); RecordHistogram.recordLongTimesHistogram( "UMA.Debug.EnableCrashUpload.DeferredStartUpDurationAsync", SystemClock.uptimeMillis() - asyncTaskStartTime, TimeUnit.MILLISECONDS); return null; } finally { TraceEvent.end("ChromeBrowserInitializer.onDeferredStartup.doInBackground"); } } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); AfterStartupTaskUtils.setStartupComplete(); PartnerBrowserCustomizations.setOnInitializeAsyncFinished( new Runnable() { @Override public void run() { String homepageUrl = HomepageManager.getHomepageUri(mAppContext); LaunchMetrics.recordHomePageLaunchMetrics( HomepageManager.isHomepageEnabled(mAppContext), NewTabPage.isNTPUrl(homepageUrl), homepageUrl); } }); // TODO(aruslan): http://b/6397072 This will be moved elsewhere PartnerBookmarksShim.kickOffReading(mAppContext); PowerMonitor.create(mAppContext); ShareHelper.clearSharedImages(mAppContext); // Clear any media notifications that existed when Chrome was last killed. MediaCaptureNotificationService.clearMediaNotifications(mAppContext); startModerateBindingManagementIfNeeded(); recordKeyboardLocaleUma(); ChromeApplication application = (ChromeApplication) mAppContext; // Starts syncing with GSA. application.createGsaHelper().startSync(); application.initializeSharedClasses(); // Start or stop Physical Web PhysicalWeb.onChromeStart(application); mDeferredStartupComplete = true; RecordHistogram.recordLongTimesHistogram( "UMA.Debug.EnableCrashUpload.DeferredStartUpDuration", SystemClock.uptimeMillis() - startDeferredStartupTime, TimeUnit.MILLISECONDS); }
/** * Verifies that a renderer that crashes in foreground has the correct visibility when recreated. */ @LargeTest @Feature({"ProcessManagement"}) public void testCrashInForeground() throws Exception { // Create a tab in foreground and wait until it is loaded. final Tab tab = ChromeApplication.getDocumentTabModelSelector() .getTabById(launchViaViewIntent(false, URL_1, "Page 1")); // Kill the renderer and wait for the crash to be noted by the browser process. assertTrue( ChildProcessLauncher.crashProcessForTesting( tab.getContentViewCore().getCurrentRenderProcessId())); assertTrue( "Renderer crash wasn't noticed by the browser.", CriteriaHelper.pollForCriteria( new Criteria() { @Override public boolean isSatisfied() { return tab.getContentViewCore().getCurrentRenderProcessId() == 0; } })); // Reload the tab, respawning the renderer. getInstrumentation() .runOnMainSync( new Runnable() { @Override public void run() { tab.reload(); } }); // Wait until the process is spawned and its visibility is determined. assertTrue( "Process for the crashed tab was not respawned.", CriteriaHelper.pollForCriteria( new Criteria() { @Override public boolean isSatisfied() { return tab.getContentViewCore().getCurrentRenderProcessId() != 0; } })); assertTrue( "isInForeground() was not called for the process.", CriteriaHelper.pollForCriteria( new Criteria() { @Override public boolean isSatisfied() { return mBindingManager.wasSetInForegroundCalled( tab.getContentViewCore().getCurrentRenderProcessId()); } })); getInstrumentation() .runOnMainSync( new Runnable() { @Override public void run() { // Verify the visibility of the renderer. assertTrue( mBindingManager.isInForeground( tab.getContentViewCore().getCurrentRenderProcessId())); } }); }
/** * Verifies that the .setProcessInForeground() signal is called correctly as the tabs are created * and switched. */ @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @LargeTest @Feature({"ProcessManagement"}) public void testTabSwitching() throws Exception { // Create two tabs and wait until they are loaded, so that their renderers are around. final Tab[] tabs = new Tab[2]; final int[] tabIds = new int[2]; final DocumentTabModelSelector selector = ChromeApplication.getDocumentTabModelSelector(); tabIds[0] = launchViaViewIntent(false, URL_1, "Page 1"); tabIds[1] = launchViaLaunchDocumentInstanceInBackground(false, URL_2, "Page 2"); final TabModel tabModel = selector.getCurrentModel(); tabs[0] = selector.getTabById(tabIds[0]); tabs[1] = selector.getTabById(tabIds[1]); getInstrumentation() .runOnMainSync( new Runnable() { @Override public void run() { // Make sure that the renderers were spawned. assertTrue(tabs[0].getContentViewCore().getCurrentRenderProcessId() > 0); assertTrue(tabs[1].getContentViewCore().getCurrentRenderProcessId() > 0); // Verify that the renderer of the foreground tab was signalled as visible. assertTrue( mBindingManager.isInForeground( tabs[0].getContentViewCore().getCurrentRenderProcessId())); // Verify that the renderer of the tab loaded in background was signalled as not // visible. assertTrue( mBindingManager.isInBackground( tabs[1].getContentViewCore().getCurrentRenderProcessId())); } }); // Wait until the activity of tabs[1] is resumed. assertTrue( "Activity was not resumed.", CriteriaHelper.pollForCriteria( new Criteria() { @Override public boolean isSatisfied() { // Switch to the tab that crashed in background. // http://crbug.com/509866: TabModelUtils#setIndex() sometimes fails. So we need to // call it repeatedly. getInstrumentation() .runOnMainSync( new Runnable() { @Override public void run() { TabModelUtils.setIndex( tabModel, TabModelUtils.getTabIndexById(tabModel, tabs[1].getId())); } }); return ApplicationStatus.getStateForActivity(((DocumentTab) tabs[1]).getActivity()) == ActivityState.RESUMED; } })); // Verify that the renderer visibility was flipped. assertTrue( mBindingManager.isInBackground(tabs[0].getContentViewCore().getCurrentRenderProcessId())); assertTrue( mBindingManager.isInForeground(tabs[1].getContentViewCore().getCurrentRenderProcessId())); }