PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/acr/browser/thunder/LightningView.java

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