// Copyright 2012 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.content_shell_apk; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; import android.widget.Toast; import org.chromium.base.BaseSwitches; import org.chromium.base.CommandLine; import org.chromium.base.MemoryPressureListener; import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.ProcessInitException; import org.chromium.content.browser.BrowserStartupController; import org.chromium.content.browser.ContentViewCore; import org.chromium.content.browser.DeviceUtils; import org.chromium.content.common.ContentSwitches; import org.chromium.content_shell.Shell; import org.chromium.content_shell.ShellManager; import org.chromium.ui.base.ActivityWindowAndroid; import org.chromium.ui.base.WindowAndroid; /** * Activity for managing the Content Shell. */ public class ContentShellActivity extends Activity { public static final String COMMAND_LINE_FILE = "/data/local/tmp/content-shell-command-line"; private static final String TAG = "ContentShellActivity"; private static final String ACTIVE_SHELL_URL_KEY = "activeUrl"; public static final String COMMAND_LINE_ARGS_KEY = "commandLineArgs"; private ShellManager mShellManager; private WindowAndroid mWindowAndroid; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Initializing the command line must occur before loading the library. if (!CommandLine.isInitialized()) { CommandLine.initFromFile(COMMAND_LINE_FILE); String[] commandLineParams = getCommandLineParamsFromIntent(getIntent()); if (commandLineParams != null) { CommandLine.getInstance().appendSwitchesAndArguments(commandLineParams); } } waitForDebuggerIfNeeded(); DeviceUtils.addDeviceSpecificUserAgentSwitch(this); try { LibraryLoader.ensureInitialized(); } catch (ProcessInitException e) { Log.e(TAG, "ContentView initialization failed.", e); // Since the library failed to initialize nothing in the application // can work, so kill the whole application not just the activity System.exit(-1); return; } setContentView(R.layout.content_shell_activity); mShellManager = (ShellManager) findViewById(R.id.shell_container); mWindowAndroid = new ActivityWindowAndroid(this); mWindowAndroid.restoreInstanceState(savedInstanceState); mShellManager.setWindow(mWindowAndroid); String startupUrl = getUrlFromIntent(getIntent()); if (!TextUtils.isEmpty(startupUrl)) { mShellManager.setStartupUrl(Shell.sanitizeUrl(startupUrl)); } if (CommandLine.getInstance().hasSwitch(ContentSwitches.DUMP_RENDER_TREE)) { try { BrowserStartupController.get(this).startBrowserProcessesSync( BrowserStartupController.MAX_RENDERERS_LIMIT); } catch (ProcessInitException e) { Log.e(TAG, "Failed to load native library.", e); System.exit(-1); } } else { try { BrowserStartupController.get(this).startBrowserProcessesAsync( new BrowserStartupController.StartupCallback() { @Override public void onSuccess(boolean alreadyStarted) { finishInitialization(savedInstanceState); } @Override public void onFailure() { initializationFailed(); } }); } catch (ProcessInitException e) { Log.e(TAG, "Unable to load native library.", e); System.exit(-1); } } } private void finishInitialization(Bundle savedInstanceState) { String shellUrl = ShellManager.DEFAULT_SHELL_URL; if (savedInstanceState != null && savedInstanceState.containsKey(ACTIVE_SHELL_URL_KEY)) { shellUrl = savedInstanceState.getString(ACTIVE_SHELL_URL_KEY); } mShellManager.launchShell(shellUrl); } private void initializationFailed() { Log.e(TAG, "ContentView initialization failed."); Toast.makeText(ContentShellActivity.this, R.string.browser_process_initialization_failed, Toast.LENGTH_SHORT).show(); finish(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); ContentViewCore contentViewCore = getActiveContentViewCore(); if (contentViewCore != null) { outState.putString(ACTIVE_SHELL_URL_KEY, contentViewCore.getUrl()); } mWindowAndroid.saveInstanceState(outState); } private void waitForDebuggerIfNeeded() { if (CommandLine.getInstance().hasSwitch(BaseSwitches.WAIT_FOR_JAVA_DEBUGGER)) { Log.e(TAG, "Waiting for Java debugger to connect..."); android.os.Debug.waitForDebugger(); Log.e(TAG, "Java debugger connected. Resuming execution."); } } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { ContentViewCore contentViewCore = getActiveContentViewCore(); if (contentViewCore != null && contentViewCore.canGoBack()) { contentViewCore.goBack(); return true; } } return super.onKeyUp(keyCode, event); } @Override protected void onNewIntent(Intent intent) { if (getCommandLineParamsFromIntent(intent) != null) { Log.i(TAG, "Ignoring command line params: can only be set when creating the activity."); } if (MemoryPressureListener.handleDebugIntent(this, intent.getAction())) return; String url = getUrlFromIntent(intent); if (!TextUtils.isEmpty(url)) { Shell activeView = getActiveShell(); if (activeView != null) { activeView.loadUrl(url); } } } @Override protected void onStop() { super.onStop(); ContentViewCore contentViewCore = getActiveContentViewCore(); if (contentViewCore != null) contentViewCore.onHide(); } @Override protected void onStart() { super.onStart(); ContentViewCore contentViewCore = getActiveContentViewCore(); if (contentViewCore != null) contentViewCore.onShow(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); mWindowAndroid.onActivityResult(requestCode, resultCode, data); } private static String getUrlFromIntent(Intent intent) { return intent != null ? intent.getDataString() : null; } private static String[] getCommandLineParamsFromIntent(Intent intent) { return intent != null ? intent.getStringArrayExtra(COMMAND_LINE_ARGS_KEY) : null; } /** * @return The {@link ShellManager} configured for the activity or null if it has not been * created yet. */ public ShellManager getShellManager() { return mShellManager; } /** * @return The currently visible {@link Shell} or null if one is not showing. */ public Shell getActiveShell() { return mShellManager != null ? mShellManager.getActiveShell() : null; } /** * @return The {@link ContentViewCore} owned by the currently visible {@link Shell} or null if * one is not showing. */ public ContentViewCore getActiveContentViewCore() { Shell shell = getActiveShell(); return shell != null ? shell.getContentViewCore() : null; } }