• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 package org.chromium.chrome.testshell;
6 
7 import android.app.Activity;
8 import android.content.Intent;
9 import android.content.res.TypedArray;
10 import android.os.Bundle;
11 import android.text.TextUtils;
12 import android.util.Log;
13 import android.view.KeyEvent;
14 import android.view.Menu;
15 import android.view.MenuItem;
16 import android.widget.Toast;
17 
18 import org.chromium.base.ApiCompatibilityUtils;
19 import org.chromium.base.BaseSwitches;
20 import org.chromium.base.CommandLine;
21 import org.chromium.base.MemoryPressureListener;
22 import org.chromium.chrome.browser.DevToolsServer;
23 import org.chromium.chrome.browser.appmenu.AppMenuHandler;
24 import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate;
25 import org.chromium.chrome.browser.printing.PrintingControllerFactory;
26 import org.chromium.chrome.browser.printing.TabPrinter;
27 import org.chromium.chrome.testshell.sync.SyncController;
28 import org.chromium.content.browser.ActivityContentVideoViewClient;
29 import org.chromium.content.browser.BrowserStartupController;
30 import org.chromium.content.browser.ContentVideoViewClient;
31 import org.chromium.content.browser.ContentView;
32 import org.chromium.content.browser.ContentViewClient;
33 import org.chromium.content.browser.DeviceUtils;
34 import org.chromium.content.common.ProcessInitException;
35 import org.chromium.printing.PrintingController;
36 import org.chromium.sync.signin.ChromeSigninController;
37 import org.chromium.ui.base.ActivityWindowAndroid;
38 import org.chromium.ui.base.WindowAndroid;
39 
40 /**
41  * The {@link android.app.Activity} component of a basic test shell to test Chrome features.
42  */
43 public class ChromiumTestShellActivity extends Activity implements AppMenuPropertiesDelegate {
44     private static final String TAG = "ChromiumTestShellActivity";
45 
46     private WindowAndroid mWindow;
47     private TabManager mTabManager;
48     private DevToolsServer mDevToolsServer;
49     private SyncController mSyncController;
50     private PrintingController mPrintingController;
51 
52     private AppMenuHandler mAppMenuHandler;
53 
54     @Override
onCreate(final Bundle savedInstanceState)55     protected void onCreate(final Bundle savedInstanceState) {
56         super.onCreate(savedInstanceState);
57 
58         ChromiumTestShellApplication.initCommandLine();
59         waitForDebuggerIfNeeded();
60 
61         DeviceUtils.addDeviceSpecificUserAgentSwitch(this);
62 
63         BrowserStartupController.StartupCallback callback =
64                 new BrowserStartupController.StartupCallback() {
65                     @Override
66                     public void onSuccess(boolean alreadyStarted) {
67                         finishInitialization(savedInstanceState);
68                     }
69 
70                     @Override
71                     public void onFailure() {
72                         Toast.makeText(ChromiumTestShellActivity.this,
73                                        R.string.browser_process_initialization_failed,
74                                        Toast.LENGTH_SHORT).show();
75                         Log.e(TAG, "Chromium browser process initialization failed");
76                         finish();
77                     }
78                 };
79         try {
80             BrowserStartupController.get(this).startBrowserProcessesAsync(callback);
81         }
82         catch (ProcessInitException e) {
83             Log.e(TAG, "Unable to load native library.", e);
84             System.exit(-1);
85         }
86     }
87 
finishInitialization(final Bundle savedInstanceState)88     private void finishInitialization(final Bundle savedInstanceState) {
89         setContentView(R.layout.testshell_activity);
90         mTabManager = (TabManager) findViewById(R.id.tab_manager);
91 
92         mWindow = new ActivityWindowAndroid(this);
93         mWindow.restoreInstanceState(savedInstanceState);
94         mTabManager.setWindow(mWindow);
95 
96         String startupUrl = getUrlFromIntent(getIntent());
97         if (!TextUtils.isEmpty(startupUrl)) {
98             mTabManager.setStartupUrl(startupUrl);
99         }
100         TestShellToolbar mToolbar = (TestShellToolbar) findViewById(R.id.toolbar);
101         mAppMenuHandler = new AppMenuHandler(this, this, R.menu.main_menu);
102         mToolbar.setMenuHandler(mAppMenuHandler);
103 
104         mDevToolsServer = new DevToolsServer("chromium_testshell");
105         mDevToolsServer.setRemoteDebuggingEnabled(true);
106 
107         mPrintingController = PrintingControllerFactory.create(this);
108 
109         mSyncController = SyncController.get(this);
110         // In case this method is called after the first onStart(), we need to inform the
111         // SyncController that we have started.
112         mSyncController.onStart();
113     }
114 
115     @Override
onDestroy()116     protected void onDestroy() {
117         super.onDestroy();
118 
119         if (mDevToolsServer != null)
120             mDevToolsServer.destroy();
121         mDevToolsServer = null;
122     }
123 
124     @Override
onSaveInstanceState(Bundle outState)125     protected void onSaveInstanceState(Bundle outState) {
126         // TODO(dtrainor): Save/restore the tab state.
127         if (mWindow != null) mWindow.saveInstanceState(outState);
128     }
129 
130     @Override
onKeyUp(int keyCode, KeyEvent event)131     public boolean onKeyUp(int keyCode, KeyEvent event) {
132         if (keyCode == KeyEvent.KEYCODE_BACK) {
133             TestShellTab tab = getActiveTab();
134             if (tab != null && tab.getContentView().canGoBack()) {
135                 tab.getContentView().goBack();
136                 return true;
137             }
138         }
139 
140         return super.onKeyUp(keyCode, event);
141     }
142 
143     @Override
onNewIntent(Intent intent)144     protected void onNewIntent(Intent intent) {
145         if (MemoryPressureListener.handleDebugIntent(this, intent.getAction())) return;
146 
147         String url = getUrlFromIntent(intent);
148         if (!TextUtils.isEmpty(url)) {
149             TestShellTab tab = getActiveTab();
150             if (tab != null) tab.loadUrlWithSanitization(url);
151         }
152     }
153 
154     @Override
onStop()155     protected void onStop() {
156         super.onStop();
157 
158         ContentView view = getActiveContentView();
159         if (view != null) view.onHide();
160     }
161 
162     @Override
onStart()163     protected void onStart() {
164         super.onStart();
165 
166         ContentView view = getActiveContentView();
167         if (view != null) view.onShow();
168 
169         if (mSyncController != null) {
170             mSyncController.onStart();
171         }
172     }
173 
174     @Override
onActivityResult(int requestCode, int resultCode, Intent data)175     public void onActivityResult(int requestCode, int resultCode, Intent data) {
176         mWindow.onActivityResult(requestCode, resultCode, data);
177     }
178 
179     /**
180      * @return The {@link WindowAndroid} associated with this activity.
181      */
getWindowAndroid()182     public WindowAndroid getWindowAndroid() {
183         return mWindow;
184     }
185 
186     /**
187      * @return The {@link TestShellTab} that is currently visible.
188      */
getActiveTab()189     public TestShellTab getActiveTab() {
190         return mTabManager != null ? mTabManager.getCurrentTab() : null;
191     }
192 
193     /**
194      * @return The ContentView of the active tab.
195      */
getActiveContentView()196     public ContentView getActiveContentView() {
197         TestShellTab tab = getActiveTab();
198         return tab != null ? tab.getContentView() : null;
199     }
200 
201     /**
202      * Creates a {@link TestShellTab} with a URL specified by {@code url}.
203      *
204      * @param url The URL the new {@link TestShellTab} should start with.
205      */
createTab(String url)206     public void createTab(String url) {
207         mTabManager.createTab(url);
208         getActiveContentView().setContentViewClient(new ContentViewClient() {
209             @Override
210             public ContentVideoViewClient getContentVideoViewClient() {
211                 return new ActivityContentVideoViewClient(ChromiumTestShellActivity.this);
212             }
213         });
214     }
215 
216     /**
217      * Override the menu key event to show AppMenu.
218      */
219     @Override
onKeyDown(int keyCode, KeyEvent event)220     public boolean onKeyDown(int keyCode, KeyEvent event) {
221         if (keyCode == KeyEvent.KEYCODE_MENU && event.getRepeatCount() == 0) {
222             mAppMenuHandler.showAppMenu(findViewById(R.id.menu_button), true, false);
223             return true;
224         }
225         return super.onKeyDown(keyCode, event);
226     }
227 
228     @Override
onOptionsItemSelected(MenuItem item)229     public boolean onOptionsItemSelected(MenuItem item) {
230         switch (item.getItemId()) {
231             case R.id.signin:
232                 if (ChromeSigninController.get(this).isSignedIn())
233                     SyncController.openSignOutDialog(getFragmentManager());
234                 else
235                     SyncController.openSigninDialog(getFragmentManager());
236                 return true;
237             case R.id.print:
238                 if (getActiveTab() != null) {
239                     mPrintingController.startPrint(new TabPrinter(getActiveTab()));
240                 }
241                 return true;
242             case R.id.back_menu_id:
243                 if (getActiveTab().canGoBack()) getActiveTab().goBack();
244                 return true;
245             case R.id.forward_menu_id:
246                 if (getActiveTab().canGoForward()) getActiveTab().goForward();
247                 return true;
248             default:
249                 return super.onOptionsItemSelected(item);
250         }
251     }
252 
waitForDebuggerIfNeeded()253     private void waitForDebuggerIfNeeded() {
254         if (CommandLine.getInstance().hasSwitch(BaseSwitches.WAIT_FOR_JAVA_DEBUGGER)) {
255             Log.e(TAG, "Waiting for Java debugger to connect...");
256             android.os.Debug.waitForDebugger();
257             Log.e(TAG, "Java debugger connected. Resuming execution.");
258         }
259     }
260 
getUrlFromIntent(Intent intent)261     private static String getUrlFromIntent(Intent intent) {
262         return intent != null ? intent.getDataString() : null;
263     }
264 
265     @Override
shouldShowAppMenu()266     public boolean shouldShowAppMenu() {
267         return true;
268     }
269 
270     @Override
prepareMenu(Menu menu)271     public void prepareMenu(Menu menu) {
272         // Disable the "Back" menu item if there is no page to go to.
273         MenuItem backMenuItem = menu.findItem(R.id.back_menu_id);
274         backMenuItem.setEnabled(getActiveTab().canGoBack());
275 
276         // Disable the "Forward" menu item if there is no page to go to.
277         MenuItem forwardMenuItem = menu.findItem(R.id.forward_menu_id);
278         forwardMenuItem.setEnabled(getActiveTab().canGoForward());
279 
280         // ChromiumTestShell does not know about bookmarks yet
281         menu.findItem(R.id.bookmark_this_page_id).setEnabled(false);
282 
283         MenuItem signinItem = menu.findItem(R.id.signin);
284         if (ChromeSigninController.get(this).isSignedIn()) {
285             signinItem.setTitle(ChromeSigninController.get(this).getSignedInAccountName());
286         } else {
287             signinItem.setTitle(R.string.signin_sign_in);
288         }
289 
290         menu.findItem(R.id.print).setVisible(ApiCompatibilityUtils.isPrintingSupported());
291 
292         menu.setGroupVisible(R.id.MAIN_MENU, true);
293     }
294 
295     @Override
shouldShowIconRow()296     public boolean shouldShowIconRow() {
297         return true;
298     }
299 
300     @Override
getMenuThemeResourceId()301     public int getMenuThemeResourceId() {
302         return android.R.style.Theme_Holo_Light;
303     }
304 
305     @Override
getItemRowHeight()306     public int getItemRowHeight() {
307         TypedArray a = obtainStyledAttributes(
308                 new int[] {android.R.attr.listPreferredItemHeightSmall});
309         int itemRowHeight = a.getDimensionPixelSize(0, 0);
310         a.recycle();
311         return itemRowHeight;
312     }
313 }
314