PageRenderTime 54ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

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

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