Home | History | Annotate | Download | only in content_shell_apk
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 package org.chromium.content_shell_apk;
      6 
      7 import android.content.BroadcastReceiver;
      8 import android.content.Context;
      9 import android.content.Intent;
     10 import android.content.IntentFilter;
     11 import android.os.Bundle;
     12 import android.text.TextUtils;
     13 import android.util.Log;
     14 import android.view.KeyEvent;
     15 
     16 import org.chromium.base.ChromiumActivity;
     17 import org.chromium.base.MemoryPressureListener;
     18 import org.chromium.content.app.LibraryLoader;
     19 import org.chromium.content.browser.ActivityContentVideoViewClient;
     20 import org.chromium.content.browser.AndroidBrowserProcess;
     21 import org.chromium.content.browser.BrowserStartupConfig;
     22 import org.chromium.content.browser.ContentVideoViewClient;
     23 import org.chromium.content.browser.ContentView;
     24 import org.chromium.content.browser.ContentViewClient;
     25 import org.chromium.content.browser.DeviceUtils;
     26 import org.chromium.content.browser.TracingIntentHandler;
     27 import org.chromium.content.common.CommandLine;
     28 import org.chromium.content.common.ProcessInitException;
     29 import org.chromium.content_shell.Shell;
     30 import org.chromium.content_shell.ShellManager;
     31 import org.chromium.ui.ActivityWindowAndroid;
     32 import org.chromium.ui.WindowAndroid;
     33 
     34 /**
     35  * Activity for managing the Content Shell.
     36  */
     37 public class ContentShellActivity extends ChromiumActivity {
     38 
     39     public static final String COMMAND_LINE_FILE = "/data/local/tmp/content-shell-command-line";
     40     private static final String TAG = "ContentShellActivity";
     41 
     42     private static final String ACTIVE_SHELL_URL_KEY = "activeUrl";
     43     private static final String ACTION_START_TRACE =
     44             "org.chromium.content_shell.action.PROFILE_START";
     45     private static final String ACTION_STOP_TRACE =
     46             "org.chromium.content_shell.action.PROFILE_STOP";
     47     public static final String COMMAND_LINE_ARGS_KEY = "commandLineArgs";
     48 
     49     /**
     50      * Sending an intent with this action will simulate a memory pressure signal
     51      * at a critical level.
     52      */
     53     private static final String ACTION_LOW_MEMORY =
     54             "org.chromium.content_shell.action.ACTION_LOW_MEMORY";
     55 
     56     /**
     57      * Sending an intent with this action will simulate a memory pressure signal
     58      * at a moderate level.
     59      */
     60     private static final String ACTION_TRIM_MEMORY_MODERATE =
     61             "org.chromium.content_shell.action.ACTION_TRIM_MEMORY_MODERATE";
     62 
     63 
     64     private ShellManager mShellManager;
     65     private WindowAndroid mWindowAndroid;
     66     private BroadcastReceiver mReceiver;
     67 
     68     @Override
     69     protected void onCreate(Bundle savedInstanceState) {
     70         super.onCreate(savedInstanceState);
     71 
     72         // Initializing the command line must occur before loading the library.
     73         if (!CommandLine.isInitialized()) {
     74             CommandLine.initFromFile(COMMAND_LINE_FILE);
     75             String[] commandLineParams = getCommandLineParamsFromIntent(getIntent());
     76             if (commandLineParams != null) {
     77                 CommandLine.getInstance().appendSwitchesAndArguments(commandLineParams);
     78             }
     79         }
     80         waitForDebuggerIfNeeded();
     81 
     82         DeviceUtils.addDeviceSpecificUserAgentSwitch(this);
     83         try {
     84             LibraryLoader.ensureInitialized();
     85 
     86             setContentView(R.layout.content_shell_activity);
     87             mShellManager = (ShellManager) findViewById(R.id.shell_container);
     88             mWindowAndroid = new ActivityWindowAndroid(this);
     89             mWindowAndroid.restoreInstanceState(savedInstanceState);
     90             mShellManager.setWindow(mWindowAndroid);
     91 
     92             String startupUrl = getUrlFromIntent(getIntent());
     93             if (!TextUtils.isEmpty(startupUrl)) {
     94                 mShellManager.setStartupUrl(Shell.sanitizeUrl(startupUrl));
     95             }
     96 
     97             if (!CommandLine.getInstance().hasSwitch(CommandLine.DUMP_RENDER_TREE)) {
     98                 BrowserStartupConfig.setAsync(new BrowserStartupConfig.StartupCallback() {
     99 
    100                     @Override
    101                     public void run(int startupResult) {
    102                         if (startupResult > 0) {
    103                             // TODO: Show error message.
    104                             Log.e(TAG, "ContentView initialization failed.");
    105                             finish();
    106                         } else {
    107                             finishInitialization();
    108                         }
    109                     }
    110                 });
    111             }
    112 
    113             if (!AndroidBrowserProcess.init(this, AndroidBrowserProcess.MAX_RENDERERS_LIMIT)) {
    114                 String shellUrl = ShellManager.DEFAULT_SHELL_URL;
    115                 if (savedInstanceState != null
    116                         && savedInstanceState.containsKey(ACTIVE_SHELL_URL_KEY)) {
    117                     shellUrl = savedInstanceState.getString(ACTIVE_SHELL_URL_KEY);
    118                 }
    119                 mShellManager.launchShell(shellUrl);
    120                 finishInitialization();
    121             }
    122         } catch (ProcessInitException e) {
    123             Log.e(TAG, "ContentView initialization failed.", e);
    124             finish();
    125         }
    126     }
    127 
    128     private void finishInitialization() {
    129         getActiveContentView().setContentViewClient(new ContentViewClient() {
    130             @Override
    131             public ContentVideoViewClient getContentVideoViewClient() {
    132                 return new ActivityContentVideoViewClient(ContentShellActivity.this);
    133             }
    134         });
    135     }
    136 
    137     @Override
    138     protected void onSaveInstanceState(Bundle outState) {
    139         super.onSaveInstanceState(outState);
    140         Shell activeShell = getActiveShell();
    141         if (activeShell != null) {
    142             outState.putString(ACTIVE_SHELL_URL_KEY, activeShell.getContentView().getUrl());
    143         }
    144 
    145         mWindowAndroid.saveInstanceState(outState);
    146     }
    147 
    148     private void waitForDebuggerIfNeeded() {
    149         if (CommandLine.getInstance().hasSwitch(CommandLine.WAIT_FOR_JAVA_DEBUGGER)) {
    150             Log.e(TAG, "Waiting for Java debugger to connect...");
    151             android.os.Debug.waitForDebugger();
    152             Log.e(TAG, "Java debugger connected. Resuming execution.");
    153         }
    154     }
    155 
    156     @Override
    157     public boolean onKeyUp(int keyCode, KeyEvent event) {
    158         if (keyCode != KeyEvent.KEYCODE_BACK) return super.onKeyUp(keyCode, event);
    159 
    160         Shell activeView = getActiveShell();
    161         if (activeView != null && activeView.getContentView().canGoBack()) {
    162             activeView.getContentView().goBack();
    163             return true;
    164         }
    165 
    166         return super.onKeyUp(keyCode, event);
    167     }
    168 
    169     @Override
    170     protected void onNewIntent(Intent intent) {
    171         if (getCommandLineParamsFromIntent(intent) != null) {
    172             Log.i(TAG, "Ignoring command line params: can only be set when creating the activity.");
    173         }
    174 
    175         if (ACTION_LOW_MEMORY.equals(intent.getAction())) {
    176             MemoryPressureListener.simulateMemoryPressureSignal(TRIM_MEMORY_COMPLETE);
    177             return;
    178         } else if (ACTION_TRIM_MEMORY_MODERATE.equals(intent.getAction())) {
    179             MemoryPressureListener.simulateMemoryPressureSignal(TRIM_MEMORY_MODERATE);
    180             return;
    181         }
    182 
    183         String url = getUrlFromIntent(intent);
    184         if (!TextUtils.isEmpty(url)) {
    185             Shell activeView = getActiveShell();
    186             if (activeView != null) {
    187                 activeView.loadUrl(url);
    188             }
    189         }
    190     }
    191 
    192     @Override
    193     protected void onPause() {
    194         ContentView view = getActiveContentView();
    195         if (view != null) view.onActivityPause();
    196 
    197         super.onPause();
    198         unregisterReceiver(mReceiver);
    199     }
    200 
    201     @Override
    202     protected void onResume() {
    203         super.onResume();
    204 
    205         ContentView view = getActiveContentView();
    206         if (view != null) view.onActivityResume();
    207         IntentFilter intentFilter = new IntentFilter(ACTION_START_TRACE);
    208         intentFilter.addAction(ACTION_STOP_TRACE);
    209         mReceiver = new BroadcastReceiver() {
    210             @Override
    211             public void onReceive(Context context, Intent intent) {
    212                 String action = intent.getAction();
    213                 String extra = intent.getStringExtra("file");
    214                 if (ACTION_START_TRACE.equals(action)) {
    215                     if (extra.isEmpty()) {
    216                         Log.e(TAG, "Can not start tracing without specifing saving location");
    217                     } else {
    218                         TracingIntentHandler.beginTracing(extra);
    219                         Log.i(TAG, "start tracing");
    220                     }
    221                 } else if (ACTION_STOP_TRACE.equals(action)) {
    222                     Log.i(TAG, "stop tracing");
    223                     TracingIntentHandler.endTracing();
    224                 }
    225             }
    226         };
    227         registerReceiver(mReceiver, intentFilter);
    228     }
    229 
    230     @Override
    231     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    232         super.onActivityResult(requestCode, resultCode, data);
    233         mWindowAndroid.onActivityResult(requestCode, resultCode, data);
    234     }
    235 
    236     private static String getUrlFromIntent(Intent intent) {
    237         return intent != null ? intent.getDataString() : null;
    238     }
    239 
    240     private static String[] getCommandLineParamsFromIntent(Intent intent) {
    241         return intent != null ? intent.getStringArrayExtra(COMMAND_LINE_ARGS_KEY) : null;
    242     }
    243 
    244     /**
    245      * @return The {@link ShellManager} configured for the activity or null if it has not been
    246      *         created yet.
    247      */
    248     public ShellManager getShellManager() {
    249         return mShellManager;
    250     }
    251 
    252     /**
    253      * @return The currently visible {@link Shell} or null if one is not showing.
    254      */
    255     public Shell getActiveShell() {
    256         return mShellManager != null ? mShellManager.getActiveShell() : null;
    257     }
    258 
    259     /**
    260      * @return The {@link ContentView} owned by the currently visible {@link Shell} or null if one
    261      *         is not showing.
    262      */
    263     public ContentView getActiveContentView() {
    264         Shell shell = getActiveShell();
    265         return shell != null ? shell.getContentView() : null;
    266     }
    267 }
    268