1 // Copyright 2013 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.android_webview.shell; 6 7 import android.app.Activity; 8 import android.content.Context; 9 import android.content.Intent; 10 import android.content.SharedPreferences; 11 import android.os.Bundle; 12 import android.text.TextUtils; 13 import android.view.Gravity; 14 import android.view.KeyEvent; 15 import android.view.View; 16 import android.view.View.OnClickListener; 17 import android.view.View.OnFocusChangeListener; 18 import android.view.ViewGroup; 19 import android.view.ViewGroup.LayoutParams; 20 import android.view.WindowManager; 21 import android.view.inputmethod.EditorInfo; 22 import android.view.inputmethod.InputMethodManager; 23 import android.webkit.WebChromeClient; 24 import android.widget.EditText; 25 import android.widget.FrameLayout; 26 import android.widget.ImageButton; 27 import android.widget.LinearLayout; 28 import android.widget.TextView; 29 import android.widget.TextView.OnEditorActionListener; 30 31 import org.chromium.android_webview.AwBrowserContext; 32 import org.chromium.android_webview.AwBrowserProcess; 33 import org.chromium.android_webview.AwContents; 34 import org.chromium.android_webview.AwContentsClient; 35 import org.chromium.android_webview.AwDevToolsServer; 36 import org.chromium.android_webview.AwSettings; 37 import org.chromium.android_webview.test.AwTestContainerView; 38 import org.chromium.android_webview.test.NullContentsClient; 39 import org.chromium.content_public.browser.LoadUrlParams; 40 import org.chromium.content_public.browser.NavigationController; 41 import org.chromium.content_public.browser.WebContents; 42 43 /** 44 * This is a lightweight activity for tests that only require WebView functionality. 45 */ 46 public class AwShellActivity extends Activity { 47 private static final String PREFERENCES_NAME = "AwShellPrefs"; 48 private static final String INITIAL_URL = "about:blank"; 49 private AwBrowserContext mBrowserContext; 50 private AwDevToolsServer mDevToolsServer; 51 private AwTestContainerView mAwTestContainerView; 52 private WebContents mWebContents; 53 private NavigationController mNavigationController; 54 private EditText mUrlTextView; 55 private ImageButton mPrevButton; 56 private ImageButton mNextButton; 57 58 @Override 59 public void onCreate(Bundle savedInstanceState) { 60 super.onCreate(savedInstanceState); 61 62 setContentView(R.layout.testshell_activity); 63 64 mAwTestContainerView = createAwTestContainerView(); 65 66 mWebContents = mAwTestContainerView.getContentViewCore().getWebContents(); 67 mNavigationController = mWebContents.getNavigationController(); 68 LinearLayout contentContainer = (LinearLayout) findViewById(R.id.content_container); 69 mAwTestContainerView.setLayoutParams(new LinearLayout.LayoutParams( 70 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1f)); 71 contentContainer.addView(mAwTestContainerView); 72 mAwTestContainerView.requestFocus(); 73 74 initializeUrlField(); 75 initializeNavigationButtons(); 76 77 String startupUrl = getUrlFromIntent(getIntent()); 78 if (TextUtils.isEmpty(startupUrl)) { 79 startupUrl = INITIAL_URL; 80 } 81 82 mAwTestContainerView.getAwContents().loadUrl(new LoadUrlParams(startupUrl)); 83 AwContents.setShouldDownloadFavicons(); 84 mUrlTextView.setText(startupUrl); 85 } 86 87 private AwTestContainerView createAwTestContainerView() { 88 AwBrowserProcess.start(this); 89 AwTestContainerView testContainerView = new AwTestContainerView(this, true); 90 AwContentsClient awContentsClient = new NullContentsClient() { 91 private View mCustomView; 92 93 @Override 94 public void onPageStarted(String url) { 95 if (mUrlTextView != null) { 96 mUrlTextView.setText(url); 97 } 98 } 99 100 @Override 101 public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) { 102 getWindow().setFlags( 103 WindowManager.LayoutParams.FLAG_FULLSCREEN, 104 WindowManager.LayoutParams.FLAG_FULLSCREEN); 105 106 getWindow().addContentView(view, 107 new FrameLayout.LayoutParams( 108 ViewGroup.LayoutParams.MATCH_PARENT, 109 ViewGroup.LayoutParams.MATCH_PARENT, 110 Gravity.CENTER)); 111 mCustomView = view; 112 } 113 114 @Override 115 public void onHideCustomView() { 116 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 117 FrameLayout decorView = (FrameLayout) getWindow().getDecorView(); 118 decorView.removeView(mCustomView); 119 mCustomView = null; 120 } 121 122 @Override 123 public boolean shouldOverrideKeyEvent(KeyEvent event) { 124 if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { 125 return true; 126 } 127 return false; 128 } 129 }; 130 131 SharedPreferences sharedPreferences = 132 getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE); 133 if (mBrowserContext == null) { 134 mBrowserContext = new AwBrowserContext(sharedPreferences); 135 } 136 final AwSettings awSettings = new AwSettings(this /*context*/, 137 false /*isAccessFromFileURLsGrantedByDefault*/, true /*supportsLegacyQuirks*/); 138 // Required for WebGL conformance tests. 139 awSettings.setMediaPlaybackRequiresUserGesture(false); 140 testContainerView.initialize(new AwContents(mBrowserContext, testContainerView, 141 testContainerView.getContext(), testContainerView.getInternalAccessDelegate(), 142 testContainerView.getNativeGLDelegate(), awContentsClient, awSettings)); 143 testContainerView.getAwContents().getSettings().setJavaScriptEnabled(true); 144 if (mDevToolsServer == null) { 145 mDevToolsServer = new AwDevToolsServer(); 146 mDevToolsServer.setRemoteDebuggingEnabled(true); 147 } 148 return testContainerView; 149 } 150 151 private static String getUrlFromIntent(Intent intent) { 152 return intent != null ? intent.getDataString() : null; 153 } 154 155 private void setKeyboardVisibilityForUrl(boolean visible) { 156 InputMethodManager imm = (InputMethodManager) getSystemService( 157 Context.INPUT_METHOD_SERVICE); 158 if (visible) { 159 imm.showSoftInput(mUrlTextView, InputMethodManager.SHOW_IMPLICIT); 160 } else { 161 imm.hideSoftInputFromWindow(mUrlTextView.getWindowToken(), 0); 162 } 163 } 164 165 private void initializeUrlField() { 166 mUrlTextView = (EditText) findViewById(R.id.url); 167 mUrlTextView.setOnEditorActionListener(new OnEditorActionListener() { 168 @Override 169 public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 170 if ((actionId != EditorInfo.IME_ACTION_GO) && (event == null || 171 event.getKeyCode() != KeyEvent.KEYCODE_ENTER || 172 event.getAction() != KeyEvent.ACTION_DOWN)) { 173 return false; 174 } 175 176 mAwTestContainerView.getAwContents().loadUrl( 177 new LoadUrlParams(mUrlTextView.getText().toString())); 178 mUrlTextView.clearFocus(); 179 setKeyboardVisibilityForUrl(false); 180 mAwTestContainerView.requestFocus(); 181 return true; 182 } 183 }); 184 mUrlTextView.setOnFocusChangeListener(new OnFocusChangeListener() { 185 @Override 186 public void onFocusChange(View v, boolean hasFocus) { 187 setKeyboardVisibilityForUrl(hasFocus); 188 mNextButton.setVisibility(hasFocus ? View.GONE : View.VISIBLE); 189 mPrevButton.setVisibility(hasFocus ? View.GONE : View.VISIBLE); 190 if (!hasFocus) { 191 mUrlTextView.setText(mWebContents.getUrl()); 192 } 193 } 194 }); 195 } 196 197 private void initializeNavigationButtons() { 198 mPrevButton = (ImageButton) findViewById(R.id.prev); 199 mPrevButton.setOnClickListener(new OnClickListener() { 200 @Override 201 public void onClick(View v) { 202 if (mNavigationController.canGoBack()) { 203 mNavigationController.goBack(); 204 } 205 } 206 }); 207 208 mNextButton = (ImageButton) findViewById(R.id.next); 209 mNextButton.setOnClickListener(new OnClickListener() { 210 @Override 211 public void onClick(View v) { 212 if (mNavigationController.canGoForward()) { 213 mNavigationController.goForward(); 214 } 215 } 216 }); 217 } 218 219 @Override 220 public boolean onKeyUp(int keyCode, KeyEvent event) { 221 if (keyCode == KeyEvent.KEYCODE_BACK) { 222 if (mNavigationController.canGoBack()) { 223 mNavigationController.goBack(); 224 return true; 225 } 226 } 227 228 return super.onKeyUp(keyCode, event); 229 } 230 } 231