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