PageRenderTime 95ms CodeModel.GetById 52ms RepoModel.GetById 4ms app.codeStats 0ms

/src/acr/browser/lightning/LightningView.java

https://github.com/ccwasden/Lightning-Browser
Java | 1043 lines | 835 code | 142 blank | 66 comment | 143 complexity | d2769a8970432e868a980ff4fb2067c1 MD5 | raw file
Possible License(s): MPL-2.0
  1. /*
  2. * Copyright 2014 A.C.R. Development
  3. */
  4. package acr.browser.lightning;
  5. import android.annotation.SuppressLint;
  6. import android.app.Activity;
  7. import android.app.AlertDialog;
  8. import android.content.*;
  9. import android.graphics.Bitmap;
  10. import android.graphics.BitmapFactory;
  11. import android.net.MailTo;
  12. import android.net.Uri;
  13. import android.net.http.SslError;
  14. import android.os.Message;
  15. import android.text.InputType;
  16. import android.text.method.PasswordTransformationMethod;
  17. import android.util.Log;
  18. import android.view.GestureDetector;
  19. import android.view.GestureDetector.SimpleOnGestureListener;
  20. import android.view.MotionEvent;
  21. import android.view.View;
  22. import android.view.View.OnTouchListener;
  23. import android.webkit.CookieManager;
  24. import android.webkit.*;
  25. import android.webkit.WebSettings.LayoutAlgorithm;
  26. import android.webkit.WebSettings.PluginState;
  27. import android.widget.EditText;
  28. import android.widget.LinearLayout;
  29. import org.apache.http.util.ByteArrayBuffer;
  30. import java.io.*;
  31. import java.net.*;
  32. public class LightningView {
  33. private Title mTitle;
  34. private WebView mWebView;
  35. private BrowserController mBrowserController;
  36. private GestureDetector mGestureDetector;
  37. private Activity mActivity;
  38. private WebSettings mSettings;
  39. private static int API = android.os.Build.VERSION.SDK_INT;
  40. private static String mHomepage;
  41. private static String mDefaultUserAgent;
  42. private static Bitmap mWebpageBitmap;
  43. private static SharedPreferences mPreferences;
  44. private static boolean mWideViewPort;
  45. private AdBlock mAdBlock;
  46. private boolean isForegroundTab;
  47. private IntentUtils mIntentUtils;
  48. @SuppressWarnings("deprecation")
  49. @SuppressLint("NewApi")
  50. public LightningView(Activity activity, String url, CookieManager cookieManager) {
  51. mActivity = activity;
  52. mWebView = new WebView(activity);
  53. mTitle = new Title(activity);
  54. mAdBlock = new AdBlock(activity);
  55. activity.getPackageName();
  56. mWebpageBitmap = BitmapFactory.decodeResource(activity.getResources(),
  57. R.drawable.ic_webpage);
  58. try {
  59. mBrowserController = (BrowserController) activity;
  60. } catch (ClassCastException e) {
  61. throw new ClassCastException(activity + " must implement BrowserController");
  62. }
  63. mIntentUtils = new IntentUtils(mBrowserController);
  64. mWebView.setDrawingCacheBackgroundColor(0x00000000);
  65. mWebView.setFocusableInTouchMode(true);
  66. mWebView.setFocusable(true);
  67. mWebView.setAnimationCacheEnabled(false);
  68. mWebView.setDrawingCacheEnabled(true);
  69. mWebView.setBackgroundColor(activity.getResources().getColor(android.R.color.white));
  70. if (API > 15) {
  71. mWebView.getRootView().setBackground(null);
  72. } else {
  73. mWebView.getRootView().setBackgroundDrawable(null);
  74. }
  75. mWebView.setWillNotCacheDrawing(false);
  76. mWebView.setAlwaysDrawnWithCacheEnabled(true);
  77. mWebView.setScrollbarFadingEnabled(true);
  78. mWebView.setSaveEnabled(true);
  79. mWebView.setWebChromeClient(new LightningChromeClient(activity));
  80. mWebView.setWebViewClient(new LightningWebClient(activity));
  81. mWebView.setDownloadListener(new LightningDownloadListener(activity));
  82. mGestureDetector = new GestureDetector(activity, new CustomGestureListener());
  83. mWebView.setOnTouchListener(new OnTouchListener() {
  84. float mLocation;
  85. float mY;
  86. int mAction;
  87. @SuppressLint("ClickableViewAccessibility")
  88. @Override
  89. public boolean onTouch(View view, MotionEvent arg1) {
  90. if (view != null && !view.hasFocus()) {
  91. view.requestFocus();
  92. }
  93. mAction = arg1.getAction();
  94. mY = arg1.getY();
  95. if (mAction == MotionEvent.ACTION_DOWN) {
  96. mLocation = mY;
  97. } else if (mAction == MotionEvent.ACTION_UP) {
  98. if ((mY - mLocation) > 10) {
  99. mBrowserController.showActionBar();
  100. } else if ((mY - mLocation) < -10) {
  101. mBrowserController.hideActionBar();
  102. }
  103. mLocation = 0;
  104. }
  105. mGestureDetector.onTouchEvent(arg1);
  106. return false;
  107. }
  108. });
  109. mDefaultUserAgent = mWebView.getSettings().getUserAgentString();
  110. mSettings = mWebView.getSettings();
  111. initializeSettings(mWebView.getSettings(), activity);
  112. initializePreferences(activity);
  113. if (url != null && !url.trim().isEmpty()) {
  114. mWebView.loadUrl(url);
  115. } else {
  116. if (mHomepage.startsWith("about:home")) {
  117. mSettings.setUseWideViewPort(false);
  118. mWebView.loadUrl(getHomepage());
  119. } else if (mHomepage.startsWith("about:bookmarks")) {
  120. mBrowserController.openBookmarkPage(mWebView);
  121. } else {
  122. mWebView.loadUrl(mHomepage);
  123. }
  124. }
  125. }
  126. public String getHomepage() {
  127. String home;
  128. home = HomepageVariables.HEAD;
  129. switch (mPreferences.getInt(PreferenceConstants.SEARCH, 1)) {
  130. case 0:
  131. // CUSTOM SEARCH
  132. home = home + "file:///android_asset/lightning.png";
  133. home = home + HomepageVariables.MIDDLE;
  134. home = home
  135. + mPreferences.getString(PreferenceConstants.SEARCH_URL,
  136. Constants.GOOGLE_SEARCH);
  137. break;
  138. case 1:
  139. // GOOGLE_SEARCH;
  140. home = home + "file:///android_asset/google.png";
  141. // + "https://www.google.com/images/srpr/logo11w.png";
  142. home = home + HomepageVariables.MIDDLE;
  143. home = home + Constants.GOOGLE_SEARCH;
  144. break;
  145. case 2:
  146. // ANDROID SEARCH;
  147. home = home + "file:///android_asset/lightning.png";
  148. home = home + HomepageVariables.MIDDLE;
  149. home = home + Constants.ANDROID_SEARCH;
  150. break;
  151. case 3:
  152. // BING_SEARCH;
  153. home = home + "file:///android_asset/bing.png";
  154. // +
  155. // "http://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Bing_logo_%282013%29.svg/500px-Bing_logo_%282013%29.svg.png";
  156. home = home + HomepageVariables.MIDDLE;
  157. home = home + Constants.BING_SEARCH;
  158. break;
  159. case 4:
  160. // YAHOO_SEARCH;
  161. home = home + "file:///android_asset/yahoo.png";
  162. // +
  163. // "http://upload.wikimedia.org/wikipedia/commons/thumb/2/24/Yahoo%21_logo.svg/799px-Yahoo%21_logo.svg.png";
  164. home = home + HomepageVariables.MIDDLE;
  165. home = home + Constants.YAHOO_SEARCH;
  166. break;
  167. case 5:
  168. // STARTPAGE_SEARCH;
  169. home = home + "file:///android_asset/startpage.png";
  170. // + "https://startpage.com/graphics/startp_logo.gif";
  171. home = home + HomepageVariables.MIDDLE;
  172. home = home + Constants.STARTPAGE_SEARCH;
  173. break;
  174. case 6:
  175. // STARTPAGE_MOBILE
  176. home = home + "file:///android_asset/startpage.png";
  177. // + "https://startpage.com/graphics/startp_logo.gif";
  178. home = home + HomepageVariables.MIDDLE;
  179. home = home + Constants.STARTPAGE_MOBILE_SEARCH;
  180. case 7:
  181. // DUCK_SEARCH;
  182. home = home + "file:///android_asset/duckduckgo.png";
  183. // +
  184. // "https://duckduckgo.com/assets/logo_homepage.normal.v101.png";
  185. home = home + HomepageVariables.MIDDLE;
  186. home = home + Constants.DUCK_SEARCH;
  187. break;
  188. case 8:
  189. // DUCK_LITE_SEARCH;
  190. home = home + "file:///android_asset/duckduckgo.png";
  191. // +
  192. // "https://duckduckgo.com/assets/logo_homepage.normal.v101.png";
  193. home = home + HomepageVariables.MIDDLE;
  194. home = home + Constants.DUCK_LITE_SEARCH;
  195. break;
  196. case 9:
  197. // BAIDU_SEARCH;
  198. home = home + "file:///android_asset/baidu.png";
  199. // + "http://www.baidu.com/img/bdlogo.gif";
  200. home = home + HomepageVariables.MIDDLE;
  201. home = home + Constants.BAIDU_SEARCH;
  202. break;
  203. case 10:
  204. // YANDEX_SEARCH;
  205. home = home + "file:///android_asset/yandex.png";
  206. // +
  207. // "http://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Yandex.svg/600px-Yandex.svg.png";
  208. home = home + HomepageVariables.MIDDLE;
  209. home = home + Constants.YANDEX_SEARCH;
  210. break;
  211. }
  212. home = home + HomepageVariables.END;
  213. File homepage = new File(mActivity.getCacheDir(), "homepage.html");
  214. try {
  215. FileWriter hWriter = new FileWriter(homepage, false);
  216. hWriter.write(home);
  217. hWriter.close();
  218. } catch (IOException e) {
  219. e.printStackTrace();
  220. }
  221. return Constants.FILE + homepage;
  222. }
  223. @SuppressWarnings("deprecation")
  224. @SuppressLint({ "NewApi", "SetJavaScriptEnabled" })
  225. public synchronized void initializePreferences(Context context) {
  226. mPreferences = context.getSharedPreferences(PreferenceConstants.PREFERENCES, 0);
  227. mHomepage = mPreferences.getString(PreferenceConstants.HOMEPAGE, Constants.HOMEPAGE);
  228. mAdBlock.updatePreference();
  229. if (mSettings == null && mWebView != null) {
  230. mSettings = mWebView.getSettings();
  231. } else if (mSettings == null) {
  232. return;
  233. }
  234. mSettings.setGeolocationEnabled(mPreferences
  235. .getBoolean(PreferenceConstants.LOCATION, false));
  236. if (API < 19) {
  237. switch (mPreferences.getInt(PreferenceConstants.ADOBE_FLASH_SUPPORT, 0)) {
  238. case 0:
  239. mSettings.setPluginState(PluginState.OFF);
  240. break;
  241. case 1:
  242. mSettings.setPluginState(PluginState.ON_DEMAND);
  243. break;
  244. case 2:
  245. mSettings.setPluginState(PluginState.ON);
  246. break;
  247. default:
  248. break;
  249. }
  250. }
  251. switch (mPreferences.getInt(PreferenceConstants.USER_AGENT, 1)) {
  252. case 1:
  253. if (API > 16) {
  254. mSettings.setUserAgentString(WebSettings.getDefaultUserAgent(context));
  255. } else {
  256. mSettings.setUserAgentString(mDefaultUserAgent);
  257. }
  258. break;
  259. case 2:
  260. mSettings.setUserAgentString(Constants.DESKTOP_USER_AGENT);
  261. break;
  262. case 3:
  263. mSettings.setUserAgentString(Constants.MOBILE_USER_AGENT);
  264. break;
  265. case 4:
  266. mSettings.setUserAgentString(mPreferences.getString(
  267. PreferenceConstants.USER_AGENT_STRING, mDefaultUserAgent));
  268. break;
  269. }
  270. if (mPreferences.getBoolean(PreferenceConstants.SAVE_PASSWORDS, false)) {
  271. if (API < 18) {
  272. mSettings.setSavePassword(true);
  273. }
  274. mSettings.setSaveFormData(true);
  275. }
  276. if (mPreferences.getBoolean(PreferenceConstants.JAVASCRIPT, true)) {
  277. mSettings.setJavaScriptEnabled(true);
  278. mSettings.setJavaScriptCanOpenWindowsAutomatically(true);
  279. }
  280. if (mPreferences.getBoolean(PreferenceConstants.TEXT_REFLOW, false)) {
  281. mSettings.setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS);
  282. } else if (API >= android.os.Build.VERSION_CODES.KITKAT) {
  283. mSettings.setLayoutAlgorithm(LayoutAlgorithm.TEXT_AUTOSIZING);
  284. } else {
  285. mSettings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
  286. }
  287. mSettings.setBlockNetworkImage(mPreferences.getBoolean(PreferenceConstants.BLOCK_IMAGES,
  288. false));
  289. mSettings.setSupportMultipleWindows(mPreferences.getBoolean(PreferenceConstants.POPUPS,
  290. true));
  291. mSettings.setUseWideViewPort(mPreferences.getBoolean(PreferenceConstants.USE_WIDE_VIEWPORT,
  292. true));
  293. mWideViewPort = mPreferences.getBoolean(PreferenceConstants.USE_WIDE_VIEWPORT, true);
  294. mSettings.setLoadWithOverviewMode(mPreferences.getBoolean(
  295. PreferenceConstants.OVERVIEW_MODE, true));
  296. switch (mPreferences.getInt(PreferenceConstants.TEXT_SIZE, 3)) {
  297. case 1:
  298. mSettings.setTextZoom(200);
  299. break;
  300. case 2:
  301. mSettings.setTextZoom(150);
  302. break;
  303. case 3:
  304. mSettings.setTextZoom(100);
  305. break;
  306. case 4:
  307. mSettings.setTextZoom(75);
  308. break;
  309. case 5:
  310. mSettings.setTextZoom(50);
  311. break;
  312. }
  313. }
  314. @SuppressWarnings("deprecation")
  315. @SuppressLint({ "SetJavaScriptEnabled", "NewApi" })
  316. public void initializeSettings(WebSettings settings, Context context) {
  317. if (API < 18) {
  318. settings.setAppCacheMaxSize(Long.MAX_VALUE);
  319. }
  320. if (API < 17) {
  321. settings.setEnableSmoothTransition(true);
  322. }
  323. if (API > 16) {
  324. settings.setMediaPlaybackRequiresUserGesture(true);
  325. }
  326. if (API < 19) {
  327. settings.setDatabasePath(context.getFilesDir().getAbsolutePath() + "/databases");
  328. }
  329. settings.setDomStorageEnabled(true);
  330. settings.setAppCachePath(context.getCacheDir().toString());
  331. settings.setAppCacheEnabled(true);
  332. settings.setCacheMode(WebSettings.LOAD_DEFAULT);
  333. settings.setGeolocationDatabasePath(context.getCacheDir().getAbsolutePath());
  334. settings.setAllowFileAccess(true);
  335. settings.setDatabaseEnabled(true);
  336. settings.setSupportZoom(true);
  337. settings.setBuiltInZoomControls(true);
  338. settings.setDisplayZoomControls(false);
  339. settings.setAllowContentAccess(true);
  340. settings.setDefaultTextEncodingName("utf-8");
  341. if (API > 16) {
  342. settings.setAllowFileAccessFromFileURLs(false);
  343. settings.setAllowUniversalAccessFromFileURLs(false);
  344. }
  345. }
  346. public boolean isShown() {
  347. return mWebView != null && mWebView.isShown();
  348. }
  349. public synchronized void onPause() {
  350. if (mWebView != null) {
  351. mWebView.onPause();
  352. }
  353. }
  354. public synchronized void onResume() {
  355. if (mWebView != null) {
  356. mWebView.onResume();
  357. }
  358. }
  359. public void setForegroundTab(boolean isForeground) {
  360. isForegroundTab = isForeground;
  361. mBrowserController.update();
  362. }
  363. public boolean isForegroundTab() {
  364. return isForegroundTab;
  365. }
  366. public int getProgress() {
  367. if (mWebView != null) {
  368. return mWebView.getProgress();
  369. } else {
  370. return 100;
  371. }
  372. }
  373. public synchronized void stopLoading() {
  374. if (mWebView != null) {
  375. mWebView.stopLoading();
  376. }
  377. }
  378. public synchronized void pauseTimers() {
  379. if (mWebView != null) {
  380. mWebView.pauseTimers();
  381. }
  382. }
  383. public synchronized void resumeTimers() {
  384. if (mWebView != null) {
  385. mWebView.resumeTimers();
  386. }
  387. }
  388. public void requestFocus() {
  389. if (mWebView != null && !mWebView.hasFocus()) {
  390. mWebView.requestFocus();
  391. }
  392. }
  393. public void setVisibility(int visible) {
  394. if (mWebView != null) {
  395. mWebView.setVisibility(visible);
  396. }
  397. }
  398. public void clearCache(boolean disk) {
  399. if (mWebView != null) {
  400. mWebView.clearCache(disk);
  401. }
  402. }
  403. public synchronized void reload() {
  404. if (mWebView != null) {
  405. mWebView.reload();
  406. }
  407. }
  408. @SuppressWarnings("deprecation")
  409. @SuppressLint("NewApi")
  410. public synchronized void find(String text) {
  411. if (mWebView != null) {
  412. if (API > 16) {
  413. mWebView.findAllAsync(text);
  414. } else {
  415. mWebView.findAll(text);
  416. }
  417. }
  418. }
  419. public Activity getActivity() {
  420. return mActivity;
  421. }
  422. public synchronized void onDestroy() {
  423. if (mWebView != null) {
  424. mWebView.stopLoading();
  425. mWebView.onPause();
  426. mWebView.clearHistory();
  427. mWebView.setVisibility(View.GONE);
  428. mWebView.removeAllViews();
  429. mWebView.destroyDrawingCache();
  430. // mWebView.destroy(); //this is causing the segfault
  431. mWebView = null;
  432. }
  433. }
  434. public synchronized void goBack() {
  435. if (mWebView != null) {
  436. mWebView.goBack();
  437. }
  438. }
  439. public String getUserAgent() {
  440. if (mWebView != null) {
  441. return mWebView.getSettings().getUserAgentString();
  442. } else {
  443. return "";
  444. }
  445. }
  446. public synchronized void goForward() {
  447. if (mWebView != null) {
  448. mWebView.goForward();
  449. }
  450. }
  451. public boolean canGoBack() {
  452. return mWebView != null && mWebView.canGoBack();
  453. }
  454. public boolean canGoForward() {
  455. return mWebView != null && mWebView.canGoForward();
  456. }
  457. public WebView getWebView() {
  458. return mWebView;
  459. }
  460. public Bitmap getFavicon() {
  461. return mTitle.getFavicon();
  462. }
  463. public synchronized void loadUrl(String url) {
  464. if (mWebView != null) {
  465. mWebView.loadUrl(url);
  466. }
  467. }
  468. public synchronized void invalidate() {
  469. if (mWebView != null) {
  470. mWebView.invalidate();
  471. }
  472. }
  473. public String getTitle() {
  474. return mTitle.getTitle();
  475. }
  476. public String getUrl() {
  477. if (mWebView != null) {
  478. return mWebView.getUrl();
  479. } else {
  480. return "";
  481. }
  482. }
  483. public class LightningWebClient extends WebViewClient {
  484. Context mActivity;
  485. LightningWebClient(Context context) {
  486. mActivity = context;
  487. }
  488. @Override
  489. public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
  490. if (mAdBlock.isAd(url)) {
  491. ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes());
  492. return new WebResourceResponse("text/plain", "utf-8", EMPTY);
  493. }
  494. boolean useProxy = mPreferences.getBoolean(PreferenceConstants.USE_PROXY, false);
  495. boolean mDoLeakHardening = false;
  496. if (!useProxy) {
  497. return null;
  498. }
  499. if (!mDoLeakHardening) {
  500. return null;
  501. }
  502. // now we are going to proxy!
  503. try {
  504. URL uURl = new URL(url);
  505. Proxy proxy = null;
  506. String host = mPreferences.getString(PreferenceConstants.USE_PROXY_HOST,
  507. "localhost");
  508. int port = mPreferences.getInt(PreferenceConstants.USE_PROXY_PORT, 8118);
  509. proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port));
  510. HttpURLConnection.setFollowRedirects(true);
  511. HttpURLConnection conn = (HttpURLConnection) uURl.openConnection(proxy);
  512. conn.setInstanceFollowRedirects(true);
  513. conn.setRequestProperty("User-Agent", mSettings.getUserAgentString());
  514. // conn.setRequestProperty("Transfer-Encoding", "chunked");
  515. // conn.setUseCaches(false);
  516. final int bufferSize = 1024 * 32;
  517. conn.setChunkedStreamingMode(bufferSize);
  518. String cType = conn.getContentType();
  519. String cEnc = conn.getContentEncoding();
  520. int connLen = conn.getContentLength();
  521. if (cType != null) {
  522. String[] ctArray = cType.split(";");
  523. cType = ctArray[0].trim();
  524. if (cEnc == null && ctArray.length > 1) {
  525. cEnc = ctArray[1];
  526. if (cEnc.indexOf('=') != -1) {
  527. cEnc = cEnc.split("=")[1].trim();
  528. }
  529. }
  530. }
  531. if (connLen <= 0) {
  532. connLen = 2048;
  533. }
  534. if (cType != null && cType.startsWith("text")) {
  535. InputStream fStream;
  536. BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
  537. ByteArrayBuffer baf = new ByteArrayBuffer(connLen);
  538. int read;
  539. int bufSize = 2048;
  540. byte[] buffer = new byte[bufSize];
  541. while (true) {
  542. read = bis.read(buffer);
  543. if (read == -1) {
  544. break;
  545. }
  546. baf.append(buffer, 0, read);
  547. }
  548. byte[] plainText = baf.toByteArray();
  549. fStream = new ByteArrayInputStream(plainText);
  550. fStream = new ReplacingInputStream(new ByteArrayInputStream(plainText),
  551. "poster=".getBytes(), "foo=".getBytes());
  552. fStream = new ReplacingInputStream(fStream, "Poster=".getBytes(),
  553. "foo=".getBytes());
  554. fStream = new ReplacingInputStream(fStream, "Poster=".getBytes(),
  555. "foo=".getBytes());
  556. fStream = new ReplacingInputStream(fStream, ".poster".getBytes(),
  557. ".foo".getBytes());
  558. fStream = new ReplacingInputStream(fStream, "\"poster\"".getBytes(),
  559. "\"foo\"".getBytes());
  560. return new WebResourceResponse(cType, cEnc, fStream);
  561. }/**
  562. * else if (mDoLeakHardening) { WebResourceResponse response =
  563. * new WebResourceResponse( cType, cEnc, conn.getInputStream());
  564. *
  565. * return response;
  566. *
  567. * }
  568. */
  569. else {
  570. return null; // let webkit handle it
  571. }
  572. } catch (Exception e) {
  573. Log.e(Constants.TAG, "Error filtering stream", e);
  574. ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes());
  575. return new WebResourceResponse("text/plain", "utf-8", EMPTY);
  576. }
  577. }
  578. @Override
  579. public void onPageFinished(WebView view, String url) {
  580. if (view.isShown()) {
  581. view.invalidate();
  582. }
  583. if (view.getTitle() == null) {
  584. mTitle.setTitle(mActivity.getString(R.string.untitled));
  585. } else if (!view.getTitle().isEmpty()) {
  586. mTitle.setTitle(view.getTitle());
  587. } else {
  588. mTitle.setTitle(mActivity.getString(R.string.untitled));
  589. }
  590. mBrowserController.update();
  591. }
  592. @Override
  593. public void onPageStarted(WebView view, String url, Bitmap favicon) {
  594. if (!mSettings.getUseWideViewPort()) {
  595. mSettings.setUseWideViewPort(mWideViewPort);
  596. }
  597. if (isShown()) {
  598. mBrowserController.updateUrl(url);
  599. mBrowserController.showActionBar();
  600. }
  601. mTitle.setFavicon(mWebpageBitmap);
  602. mBrowserController.update();
  603. }
  604. @Override
  605. public void onReceivedHttpAuthRequest(final WebView view, final HttpAuthHandler handler,
  606. final String host, final String realm) {
  607. AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
  608. final EditText name = new EditText(mActivity);
  609. final EditText password = new EditText(mActivity);
  610. LinearLayout passLayout = new LinearLayout(mActivity);
  611. passLayout.setOrientation(LinearLayout.VERTICAL);
  612. passLayout.addView(name);
  613. passLayout.addView(password);
  614. name.setHint(mActivity.getString(R.string.hint_username));
  615. password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
  616. password.setTransformationMethod(new PasswordTransformationMethod());
  617. password.setHint(mActivity.getString(R.string.hint_password));
  618. builder.setTitle(mActivity.getString(R.string.title_sign_in));
  619. builder.setView(passLayout);
  620. builder.setCancelable(true)
  621. .setPositiveButton(mActivity.getString(R.string.title_sign_in),
  622. new DialogInterface.OnClickListener() {
  623. @Override
  624. public void onClick(DialogInterface dialog, int id) {
  625. String user = name.getText().toString();
  626. String pass = password.getText().toString();
  627. handler.proceed(user.trim(), pass.trim());
  628. Log.i(Constants.TAG, "Request Login");
  629. }
  630. })
  631. .setNegativeButton(mActivity.getString(R.string.action_cancel),
  632. new DialogInterface.OnClickListener() {
  633. @Override
  634. public void onClick(DialogInterface dialog, int id) {
  635. handler.cancel();
  636. }
  637. });
  638. AlertDialog alert = builder.create();
  639. alert.show();
  640. }
  641. @Override
  642. public void onScaleChanged(WebView view, float oldScale, float newScale) {
  643. if (view.isShown()) {
  644. view.invalidate();
  645. }
  646. }
  647. @Override
  648. public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
  649. AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
  650. builder.setTitle(mActivity.getString(R.string.title_warning));
  651. builder.setMessage(mActivity.getString(R.string.message_untrusted_certificate))
  652. .setCancelable(true)
  653. .setPositiveButton(mActivity.getString(R.string.action_yes),
  654. new DialogInterface.OnClickListener() {
  655. @Override
  656. public void onClick(DialogInterface dialog, int id) {
  657. handler.proceed();
  658. }
  659. })
  660. .setNegativeButton(mActivity.getString(R.string.action_no),
  661. new DialogInterface.OnClickListener() {
  662. @Override
  663. public void onClick(DialogInterface dialog, int id) {
  664. handler.cancel();
  665. }
  666. });
  667. AlertDialog alert = builder.create();
  668. if (error.getPrimaryError() == SslError.SSL_UNTRUSTED) {
  669. alert.show();
  670. } else {
  671. handler.proceed();
  672. }
  673. }
  674. @Override
  675. public void onFormResubmission(WebView view, final Message dontResend, final Message resend) {
  676. AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
  677. builder.setTitle(mActivity.getString(R.string.title_form_resubmission));
  678. builder.setMessage(mActivity.getString(R.string.message_form_resubmission))
  679. .setCancelable(true)
  680. .setPositiveButton(mActivity.getString(R.string.action_yes),
  681. new DialogInterface.OnClickListener() {
  682. @Override
  683. public void onClick(DialogInterface dialog, int id) {
  684. resend.sendToTarget();
  685. }
  686. })
  687. .setNegativeButton(mActivity.getString(R.string.action_no),
  688. new DialogInterface.OnClickListener() {
  689. @Override
  690. public void onClick(DialogInterface dialog, int id) {
  691. dontResend.sendToTarget();
  692. }
  693. });
  694. AlertDialog alert = builder.create();
  695. alert.show();
  696. }
  697. @Override
  698. public boolean shouldOverrideUrlLoading(WebView view, String url) {
  699. if (url.startsWith("about:")) {
  700. return super.shouldOverrideUrlLoading(view, url);
  701. }
  702. if (url.contains("mailto:")) {
  703. MailTo mailTo = MailTo.parse(url);
  704. Intent i = Utils.newEmailIntent(mActivity, mailTo.getTo(), mailTo.getSubject(),
  705. mailTo.getBody(), mailTo.getCc());
  706. mActivity.startActivity(i);
  707. view.reload();
  708. return true;
  709. } else if (url.startsWith("intent://")) {
  710. Intent intent = null;
  711. try {
  712. intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
  713. } catch (URISyntaxException ex) {
  714. return false;
  715. }
  716. if (intent != null) {
  717. try {
  718. mActivity.startActivity(intent);
  719. } catch (ActivityNotFoundException e) {
  720. Log.e(Constants.TAG, "ActivityNotFoundException");
  721. }
  722. return true;
  723. }
  724. }
  725. return mIntentUtils.startActivityForUrl(mWebView, url);
  726. }
  727. }
  728. public class LightningChromeClient extends WebChromeClient {
  729. Context mActivity;
  730. LightningChromeClient(Context context) {
  731. mActivity = context;
  732. }
  733. @Override
  734. public void onProgressChanged(WebView view, int newProgress) {
  735. if (isShown()) {
  736. mBrowserController.updateProgress(newProgress);
  737. }
  738. }
  739. @Override
  740. public void onReceivedIcon(WebView view, Bitmap icon) {
  741. mTitle.setFavicon(icon);
  742. mBrowserController.update();
  743. }
  744. @Override
  745. public void onReceivedTitle(WebView view, String title) {
  746. if (!title.isEmpty()) {
  747. mTitle.setTitle(title);
  748. } else {
  749. mTitle.setTitle(mActivity.getString(R.string.untitled));
  750. }
  751. mBrowserController.update();
  752. mBrowserController.updateHistory(title, view.getUrl());
  753. }
  754. @Override
  755. public void onGeolocationPermissionsShowPrompt(final String origin,
  756. final GeolocationPermissions.Callback callback) {
  757. final boolean remember = true;
  758. AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
  759. builder.setTitle(mActivity.getString(R.string.location));
  760. String org = null;
  761. if (origin.length() > 50) {
  762. org = origin.subSequence(0, 50) + "...";
  763. } else {
  764. org = origin;
  765. }
  766. builder.setMessage(org + mActivity.getString(R.string.message_location))
  767. .setCancelable(true)
  768. .setPositiveButton(mActivity.getString(R.string.action_allow),
  769. new DialogInterface.OnClickListener() {
  770. @Override
  771. public void onClick(DialogInterface dialog, int id) {
  772. callback.invoke(origin, true, remember);
  773. }
  774. })
  775. .setNegativeButton(mActivity.getString(R.string.action_dont_allow),
  776. new DialogInterface.OnClickListener() {
  777. @Override
  778. public void onClick(DialogInterface dialog, int id) {
  779. callback.invoke(origin, false, remember);
  780. }
  781. });
  782. AlertDialog alert = builder.create();
  783. alert.show();
  784. }
  785. @Override
  786. public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture,
  787. Message resultMsg) {
  788. mBrowserController.onCreateWindow(isUserGesture, resultMsg);
  789. return isUserGesture;
  790. }
  791. @Override
  792. public void onCloseWindow(WebView window) {
  793. // TODO Auto-generated method stub
  794. super.onCloseWindow(window);
  795. }
  796. public void openFileChooser(ValueCallback<Uri> uploadMsg) {
  797. mBrowserController.openFileChooser(uploadMsg);
  798. }
  799. public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
  800. mBrowserController.openFileChooser(uploadMsg);
  801. }
  802. public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
  803. mBrowserController.openFileChooser(uploadMsg);
  804. }
  805. @Override
  806. public Bitmap getDefaultVideoPoster() {
  807. return mBrowserController.getDefaultVideoPoster();
  808. }
  809. @Override
  810. public View getVideoLoadingProgressView() {
  811. return mBrowserController.getVideoLoadingProgressView();
  812. }
  813. @Override
  814. public void onHideCustomView() {
  815. mBrowserController.onHideCustomView();
  816. super.onHideCustomView();
  817. }
  818. @Override
  819. public void onShowCustomView(View view, CustomViewCallback callback) {
  820. // While these lines might look like they work, in practice,
  821. // Full-screen videos won't work correctly. I may test this out some
  822. // more
  823. // if (view instanceof FrameLayout) {
  824. // FrameLayout frame = (FrameLayout) view;
  825. // if (frame.getFocusedChild() instanceof VideoView) {
  826. // VideoView video = (VideoView) frame.getFocusedChild();
  827. // video.stopPlayback();
  828. // frame.removeView(video);
  829. // video.setVisibility(View.GONE);
  830. // }
  831. // } else {
  832. Activity activity = mBrowserController.getActivity();
  833. mBrowserController.onShowCustomView(view, activity.getRequestedOrientation(), callback);
  834. // }
  835. super.onShowCustomView(view, callback);
  836. }
  837. @Override
  838. @Deprecated
  839. public void onShowCustomView(View view, int requestedOrientation,
  840. CustomViewCallback callback) {
  841. // While these lines might look like they work, in practice,
  842. // Full-screen videos won't work correctly. I may test this out some
  843. // more
  844. // if (view instanceof FrameLayout) {
  845. // FrameLayout frame = (FrameLayout) view;
  846. // if (frame.getFocusedChild() instanceof VideoView) {
  847. // VideoView video = (VideoView) frame.getFocusedChild();
  848. // video.stopPlayback();
  849. // frame.removeView(video);
  850. // video.setVisibility(View.GONE);
  851. // }
  852. // } else {
  853. mBrowserController.onShowCustomView(view, requestedOrientation, callback);
  854. // }
  855. super.onShowCustomView(view, requestedOrientation, callback);
  856. }
  857. }
  858. public class Title {
  859. private Bitmap mFavicon;
  860. private String mTitle;
  861. private Bitmap mDefaultIcon;
  862. public Title(Context context) {
  863. mDefaultIcon = BitmapFactory.decodeResource(context.getResources(),
  864. R.drawable.ic_webpage);
  865. mFavicon = mDefaultIcon;
  866. mTitle = mActivity.getString(R.string.action_new_tab);
  867. }
  868. public void setFavicon(Bitmap favicon) {
  869. mFavicon = favicon;
  870. if (mFavicon == null) {
  871. mFavicon = mDefaultIcon;
  872. }
  873. }
  874. public void setTitle(String title) {
  875. if (title == null) {
  876. mTitle = "";
  877. } else {
  878. mTitle = title;
  879. }
  880. }
  881. public void setTitleAndFavicon(String title, Bitmap favicon) {
  882. mTitle = title;
  883. mFavicon = favicon;
  884. if (mFavicon == null) {
  885. mFavicon = mDefaultIcon;
  886. }
  887. }
  888. public String getTitle() {
  889. return mTitle;
  890. }
  891. public Bitmap getFavicon() {
  892. return mFavicon;
  893. }
  894. }
  895. private class CustomGestureListener extends SimpleOnGestureListener {
  896. @Override
  897. public void onLongPress(MotionEvent e) {
  898. mBrowserController.onLongPress();
  899. }
  900. }
  901. }