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
5package org.chromium.android_webview.shell;
6
7import android.app.Activity;
8import android.content.Context;
9import android.content.Intent;
10import android.content.SharedPreferences;
11import android.os.Bundle;
12import android.text.TextUtils;
13import android.view.Gravity;
14import android.view.KeyEvent;
15import android.view.View;
16import android.view.View.OnClickListener;
17import android.view.View.OnFocusChangeListener;
18import android.view.ViewGroup;
19import android.view.ViewGroup.LayoutParams;
20import android.view.WindowManager;
21import android.view.inputmethod.EditorInfo;
22import android.view.inputmethod.InputMethodManager;
23import android.webkit.WebChromeClient;
24import android.widget.EditText;
25import android.widget.FrameLayout;
26import android.widget.ImageButton;
27import android.widget.LinearLayout;
28import android.widget.TextView;
29import android.widget.TextView.OnEditorActionListener;
30
31import org.chromium.android_webview.AwBrowserContext;
32import org.chromium.android_webview.AwBrowserProcess;
33import org.chromium.android_webview.AwContents;
34import org.chromium.android_webview.AwContentsClient;
35import org.chromium.android_webview.AwDevToolsServer;
36import org.chromium.android_webview.AwSettings;
37import org.chromium.android_webview.test.AwTestContainerView;
38import org.chromium.android_webview.test.NullContentsClient;
39import org.chromium.content_public.browser.LoadUrlParams;
40import org.chromium.content_public.browser.NavigationController;
41import org.chromium.content_public.browser.WebContents;
42
43/**
44 * This is a lightweight activity for tests that only require WebView functionality.
45 */
46public 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