ContentShellActivity.java revision 0529e5d033099cbfc42635f6f6183833b09dff6e
1// Copyright 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
5package org.chromium.content_shell_apk;
6
7import android.app.Activity;
8import android.content.Intent;
9import android.os.Bundle;
10import android.text.TextUtils;
11import android.util.Log;
12import android.view.KeyEvent;
13import android.widget.Toast;
14
15import org.chromium.base.BaseSwitches;
16import org.chromium.base.CommandLine;
17import org.chromium.base.MemoryPressureListener;
18import org.chromium.base.library_loader.LibraryLoader;
19import org.chromium.base.library_loader.ProcessInitException;
20import org.chromium.content.browser.BrowserStartupController;
21import org.chromium.content.browser.ContentViewCore;
22import org.chromium.content.browser.DeviceUtils;
23import org.chromium.content.common.ContentSwitches;
24import org.chromium.content_shell.Shell;
25import org.chromium.content_shell.ShellManager;
26import org.chromium.ui.base.ActivityWindowAndroid;
27import org.chromium.ui.base.WindowAndroid;
28
29/**
30 * Activity for managing the Content Shell.
31 */
32public class ContentShellActivity extends Activity {
33
34    public static final String COMMAND_LINE_FILE = "/data/local/tmp/content-shell-command-line";
35    private static final String TAG = "ContentShellActivity";
36
37    private static final String ACTIVE_SHELL_URL_KEY = "activeUrl";
38    public static final String COMMAND_LINE_ARGS_KEY = "commandLineArgs";
39
40    private ShellManager mShellManager;
41    private WindowAndroid mWindowAndroid;
42
43    @Override
44    protected void onCreate(final Bundle savedInstanceState) {
45        super.onCreate(savedInstanceState);
46
47        // Initializing the command line must occur before loading the library.
48        if (!CommandLine.isInitialized()) {
49            CommandLine.initFromFile(COMMAND_LINE_FILE);
50            String[] commandLineParams = getCommandLineParamsFromIntent(getIntent());
51            if (commandLineParams != null) {
52                CommandLine.getInstance().appendSwitchesAndArguments(commandLineParams);
53            }
54        }
55        waitForDebuggerIfNeeded();
56
57        DeviceUtils.addDeviceSpecificUserAgentSwitch(this);
58        try {
59            LibraryLoader.ensureInitialized();
60        } catch (ProcessInitException e) {
61            Log.e(TAG, "ContentView initialization failed.", e);
62            // Since the library failed to initialize nothing in the application
63            // can work, so kill the whole application not just the activity
64            System.exit(-1);
65            return;
66        }
67
68        setContentView(R.layout.content_shell_activity);
69        mShellManager = (ShellManager) findViewById(R.id.shell_container);
70        mWindowAndroid = new ActivityWindowAndroid(this);
71        mWindowAndroid.restoreInstanceState(savedInstanceState);
72        mShellManager.setWindow(mWindowAndroid);
73
74        String startupUrl = getUrlFromIntent(getIntent());
75        if (!TextUtils.isEmpty(startupUrl)) {
76            mShellManager.setStartupUrl(Shell.sanitizeUrl(startupUrl));
77        }
78
79        if (CommandLine.getInstance().hasSwitch(ContentSwitches.DUMP_RENDER_TREE)) {
80            try {
81                BrowserStartupController.get(this).startBrowserProcessesSync(
82                       BrowserStartupController.MAX_RENDERERS_LIMIT);
83            } catch (ProcessInitException e) {
84                Log.e(TAG, "Failed to load native library.", e);
85                System.exit(-1);
86            }
87        } else {
88            try {
89                BrowserStartupController.get(this).startBrowserProcessesAsync(
90                        new BrowserStartupController.StartupCallback() {
91                            @Override
92                            public void onSuccess(boolean alreadyStarted) {
93                                finishInitialization(savedInstanceState);
94                            }
95
96                            @Override
97                            public void onFailure() {
98                                initializationFailed();
99                            }
100                        });
101            } catch (ProcessInitException e) {
102                Log.e(TAG, "Unable to load native library.", e);
103                System.exit(-1);
104            }
105        }
106    }
107
108    private void finishInitialization(Bundle savedInstanceState) {
109        String shellUrl = ShellManager.DEFAULT_SHELL_URL;
110        if (savedInstanceState != null
111                && savedInstanceState.containsKey(ACTIVE_SHELL_URL_KEY)) {
112            shellUrl = savedInstanceState.getString(ACTIVE_SHELL_URL_KEY);
113        }
114        mShellManager.launchShell(shellUrl);
115    }
116
117    private void initializationFailed() {
118        Log.e(TAG, "ContentView initialization failed.");
119        Toast.makeText(ContentShellActivity.this,
120                R.string.browser_process_initialization_failed,
121                Toast.LENGTH_SHORT).show();
122        finish();
123    }
124
125    @Override
126    protected void onSaveInstanceState(Bundle outState) {
127        super.onSaveInstanceState(outState);
128        ContentViewCore contentViewCore = getActiveContentViewCore();
129        if (contentViewCore != null) {
130            outState.putString(ACTIVE_SHELL_URL_KEY, contentViewCore.getUrl());
131        }
132
133        mWindowAndroid.saveInstanceState(outState);
134    }
135
136    private void waitForDebuggerIfNeeded() {
137        if (CommandLine.getInstance().hasSwitch(BaseSwitches.WAIT_FOR_JAVA_DEBUGGER)) {
138            Log.e(TAG, "Waiting for Java debugger to connect...");
139            android.os.Debug.waitForDebugger();
140            Log.e(TAG, "Java debugger connected. Resuming execution.");
141        }
142    }
143
144    @Override
145    public boolean onKeyUp(int keyCode, KeyEvent event) {
146        if (keyCode == KeyEvent.KEYCODE_BACK) {
147            ContentViewCore contentViewCore = getActiveContentViewCore();
148            if (contentViewCore != null && contentViewCore.canGoBack()) {
149                contentViewCore.goBack();
150                return true;
151            }
152        }
153
154        return super.onKeyUp(keyCode, event);
155    }
156
157    @Override
158    protected void onNewIntent(Intent intent) {
159        if (getCommandLineParamsFromIntent(intent) != null) {
160            Log.i(TAG, "Ignoring command line params: can only be set when creating the activity.");
161        }
162
163        if (MemoryPressureListener.handleDebugIntent(this, intent.getAction())) return;
164
165        String url = getUrlFromIntent(intent);
166        if (!TextUtils.isEmpty(url)) {
167            Shell activeView = getActiveShell();
168            if (activeView != null) {
169                activeView.loadUrl(url);
170            }
171        }
172    }
173
174    @Override
175    protected void onStop() {
176        super.onStop();
177
178        ContentViewCore contentViewCore = getActiveContentViewCore();
179        if (contentViewCore != null) contentViewCore.onHide();
180    }
181
182    @Override
183    protected void onStart() {
184        super.onStart();
185
186        ContentViewCore contentViewCore = getActiveContentViewCore();
187        if (contentViewCore != null) contentViewCore.onShow();
188    }
189
190    @Override
191    public void onActivityResult(int requestCode, int resultCode, Intent data) {
192        super.onActivityResult(requestCode, resultCode, data);
193        mWindowAndroid.onActivityResult(requestCode, resultCode, data);
194    }
195
196    private static String getUrlFromIntent(Intent intent) {
197        return intent != null ? intent.getDataString() : null;
198    }
199
200    private static String[] getCommandLineParamsFromIntent(Intent intent) {
201        return intent != null ? intent.getStringArrayExtra(COMMAND_LINE_ARGS_KEY) : null;
202    }
203
204    /**
205     * @return The {@link ShellManager} configured for the activity or null if it has not been
206     *         created yet.
207     */
208    public ShellManager getShellManager() {
209        return mShellManager;
210    }
211
212    /**
213     * @return The currently visible {@link Shell} or null if one is not showing.
214     */
215    public Shell getActiveShell() {
216        return mShellManager != null ? mShellManager.getActiveShell() : null;
217    }
218
219    /**
220     * @return The {@link ContentViewCore} owned by the currently visible {@link Shell} or null if
221     *         one is not showing.
222     */
223    public ContentViewCore getActiveContentViewCore() {
224        Shell shell = getActiveShell();
225        return shell != null ? shell.getContentViewCore() : null;
226    }
227}
228