787161c2fd9eeaefe2e1670e02fc7caa41047699
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / android / core_shell / src / org / xwalk / core / xwview / shell / XWalkViewShellActivity.java
1 // Copyright (c) 2013-2014 Intel Corporation. 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.xwalk.core.xwview.shell;
6
7 import java.util.HashMap;
8
9 import android.app.ActionBar;
10 import android.app.ActionBar.Tab;
11 import android.app.FragmentTransaction;
12 import android.content.BroadcastReceiver;
13 import android.content.Intent;
14 import android.content.Context;
15 import android.content.IntentFilter;
16 import android.graphics.drawable.ClipDrawable;
17 import android.os.Bundle;
18 import android.os.Looper;
19 import android.os.MessageQueue;
20 import android.support.v4.app.FragmentActivity;
21 import android.support.v4.view.ViewPager;
22 import android.util.Log;
23 import android.view.KeyEvent;
24 import android.view.View;
25 import android.view.View.OnClickListener;
26 import android.view.View.OnFocusChangeListener;
27 import android.view.inputmethod.EditorInfo;
28 import android.view.inputmethod.InputMethodManager;
29 import android.widget.EditText;
30 import android.widget.ImageButton;
31 import android.widget.LinearLayout;
32 import android.widget.TextView;
33 import android.widget.TextView.OnEditorActionListener;
34
35 import org.chromium.base.BaseSwitches;
36 import org.chromium.base.CommandLine;
37 import org.chromium.base.library_loader.LibraryLoader;
38 import org.chromium.content.browser.TracingControllerAndroid;
39 import org.xwalk.core.XWalkNavigationHistory;
40 import org.xwalk.core.XWalkPreferences;
41 import org.xwalk.core.XWalkResourceClientImpl;
42 import org.xwalk.core.XWalkView;
43 import org.xwalk.core.XWalkWebChromeClient;
44
45 public class XWalkViewShellActivity extends FragmentActivity
46         implements ActionBar.TabListener, XWalkViewSectionFragment.OnXWalkViewCreatedListener{
47     public static final String COMMAND_LINE_FILE = "/data/local/tmp/xwview-shell-command-line";
48     private static final String TAG = XWalkViewShellActivity.class.getName();
49     public static final String COMMAND_LINE_ARGS_KEY = "commandLineArgs";
50     private static final long COMPLETED_PROGRESS_TIMEOUT_MS = 200;
51     private static final String ACTION_LAUNCH_URL = "org.xwalk.core.xwview.shell.launch";
52
53     private LinearLayout mToolbar;
54     private EditText mUrlTextView;
55     private ImageButton mPrevButton;
56     private ImageButton mNextButton;
57     private ImageButton mStopButton;
58     private ImageButton mReloadButton;
59     private ClipDrawable mProgressDrawable;
60     private XWalkView mActiveView;
61     private TracingControllerAndroid mTracingController;
62     private BroadcastReceiver mReceiver;
63     private ActionBar mActionBar;
64     private SectionsPagerAdapter mSectionsPagerAdapter;
65     private ViewPager mViewPager;
66     private HashMap<XWalkView, Integer> mProgressMap;
67
68     private Runnable mClearProgressRunnable = new Runnable() {
69         @Override
70         public void run() {
71             mProgressDrawable.setLevel(0);
72         }
73     };
74
75     TracingControllerAndroid getTracingController() {
76         if (mTracingController == null) {
77             mTracingController = new TracingControllerAndroid(this);
78         }
79         return mTracingController;
80     }
81
82     private void registerTracingReceiverWhenIdle() {
83         // Delay tracing receiver registration until the main loop is idle.
84         Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
85             @Override
86             public boolean queueIdle() {
87                 // Will retry if the native library is not initialized yet.
88                 if (!LibraryLoader.isInitialized()) return true;
89                 try {
90                     getTracingController().registerReceiver(XWalkViewShellActivity.this);
91                 } catch (SecurityException e) {
92                     Log.w(TAG, "failed to register tracing receiver: " + e.getMessage());
93                 }
94                 return false;
95             }
96         });
97     }
98
99     private void unregisterTracingReceiver() {
100         try {
101             getTracingController().unregisterReceiver(this);
102         } catch (SecurityException e) {
103             Log.w(TAG, "failed to unregister tracing receiver: " + e.getMessage());
104         }
105     }
106
107     @Override
108     public void onCreate(Bundle savedInstanceState) {
109         super.onCreate(savedInstanceState);
110
111         registerTracingReceiverWhenIdle();
112
113         if (!CommandLine.isInitialized()) {
114             CommandLine.initFromFile(COMMAND_LINE_FILE);
115             String[] commandLineParams = getCommandLineParamsFromIntent(getIntent());
116             if (commandLineParams != null) {
117                 CommandLine.getInstance().appendSwitchesAndArguments(commandLineParams);
118             }
119         }
120
121         waitForDebuggerIfNeeded();
122
123         setContentView(R.layout.testshell_activity);
124
125         mActionBar = getActionBar();
126         mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
127         mSectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager(), mActionBar);
128
129         mViewPager = (ViewPager) findViewById(R.id.pager);
130         mViewPager.setAdapter(mSectionsPagerAdapter);
131         mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
132             @Override
133             public void onPageSelected(int position) {
134                 mActionBar.setSelectedNavigationItem(position);
135             }
136         });
137
138         mProgressMap = new HashMap<XWalkView, Integer>();
139         // Add two tabs.
140         mActionBar.addTab(
141                 mActionBar.newTab()
142                         .setText(mSectionsPagerAdapter.getPageTitle(0))
143                         .setTabListener(this));
144         mActionBar.addTab(
145                 mActionBar.newTab()
146                         .setText(mSectionsPagerAdapter.getPageTitle(1))
147                         .setTabListener(this));
148
149         mToolbar = (LinearLayout) findViewById(R.id.toolbar);
150         mProgressDrawable = (ClipDrawable) findViewById(R.id.toolbar).getBackground();
151
152         IntentFilter intentFilter = new IntentFilter(ACTION_LAUNCH_URL);
153         mReceiver = new BroadcastReceiver() {
154             @Override
155             public void onReceive(Context context, Intent intent) {
156                 Bundle bundle = intent.getExtras();
157                 if (bundle == null)
158                     return;
159
160                 if (bundle.containsKey("url")) {
161                     String extra = bundle.getString("url");
162                     if (mActiveView != null)
163                         mActiveView.load(sanitizeUrl(extra), null);
164                 }
165             }
166         };
167         registerReceiver(mReceiver, intentFilter);
168     }
169
170     @Override
171     public void onPause() {
172         super.onPause();
173         mSectionsPagerAdapter.onPause();
174     }
175
176     @Override
177     public void onResume() {
178         super.onResume();
179         mSectionsPagerAdapter.onResume();
180     }
181
182     @Override
183     public void onDestroy() {
184         super.onDestroy();
185         unregisterReceiver(mReceiver);
186         unregisterTracingReceiver();
187         mSectionsPagerAdapter.onDestroy();
188     }
189
190     @Override
191     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
192         if (mActiveView != null) mActiveView.onActivityResult(requestCode, resultCode, data);
193     }
194
195     @Override
196     public boolean onKeyUp(int keyCode, KeyEvent event) {
197         if (mActiveView != null) {
198             return mActiveView.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event);
199         }
200         return super.onKeyUp(keyCode, event);
201     }
202
203     @Override
204     public void onNewIntent(Intent intent) {
205         if (mActiveView != null) {
206             if (!mActiveView.onNewIntent(intent)) super.onNewIntent(intent);
207         }
208     }
209
210     private void waitForDebuggerIfNeeded() {
211         if (CommandLine.getInstance().hasSwitch(BaseSwitches.WAIT_FOR_JAVA_DEBUGGER)) {
212             Log.e(TAG, "Waiting for Java debugger to connect...");
213             android.os.Debug.waitForDebugger();
214             Log.e(TAG, "Java debugger connected. Resuming execution.");
215         }
216     }
217
218     private static String[] getCommandLineParamsFromIntent(Intent intent) {
219         return intent != null ? intent.getStringArrayExtra(COMMAND_LINE_ARGS_KEY) : null;
220     }
221
222     private static String sanitizeUrl(String url) {
223         if (url == null) return url;
224         if (url.startsWith("www.") || url.indexOf(":") == -1) url = "http://" + url;
225         return url;
226     }
227
228     private void initializeUrlField() {
229         mUrlTextView = (EditText) findViewById(R.id.url);
230         mUrlTextView.setOnEditorActionListener(new OnEditorActionListener() {
231             @Override
232             public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
233                 if ((actionId != EditorInfo.IME_ACTION_GO) && (event == null ||
234                         event.getKeyCode() != KeyEvent.KEYCODE_ENTER ||
235                         event.getAction() != KeyEvent.ACTION_DOWN)) {
236                     return false;
237                 }
238
239                 if (mActiveView == null) return true;
240                 mActiveView.load(sanitizeUrl(mUrlTextView.getText().toString()), null);
241                 mUrlTextView.clearFocus();
242                 setKeyboardVisibilityForUrl(false);
243                 return true;
244             }
245         });
246         mUrlTextView.setOnFocusChangeListener(new OnFocusChangeListener() {
247             @Override
248             public void onFocusChange(View v, boolean hasFocus) {
249                 setKeyboardVisibilityForUrl(hasFocus);
250                 mNextButton.setVisibility(hasFocus ? View.GONE : View.VISIBLE);
251                 mPrevButton.setVisibility(hasFocus ? View.GONE : View.VISIBLE);
252                 mStopButton.setVisibility(hasFocus ? View.GONE : View.VISIBLE);
253                 mReloadButton.setVisibility(hasFocus ? View.GONE : View.VISIBLE);
254                 if (!hasFocus) {
255                     if (mActiveView == null) return;
256                     mUrlTextView.setText(mActiveView.getUrl());
257                 }
258             }
259         });
260     }
261
262     private void initializeButtons() {
263         mPrevButton = (ImageButton) findViewById(R.id.prev);
264         mPrevButton.setOnClickListener(new OnClickListener() {
265             @Override
266             public void onClick(View v) {
267                 if (mActiveView != null &&
268                         mActiveView.getNavigationHistory().canGoBack()) {
269                     mActiveView.getNavigationHistory().navigate(
270                             XWalkNavigationHistory.Direction.BACKWARD, 1);
271                 }
272             }
273         });
274
275         mNextButton = (ImageButton) findViewById(R.id.next);
276         mNextButton.setOnClickListener(new OnClickListener() {
277             @Override
278             public void onClick(View v) {
279                 if (mActiveView != null &&
280                         mActiveView.getNavigationHistory().canGoForward()) {
281                     mActiveView.getNavigationHistory().navigate(
282                             XWalkNavigationHistory.Direction.FORWARD, 1);
283                 }
284             }
285         });
286
287         mStopButton = (ImageButton) findViewById(R.id.stop);
288         mStopButton.setOnClickListener(new OnClickListener() {
289             @Override
290             public void onClick(View v) {
291                 if (mActiveView != null) mActiveView.stopLoading();
292             }
293         });
294
295         mReloadButton = (ImageButton) findViewById(R.id.reload);
296         mReloadButton.setOnClickListener(new OnClickListener() {
297             @Override
298             public void onClick(View v) {
299                 if (mActiveView != null) mActiveView.reload();
300             }
301         });
302     }
303
304     private void initializeXWalkViewClients(XWalkView xwalkView) {
305         xwalkView.setResourceClient(new XWalkResourceClientImpl(this, xwalkView) {
306             @Override
307             public void onProgressChanged(XWalkView view, int newProgress) {
308                 if (view != mActiveView) return;
309                 mToolbar.removeCallbacks(mClearProgressRunnable);
310
311                 mProgressDrawable.setLevel((int) (100.0 * newProgress));
312                 mProgressMap.put(view, (int) (100.0 * newProgress));
313                 if (newProgress == 100) {
314                     mToolbar.postDelayed(mClearProgressRunnable, COMPLETED_PROGRESS_TIMEOUT_MS);
315                     mProgressMap.put(view, 0);
316                 }
317                 mUrlTextView.setText(mActiveView.getUrl());
318             }
319         });
320
321         xwalkView.setXWalkWebChromeClient(new XWalkWebChromeClient(this, xwalkView) {
322             @Override
323             public void onReceivedTitle(XWalkView view, String title) {
324                 mSectionsPagerAdapter.setPageTitle(view, title);
325             }
326         });
327     }
328
329     private void setKeyboardVisibilityForUrl(boolean visible) {
330         InputMethodManager imm = (InputMethodManager) getSystemService(
331                 Context.INPUT_METHOD_SERVICE);
332         if (visible) {
333             imm.showSoftInput(mUrlTextView, InputMethodManager.SHOW_IMPLICIT);
334         } else {
335             imm.hideSoftInputFromWindow(mUrlTextView.getWindowToken(), 0);
336         }
337     }
338
339     @Override
340     public void onTabReselected(Tab tab, FragmentTransaction ft) {
341         // Do nothing here currently, just make compiler happy.
342     }
343
344     @Override
345     public void onTabSelected(Tab tab, FragmentTransaction ft) {
346         mViewPager.setCurrentItem(tab.getPosition());
347         android.support.v4.app.Fragment fragment = mSectionsPagerAdapter.getItem(tab.getPosition());
348         if (fragment!= null && fragment instanceof XWalkViewSectionFragment) {
349             mActiveView = ((XWalkViewSectionFragment)fragment).getXWalkView();
350         } else {
351             mActiveView = null;
352         }
353         if (mActiveView != null) {
354             mUrlTextView.setText(mActiveView.getUrl());
355             if (mProgressMap.containsKey(mActiveView)) {
356                 mProgressDrawable.setLevel(mProgressMap.get(mActiveView));
357             } else {
358                 mProgressDrawable.setLevel(0);
359             }
360         }
361     }
362
363     @Override
364     public void onTabUnselected(Tab tab, FragmentTransaction ft) {
365         // Do nothing here currently, just make compiler happy.
366     }
367
368     @Override
369     public void onXWalkViewCreated(XWalkView view) {
370         if (mActiveView == null) {
371             mActiveView = view;
372             initializeUrlField();
373             initializeButtons();
374             mUrlTextView.setText("");
375             mProgressDrawable.setLevel(0);
376         }
377         initializeXWalkViewClients(view);
378         mProgressMap.put(view, 0);
379         XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING, true);
380     }
381 }