diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 40622c5db..000000000
--- a/.gitmodules
+++ /dev/null
@@ -1,10 +0,0 @@
-[submodule "external/netcipher"]
- path = external/netcipher
- url = https://github.com/guardianproject/NetCipher.git
- branch = master
-[submodule "Bonsai"]
- path = Bonsai
- url = https://github.com/anthonycr/Bonsai.git
-[submodule "AnimatedProgressBar"]
- path = AnimatedProgressBar
- url = https://github.com/anthonycr/AnimatedProgressBar.git
diff --git a/.travis.yml b/.travis.yml
index 1fc5f7032..d0075eb88 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,12 +5,8 @@ jdk:
android:
components:
- tools
- - build-tools-24.0.3
- - build-tools-23.0.3
- - build-tools-22.0.1
- - android-24
- - android-23
- - android-22
+ - build-tools-25.0.3
+ - android-25
- extra-android-support
- extra-android-m2repository
licenses:
diff --git a/AnimatedProgressBar b/AnimatedProgressBar
deleted file mode 160000
index 2d7f756be..000000000
--- a/AnimatedProgressBar
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 2d7f756be8f562b2cedca46de7d2ff24f9383040
diff --git a/Bonsai b/Bonsai
deleted file mode 160000
index 53608c03b..000000000
--- a/Bonsai
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 53608c03b77d598aaebd17eb0acbedd8ffb1bf51
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 000000000..8d1521ce8
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,74 @@
+Change Log
+==========
+
+Version 4.5.0 *(2017-06-08)*
+----------------------------
+- Translation updates
+- Memory leak fixes
+- Basic keyboard shortcut support
+- Improved browser dialogs
+- Improved ad block efficiency
+- Improved bookmark storage
+- Added setting for black status bar
+- Added downloads page
+- Baidu search suggestions option
+- Updated bookmark page UI
+- Updated history page UI
+- Fixed numerous bugs
+
+Version 4.4.1 *(2016-11-05)*
+----------------------------
+- Fixed bookmark/tab drawer crash
+- Fixed search suggestions crash on start up
+- Fixed bug where links wouldn't open in the browser if you had the "restore lost tabs" option disabled
+
+Version 4.4.0 *(2016-10-30)*
+----------------------------
+- Android 7.0 support
+- Improved long-press menu
+- Bookmark and tab drawers can be swapped
+- Improved downloading of files
+- Improved link handling for apps
+- DuckDuckGo powered search suggestions
+- UI improvements for readability
+- Fixed text selection bugs in URL bar
+- Fixed find in page bug
+- Fixed image sync problems with bookmarks
+- Fixed various crashes
+- Fixed search suggestion bug
+
+
+Version 4.3.3 *(2016-04-23)*
+----------------------------
+- Added option to request "Do Not Track"
+- Added option to hide X-Requested-With header
+- Added option to hide X-Wap-Profile
+- Added language support in google search suggestions
+- Added home screen widget
+- Added new tab button on tablet UI
+- Added tab add/remove animation on both tablet and phone UI
+- Added close tabs dialog (long-press back button)
+- Number icon instead of hamburger icon for better usability
+- Back/forward arrows change color in tablet UI to indicate that you can go back/forward
+- Search bar color now matches rest of UI
+- Smoothed drawer/open close experience
+- Fixed intent handling vulnerability
+- Fixed downloading crash (marshmallow)
+- Fixed various bugs related to settings, settings not getting remembered, etc.
+- Fixed bugs that happened when browser went to the background
+- Fixed bugs with search bar size changing/not changing when supposed to
+- Updated ad block definition
+- Started to improve app architecture
+
+Version 4.2.3 *(2015-09-30)*
+----------------------------
+- Tablet UI (optional)
+- Support for Marshmallow
+- Improved Reading Mode
+- Added animations between screens
+- Fixed some memory leaks
+- Added bookmark folder support!
+- Improved full-screen mode
+- Settings revamp (thanks community)
+- Updated icons + UI cleanup
+- Added actions to the bookmarks drawer
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 66f4f57ab..a612ad981 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,10 +1,373 @@
-Copyright 2014 Anthony Restaino
+Mozilla Public License Version 2.0
+==================================
-Lightning Browser
+1. Definitions
+--------------
- This Source Code Form is subject to the terms of the
- Mozilla Public License, v. 2.0. If a copy of the MPL
- was not distributed with this file, You can obtain one at
-
- http://mozilla.org/MPL/2.0/
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/Lightning-Browser.iml b/Lightning-Browser.iml
deleted file mode 100644
index 1f7c20064..000000000
--- a/Lightning-Browser.iml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Mozilla Public License v. 2.0 b/Mozilla Public License v. 2.0
deleted file mode 100644
index be2cc4dfb..000000000
--- a/Mozilla Public License v. 2.0
+++ /dev/null
@@ -1,362 +0,0 @@
-Mozilla Public License, version 2.0
-
-1. Definitions
-
-1.1. "Contributor"
-
- means each individual or legal entity that creates, contributes to the
- creation of, or owns Covered Software.
-
-1.2. "Contributor Version"
-
- means the combination of the Contributions of others (if any) used by a
- Contributor and that particular Contributor's Contribution.
-
-1.3. "Contribution"
-
- means Covered Software of a particular Contributor.
-
-1.4. "Covered Software"
-
- means Source Code Form to which the initial Contributor has attached the
- notice in Exhibit A, the Executable Form of such Source Code Form, and
- Modifications of such Source Code Form, in each case including portions
- thereof.
-
-1.5. "Incompatible With Secondary Licenses"
- means
-
- a. that the initial Contributor has attached the notice described in
- Exhibit B to the Covered Software; or
-
- b. that the Covered Software was made available under the terms of
- version 1.1 or earlier of the License, but not also under the terms of
- a Secondary License.
-
-1.6. "Executable Form"
-
- means any form of the work other than Source Code Form.
-
-1.7. "Larger Work"
-
- means a work that combines Covered Software with other material, in a
- separate file or files, that is not Covered Software.
-
-1.8. "License"
-
- means this document.
-
-1.9. "Licensable"
-
- means having the right to grant, to the maximum extent possible, whether
- at the time of the initial grant or subsequently, any and all of the
- rights conveyed by this License.
-
-1.10. "Modifications"
-
- means any of the following:
-
- a. any file in Source Code Form that results from an addition to,
- deletion from, or modification of the contents of Covered Software; or
-
- b. any new file in Source Code Form that contains any Covered Software.
-
-1.11. "Patent Claims" of a Contributor
-
- means any patent claim(s), including without limitation, method,
- process, and apparatus claims, in any patent Licensable by such
- Contributor that would be infringed, but for the grant of the License,
- by the making, using, selling, offering for sale, having made, import,
- or transfer of either its Contributions or its Contributor Version.
-
-1.12. "Secondary License"
-
- means either the GNU General Public License, Version 2.0, the GNU Lesser
- General Public License, Version 2.1, the GNU Affero General Public
- License, Version 3.0, or any later versions of those licenses.
-
-1.13. "Source Code Form"
-
- means the form of the work preferred for making modifications.
-
-1.14. "You" (or "Your")
-
- means an individual or a legal entity exercising rights under this
- License. For legal entities, "You" includes any entity that controls, is
- controlled by, or is under common control with You. For purposes of this
- definition, "control" means (a) the power, direct or indirect, to cause
- the direction or management of such entity, whether by contract or
- otherwise, or (b) ownership of more than fifty percent (50%) of the
- outstanding shares or beneficial ownership of such entity.
-
-
-2. License Grants and Conditions
-
-2.1. Grants
-
- Each Contributor hereby grants You a world-wide, royalty-free,
- non-exclusive license:
-
- a. under intellectual property rights (other than patent or trademark)
- Licensable by such Contributor to use, reproduce, make available,
- modify, display, perform, distribute, and otherwise exploit its
- Contributions, either on an unmodified basis, with Modifications, or
- as part of a Larger Work; and
-
- b. under Patent Claims of such Contributor to make, use, sell, offer for
- sale, have made, import, and otherwise transfer either its
- Contributions or its Contributor Version.
-
-2.2. Effective Date
-
- The licenses granted in Section 2.1 with respect to any Contribution
- become effective for each Contribution on the date the Contributor first
- distributes such Contribution.
-
-2.3. Limitations on Grant Scope
-
- The licenses granted in this Section 2 are the only rights granted under
- this License. No additional rights or licenses will be implied from the
- distribution or licensing of Covered Software under this License.
- Notwithstanding Section 2.1(b) above, no patent license is granted by a
- Contributor:
-
- a. for any code that a Contributor has removed from Covered Software; or
-
- b. for infringements caused by: (i) Your and any other third party's
- modifications of Covered Software, or (ii) the combination of its
- Contributions with other software (except as part of its Contributor
- Version); or
-
- c. under Patent Claims infringed by Covered Software in the absence of
- its Contributions.
-
- This License does not grant any rights in the trademarks, service marks,
- or logos of any Contributor (except as may be necessary to comply with
- the notice requirements in Section 3.4).
-
-2.4. Subsequent Licenses
-
- No Contributor makes additional grants as a result of Your choice to
- distribute the Covered Software under a subsequent version of this
- License (see Section 10.2) or under the terms of a Secondary License (if
- permitted under the terms of Section 3.3).
-
-2.5. Representation
-
- Each Contributor represents that the Contributor believes its
- Contributions are its original creation(s) or it has sufficient rights to
- grant the rights to its Contributions conveyed by this License.
-
-2.6. Fair Use
-
- This License is not intended to limit any rights You have under
- applicable copyright doctrines of fair use, fair dealing, or other
- equivalents.
-
-2.7. Conditions
-
- Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
- Section 2.1.
-
-
-3. Responsibilities
-
-3.1. Distribution of Source Form
-
- All distribution of Covered Software in Source Code Form, including any
- Modifications that You create or to which You contribute, must be under
- the terms of this License. You must inform recipients that the Source
- Code Form of the Covered Software is governed by the terms of this
- License, and how they can obtain a copy of this License. You may not
- attempt to alter or restrict the recipients' rights in the Source Code
- Form.
-
-3.2. Distribution of Executable Form
-
- If You distribute Covered Software in Executable Form then:
-
- a. such Covered Software must also be made available in Source Code Form,
- as described in Section 3.1, and You must inform recipients of the
- Executable Form how they can obtain a copy of such Source Code Form by
- reasonable means in a timely manner, at a charge no more than the cost
- of distribution to the recipient; and
-
- b. You may distribute such Executable Form under the terms of this
- License, or sublicense it under different terms, provided that the
- license for the Executable Form does not attempt to limit or alter the
- recipients' rights in the Source Code Form under this License.
-
-3.3. Distribution of a Larger Work
-
- You may create and distribute a Larger Work under terms of Your choice,
- provided that You also comply with the requirements of this License for
- the Covered Software. If the Larger Work is a combination of Covered
- Software with a work governed by one or more Secondary Licenses, and the
- Covered Software is not Incompatible With Secondary Licenses, this
- License permits You to additionally distribute such Covered Software
- under the terms of such Secondary License(s), so that the recipient of
- the Larger Work may, at their option, further distribute the Covered
- Software under the terms of either this License or such Secondary
- License(s).
-
-3.4. Notices
-
- You may not remove or alter the substance of any license notices
- (including copyright notices, patent notices, disclaimers of warranty, or
- limitations of liability) contained within the Source Code Form of the
- Covered Software, except that You may alter any license notices to the
- extent required to remedy known factual inaccuracies.
-
-3.5. Application of Additional Terms
-
- You may choose to offer, and to charge a fee for, warranty, support,
- indemnity or liability obligations to one or more recipients of Covered
- Software. However, You may do so only on Your own behalf, and not on
- behalf of any Contributor. You must make it absolutely clear that any
- such warranty, support, indemnity, or liability obligation is offered by
- You alone, and You hereby agree to indemnify every Contributor for any
- liability incurred by such Contributor as a result of warranty, support,
- indemnity or liability terms You offer. You may include additional
- disclaimers of warranty and limitations of liability specific to any
- jurisdiction.
-
-4. Inability to Comply Due to Statute or Regulation
-
- If it is impossible for You to comply with any of the terms of this License
- with respect to some or all of the Covered Software due to statute,
- judicial order, or regulation then You must: (a) comply with the terms of
- this License to the maximum extent possible; and (b) describe the
- limitations and the code they affect. Such description must be placed in a
- text file included with all distributions of the Covered Software under
- this License. Except to the extent prohibited by statute or regulation,
- such description must be sufficiently detailed for a recipient of ordinary
- skill to be able to understand it.
-
-5. Termination
-
-5.1. The rights granted under this License will terminate automatically if You
- fail to comply with any of its terms. However, if You become compliant,
- then the rights granted under this License from a particular Contributor
- are reinstated (a) provisionally, unless and until such Contributor
- explicitly and finally terminates Your grants, and (b) on an ongoing
- basis, if such Contributor fails to notify You of the non-compliance by
- some reasonable means prior to 60 days after You have come back into
- compliance. Moreover, Your grants from a particular Contributor are
- reinstated on an ongoing basis if such Contributor notifies You of the
- non-compliance by some reasonable means, this is the first time You have
- received notice of non-compliance with this License from such
- Contributor, and You become compliant prior to 30 days after Your receipt
- of the notice.
-
-5.2. If You initiate litigation against any entity by asserting a patent
- infringement claim (excluding declaratory judgment actions,
- counter-claims, and cross-claims) alleging that a Contributor Version
- directly or indirectly infringes any patent, then the rights granted to
- You by any and all Contributors for the Covered Software under Section
- 2.1 of this License shall terminate.
-
-5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
- license agreements (excluding distributors and resellers) which have been
- validly granted by You or Your distributors under this License prior to
- termination shall survive termination.
-
-6. Disclaimer of Warranty
-
- Covered Software is provided under this License on an "as is" basis,
- without warranty of any kind, either expressed, implied, or statutory,
- including, without limitation, warranties that the Covered Software is free
- of defects, merchantable, fit for a particular purpose or non-infringing.
- The entire risk as to the quality and performance of the Covered Software
- is with You. Should any Covered Software prove defective in any respect,
- You (not any Contributor) assume the cost of any necessary servicing,
- repair, or correction. This disclaimer of warranty constitutes an essential
- part of this License. No use of any Covered Software is authorized under
- this License except under this disclaimer.
-
-7. Limitation of Liability
-
- Under no circumstances and under no legal theory, whether tort (including
- negligence), contract, or otherwise, shall any Contributor, or anyone who
- distributes Covered Software as permitted above, be liable to You for any
- direct, indirect, special, incidental, or consequential damages of any
- character including, without limitation, damages for lost profits, loss of
- goodwill, work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses, even if such party shall have been
- informed of the possibility of such damages. This limitation of liability
- shall not apply to liability for death or personal injury resulting from
- such party's negligence to the extent applicable law prohibits such
- limitation. Some jurisdictions do not allow the exclusion or limitation of
- incidental or consequential damages, so this exclusion and limitation may
- not apply to You.
-
-8. Litigation
-
- Any litigation relating to this License may be brought only in the courts
- of a jurisdiction where the defendant maintains its principal place of
- business and such litigation shall be governed by laws of that
- jurisdiction, without reference to its conflict-of-law provisions. Nothing
- in this Section shall prevent a party's ability to bring cross-claims or
- counter-claims.
-
-9. Miscellaneous
-
- This License represents the complete agreement concerning the subject
- matter hereof. If any provision of this License is held to be
- unenforceable, such provision shall be reformed only to the extent
- necessary to make it enforceable. Any law or regulation which provides that
- the language of a contract shall be construed against the drafter shall not
- be used to construe this License against a Contributor.
-
-
-10. Versions of the License
-
-10.1. New Versions
-
- Mozilla Foundation is the license steward. Except as provided in Section
- 10.3, no one other than the license steward has the right to modify or
- publish new versions of this License. Each version will be given a
- distinguishing version number.
-
-10.2. Effect of New Versions
-
- You may distribute the Covered Software under the terms of the version
- of the License under which You originally received the Covered Software,
- or under the terms of any subsequent version published by the license
- steward.
-
-10.3. Modified Versions
-
- If you create software not governed by this License, and you want to
- create a new license for such software, you may create and use a
- modified version of this License if you rename the license and remove
- any references to the name of the license steward (except to note that
- such modified license differs from this License).
-
-10.4. Distributing Source Code Form that is Incompatible With Secondary
- Licenses If You choose to distribute Source Code Form that is
- Incompatible With Secondary Licenses under the terms of this version of
- the License, the notice described in Exhibit B of this License must be
- attached.
-
-Exhibit A - Source Code Form License Notice
-
- This Source Code Form is subject to the
- terms of the Mozilla Public License, v.
- 2.0. If a copy of the MPL was not
- distributed with this file, You can
- obtain one at
- http://mozilla.org/MPL/2.0/.
-
-If it is not possible or desirable to put the notice in a particular file,
-then You may include the notice in a location (such as a LICENSE file in a
-relevant directory) where a recipient would be likely to look for such a
-notice.
-
-You may add additional accurate notices of copyright ownership.
-
-Exhibit B - "Incompatible With Secondary Licenses" Notice
-
- This Source Code Form is "Incompatible
- With Secondary Licenses", as defined by
- the Mozilla Public License, v. 2.0.
diff --git a/README.md b/README.md
index 411e2cc30..43a7f3bab 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,9 @@
-#Lightning Browser [![Build Status](https://travis-ci.org/anthonycr/Lightning-Browser.svg?branch=master)](https://travis-ci.org/anthonycr/Lightning-Browser)
-####Speed, Simplicity, Security
-#![](ic_launcher_small.png)
-####Download
+# Lightning Browser [![Build Status](https://travis-ci.org/anthonycr/Lightning-Browser.svg?branch=master)](https://travis-ci.org/anthonycr/Lightning-Browser)
+
+#### Speed, Simplicity, Security
+![](ic_launcher_small.png)
+
+#### Download
* [Download APK from here](https://github.com/anthonycr/Lightning-Browser/releases)
* [Download from F-Droid](https://f-droid.org/repository/browse/?fdfilter=lightning&fdid=acr.browser.lightning)
@@ -10,13 +12,13 @@
* [Download Paid from Google Play](https://play.google.com/store/apps/details?id=acr.browser.lightning)
-####Master Branch
+#### Master Branch
* [![Build Status](https://travis-ci.org/anthonycr/Lightning-Browser.svg?branch=master)](https://travis-ci.org/anthonycr/Lightning-Browser)
-####Dev Branch
+#### Dev Branch
* [![Build Status](https://travis-ci.org/anthonycr/Lightning-Browser.svg?branch=dev)](https://travis-ci.org/anthonycr/Lightning-Browser)
-####Features
+#### Features
* Bookmarks
* History
@@ -33,7 +35,7 @@
* Orbot Proxy support and I2P support
-####Permissions
+#### Permissions
* ````INTERNET````: For accessing the web
@@ -45,11 +47,11 @@
* ````ACCESS_NETWORK_STATE````: Required for the WebView to function by some OEM versions of WebKit
-####The Code
+#### The Code
* Please contribute code back if you can. The code isn't perfect.
* Please add translations/translation fixes as you see need
-####Contributing
+#### Contributing
* [The Trello Board](https://trello.com/b/Gwjx8MC3/lightning-browser)
* Contributions are always welcome
* If you want a feature and can code, feel free to fork and add the change yourself and make a pull request
@@ -60,15 +62,8 @@
* Prefix static member variables with 's'
* Use 4 spaces instead of a tab (\t)
-####Setting Up the Project
-Due to the inclusion of the netcipher library for Orbot proxy support, importing the project will show you some errors. To fix this, first run the following git command in your project folder (NOTE: You need the git command installed to use this):
-````
-git submodule update --init --recursive
-````
-Once you run that command, the IDE should automatically import netcipher and a couple submodules in as separate projects. Than you need to set the netcipher library project as a libary of the browser project however your IDE makes you do that. Once those steps are done, the project should be all set up and ready to go. [Please read this tutorial for more information on git submodules](http://www.vogella.com/tutorials/Git/article.html#submodules)
-
-####License
-````
+#### License
+```
Copyright 2014 Anthony Restaino
Lightning Browser
@@ -78,7 +73,4 @@ Lightning Browser
was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/
-````
-This means that you MUST provide attribution in your application to Lightning Browser for the use of this code. The way you can do this is to provide a separate screen in settings showing what open-source libraries and/or apps (this one) you used in your application. You must also open-source any files that you use from this repository and if you use any code at all from this repository, the file you put it in must be open-sourced according the the MPL 2.0 license. To put it simply, if you create a fork of this browser, your browser must be open-source, no exceptions. The only way to avoid open-sourcing a file is to completely write all the code yourself and to not use any code from Lightning. This is in order to provide a way for companies to utilize the code without making private server code public. For further explanation, please email me, or seek legal counsel :-P
-
-If you have any questions regarding the open-source license, please contact me at [anthonyrestaino11@gmail.com](mailto:anthonyrestaino11@gmail.com)
+```
diff --git a/app/build.gradle b/app/build.gradle
index 2ae1a3c3b..451c6d713 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,15 +1,14 @@
apply plugin: 'com.android.application'
-apply plugin: 'com.neenbedankt.android-apt'
apply plugin: 'com.getkeepsafe.dexcount'
android {
- compileSdkVersion 24
- buildToolsVersion "24.0.3"
+ compileSdkVersion 25
+ buildToolsVersion '25.0.3'
defaultConfig {
minSdkVersion 14
- targetSdkVersion 24
- versionName "4.4.1"
+ targetSdkVersion 25
+ versionName project.versionName
vectorDrawables.useSupportLibrary = true
}
@@ -34,15 +33,15 @@ android {
productFlavors {
lightningPlus {
- buildConfigField "boolean", "FULL_VERSION", "true"
+ buildConfigField "boolean", "FULL_VERSION", "Boolean.parseBoolean(\"true\")"
applicationId "acr.browser.lightning"
- versionCode 90
+ versionCode project.versionCode_plus
}
lightningLite {
- buildConfigField "boolean", "FULL_VERSION", "false"
+ buildConfigField "boolean", "FULL_VERSION", "Boolean.parseBoolean(\"false\")"
applicationId "acr.browser.barebones"
- versionCode 92
+ versionCode project.versionCode_lite
}
}
@@ -58,7 +57,7 @@ android {
dexcount {
includeClasses = false
includeFieldCount = false
- printAsTree = true
+ format = "tree"
orderByMethodCount = true
verbose = false
}
@@ -66,25 +65,26 @@ dexcount {
dependencies {
// support libraries
- compile 'com.android.support:palette-v7:24.2.1'
- compile 'com.android.support:appcompat-v7:24.2.1'
- compile 'com.android.support:design:24.2.1'
- compile 'com.android.support:recyclerview-v7:24.2.1'
- compile 'com.android.support:support-v4:24.2.1'
+ def supportLibVersion = '25.3.1'
+ compile "com.android.support:palette-v7:$supportLibVersion"
+ compile "com.android.support:appcompat-v7:$supportLibVersion"
+ compile "com.android.support:design:$supportLibVersion"
+ compile "com.android.support:recyclerview-v7:$supportLibVersion"
+ compile "com.android.support:support-v4:$supportLibVersion"
// html parsing for reading mode
- compile 'org.jsoup:jsoup:1.9.2'
-
- // event bus
- compile 'com.squareup:otto:1.3.8'
+ compile 'org.jsoup:jsoup:1.10.2'
// dependency injection
- compile 'com.google.dagger:dagger:2.0.2'
- apt 'com.google.dagger:dagger-compiler:2.0.2'
+ def daggerVersion = '2.11'
+ compile "com.google.dagger:dagger:$daggerVersion"
+ annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
provided 'javax.annotation:jsr250-api:1.0'
// view binding
- compile 'com.jakewharton:butterknife:7.0.1'
+ def butterknifeVersion = '8.6.0'
+ compile "com.jakewharton:butterknife:$butterknifeVersion"
+ annotationProcessor "com.jakewharton:butterknife-compiler:$butterknifeVersion"
// permissions
compile 'com.anthonycr.grant:permissions:1.1.2'
@@ -92,16 +92,19 @@ dependencies {
// proxy support
compile 'net.i2p.android:client:0.8'
- // Use the following code to update the libnetcipher submodule
- // git submodule foreach git reset --hard
- // git submodule update --remote
- compile project(':libnetcipher')
+ compile 'com.squareup.okhttp3:okhttp:3.8.0'
+
+ // tor proxy
+ def netcipherVersion = '2.0.0-alpha1'
+ compile "info.guardianproject.netcipher:netcipher:$netcipherVersion"
+ compile "info.guardianproject.netcipher:netcipher-webkit:$netcipherVersion"
- compile project(':bonsai')
+ compile 'com.anthonycr.bonsai:bonsai:1.1.0'
- compile project(':animated-progress-bar')
+ compile 'com.anthonycr.progress:animated-progress:1.0'
// memory leak analysis
- debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4'
- releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4'
-}
\ No newline at end of file
+ def leakCanaryVersion = '1.5.1'
+ debugCompile "com.squareup.leakcanary:leakcanary-android:$leakCanaryVersion"
+ releaseCompile "com.squareup.leakcanary:leakcanary-android-no-op:$leakCanaryVersion"
+}
diff --git a/app/proguard-project.txt b/app/proguard-project.txt
index 40cddda10..4c1bb3ddb 100644
--- a/app/proguard-project.txt
+++ b/app/proguard-project.txt
@@ -111,3 +111,8 @@
-dontwarn org.apache.http.conn.ssl.DefaultHostnameVerifier
-dontwarn org.apache.http.HttpHost
+
+# Needed for okhttp
+-dontwarn okio.**
+-dontwarn javax.annotation.Nullable
+-dontwarn javax.annotation.ParametersAreNonnullByDefault
diff --git a/app/src/LightningPlus/assets/hosts.txt b/app/src/LightningPlus/assets/hosts.txt
index 5377c6a1f..e9d12ca49 100644
--- a/app/src/LightningPlus/assets/hosts.txt
+++ b/app/src/LightningPlus/assets/hosts.txt
@@ -15,6 +15,7 @@
127.0.0.1 007.go2cloud.org
127.0.0.1 0075-7112-e7eb-f9b9.reporo.net
127.0.0.1 008.free-counter.co.uk
+127.0.0.1 00zasdf.pw
127.0.0.1 011i5.voluumtrk.com
127.0.0.1 0124498474f7c13ac9a2-6b191446002b31342189d56cabcf5227.r11.cf2.rackcdn.com
127.0.0.1 02gzx.voluumtrk.com
@@ -1797,6 +1798,10 @@
127.0.0.1 abandonglare.8m.com
127.0.0.1 abbie-surber.us
127.0.0.1 abbott.vo.llnwd.net
+127.0.0.1 abbp1.pw
+127.0.0.1 abbp1.science
+127.0.0.1 abbp1.space
+127.0.0.1 abbp1.website
127.0.0.1 abby-clowers.us
127.0.0.1 abc.apportium.com
127.0.0.1 abc.bnex.com
@@ -18571,6 +18576,8 @@
127.0.0.1 adspaes.ero-advertising.com
127.0.0.1 adspages.ero-advertising.com
127.0.0.1 adspaper.org
+127.0.0.1 adspayformy.site
+127.0.0.1 adspayformymortgage.win
127.0.0.1 adspcces.ero-advertising.com
127.0.0.1 adspdbl.com
127.0.0.1 adspeed.com
@@ -24020,7 +24027,25 @@
127.0.0.1 cdn1.tribalfusion.com
127.0.0.1 cdn10-ref.landing.comcontent.net
127.0.0.1 cdn11-ref.landing.comcontent.net
+127.0.0.1 cdn11.00zasdf.pw
+127.0.0.1 cdn11.abbp1.pw
+127.0.0.1 cdn11.abbp1.science
+127.0.0.1 cdn11.abbp1.space
+127.0.0.1 cdn11.abbp1.website
+127.0.0.1 cdn11.adspayformy.site
+127.0.0.1 cdn11.adspayformymortgage.win
127.0.0.1 cdn11.contentabc.com
+127.0.0.1 cdn11.monzta.pet
+127.0.0.1 cdn11.oknplm.website
+127.0.0.1 cdn11.olmknp.space
+127.0.0.1 cdn11.pleasedontslaymy.download
+127.0.0.1 cdn11.plmokn.pw
+127.0.0.1 cdn11.poolnoodle.tech
+127.0.0.1 cdn11.routehero.com
+127.0.0.1 cdn11.tgbvfr.website
+127.0.0.1 cdn11.yuiop.trade
+127.0.0.1 cdn11.yuiout.online
+127.0.0.1 cdn11.zxcvb.space
127.0.0.1 cdn12-ref.landing.comcontent.net
127.0.0.1 cdn13-ref.landing.comcontent.net
127.0.0.1 cdn14-ref.landing.comcontent.net
@@ -26278,10 +26303,21 @@
127.0.0.1 coxnetmasterglobal.112.2o7.net
127.0.0.1 coxnews.cimedia.com
127.0.0.1 coxpalmbeachpost.112.2o7.net
+127.0.0.1 cp.abbp1.pw
+127.0.0.1 cp.abbp1.science
+127.0.0.1 cp.abbp1.space
+127.0.0.1 cp.abbp1.website
+127.0.0.1 cp.adspayformy.site
127.0.0.1 cp.doublepimp.com
127.0.0.1 cp.intl.match.com
+127.0.0.1 cp.monzta.pet
+127.0.0.1 cp.pleasedontslaymy.download
+127.0.0.1 cp.poolnoodle.tech
127.0.0.1 cp.pushwoosh.com
+127.0.0.1 cp.routehero.com
127.0.0.1 cp.surf-town.net
+127.0.0.1 cp.yuiop.trade
+127.0.0.1 cp.yuiout.online
127.0.0.1 cp1dk.voluumtrk.com
127.0.0.1 cpa.ly
127.0.0.1 cpaaltima.go2cloud.org
@@ -29283,6 +29319,7 @@
127.0.0.1 ftp01.dus.vmsn.de
127.0.0.1 ftpcontent.worldnow.com
127.0.0.1 ftr2.external.xerox.com
+127.0.0.1 ftrackb.net
127.0.0.1 fu7fb.voluumtrk.com
127.0.0.1 fuauq.voluumtrk.com
127.0.0.1 fucktubenetwork.com
@@ -29699,6 +29736,7 @@
127.0.0.1 go-clicks.de
127.0.0.1 go.activengage.com
127.0.0.1 go.ad2up.com
+127.0.0.1 go.ad2upapp.com
127.0.0.1 go.adify.com
127.0.0.1 go.adinfuse.com
127.0.0.1 go.adversal.com
@@ -29707,6 +29745,7 @@
127.0.0.1 go.by
127.0.0.1 go.coxds.com
127.0.0.1 go.cpmadvisors.com
+127.0.0.1 go.deliverymodo.com
127.0.0.1 go.delnapb.com
127.0.0.1 go.feedxfeed.com
127.0.0.1 go.goroost.com
@@ -33428,6 +33467,7 @@
127.0.0.1 monitor01.con.vmsn.de
127.0.0.1 monster.gostats.com
127.0.0.1 monsterpops.com
+127.0.0.1 monzta.pet
127.0.0.1 moo.go2cloud.org
127.0.0.1 mopo.ivwbox.de
127.0.0.1 mopub.web107-east.manage.com
@@ -34350,6 +34390,7 @@
127.0.0.1 oin.valuead.com
127.0.0.1 ojolink.com
127.0.0.1 ojrq.net
+127.0.0.1 oknplm.website
127.0.0.1 okohp.voluumtrk.com
127.0.0.1 okpgn.voluumtrk.com
127.0.0.1 okrg0.voluumtrk.com
@@ -34363,6 +34404,7 @@
127.0.0.1 olivia-hermes.us
127.0.0.1 olivia-stanfield.us
127.0.0.1 olizyr.com
+127.0.0.1 olmknp.space
127.0.0.1 om.1and1.co.uk
127.0.0.1 om.1und1.info
127.0.0.1 om.cbsi.com
@@ -35207,6 +35249,7 @@
127.0.0.1 playminigolf.com
127.0.0.1 playtomic.com
127.0.0.1 plb27.voluumtrk.com
+127.0.0.1 pleasedontslaymy.download
127.0.0.1 plemedia.com
127.0.0.1 plemx.com
127.0.0.1 plenews.net
@@ -35215,6 +35258,7 @@
127.0.0.1 plex.r.worldssl.net
127.0.0.1 plex2.com
127.0.0.1 pll28.voluumtrk.com
+127.0.0.1 plmokn.pw
127.0.0.1 plocia.com
127.0.0.1 ploko.voluumtrk.com
127.0.0.1 pls.webtype.com
@@ -35274,10 +35318,12 @@
127.0.0.1 pongoresume.com
127.0.0.1 pons.ivwbox.de
127.0.0.1 pontiflex.com
+127.0.0.1 pool.admedo.com
127.0.0.1 pool.ads.netlog.com
127.0.0.1 pool.skyhookwireless.com
127.0.0.1 pool01.2cnt.net
127.0.0.1 pool02.2cnt.net
+127.0.0.1 poolnoodle.tech
127.0.0.1 poopoo.freestats.com
127.0.0.1 pop.adcocktail.com
127.0.0.1 pop.adconjure.com
@@ -36366,6 +36412,7 @@
127.0.0.1 rotator.tradetracker.nl
127.0.0.1 rotator.trafficstars.com
127.0.0.1 rotrk.com
+127.0.0.1 routehero.com
127.0.0.1 router.adlure.net
127.0.0.1 router.revmob.com
127.0.0.1 router.tlvmedia.com
@@ -36476,7 +36523,6 @@
127.0.0.1 rwbd0.voluumtrk.com
127.0.0.1 rwnkj.voluumtrk.com
127.0.0.1 rxdja.voluumtrk.com
-127.0.0.1 rxf.answcdn.com
127.0.0.1 ry7c5.directadsopt.com
127.0.0.1 ryan-lietz.us
127.0.0.1 rydium.us.intellitxt.com
@@ -38900,6 +38946,7 @@
127.0.0.1 tfp.2ref.co
127.0.0.1 tga.acs86.com
127.0.0.1 tga.csbew.com
+127.0.0.1 tgbvfr.website
127.0.0.1 tgp.buzzsession.com
127.0.0.1 tgp.pornsponsors.com
127.0.0.1 thaliaat02.webtrekk.net
@@ -39310,6 +39357,7 @@
127.0.0.1 track.scorpiointeractive.com
127.0.0.1 track.searchignite.com
127.0.0.1 track.sexchangegirl.com
+127.0.0.1 track.sharktrkr.xyz
127.0.0.1 track.shop2market.com
127.0.0.1 track.sigfig.com
127.0.0.1 track.slideshare.net
@@ -44537,7 +44585,6 @@
127.0.0.1 webtrack-brickstreetconnect-mkt-prd.hsbc.com.hk
127.0.0.1 webtrack.jwgrant.co.uk
127.0.0.1 webtracker.educationconnection.com
-127.0.0.1 webtracker.tnt.com
127.0.0.1 webtrackerplus.com
127.0.0.1 webtracking.touchclarity.com
127.0.0.1 webtraffic.ttinet.com
@@ -44736,9 +44783,27 @@
127.0.0.1 wrestling.searchwho.com
127.0.0.1 ws-eu.amazon-adsystem.com
127.0.0.1 ws-na.amazon-adsystem.com
+127.0.0.1 ws.00zasdf.pw
+127.0.0.1 ws.abbp1.pw
+127.0.0.1 ws.abbp1.science
+127.0.0.1 ws.abbp1.space
+127.0.0.1 ws.abbp1.website
+127.0.0.1 ws.adspayformy.site
+127.0.0.1 ws.adspayformymortgage.win
127.0.0.1 ws.amazon.com
+127.0.0.1 ws.monzta.pet
+127.0.0.1 ws.oknplm.website
+127.0.0.1 ws.olmknp.space
+127.0.0.1 ws.pleasedontslaymy.download
+127.0.0.1 ws.plmokn.pw
+127.0.0.1 ws.poolnoodle.tech
+127.0.0.1 ws.routehero.com
127.0.0.1 ws.sharethis.com
127.0.0.1 ws.tapjoyads.com
+127.0.0.1 ws.tgbvfr.website
+127.0.0.1 ws.yuiop.trade
+127.0.0.1 ws.yuiout.online
+127.0.0.1 ws.zxcvb.space
127.0.0.1 ws1.surf-town.net
127.0.0.1 ws10.surf-town.net
127.0.0.1 ws11.surf-town.net
@@ -44782,6 +44847,7 @@
127.0.0.1 wsc1.webspectator.com
127.0.0.1 wsc4.webspectator.com
127.0.0.1 wsclick.infospace.com
+127.0.0.1 wsg.abbp1.pw
127.0.0.1 wsi1.surf-town.net
127.0.0.1 wsod.com
127.0.0.1 wsp1.surf-town.net
@@ -44953,6 +45019,7 @@
127.0.0.1 www.ad-lite.com
127.0.0.1 www.ad-maker.net
127.0.0.1 www.ad-media.org
+127.0.0.1 www.ad-rev.in
127.0.0.1 www.ad-search.com
127.0.0.1 www.ad-solutions.com
127.0.0.1 www.ad-space.net
@@ -45085,6 +45152,7 @@
127.0.0.1 www.adsniper.ru
127.0.0.1 www.adsoogle.com
127.0.0.1 www.adspaces.ero-advertising.com
+127.0.0.1 www.adspayformy.site
127.0.0.1 www.adsphinx.com
127.0.0.1 www.adspics.com
127.0.0.1 www.adspinner.com
@@ -45880,6 +45948,7 @@
127.0.0.1 www.freeviral.com
127.0.0.1 www.freewha.com
127.0.0.1 www.friendlyduck.com
+127.0.0.1 www.ftrackb.net
127.0.0.1 www.fucktubenetwork.com
127.0.0.1 www.fuel451.com
127.0.0.1 www.fullqurandownload.com
@@ -46682,6 +46751,7 @@
127.0.0.1 www.pixetrk.com
127.0.0.1 www.placehold.it
127.0.0.1 www.platinscience.com
+127.0.0.1 www.pleasedontslaymy.download
127.0.0.1 www.plocia.com
127.0.0.1 www.plug-media.com
127.0.0.1 www.plus500.com
@@ -47727,6 +47797,8 @@
127.0.0.1 ysm.hauchi.com.tw
127.0.0.1 ytubevideoqualitymanager.com
127.0.0.1 yuilop.com
+127.0.0.1 yuiop.trade
+127.0.0.1 yuiout.online
127.0.0.1 yume.com
127.0.0.1 yuppy.2cnt.net
127.0.0.1 yvap.query.yahoo.com
@@ -47894,6 +47966,7 @@
127.0.0.1 zw.zeroredirect1.com
127.0.0.1 zww.ero-advertising.com
127.0.0.1 zx.zeroredirect1.com
+127.0.0.1 zxcvb.space
127.0.0.1 zxypenguin.people-group.su
127.0.0.1 zy.zeroredirect1.com
127.0.0.1 zyngawithfriends.com
@@ -47901,4 +47974,4 @@
127.0.0.1 zz.zeroredirect1.com
127.0.0.1 zzz.clickbank.net
127.0.0.1 _thums.ero-advertising.com
-# Hosts: 47893
\ No newline at end of file
+# Hosts: 47966
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 80751bde2..f955ce5b3 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
@@ -30,6 +30,13 @@
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/duckduckgo.png b/app/src/main/assets/duckduckgo.png
index a62119e58..74091ee3c 100644
Binary files a/app/src/main/assets/duckduckgo.png and b/app/src/main/assets/duckduckgo.png differ
diff --git a/app/src/main/java/acr/browser/lightning/activity/BookmarkUiModel.java b/app/src/main/java/acr/browser/lightning/activity/BookmarkUiModel.java
new file mode 100644
index 000000000..457a98417
--- /dev/null
+++ b/app/src/main/java/acr/browser/lightning/activity/BookmarkUiModel.java
@@ -0,0 +1,48 @@
+package acr.browser.lightning.activity;
+
+import android.support.annotation.Nullable;
+
+import acr.browser.lightning.browser.BookmarksView;
+
+/**
+ * The UI model representing the current folder shown
+ * by the {@link BookmarksView}.
+ *
+ * Created by anthonycr on 5/7/17.
+ */
+public class BookmarkUiModel {
+
+ @Nullable private String mCurrentFolder;
+
+ /**
+ * Sets the current folder that is being shown.
+ * Use null as the root folder.
+ *
+ * @param folder the current folder, null for root.
+ */
+ public void setCurrentFolder(@Nullable String folder) {
+ mCurrentFolder = folder;
+ }
+
+ /**
+ * Determines if the current folder is
+ * the root folder.
+ *
+ * @return true if the current folder is
+ * the root, false otherwise.
+ */
+ public boolean isRootFolder() {
+ return mCurrentFolder == null;
+ }
+
+ /**
+ * Gets the current folder that is being shown.
+ *
+ * @return the current folder, null for root.
+ */
+ @Nullable
+ public String getCurrentFolder() {
+ return mCurrentFolder;
+ }
+
+}
diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java
index b848b0a0f..56edc7202 100644
--- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java
+++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java
@@ -13,7 +13,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
-import android.database.sqlite.SQLiteException;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
@@ -23,7 +22,6 @@
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.support.annotation.ColorInt;
@@ -51,7 +49,6 @@
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnKeyListener;
-import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
@@ -80,12 +77,12 @@
import android.widget.TextView.OnEditorActionListener;
import android.widget.VideoView;
-import com.anthonycr.bonsai.Observable;
+import com.anthonycr.bonsai.Completable;
+import com.anthonycr.bonsai.CompletableOnSubscribe;
import com.anthonycr.bonsai.Schedulers;
+import com.anthonycr.bonsai.SingleOnSubscribe;
import com.anthonycr.grant.PermissionsManager;
import com.anthonycr.progress.AnimatedProgressBar;
-import com.squareup.otto.Bus;
-import com.squareup.otto.Subscribe;
import java.io.File;
import java.io.IOException;
@@ -98,15 +95,14 @@
import acr.browser.lightning.browser.BrowserPresenter;
import acr.browser.lightning.browser.BrowserView;
import acr.browser.lightning.browser.TabsView;
-import acr.browser.lightning.bus.BookmarkEvents;
-import acr.browser.lightning.bus.BrowserEvents;
import acr.browser.lightning.constant.BookmarkPage;
import acr.browser.lightning.constant.Constants;
+import acr.browser.lightning.constant.DownloadsPage;
import acr.browser.lightning.constant.HistoryPage;
import acr.browser.lightning.controller.UIController;
-import acr.browser.lightning.database.BookmarkManager;
-import acr.browser.lightning.database.HistoryDatabase;
import acr.browser.lightning.database.HistoryItem;
+import acr.browser.lightning.database.bookmark.BookmarkModel;
+import acr.browser.lightning.database.history.HistoryModel;
import acr.browser.lightning.dialog.BrowserDialog;
import acr.browser.lightning.dialog.LightningDialogBuilder;
import acr.browser.lightning.fragment.BookmarksFragment;
@@ -115,6 +111,8 @@
import acr.browser.lightning.receiver.NetworkReceiver;
import acr.browser.lightning.search.SuggestionsAdapter;
import acr.browser.lightning.utils.DrawableUtils;
+import acr.browser.lightning.utils.IntentUtils;
+import acr.browser.lightning.utils.Preconditions;
import acr.browser.lightning.utils.ProxyUtils;
import acr.browser.lightning.utils.ThemeUtils;
import acr.browser.lightning.utils.UrlUtils;
@@ -123,12 +121,12 @@
import acr.browser.lightning.view.Handlers;
import acr.browser.lightning.view.LightningView;
import acr.browser.lightning.view.SearchView;
-import butterknife.Bind;
+import butterknife.BindView;
import butterknife.ButterKnife;
-public abstract class BrowserActivity extends ThemableBrowserActivity implements BrowserView, UIController, OnClickListener, OnLongClickListener {
+public abstract class BrowserActivity extends ThemableBrowserActivity implements BrowserView, UIController, OnClickListener {
- private static final String TAG = BrowserActivity.class.getSimpleName();
+ private static final String TAG = "BrowserActivity";
private static final String INTENT_PANIC_TRIGGER = "info.guardianproject.panic.action.TRIGGER";
@@ -136,18 +134,17 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
private static final String TAG_TABS_FRAGMENT = "TAG_TABS_FRAGMENT";
// Static Layout
- @Bind(R.id.drawer_layout) DrawerLayout mDrawerLayout;
- @Bind(R.id.content_frame) FrameLayout mBrowserFrame;
- @Bind(R.id.left_drawer) ViewGroup mDrawerLeft;
- @Bind(R.id.right_drawer) ViewGroup mDrawerRight;
- @Bind(R.id.ui_layout) ViewGroup mUiLayout;
- @Bind(R.id.toolbar_layout) ViewGroup mToolbarLayout;
- @Bind(R.id.progress_view) AnimatedProgressBar mProgressBar;
- @Bind(R.id.search_bar) RelativeLayout mSearchBar;
-
+ @BindView(R.id.drawer_layout) DrawerLayout mDrawerLayout;
+ @BindView(R.id.content_frame) FrameLayout mBrowserFrame;
+ @BindView(R.id.left_drawer) ViewGroup mDrawerLeft;
+ @BindView(R.id.right_drawer) ViewGroup mDrawerRight;
+ @BindView(R.id.ui_layout) ViewGroup mUiLayout;
+ @BindView(R.id.toolbar_layout) ViewGroup mToolbarLayout;
+ @BindView(R.id.progress_view) AnimatedProgressBar mProgressBar;
+ @BindView(R.id.search_bar) RelativeLayout mSearchBar;
// Toolbar Views
- @Bind(R.id.toolbar) Toolbar mToolbar;
+ @BindView(R.id.toolbar) Toolbar mToolbar;
private View mSearchBackground;
private SearchView mSearch;
private ImageView mArrowImage;
@@ -168,7 +165,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
private ValueCallback mUploadMessage;
private ValueCallback mFilePathCallback;
- // Primatives
+ // Primitives
private boolean mFullScreen;
private boolean mDarkTheme;
private boolean mIsFullScreen = false;
@@ -185,20 +182,13 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
private String mUntitledTitle;
private String mCameraPhotoPath;
- private final Handler mDrawerHandler = new Handler();
-
// The singleton BookmarkManager
- @Inject BookmarkManager mBookmarkManager;
-
- // Event bus
- @Inject Bus mEventBus;
+ @Inject BookmarkModel mBookmarkManager;
@Inject LightningDialogBuilder mBookmarksDialogBuilder;
private TabsManager mTabsManager;
- @Inject HistoryDatabase mHistoryDatabase;
-
// Image
private Bitmap mWebpageBitmap;
private final ColorDrawable mBackground = new ColorDrawable();
@@ -225,7 +215,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
public abstract void updateHistory(@Nullable final String title, @NonNull final String url);
- abstract Observable updateCookiePreference();
+ @NonNull
+ abstract Completable updateCookiePreference();
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -292,20 +283,27 @@ public void onDrawerStateChanged(int newState) {
mWebpageBitmap = ThemeUtils.getThemedBitmap(this, R.drawable.ic_webpage, mDarkTheme);
- final TabsFragment tabsFragment = new TabsFragment();
+ final FragmentManager fragmentManager = getSupportFragmentManager();
+
+ TabsFragment tabsFragment = (TabsFragment) fragmentManager.findFragmentByTag(TAG_TABS_FRAGMENT);
+ BookmarksFragment bookmarksFragment = (BookmarksFragment) fragmentManager.findFragmentByTag(TAG_BOOKMARK_FRAGMENT);
+
+ if (tabsFragment != null) {
+ fragmentManager.beginTransaction().remove(tabsFragment).commit();
+ }
+ tabsFragment = TabsFragment.createTabsFragment(isIncognito(), mShowTabsInDrawer);
+
mTabsView = tabsFragment;
- final Bundle tabsFragmentArguments = new Bundle();
- tabsFragmentArguments.putBoolean(TabsFragment.IS_INCOGNITO, isIncognito());
- tabsFragmentArguments.putBoolean(TabsFragment.VERTICAL_MODE, mShowTabsInDrawer);
- tabsFragment.setArguments(tabsFragmentArguments);
- final BookmarksFragment bookmarksFragment = new BookmarksFragment();
+ if (bookmarksFragment != null) {
+ fragmentManager.beginTransaction().remove(bookmarksFragment).commit();
+ }
+ bookmarksFragment = BookmarksFragment.createFragment(isIncognito());
+
mBookmarksView = bookmarksFragment;
- final Bundle bookmarksFragmentArguments = new Bundle();
- bookmarksFragmentArguments.putBoolean(BookmarksFragment.INCOGNITO_MODE, isIncognito());
- bookmarksFragment.setArguments(bookmarksFragmentArguments);
- final FragmentManager fragmentManager = getSupportFragmentManager();
+ fragmentManager.executePendingTransactions();
+
fragmentManager
.beginTransaction()
.replace(getTabsFragmentViewId(), tabsFragment, TAG_TABS_FRAGMENT)
@@ -315,8 +313,7 @@ public void onDrawerStateChanged(int newState) {
mToolbarLayout.removeView(findViewById(R.id.tabs_toolbar_container));
}
- if (actionBar == null)
- return;
+ Preconditions.checkNonNull(actionBar);
// set display options of the ActionBar
actionBar.setDisplayShowTitleEnabled(false);
@@ -337,11 +334,35 @@ public void onDrawerStateChanged(int newState) {
mArrowImage.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
}
updateTabNumber(0);
+
+ // Post drawer locking in case the activity is being recreated
+ Handlers.MAIN.post(new Runnable() {
+ @Override
+ public void run() {
+ mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, getTabDrawer());
+ }
+ });
} else {
- mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, getTabDrawer());
+
+ // Post drawer locking in case the activity is being recreated
+ Handlers.MAIN.post(new Runnable() {
+ @Override
+ public void run() {
+ mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, getTabDrawer());
+ }
+ });
mArrowImage.setImageResource(R.drawable.ic_action_home);
mArrowImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN);
}
+
+ // Post drawer locking in case the activity is being recreated
+ Handlers.MAIN.post(new Runnable() {
+ @Override
+ public void run() {
+ mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, getBookmarkDrawer());
+ }
+ });
+
arrowButton.setOnClickListener(this);
// create the search EditText in the ToolBar
@@ -414,6 +435,14 @@ private int getTabsFragmentViewId() {
}
}
+ /**
+ * Determines if an intent is originating
+ * from a panic trigger.
+ *
+ * @param intent the intent to check.
+ * @return true if the panic trigger sent
+ * the intent, false otherwise.
+ */
static boolean isPanicTrigger(@Nullable Intent intent) {
return intent != null && INTENT_PANIC_TRIGGER.equals(intent.getAction());
}
@@ -423,7 +452,7 @@ void panicClean() {
mTabsManager.newTab(this, "", false);
mTabsManager.switchToTab(0);
mTabsManager.clearSavedState();
- HistoryPage.deleteHistoryPage(getApplication());
+ HistoryPage.deleteHistoryPage(getApplication()).subscribe();
closeBrowser();
// System exit needed in the case of receiving
// the panic intent since finish() isn't completely
@@ -520,10 +549,10 @@ public void onPreFocus() {
return;
}
String url = currentView.getUrl();
- if (UrlUtils.isSpecialUrl(url)) {
- mSearch.setText("");
- } else {
- mSearch.setText(url);
+ if (!UrlUtils.isSpecialUrl(url)) {
+ if (!mSearch.hasFocus()) {
+ mSearch.setText(url);
+ }
}
}
}
@@ -532,19 +561,25 @@ private class DrawerLocker implements DrawerListener {
@Override
public void onDrawerClosed(View v) {
- if (v == mDrawerRight && mShowTabsInDrawer) {
- mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, mDrawerLeft);
- } else {
- mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, mDrawerRight);
+ View tabsDrawer = getTabDrawer();
+ View bookmarksDrawer = getBookmarkDrawer();
+
+ if (v == tabsDrawer) {
+ mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, bookmarksDrawer);
+ } else if (mShowTabsInDrawer) {
+ mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, tabsDrawer);
}
}
@Override
public void onDrawerOpened(View v) {
- if (v == mDrawerRight) {
- mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mDrawerLeft);
+ View tabsDrawer = getTabDrawer();
+ View bookmarksDrawer = getBookmarkDrawer();
+
+ if (v == tabsDrawer) {
+ mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, bookmarksDrawer);
} else {
- mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mDrawerRight);
+ mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, tabsDrawer);
}
}
@@ -612,7 +647,6 @@ private void initializePreferences() {
((BookmarksFragment) bookmarksFragment).reinitializePreferences();
}
-
// TODO layout transition causing memory leak
// mBrowserFrame.setLayoutTransition(new LayoutTransition());
@@ -712,6 +746,59 @@ public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
return super.onKeyUp(keyCode, event);
}
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ // Keyboard shortcuts
+ if (event.isCtrlPressed() && event.getAction() == KeyEvent.ACTION_DOWN) {
+ switch (event.getKeyCode()) {
+ case KeyEvent.KEYCODE_T:
+ // Open new tab
+ newTab(null, true);
+ return true;
+ case KeyEvent.KEYCODE_W:
+ // Close current tab
+ mPresenter.deleteTab(mTabsManager.indexOfCurrentTab());
+ return true;
+ case KeyEvent.KEYCODE_Q:
+ // Close browser
+ closeBrowser();
+ return true;
+ case KeyEvent.KEYCODE_R:
+ // Refresh current tab
+ LightningView currentTab = mTabsManager.getCurrentTab();
+ if (currentTab != null) {
+ currentTab.reload();
+ }
+ return true;
+ case KeyEvent.KEYCODE_TAB:
+ int nextIndex = 0;
+ if (event.isShiftPressed()) {
+ // Go back one tab
+ if (mTabsManager.indexOfCurrentTab() > 0) {
+ nextIndex = mTabsManager.indexOfCurrentTab() - 1;
+ } else {
+ nextIndex = mTabsManager.last();
+ }
+ } else {
+ // Go forward one tab
+ if (mTabsManager.indexOfCurrentTab() < mTabsManager.last()) {
+ nextIndex = mTabsManager.indexOfCurrentTab() + 1;
+ } else {
+ nextIndex = 0;
+ }
+ }
+ mPresenter.tabChanged(nextIndex);
+ return true;
+ }
+ } else if (event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_SEARCH) {
+ // Highlight search field
+ mSearch.requestFocus();
+ mSearch.selectAll();
+ return true;
+ }
+ return super.dispatchKeyEvent(event);
+ }
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
final LightningView currentView = mTabsManager.getCurrentTab();
@@ -748,13 +835,7 @@ public boolean onOptionsItemSelected(MenuItem item) {
overridePendingTransition(R.anim.slide_up_in, R.anim.fade_out_scale);
return true;
case R.id.action_share:
- if (currentUrl != null && !UrlUtils.isSpecialUrl(currentUrl)) {
- Intent shareIntent = new Intent(Intent.ACTION_SEND);
- shareIntent.setType("text/plain");
- shareIntent.putExtra(Intent.EXTRA_SUBJECT, currentView.getTitle());
- shareIntent.putExtra(Intent.EXTRA_TEXT, currentUrl);
- startActivity(Intent.createChooser(shareIntent, getResources().getString(R.string.dialog_title_share)));
- }
+ new IntentUtils(this).shareUrl(currentUrl, currentView != null ? currentView.getTitle() : null);
return true;
case R.id.action_bookmarks:
openBookmarks();
@@ -773,6 +854,9 @@ public boolean onOptionsItemSelected(MenuItem item) {
case R.id.action_history:
openHistory();
return true;
+ case R.id.action_downloads:
+ openDownloads();
+ return true;
case R.id.action_add_bookmark:
if (currentUrl != null && !UrlUtils.isSpecialUrl(currentUrl)) {
addBookmark(currentView.getTitle(), currentUrl);
@@ -795,23 +879,37 @@ public boolean onOptionsItemSelected(MenuItem item) {
// By using a manager, adds a bookmark and notifies third parties about that
private void addBookmark(final String title, final String url) {
- final HistoryItem item = !mBookmarkManager.isBookmark(url)
- ? new HistoryItem(url, title)
- : null;
- if (item != null && mBookmarkManager.addBookmark(item)) {
- mSuggestionsAdapter.refreshBookmarks();
- mBookmarksView.handleUpdatedUrl(url);
- }
+
+ final HistoryItem item = new HistoryItem(url, title);
+ mBookmarkManager.addBookmarkIfNotExists(item)
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.main())
+ .subscribe(new SingleOnSubscribe() {
+ @Override
+ public void onItem(@Nullable Boolean item) {
+ if (Boolean.TRUE.equals(item)) {
+ mSuggestionsAdapter.refreshBookmarks();
+ mBookmarksView.handleUpdatedUrl(url);
+ }
+ }
+ });
}
private void deleteBookmark(final String title, final String url) {
- final HistoryItem item = mBookmarkManager.isBookmark(url)
- ? new HistoryItem(url, title)
- : null;
- if (item != null && mBookmarkManager.deleteBookmark(item)) {
- mSuggestionsAdapter.refreshBookmarks();
- mBookmarksView.handleUpdatedUrl(url);
- }
+ final HistoryItem item = new HistoryItem(url, title);
+
+ mBookmarkManager.deleteBookmark(item)
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.main())
+ .subscribe(new SingleOnSubscribe() {
+ @Override
+ public void onItem(@Nullable Boolean item) {
+ if (Boolean.TRUE.equals(item)) {
+ mSuggestionsAdapter.refreshBookmarks();
+ mBookmarksView.handleUpdatedUrl(url);
+ }
+ }
+ });
}
private void putToolbarInRoot() {
@@ -956,7 +1054,7 @@ public void removeTabView() {
// Use a delayed handler to make the transition smooth
// otherwise it will get caught up with the showTab code
// and cause a janky motion
- mDrawerHandler.postDelayed(new Runnable() {
+ Handlers.MAIN.postDelayed(new Runnable() {
@Override
public void run() {
mDrawerLayout.closeDrawers();
@@ -995,14 +1093,14 @@ public void setTabView(@NonNull final View view) {
// Use a delayed handler to make the transition smooth
// otherwise it will get caught up with the showTab code
// and cause a janky motion
- mDrawerHandler.postDelayed(new Runnable() {
+ Handlers.MAIN.postDelayed(new Runnable() {
@Override
public void run() {
mDrawerLayout.closeDrawers();
}
}, 200);
- // mDrawerHandler.postDelayed(new Runnable() {
+ // Handlers.MAIN.postDelayed(new Runnable() {
// @Override
// public void run() {
// Remove browser frame background to reduce overdraw
@@ -1066,11 +1164,19 @@ public void bookmarkButtonClicked() {
}
if (!UrlUtils.isSpecialUrl(url)) {
- if (!mBookmarkManager.isBookmark(url)) {
- addBookmark(title, url);
- } else {
- deleteBookmark(title, url);
- }
+ mBookmarkManager.isBookmark(url)
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.main())
+ .subscribe(new SingleOnSubscribe() {
+ @Override
+ public void onItem(@Nullable Boolean item) {
+ if (Boolean.TRUE.equals(item)) {
+ deleteBookmark(title, url);
+ } else {
+ addBookmark(title, url);
+ }
+ }
+ });
}
}
@@ -1079,7 +1185,7 @@ public void bookmarkItemClicked(@NonNull HistoryItem item) {
mPresenter.loadUrlInCurrentView(item.getUrl());
// keep any jank from happening when the drawer is closed after the
// URL starts to load
- mDrawerHandler.postDelayed(new Runnable() {
+ Handlers.MAIN.postDelayed(new Runnable() {
@Override
public void run() {
closeDrawers(null);
@@ -1087,6 +1193,11 @@ public void run() {
}, 150);
}
+ @Override
+ public void handleHistoryChange() {
+ openHistory();
+ }
+
/**
* displays the WebView contained in the LightningView Also handles the
* removal of previous views
@@ -1139,7 +1250,7 @@ void performExitCleanUp() {
Log.d(TAG, "Cache Cleared");
}
if (mPreferences.getClearHistoryExitEnabled() && !isIncognito()) {
- WebUtils.clearHistory(this, mHistoryDatabase);
+ WebUtils.clearHistory(this);
Log.d(TAG, "History Cleared");
}
if (mPreferences.getClearCookiesExitEnabled() && !isIncognito()) {
@@ -1249,15 +1360,13 @@ protected void onPause() {
Log.d(TAG, "onPause");
mTabsManager.pauseAll();
try {
- BrowserApp.get(this).unregisterReceiver(mNetworkReceiver);
+ getApplication().unregisterReceiver(mNetworkReceiver);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Receiver was not registered", e);
}
if (isIncognito() && isFinishing()) {
overridePendingTransition(R.anim.fade_in_scale, R.anim.slide_down_out);
}
-
- mEventBus.unregister(mBusEventListener);
}
void saveOpenTabs() {
@@ -1276,15 +1385,10 @@ protected void onStop() {
protected void onDestroy() {
Log.d(TAG, "onDestroy");
- mDrawerHandler.removeCallbacksAndMessages(null);
+ Handlers.MAIN.removeCallbacksAndMessages(null);
mPresenter.shutdown();
- if (mHistoryDatabase != null) {
- mHistoryDatabase.close();
- mHistoryDatabase = null;
- }
-
super.onDestroy();
}
@@ -1319,9 +1423,7 @@ protected void onResume() {
IntentFilter filter = new IntentFilter();
filter.addAction(NETWORK_BROADCAST_ACTION);
- BrowserApp.get(this).registerReceiver(mNetworkReceiver, filter);
-
- mEventBus.register(mBusEventListener);
+ getApplication().registerReceiver(mNetworkReceiver, filter);
if (mFullScreen) {
overlayToolbarOnWebView();
@@ -1481,20 +1583,15 @@ void addItemToHistory(@Nullable final String title, @NonNull final String url) {
if (UrlUtils.isSpecialUrl(url)) {
return;
}
- BrowserApp.getIOThread().execute(new Runnable() {
- @Override
- public void run() {
- try {
- mHistoryDatabase.visitHistoryItem(url, title);
- } catch (IllegalStateException e) {
- Log.e(TAG, "IllegalStateException in updateHistory", e);
- } catch (NullPointerException e) {
- Log.e(TAG, "NullPointerException in updateHistory", e);
- } catch (SQLiteException e) {
- Log.e(TAG, "SQLiteException in updateHistory", e);
+
+ HistoryModel.visitHistoryItem(url, title)
+ .subscribeOn(Schedulers.io())
+ .subscribe(new CompletableOnSubscribe() {
+ @Override
+ public void onError(@NonNull Throwable throwable) {
+ Log.e(TAG, "Exception while updating history", throwable);
}
- }
- });
+ });
}
/**
@@ -1543,7 +1640,35 @@ public void onItemClick(AdapterView> adapterView, View view, int pos, long l)
* function that opens the HTML history page in the browser
*/
private void openHistory() {
- new HistoryPage(mTabsManager.getCurrentTab(), getApplication(), mHistoryDatabase).load();
+ new HistoryPage().getHistoryPage()
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.main())
+ .subscribe(new SingleOnSubscribe() {
+ @Override
+ public void onItem(@Nullable String item) {
+ Preconditions.checkNonNull(item);
+ LightningView view = mTabsManager.getCurrentTab();
+ if (view != null) {
+ view.loadUrl(item);
+ }
+ }
+ });
+ }
+
+ private void openDownloads() {
+ new DownloadsPage().getDownloadsPage()
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.main())
+ .subscribe(new SingleOnSubscribe() {
+ @Override
+ public void onItem(@Nullable String item) {
+ Preconditions.checkNonNull(item);
+ LightningView view = mTabsManager.getCurrentTab();
+ if (view != null) {
+ view.loadUrl(item);
+ }
+ }
+ });
}
private View getBookmarkDrawer() {
@@ -1884,6 +2009,7 @@ public void onBackButtonPressed() {
if (currentTab != null) {
if (currentTab.canGoBack()) {
currentTab.goBack();
+ closeDrawers(null);
} else {
mPresenter.deleteTab(mTabsManager.positionOf(currentTab));
}
@@ -1896,6 +2022,7 @@ public void onForwardButtonPressed() {
if (currentTab != null) {
if (currentTab.canGoForward()) {
currentTab.goForward();
+ closeDrawers(null);
}
}
}
@@ -2046,6 +2173,55 @@ protected void applyTransformation(float interpolatedTime, Transformation t) {
}
}
+ @Override
+ public void handleBookmarksChange() {
+ final LightningView currentTab = mTabsManager.getCurrentTab();
+ if (currentTab != null && currentTab.getUrl().startsWith(Constants.FILE)
+ && currentTab.getUrl().endsWith(BookmarkPage.FILENAME)) {
+ currentTab.loadBookmarkpage();
+ }
+ if (currentTab != null) {
+ mBookmarksView.handleUpdatedUrl(currentTab.getUrl());
+ }
+ }
+
+ @Override
+ public void handleDownloadDeleted() {
+ final LightningView currentTab = mTabsManager.getCurrentTab();
+ if (currentTab != null && currentTab.getUrl().startsWith(Constants.FILE)
+ && currentTab.getUrl().endsWith(DownloadsPage.FILENAME)) {
+ currentTab.loadDownloadspage();
+ }
+ if (currentTab != null) {
+ mBookmarksView.handleUpdatedUrl(currentTab.getUrl());
+ }
+ }
+
+ @Override
+ public void handleBookmarkDeleted(@NonNull HistoryItem item) {
+ mBookmarksView.handleBookmarkDeleted(item);
+ handleBookmarksChange();
+ }
+
+ @Override
+ public void handleNewTab(@NonNull LightningDialogBuilder.NewTab newTabType, @NonNull String url) {
+ mDrawerLayout.closeDrawers();
+ switch (newTabType) {
+ case FOREGROUND:
+ newTab(url, true);
+ break;
+ case BACKGROUND:
+ newTab(url, false);
+ break;
+ case INCOGNITO:
+ Intent intent = new Intent(BrowserActivity.this, IncognitoActivity.class);
+ intent.setData(Uri.parse(url));
+ startActivity(intent);
+ overridePendingTransition(R.anim.slide_up_in, R.anim.fade_out_scale);
+ break;
+ }
+ }
+
/**
* Performs an action when the provided view is laid out.
*
@@ -2142,21 +2318,6 @@ public void onClick(View v) {
}
}
- /**
- * Handle long presses on views that use this class
- * as their OnLongClickListener. This method should
- * distinguish between the IDs of the views that are
- * getting clicked.
- *
- * @param view the view that has been long pressed
- * @return returns true since the method handles the long press
- * event
- */
- @Override
- public boolean onLongClick(View view) {
- return true;
- }
-
/**
* This NetworkReceiver notifies each of the WebViews in the browser whether
* the network is currently connected or not. This is important because some
@@ -2186,66 +2347,4 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
- private final Object mBusEventListener = new Object() {
-
- @Subscribe
- public void loadHistory(final BrowserEvents.OpenHistoryInCurrentTab event) {
- new HistoryPage(mTabsManager.getCurrentTab(), getApplication(), mHistoryDatabase).load();
- }
-
- /**
- * Load the given url in a new tab, used by the the
- * {@link acr.browser.lightning.fragment.BookmarksFragment} and by the
- * {@link LightningDialogBuilder}
- *
- * @param event Bus event indicating that the user wishes
- * to open a bookmark in a new tab
- */
- @Subscribe
- public void loadUrlInNewTab(final BrowserEvents.OpenUrlInNewTab event) {
- mDrawerLayout.closeDrawers();
- if (event.location == BrowserEvents.OpenUrlInNewTab.Location.NEW_TAB) {
- newTab(event.url, true);
- } else if (event.location == BrowserEvents.OpenUrlInNewTab.Location.BACKGROUND) {
- newTab(event.url, false);
- } else if (event.location == BrowserEvents.OpenUrlInNewTab.Location.INCOGNITO) {
- Intent intent = new Intent(BrowserActivity.this, IncognitoActivity.class);
- intent.setData(Uri.parse(event.url));
- startActivity(intent);
- overridePendingTransition(R.anim.slide_up_in, R.anim.fade_out_scale);
- }
- }
-
- /**
- * This method is called when the user edits a bookmark.
- *
- * @param event the event that the bookmark has changed.
- */
- @Subscribe
- public void bookmarkChanged(final BookmarkEvents.BookmarkChanged event) {
- handleBookmarksChange();
- }
-
- /**
- * Notify the browser that a bookmark was deleted.
- *
- * @param event the event that the bookmark has been deleted
- */
- @Subscribe
- public void bookmarkDeleted(final BookmarkEvents.Deleted event) {
- handleBookmarksChange();
- }
-
- private void handleBookmarksChange() {
- final LightningView currentTab = mTabsManager.getCurrentTab();
- if (currentTab != null && currentTab.getUrl().startsWith(Constants.FILE)
- && currentTab.getUrl().endsWith(BookmarkPage.FILENAME)) {
- currentTab.loadBookmarkpage();
- }
- if (currentTab != null) {
- mBookmarksView.handleUpdatedUrl(currentTab.getUrl());
- }
- }
-
- };
}
diff --git a/app/src/main/java/acr/browser/lightning/activity/IncognitoActivity.java b/app/src/main/java/acr/browser/lightning/activity/IncognitoActivity.java
index e939e5ad8..9f085b507 100644
--- a/app/src/main/java/acr/browser/lightning/activity/IncognitoActivity.java
+++ b/app/src/main/java/acr/browser/lightning/activity/IncognitoActivity.java
@@ -8,19 +8,21 @@
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
+import com.anthonycr.bonsai.Completable;
+import com.anthonycr.bonsai.CompletableAction;
+import com.anthonycr.bonsai.CompletableSubscriber;
+
import acr.browser.lightning.R;
-import com.anthonycr.bonsai.Action;
-import com.anthonycr.bonsai.Observable;
-import com.anthonycr.bonsai.Subscriber;
@SuppressWarnings("deprecation")
public class IncognitoActivity extends BrowserActivity {
+ @NonNull
@Override
- public Observable updateCookiePreference() {
- return Observable.create(new Action() {
+ public Completable updateCookiePreference() {
+ return Completable.create(new CompletableAction() {
@Override
- public void onSubscribe(@NonNull Subscriber subscriber) {
+ public void onSubscribe(@NonNull CompletableSubscriber subscriber) {
CookieManager cookieManager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
CookieSyncManager.createInstance(IncognitoActivity.this);
@@ -32,7 +34,7 @@ public void onSubscribe(@NonNull Subscriber subscriber) {
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
+ public boolean onCreateOptionsMenu(@NonNull Menu menu) {
getMenuInflater().inflate(R.menu.incognito, menu);
return super.onCreateOptionsMenu(menu);
}
diff --git a/app/src/main/java/acr/browser/lightning/activity/MainActivity.java b/app/src/main/java/acr/browser/lightning/activity/MainActivity.java
index 982bec75e..058085937 100644
--- a/app/src/main/java/acr/browser/lightning/activity/MainActivity.java
+++ b/app/src/main/java/acr/browser/lightning/activity/MainActivity.java
@@ -8,19 +8,21 @@
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
+import com.anthonycr.bonsai.Completable;
+import com.anthonycr.bonsai.CompletableAction;
+import com.anthonycr.bonsai.CompletableSubscriber;
+
import acr.browser.lightning.R;
-import com.anthonycr.bonsai.Action;
-import com.anthonycr.bonsai.Observable;
-import com.anthonycr.bonsai.Subscriber;
@SuppressWarnings("deprecation")
public class MainActivity extends BrowserActivity {
+ @NonNull
@Override
- public Observable updateCookiePreference() {
- return Observable.create(new Action() {
+ public Completable updateCookiePreference() {
+ return Completable.create(new CompletableAction() {
@Override
- public void onSubscribe(@NonNull Subscriber subscriber) {
+ public void onSubscribe(@NonNull CompletableSubscriber subscriber) {
CookieManager cookieManager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
CookieSyncManager.createInstance(MainActivity.this);
@@ -32,7 +34,7 @@ public void onSubscribe(@NonNull Subscriber subscriber) {
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
+ public boolean onCreateOptionsMenu(@NonNull Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
diff --git a/app/src/main/java/acr/browser/lightning/activity/ReadingActivity.java b/app/src/main/java/acr/browser/lightning/activity/ReadingActivity.java
index 90b943edd..f554c6fd8 100644
--- a/app/src/main/java/acr/browser/lightning/activity/ReadingActivity.java
+++ b/app/src/main/java/acr/browser/lightning/activity/ReadingActivity.java
@@ -30,28 +30,27 @@
import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.dialog.BrowserDialog;
import acr.browser.lightning.preference.PreferenceManager;
-import com.anthonycr.bonsai.Action;
-import com.anthonycr.bonsai.Observable;
-import com.anthonycr.bonsai.OnSubscribe;
-import com.anthonycr.bonsai.Subscriber;
+
import com.anthonycr.bonsai.Schedulers;
+import com.anthonycr.bonsai.Single;
+import com.anthonycr.bonsai.SingleAction;
+import com.anthonycr.bonsai.SingleOnSubscribe;
+import com.anthonycr.bonsai.SingleSubscriber;
import com.anthonycr.bonsai.Subscription;
+
import acr.browser.lightning.reading.HtmlFetcher;
import acr.browser.lightning.reading.JResult;
import acr.browser.lightning.utils.ThemeUtils;
import acr.browser.lightning.utils.Utils;
-import butterknife.Bind;
+import butterknife.BindView;
import butterknife.ButterKnife;
public class ReadingActivity extends AppCompatActivity {
- private static final String TAG = ReadingActivity.class.getSimpleName();
+ private static final String TAG = "ReadingActivity";
- @Bind(R.id.textViewTitle)
- TextView mTitle;
-
- @Bind(R.id.textViewBody)
- TextView mBody;
+ @BindView(R.id.textViewTitle) TextView mTitle;
+ @BindView(R.id.textViewBody) TextView mBody;
@Inject PreferenceManager mPreferences;
@@ -132,11 +131,17 @@ public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.reading, menu);
MenuItem invert = menu.findItem(R.id.invert_item);
MenuItem textSize = menu.findItem(R.id.text_size_item);
- int iconColor = mInvert ? ThemeUtils.getIconDarkThemeColor(this) : ThemeUtils.getIconLightThemeColor(this);
- if (invert != null && invert.getIcon() != null)
- invert.getIcon().setColorFilter(iconColor, PorterDuff.Mode.SRC_IN);
- if (textSize != null && textSize.getIcon() != null)
- textSize.getIcon().setColorFilter(iconColor, PorterDuff.Mode.SRC_IN);
+
+ int iconColor = ThemeUtils.getIconThemeColor(this, mInvert);
+
+ if (invert != null && invert.getIcon() != null) {
+ invert.getIcon().mutate().setColorFilter(iconColor, PorterDuff.Mode.SRC_IN);
+ }
+
+ if (textSize != null && textSize.getIcon() != null) {
+ textSize.getIcon().mutate().setColorFilter(iconColor, PorterDuff.Mode.SRC_IN);
+ }
+
return super.onCreateOptionsMenu(menu);
}
@@ -151,56 +156,56 @@ private boolean loadPage(Intent intent) {
if (getSupportActionBar() != null)
getSupportActionBar().setTitle(Utils.getDomainName(mUrl));
mPageLoaderSubscription = loadPage(mUrl).subscribeOn(Schedulers.worker())
- .observeOn(Schedulers.main())
- .subscribe(new OnSubscribe() {
- @Override
- public void onStart() {
- mProgressDialog = new ProgressDialog(ReadingActivity.this);
- mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
- mProgressDialog.setCancelable(false);
- mProgressDialog.setIndeterminate(true);
- mProgressDialog.setMessage(getString(R.string.loading));
- mProgressDialog.show();
- BrowserDialog.setDialogSize(ReadingActivity.this, mProgressDialog);
- }
+ .observeOn(Schedulers.main())
+ .subscribe(new SingleOnSubscribe() {
+ @Override
+ public void onStart() {
+ mProgressDialog = new ProgressDialog(ReadingActivity.this);
+ mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+ mProgressDialog.setCancelable(false);
+ mProgressDialog.setIndeterminate(true);
+ mProgressDialog.setMessage(getString(R.string.loading));
+ mProgressDialog.show();
+ BrowserDialog.setDialogSize(ReadingActivity.this, mProgressDialog);
+ }
- @Override
- public void onNext(@Nullable ReaderInfo item) {
- if (item == null || item.getTitle().isEmpty() || item.getBody().isEmpty()) {
- setText(getString(R.string.untitled), getString(R.string.loading_failed));
- } else {
- setText(item.getTitle(), item.getBody());
- }
+ @Override
+ public void onItem(@Nullable ReaderInfo item) {
+ if (item == null || item.getTitle().isEmpty() || item.getBody().isEmpty()) {
+ setText(getString(R.string.untitled), getString(R.string.loading_failed));
+ } else {
+ setText(item.getTitle(), item.getBody());
}
+ }
- @Override
- public void onError(@NonNull Throwable throwable) {
- setText(getString(R.string.untitled), getString(R.string.loading_failed));
- if (mProgressDialog != null && mProgressDialog.isShowing()) {
- mProgressDialog.dismiss();
- mProgressDialog = null;
- }
+ @Override
+ public void onError(@NonNull Throwable throwable) {
+ setText(getString(R.string.untitled), getString(R.string.loading_failed));
+ if (mProgressDialog != null && mProgressDialog.isShowing()) {
+ mProgressDialog.dismiss();
+ mProgressDialog = null;
}
+ }
- @Override
- public void onComplete() {
- if (mProgressDialog != null && mProgressDialog.isShowing()) {
- mProgressDialog.dismiss();
- mProgressDialog = null;
- }
+ @Override
+ public void onComplete() {
+ if (mProgressDialog != null && mProgressDialog.isShowing()) {
+ mProgressDialog.dismiss();
+ mProgressDialog = null;
}
- });
+ }
+ });
return true;
}
- private static Observable loadPage(@NonNull final String url) {
- return Observable.create(new Action() {
+ private static Single loadPage(@NonNull final String url) {
+ return Single.create(new SingleAction() {
@Override
- public void onSubscribe(@NonNull Subscriber subscriber) {
+ public void onSubscribe(@NonNull SingleSubscriber subscriber) {
HtmlFetcher fetcher = new HtmlFetcher();
try {
JResult result = fetcher.fetchAndExtract(url, 2500, true);
- subscriber.onNext(new ReaderInfo(result.getTitle(), result.getText()));
+ subscriber.onItem(new ReaderInfo(result.getTitle(), result.getText()));
} catch (Exception e) {
subscriber.onError(new Throwable("Encountered exception"));
Log.e(TAG, "Error parsing page", e);
@@ -290,9 +295,8 @@ public boolean onOptionsItemSelected(MenuItem item) {
finish();
break;
case R.id.text_size_item:
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- LayoutInflater inflater = this.getLayoutInflater();
- View view = inflater.inflate(R.layout.seek_layout, null);
+
+ View view = LayoutInflater.from(this).inflate(R.layout.dialog_seek_bar, null);
final SeekBar bar = (SeekBar) view.findViewById(R.id.text_size_seekbar);
bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@@ -312,18 +316,20 @@ public void onStopTrackingTouch(SeekBar arg0) {
});
bar.setMax(5);
bar.setProgress(mTextSize);
- builder.setView(view);
- builder.setTitle(R.string.size);
- builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
- @Override
- public void onClick(DialogInterface arg0, int arg1) {
- mTextSize = bar.getProgress();
- mBody.setTextSize(getTextSize(mTextSize));
- mPreferences.setReadingTextSize(bar.getProgress());
- }
+ AlertDialog.Builder builder = new AlertDialog.Builder(this)
+ .setView(view)
+ .setTitle(R.string.size)
+ .setPositiveButton(android.R.string.ok, new OnClickListener() {
- });
+ @Override
+ public void onClick(DialogInterface dialog, int arg1) {
+ mTextSize = bar.getProgress();
+ mBody.setTextSize(getTextSize(mTextSize));
+ mPreferences.setReadingTextSize(bar.getProgress());
+ }
+
+ });
Dialog dialog = builder.show();
BrowserDialog.setDialogSize(this, dialog);
break;
diff --git a/app/src/main/java/acr/browser/lightning/activity/SettingsActivity.java b/app/src/main/java/acr/browser/lightning/activity/SettingsActivity.java
index 6fcdb29a9..498bd06bf 100644
--- a/app/src/main/java/acr/browser/lightning/activity/SettingsActivity.java
+++ b/app/src/main/java/acr/browser/lightning/activity/SettingsActivity.java
@@ -23,7 +23,7 @@
public class SettingsActivity extends ThemableSettingsActivity {
- private static final List mFragments = new ArrayList<>(7);
+ @NonNull private static final List mFragments = new ArrayList<>(7);
@Override
protected void onCreate(Bundle savedInstanceState) {
diff --git a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java
index 08c85a62a..11ce58cc8 100644
--- a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java
+++ b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java
@@ -14,7 +14,15 @@
import android.util.Log;
import android.webkit.WebView;
-import com.squareup.otto.Bus;
+import com.anthonycr.bonsai.Completable;
+import com.anthonycr.bonsai.CompletableAction;
+import com.anthonycr.bonsai.CompletableSubscriber;
+import com.anthonycr.bonsai.Schedulers;
+import com.anthonycr.bonsai.SingleOnSubscribe;
+import com.anthonycr.bonsai.Stream;
+import com.anthonycr.bonsai.StreamAction;
+import com.anthonycr.bonsai.StreamOnSubscribe;
+import com.anthonycr.bonsai.StreamSubscriber;
import java.util.ArrayList;
import java.util.List;
@@ -25,20 +33,13 @@
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.constant.BookmarkPage;
import acr.browser.lightning.constant.Constants;
+import acr.browser.lightning.constant.DownloadsPage;
import acr.browser.lightning.constant.HistoryPage;
import acr.browser.lightning.constant.StartPage;
-import acr.browser.lightning.database.BookmarkManager;
-import acr.browser.lightning.database.HistoryDatabase;
import acr.browser.lightning.dialog.BrowserDialog;
import acr.browser.lightning.preference.PreferenceManager;
-
-import com.anthonycr.bonsai.Action;
-import com.anthonycr.bonsai.Observable;
-import com.anthonycr.bonsai.OnSubscribe;
-import com.anthonycr.bonsai.Schedulers;
-import com.anthonycr.bonsai.Subscriber;
-
import acr.browser.lightning.utils.FileUtils;
+import acr.browser.lightning.utils.Preconditions;
import acr.browser.lightning.utils.UrlUtils;
import acr.browser.lightning.view.LightningView;
@@ -49,22 +50,20 @@
*/
public class TabsManager {
- private static final String TAG = TabsManager.class.getSimpleName();
+ private static final String TAG = "TabsManager";
+
private static final String BUNDLE_KEY = "WEBVIEW_";
private static final String URL_KEY = "URL_KEY";
private static final String BUNDLE_STORAGE = "SAVED_TABS.parcel";
- private final List mTabList = new ArrayList<>(1);
+ @NonNull private final List mTabList = new ArrayList<>(1);
@Nullable private LightningView mCurrentTab;
@Nullable private TabNumberChangedListener mTabNumberListener;
private boolean mIsInitialized = false;
- private final List mPostInitializationWorkList = new ArrayList<>();
+ @NonNull private final List mPostInitializationWorkList = new ArrayList<>();
@Inject PreferenceManager mPreferenceManager;
- @Inject BookmarkManager mBookmarkManager;
- @Inject HistoryDatabase mHistoryManager;
- @Inject Bus mEventBus;
@Inject Application mApp;
public TabsManager() {
@@ -108,13 +107,13 @@ private synchronized void finishInitialization() {
* @param intent the intent that started the browser activity.
* @param incognito whether or not we are in incognito mode.
*/
- public synchronized Observable initializeTabs(@NonNull final Activity activity,
- @Nullable final Intent intent,
- final boolean incognito) {
- return Observable.create(new Action() {
+ @NonNull
+ public synchronized Completable initializeTabs(@NonNull final Activity activity,
+ @Nullable final Intent intent,
+ final boolean incognito) {
+ return Completable.create(new CompletableAction() {
@Override
- public void onSubscribe(@NonNull final Subscriber subscriber) {
-
+ public void onSubscribe(@NonNull CompletableSubscriber subscriber) {
// Make sure we start with a clean tab list
shutdown();
@@ -150,70 +149,111 @@ public void onSubscribe(@NonNull final Subscriber subscriber) {
}
private void restoreLostTabs(@Nullable final String url, @NonNull final Activity activity,
- @NonNull final Subscriber subscriber) {
-
- restoreState().subscribeOn(Schedulers.io())
- .observeOn(Schedulers.main()).subscribe(new OnSubscribe() {
- @Override
- public void onNext(Bundle item) {
- LightningView tab = newTab(activity, "", false);
- String url = item.getString(URL_KEY);
- if (url != null && tab.getWebView() != null) {
- if (UrlUtils.isBookmarkUrl(url)) {
- new BookmarkPage(tab, activity, mBookmarkManager).load();
- } else if (UrlUtils.isStartPageUrl(url)) {
- new StartPage(tab, mApp).load();
- } else if (UrlUtils.isHistoryUrl(url)) {
- new HistoryPage(tab, mApp, mHistoryManager).load();
+ @NonNull final CompletableSubscriber subscriber) {
+
+ restoreState()
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.main())
+ .subscribe(new StreamOnSubscribe() {
+ @Override
+ public void onNext(@Nullable Bundle item) {
+ final LightningView tab = newTab(activity, "", false);
+ Preconditions.checkNonNull(item);
+ String url = item.getString(URL_KEY);
+ if (url != null && tab.getWebView() != null) {
+ if (UrlUtils.isBookmarkUrl(url)) {
+ new BookmarkPage(activity).getBookmarkPage()
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.main())
+ .subscribe(new SingleOnSubscribe() {
+ @Override
+ public void onItem(@Nullable String item) {
+ Preconditions.checkNonNull(item);
+ tab.loadUrl(item);
+ }
+ });
+ } else if (UrlUtils.isDownloadsUrl(url)) {
+ new DownloadsPage().getDownloadsPage()
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.main())
+ .subscribe(new SingleOnSubscribe() {
+ @Override
+ public void onItem(@Nullable String item) {
+ Preconditions.checkNonNull(item);
+ tab.loadUrl(item);
+ }
+ });
+ } else if (UrlUtils.isStartPageUrl(url)) {
+ new StartPage().getHomepage()
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.main())
+ .subscribe(new SingleOnSubscribe() {
+ @Override
+ public void onItem(@Nullable String item) {
+ Preconditions.checkNonNull(item);
+ tab.loadUrl(item);
+ }
+ });
+ } else if (UrlUtils.isHistoryUrl(url)) {
+ new HistoryPage().getHistoryPage()
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.main())
+ .subscribe(new SingleOnSubscribe() {
+ @Override
+ public void onItem(@Nullable String item) {
+ Preconditions.checkNonNull(item);
+ tab.loadUrl(item);
+ }
+ });
+ }
+ } else if (tab.getWebView() != null) {
+ tab.getWebView().restoreState(item);
}
- } else if (tab.getWebView() != null) {
- tab.getWebView().restoreState(item);
}
- }
- @Override
- public void onComplete() {
- if (url != null) {
- if (url.startsWith(Constants.FILE)) {
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- Dialog dialog = builder.setCancelable(true)
- .setTitle(R.string.title_warning)
- .setMessage(R.string.message_blocked_local)
- .setOnDismissListener(new DialogInterface.OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface dialog) {
- if (mTabList.isEmpty()) {
- newTab(activity, null, false);
+ @Override
+ public void onComplete() {
+ if (url != null) {
+ if (url.startsWith(Constants.FILE)) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ Dialog dialog = builder.setCancelable(true)
+ .setTitle(R.string.title_warning)
+ .setMessage(R.string.message_blocked_local)
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ if (mTabList.isEmpty()) {
+ newTab(activity, null, false);
+ }
+ finishInitialization();
+ subscriber.onComplete();
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, null)
+ .setPositiveButton(R.string.action_open, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ newTab(activity, url, false);
}
- finishInitialization();
- subscriber.onComplete();
- }
- })
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(R.string.action_open, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- newTab(activity, url, false);
- }
- }).show();
- BrowserDialog.setDialogSize(activity, dialog);
+ }).show();
+ BrowserDialog.setDialogSize(activity, dialog);
+ } else {
+ newTab(activity, url, false);
+ if (mTabList.isEmpty()) {
+ newTab(activity, null, false);
+ }
+ finishInitialization();
+ subscriber.onComplete();
+ }
} else {
- newTab(activity, url, false);
if (mTabList.isEmpty()) {
newTab(activity, null, false);
}
finishInitialization();
subscriber.onComplete();
}
- } else {
- if (mTabList.isEmpty()) {
- newTab(activity, null, false);
- }
- finishInitialization();
- subscriber.onComplete();
}
- }
- });
+ });
}
/**
@@ -443,7 +483,7 @@ public synchronized int positionOf(final LightningView tab) {
*/
public void saveState() {
Bundle outState = new Bundle(ClassLoader.getSystemClassLoader());
- Log.d(Constants.TAG, "Saving tab state");
+ Log.d(TAG, "Saving tab state");
for (int n = 0; n < mTabList.size(); n++) {
LightningView tab = mTabList.get(n);
if (TextUtils.isEmpty(tab.getUrl())) {
@@ -477,13 +517,13 @@ public void clearSavedState() {
* and will delete the saved instance file when
* restoration is complete.
*/
- private Observable restoreState() {
- return Observable.create(new Action() {
+ private Stream restoreState() {
+ return Stream.create(new StreamAction() {
@Override
- public void onSubscribe(@NonNull Subscriber subscriber) {
+ public void onSubscribe(@NonNull StreamSubscriber subscriber) {
Bundle savedState = FileUtils.readBundleFromStorage(mApp, BUNDLE_STORAGE);
if (savedState != null) {
- Log.d(Constants.TAG, "Restoring previous WebView state now");
+ Log.d(TAG, "Restoring previous WebView state now");
for (String key : savedState.keySet()) {
if (key.startsWith(BUNDLE_KEY)) {
subscriber.onNext(savedState.getBundle(key));
@@ -496,17 +536,6 @@ public void onSubscribe(@NonNull Subscriber subscriber) {
});
}
- /**
- * Return the {@link WebView} associated to the current tab,
- * or null if there is no current tab.
- *
- * @return a {@link WebView} or null if there is no current tab.
- */
- @Nullable
- public synchronized WebView getCurrentWebView() {
- return mCurrentTab != null ? mCurrentTab.getWebView() : null;
- }
-
/**
* Returns the index of the current tab.
*
@@ -538,6 +567,26 @@ public synchronized LightningView getCurrentTab() {
return mCurrentTab;
}
+ /**
+ * Returns the {@link LightningView} with
+ * the provided hash, or null if there is
+ * no tab with the hash.
+ *
+ * @param hashCode the hashcode.
+ * @return the tab with an identical hash, or null.
+ */
+ @Nullable
+ public synchronized LightningView getTabForHashCode(int hashCode) {
+ for (LightningView tab : mTabList) {
+ if (tab.getWebView() != null) {
+ if (tab.getWebView().hashCode() == hashCode) {
+ return tab;
+ }
+ }
+ }
+ return null;
+ }
+
/**
* Switch the current tab to the one at the given position.
* It returns the selected tab that has been switced to.
diff --git a/app/src/main/java/acr/browser/lightning/activity/ThemableBrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/ThemableBrowserActivity.java
index b4d112fdd..3a29986da 100644
--- a/app/src/main/java/acr/browser/lightning/activity/ThemableBrowserActivity.java
+++ b/app/src/main/java/acr/browser/lightning/activity/ThemableBrowserActivity.java
@@ -2,6 +2,8 @@
import android.content.Intent;
import android.content.res.Configuration;
+import android.graphics.Color;
+import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
@@ -10,6 +12,7 @@
import acr.browser.lightning.R;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.preference.PreferenceManager;
+import acr.browser.lightning.utils.ThemeUtils;
public abstract class ThemableBrowserActivity extends AppCompatActivity {
@@ -32,6 +35,18 @@ protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.Theme_BlackTheme);
}
super.onCreate(savedInstanceState);
+
+ resetPreferences();
+ }
+
+ private void resetPreferences() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ if (mPreferences.getUseBlackStatusBar()) {
+ getWindow().setStatusBarColor(Color.BLACK);
+ } else {
+ getWindow().setStatusBarColor(ThemeUtils.getStatusBarColor(this));
+ }
+ }
}
@Override
@@ -56,6 +71,7 @@ void onWindowVisibleToUserAfterResume() {
@Override
protected void onResume() {
super.onResume();
+ resetPreferences();
mShouldRunOnResumeActions = true;
int theme = mPreferences.getUseTheme();
boolean drawerTabs = mPreferences.getShowTabsInDrawer(!isTablet());
diff --git a/app/src/main/java/acr/browser/lightning/activity/ThemableSettingsActivity.java b/app/src/main/java/acr/browser/lightning/activity/ThemableSettingsActivity.java
index 4d3cbe5f9..ebc2c1e78 100644
--- a/app/src/main/java/acr/browser/lightning/activity/ThemableSettingsActivity.java
+++ b/app/src/main/java/acr/browser/lightning/activity/ThemableSettingsActivity.java
@@ -1,6 +1,8 @@
package acr.browser.lightning.activity;
+import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
+import android.os.Build;
import android.os.Bundle;
import javax.inject.Inject;
@@ -14,12 +16,12 @@ public abstract class ThemableSettingsActivity extends AppCompatPreferenceActivi
private int mTheme;
- @Inject PreferenceManager mPreferenceManager;
+ @Inject PreferenceManager mPreferences;
@Override
protected void onCreate(Bundle savedInstanceState) {
BrowserApp.getAppComponent().inject(this);
- mTheme = mPreferenceManager.getUseTheme();
+ mTheme = mPreferences.getUseTheme();
// set the theme
if (mTheme == 0) {
@@ -33,12 +35,25 @@ protected void onCreate(Bundle savedInstanceState) {
this.getWindow().setBackgroundDrawable(new ColorDrawable(ThemeUtils.getPrimaryColorDark(this)));
}
super.onCreate(savedInstanceState);
+
+ resetPreferences();
+ }
+
+ private void resetPreferences() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ if (mPreferences.getUseBlackStatusBar()) {
+ getWindow().setStatusBarColor(Color.BLACK);
+ } else {
+ getWindow().setStatusBarColor(ThemeUtils.getStatusBarColor(this));
+ }
+ }
}
@Override
protected void onResume() {
super.onResume();
- if (mPreferenceManager.getUseTheme() != mTheme) {
+ resetPreferences();
+ if (mPreferences.getUseTheme() != mTheme) {
restart();
}
}
diff --git a/app/src/main/java/acr/browser/lightning/animation/AnimationUtils.java b/app/src/main/java/acr/browser/lightning/animation/AnimationUtils.java
new file mode 100644
index 000000000..825144847
--- /dev/null
+++ b/app/src/main/java/acr/browser/lightning/animation/AnimationUtils.java
@@ -0,0 +1,52 @@
+package acr.browser.lightning.animation;
+
+import android.support.annotation.DrawableRes;
+import android.support.annotation.NonNull;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+import android.widget.ImageView;
+
+/**
+ * Animation specific helper code.
+ */
+public class AnimationUtils {
+
+ /**
+ * Creates an animation that rotates an {@link ImageView}
+ * around the Y axis by 180 degrees and changes the image
+ * resource shown when the view is rotated 90 degrees to the user.
+ *
+ * @param imageView the view to rotate.
+ * @param drawableRes the drawable to set when the view
+ * is rotated by 90 degrees.
+ * @return an animation that will change the image shown by the view.
+ */
+ @NonNull
+ public static Animation createRotationTransitionAnimation(@NonNull final ImageView imageView,
+ @DrawableRes final int drawableRes) {
+ Animation animation = new Animation() {
+
+ private boolean mSetFinalDrawable;
+
+ @Override
+ protected void applyTransformation(float interpolatedTime, Transformation t) {
+ if (interpolatedTime < 0.5f) {
+ imageView.setRotationY(90 * interpolatedTime * 2f);
+ } else {
+ if (!mSetFinalDrawable) {
+ mSetFinalDrawable = true;
+ imageView.setImageResource(drawableRes);
+ }
+ imageView.setRotationY((-90) + (90 * (interpolatedTime - 0.5f) * 2f));
+ }
+ }
+ };
+
+ animation.setDuration(300);
+ animation.setInterpolator(new AccelerateDecelerateInterpolator());
+
+ return animation;
+ }
+
+}
diff --git a/app/src/main/java/acr/browser/lightning/app/AppComponent.java b/app/src/main/java/acr/browser/lightning/app/AppComponent.java
index c28da576e..8ca9d5c4f 100644
--- a/app/src/main/java/acr/browser/lightning/app/AppComponent.java
+++ b/app/src/main/java/acr/browser/lightning/app/AppComponent.java
@@ -8,7 +8,11 @@
import acr.browser.lightning.activity.ThemableBrowserActivity;
import acr.browser.lightning.activity.ThemableSettingsActivity;
import acr.browser.lightning.browser.BrowserPresenter;
+import acr.browser.lightning.constant.BookmarkPage;
+import acr.browser.lightning.constant.DownloadsPage;
+import acr.browser.lightning.constant.HistoryPage;
import acr.browser.lightning.constant.StartPage;
+import acr.browser.lightning.database.history.HistoryDatabase;
import acr.browser.lightning.dialog.LightningDialogBuilder;
import acr.browser.lightning.download.LightningDownloadListener;
import acr.browser.lightning.fragment.BookmarkSettingsFragment;
@@ -18,8 +22,8 @@
import acr.browser.lightning.fragment.PrivacySettingsFragment;
import acr.browser.lightning.fragment.TabsFragment;
import acr.browser.lightning.search.SuggestionsAdapter;
-import acr.browser.lightning.utils.AdBlock;
import acr.browser.lightning.utils.ProxyUtils;
+import acr.browser.lightning.view.LightningChromeClient;
import acr.browser.lightning.view.LightningView;
import acr.browser.lightning.view.LightningWebClient;
import dagger.Component;
@@ -54,14 +58,18 @@ public interface AppComponent {
void inject(ThemableSettingsActivity activity);
- void inject(AdBlock adBlock);
-
void inject(LightningDownloadListener listener);
void inject(PrivacySettingsFragment fragment);
void inject(StartPage startPage);
+ void inject(HistoryPage historyPage);
+
+ void inject(BookmarkPage bookmarkPage);
+
+ void inject(DownloadsPage downloadsPage);
+
void inject(BrowserPresenter presenter);
void inject(TabsManager manager);
@@ -70,4 +78,8 @@ public interface AppComponent {
void inject(SuggestionsAdapter suggestionsAdapter);
+ void inject(LightningChromeClient chromeClient);
+
+ HistoryDatabase historyDatabase();
+
}
diff --git a/app/src/main/java/acr/browser/lightning/app/AppModule.java b/app/src/main/java/acr/browser/lightning/app/AppModule.java
index 9a4811eef..400d78374 100644
--- a/app/src/main/java/acr/browser/lightning/app/AppModule.java
+++ b/app/src/main/java/acr/browser/lightning/app/AppModule.java
@@ -4,23 +4,23 @@
import android.content.Context;
import android.support.annotation.NonNull;
-import com.squareup.otto.Bus;
-
import net.i2p.android.ui.I2PAndroidHelper;
import javax.inject.Singleton;
+import acr.browser.lightning.database.bookmark.BookmarkDatabase;
+import acr.browser.lightning.database.bookmark.BookmarkModel;
+import acr.browser.lightning.database.downloads.DownloadsDatabase;
+import acr.browser.lightning.database.downloads.DownloadsModel;
import dagger.Module;
import dagger.Provides;
@Module
public class AppModule {
private final BrowserApp mApp;
- @NonNull private final Bus mBus;
public AppModule(BrowserApp app) {
this.mApp = app;
- this.mBus = new Bus();
}
@Provides
@@ -35,8 +35,16 @@ public Context provideContext() {
@NonNull
@Provides
- public Bus provideBus() {
- return mBus;
+ @Singleton
+ public BookmarkModel provideBookmarkMode() {
+ return new BookmarkDatabase(mApp);
+ }
+
+ @NonNull
+ @Provides
+ @Singleton
+ public DownloadsModel provideDownloadsMode() {
+ return new DownloadsDatabase(mApp);
}
@NonNull
diff --git a/app/src/main/java/acr/browser/lightning/app/BrowserApp.java b/app/src/main/java/acr/browser/lightning/app/BrowserApp.java
index 6bf6d734c..1bbc19a56 100644
--- a/app/src/main/java/acr/browser/lightning/app/BrowserApp.java
+++ b/app/src/main/java/acr/browser/lightning/app/BrowserApp.java
@@ -8,32 +8,45 @@
import android.os.Build;
import android.os.StrictMode;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatDelegate;
import android.util.Log;
import android.webkit.WebView;
+import com.anthonycr.bonsai.Schedulers;
import com.squareup.leakcanary.LeakCanary;
-import com.squareup.otto.Bus;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
+import java.util.List;
import javax.inject.Inject;
import acr.browser.lightning.BuildConfig;
+import acr.browser.lightning.database.HistoryItem;
+import acr.browser.lightning.database.bookmark.BookmarkExporter;
+import acr.browser.lightning.database.bookmark.legacy.LegacyBookmarkManager;
+import acr.browser.lightning.database.bookmark.BookmarkModel;
import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.FileUtils;
import acr.browser.lightning.utils.MemoryLeakUtils;
+import acr.browser.lightning.utils.Preconditions;
public class BrowserApp extends Application {
- private static final String TAG = BrowserApp.class.getSimpleName();
+ private static final String TAG = "BrowserApp";
- private static AppComponent mAppComponent;
- private static final Executor mIOThread = Executors.newSingleThreadExecutor();
- private static final Executor mTaskThread = Executors.newCachedThreadPool();
+ static {
+ AppCompatDelegate.setCompatVectorFromResourcesEnabled(Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT);
+ }
+
+ @Nullable private static AppComponent sAppComponent;
- @Inject Bus mBus;
@Inject PreferenceManager mPreferenceManager;
+ @Inject BookmarkModel mBookmarkModel;
+
+ @Override
+ protected void attachBaseContext(Context base) {
+ super.attachBaseContext(base);
+ }
@Override
public void onCreate() {
@@ -53,7 +66,7 @@ public void onCreate() {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
- public void uncaughtException(Thread thread, Throwable ex) {
+ public void uncaughtException(Thread thread, @NonNull Throwable ex) {
if (BuildConfig.DEBUG) {
FileUtils.writeCrashToStorage(ex);
@@ -67,8 +80,24 @@ public void uncaughtException(Thread thread, Throwable ex) {
}
});
- mAppComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
- mAppComponent.inject(this);
+ sAppComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
+ sAppComponent.inject(this);
+
+ Schedulers.worker().execute(new Runnable() {
+ @Override
+ public void run() {
+ List oldBookmarks = LegacyBookmarkManager.destructiveGetBookmarks(BrowserApp.this);
+
+ if (!oldBookmarks.isEmpty()) {
+ // If there are old bookmarks, import them
+ mBookmarkModel.addBookmarkList(oldBookmarks).subscribeOn(Schedulers.io()).subscribe();
+ } else if (mBookmarkModel.count() == 0) {
+ // If the database is empty, fill it from the assets list
+ List assetsBookmarks = BookmarkExporter.importBookmarksFromAssets(BrowserApp.this);
+ mBookmarkModel.addBookmarkList(assetsBookmarks).subscribeOn(Schedulers.io()).subscribe();
+ }
+ }
+ });
if (mPreferenceManager.getUseLeakCanary() && !isRelease()) {
LeakCanary.install(this);
@@ -87,26 +116,9 @@ public void onActivityDestroyed(Activity activity) {
}
@NonNull
- public static BrowserApp get(@NonNull Context context) {
- return (BrowserApp) context.getApplicationContext();
- }
-
public static AppComponent getAppComponent() {
- return mAppComponent;
- }
-
- @NonNull
- public static Executor getIOThread() {
- return mIOThread;
- }
-
- @NonNull
- public static Executor getTaskThread() {
- return mTaskThread;
- }
-
- public static Bus getBus(@NonNull Context context) {
- return get(context).mBus;
+ Preconditions.checkNonNull(sAppComponent);
+ return sAppComponent;
}
/**
diff --git a/app/src/main/java/acr/browser/lightning/async/AsyncExecutor.java b/app/src/main/java/acr/browser/lightning/async/AsyncExecutor.java
deleted file mode 100644
index 7dea22476..000000000
--- a/app/src/main/java/acr/browser/lightning/async/AsyncExecutor.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package acr.browser.lightning.async;
-
-import android.support.annotation.NonNull;
-import android.util.Log;
-
-import java.util.ArrayDeque;
-import java.util.Queue;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.RejectedExecutionException;
-
-/**
- * Created 9/27/2015 Anthony Restaino
- */
-public class AsyncExecutor implements Executor {
-
- private static final String TAG = AsyncExecutor.class.getSimpleName();
- private static final AsyncExecutor INSTANCE = new AsyncExecutor();
- private final Queue mQueue = new ArrayDeque<>(1);
- private final ExecutorService mExecutor = Executors.newFixedThreadPool(4);
-
- private AsyncExecutor() {}
-
- @NonNull
- public static AsyncExecutor getInstance() {
- return INSTANCE;
- }
-
- public synchronized void notifyThreadFinish() {
- if (mQueue.isEmpty()) {
- return;
- }
- Runnable runnable = mQueue.remove();
- execute(runnable);
- }
-
- @Override
- protected void finalize() throws Throwable {
- mExecutor.shutdownNow();
- super.finalize();
- }
-
- @Override
- public void execute(@NonNull Runnable command) {
- try {
- mExecutor.execute(command);
- } catch (RejectedExecutionException ignored) {
- mQueue.add(command);
- Log.d(TAG, "Thread was enqueued");
- }
- }
-}
diff --git a/app/src/main/java/acr/browser/lightning/async/ImageDownloadTask.java b/app/src/main/java/acr/browser/lightning/async/ImageDownloadTask.java
deleted file mode 100644
index 60cd9bfd4..000000000
--- a/app/src/main/java/acr/browser/lightning/async/ImageDownloadTask.java
+++ /dev/null
@@ -1,156 +0,0 @@
-package acr.browser.lightning.async;
-
-import android.app.Application;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.support.annotation.NonNull;
-import android.util.Log;
-import android.widget.ImageView;
-
-import com.anthonycr.bonsai.Schedulers;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.lang.ref.WeakReference;
-import java.net.HttpURLConnection;
-import java.net.URL;
-
-import acr.browser.lightning.constant.Constants;
-import acr.browser.lightning.database.HistoryItem;
-import acr.browser.lightning.utils.Utils;
-
-public class ImageDownloadTask extends AsyncTask {
-
- private static final String TAG = ImageDownloadTask.class.getSimpleName();
- @NonNull private final WeakReference mFaviconImage;
- @NonNull private final Application mContext;
- @NonNull private final HistoryItem mWeb;
- private final String mUrl;
- @NonNull private final Bitmap mDefaultBitmap;
-
- public ImageDownloadTask(@NonNull ImageView bmImage,
- @NonNull HistoryItem web,
- @NonNull Bitmap defaultBitmap,
- @NonNull Application context) {
- // Set a tag on the ImageView so we know if the view
- // has gone out of scope and should not be used
- bmImage.setTag(web.getUrl().hashCode());
- this.mFaviconImage = new WeakReference<>(bmImage);
- this.mWeb = web;
- this.mUrl = web.getUrl();
- this.mDefaultBitmap = defaultBitmap;
- this.mContext = context;
- }
-
- @NonNull
- @Override
- protected Bitmap doInBackground(Void... params) {
- Bitmap mIcon = null;
- // unique path for each url that is bookmarked.
- if (mUrl == null) {
- return mDefaultBitmap;
- }
- File cache = mContext.getCacheDir();
- final Uri uri = Uri.parse(mUrl);
- if (uri.getHost() == null || uri.getScheme() == null) {
- return mDefaultBitmap;
- }
- final String hash = String.valueOf(uri.getHost().hashCode());
- final File image = new File(cache, hash + ".png");
- final String urlDisplay = uri.getScheme() + "://" + uri.getHost() + "/favicon.ico";
- if (Constants.FILE.startsWith(uri.getScheme())) {
- return mDefaultBitmap;
- }
- // checks to see if the image exists
- if (!image.exists()) {
- FileOutputStream fos = null;
- InputStream in = null;
- try {
- // if not, download it...
- final URL urlDownload = new URL(urlDisplay);
- final HttpURLConnection connection = (HttpURLConnection) urlDownload.openConnection();
- connection.setDoInput(true);
- connection.setConnectTimeout(1000);
- connection.setReadTimeout(1000);
- connection.connect();
- in = connection.getInputStream();
-
- if (in != null) {
- mIcon = BitmapFactory.decodeStream(in);
- }
- // ...and cache it
- if (mIcon != null) {
- fos = new FileOutputStream(image);
- mIcon.compress(Bitmap.CompressFormat.PNG, 100, fos);
- fos.flush();
- Log.d(Constants.TAG, "Downloaded: " + urlDisplay);
- }
-
- } catch (Exception ignored) {
- Log.d(TAG, "Could not download: " + urlDisplay);
- } finally {
- Utils.close(in);
- Utils.close(fos);
- }
- } else {
- // if it exists, retrieve it from the cache
- mIcon = BitmapFactory.decodeFile(image.getPath());
- }
- if (mIcon == null) {
- InputStream in = null;
- FileOutputStream fos = null;
- try {
- // if not, download it...
- final URL urlDownload = new URL("https://www.google.com/s2/favicons?domain_url=" + uri.toString());
- final HttpURLConnection connection = (HttpURLConnection) urlDownload.openConnection();
- connection.setDoInput(true);
- connection.setConnectTimeout(1000);
- connection.setReadTimeout(1000);
- connection.connect();
- in = connection.getInputStream();
-
- if (in != null) {
- mIcon = BitmapFactory.decodeStream(in);
- }
- // ...and cache it
- if (mIcon != null) {
- fos = new FileOutputStream(image);
- mIcon.compress(Bitmap.CompressFormat.PNG, 100, fos);
- fos.flush();
- }
-
- } catch (Exception e) {
- Log.d(TAG, "Could not download Google favicon");
- } finally {
- Utils.close(in);
- Utils.close(fos);
- }
- }
- if (mIcon == null) {
- return mDefaultBitmap;
- } else {
- return mIcon;
- }
- }
-
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- super.onPostExecute(bitmap);
- AsyncExecutor.getInstance().notifyThreadFinish();
- final Bitmap fav = Utils.padFavicon(bitmap);
- final ImageView view = mFaviconImage.get();
- if (view != null && view.getTag().equals(mWeb.getUrl().hashCode())) {
- Schedulers.main().execute(new Runnable() {
- @Override
- public void run() {
- view.setImageBitmap(fav);
- }
- });
- }
- mWeb.setBitmap(fav);
- }
-
-}
diff --git a/app/src/main/java/acr/browser/lightning/browser/BookmarksView.java b/app/src/main/java/acr/browser/lightning/browser/BookmarksView.java
index de578ca57..c09b4c789 100644
--- a/app/src/main/java/acr/browser/lightning/browser/BookmarksView.java
+++ b/app/src/main/java/acr/browser/lightning/browser/BookmarksView.java
@@ -2,10 +2,14 @@
import android.support.annotation.NonNull;
+import acr.browser.lightning.database.HistoryItem;
+
public interface BookmarksView {
void navigateBack();
void handleUpdatedUrl(@NonNull String url);
+ void handleBookmarkDeleted(@NonNull HistoryItem item);
+
}
diff --git a/app/src/main/java/acr/browser/lightning/browser/BrowserPresenter.java b/app/src/main/java/acr/browser/lightning/browser/BrowserPresenter.java
index 2c19fbf31..5ccfa72d2 100644
--- a/app/src/main/java/acr/browser/lightning/browser/BrowserPresenter.java
+++ b/app/src/main/java/acr/browser/lightning/browser/BrowserPresenter.java
@@ -7,11 +7,12 @@
import android.support.annotation.Nullable;
import android.util.Log;
+import com.anthonycr.bonsai.CompletableOnSubscribe;
import com.anthonycr.bonsai.Schedulers;
-import com.squareup.otto.Bus;
import javax.inject.Inject;
+import acr.browser.lightning.BuildConfig;
import acr.browser.lightning.R;
import acr.browser.lightning.activity.TabsManager;
import acr.browser.lightning.app.BrowserApp;
@@ -19,8 +20,6 @@
import acr.browser.lightning.controller.UIController;
import acr.browser.lightning.preference.PreferenceManager;
-import com.anthonycr.bonsai.OnSubscribe;
-
import acr.browser.lightning.utils.UrlUtils;
import acr.browser.lightning.view.LightningView;
@@ -31,11 +30,10 @@
*/
public class BrowserPresenter {
- private static final String TAG = BrowserPresenter.class.getSimpleName();
+ private static final String TAG = "BrowserPresenter";
@NonNull private final TabsManager mTabsModel;
@Inject PreferenceManager mPreferences;
- @Inject Bus mEventBus;
@NonNull private final BrowserView mView;
@Nullable private LightningView mCurrentTab;
@@ -65,7 +63,7 @@ public void tabNumberChanged(int newNumber) {
public void setupTabs(@Nullable Intent intent) {
mTabsModel.initializeTabs((Activity) mView, intent, mIsIncognito)
.subscribeOn(Schedulers.main())
- .subscribe(new OnSubscribe() {
+ .subscribe(new CompletableOnSubscribe() {
@Override
public void onComplete() {
// At this point we always have at least a tab in the tab manager
@@ -108,12 +106,12 @@ private void onTabChanged(@Nullable LightningView newTab) {
// TODO: Restore this when Google fixes the bug where the WebView is
// blank after calling onPause followed by onResume.
// mCurrentTab.onPause();
- mCurrentTab.setForegroundTab(false);
+ mCurrentTab.setIsForegroundTab(false);
}
newTab.resumeTimers();
newTab.onResume();
- newTab.setForegroundTab(true);
+ newTab.setIsForegroundTab(true);
mView.updateProgress(newTab.getProgress());
mView.setBackButtonEnabled(newTab.canGoBack());
@@ -164,10 +162,10 @@ public void deleteTab(int position) {
}
final boolean isShown = tabToDelete.isShown();
- boolean shouldClose = mShouldClose && isShown && Boolean.TRUE.equals(tabToDelete.getTag());
+ boolean shouldClose = mShouldClose && isShown && tabToDelete.isNewTab();
final LightningView currentTab = mTabsModel.getCurrentTab();
if (mTabsModel.size() == 1 && currentTab != null &&
- (UrlUtils.isSpecialUrl(currentTab.getUrl()) ||
+ (UrlUtils.isStartPageUrl(currentTab.getUrl()) ||
currentTab.getUrl().equals(mPreferences.getHomepage()))) {
mView.closeActivity();
return;
@@ -223,13 +221,16 @@ public void run() {
} else {
url = null;
}
- int num = 0;
+ int tabHashCode = 0;
if (intent != null && intent.getExtras() != null) {
- num = intent.getExtras().getInt(Constants.INTENT_ORIGIN);
+ tabHashCode = intent.getExtras().getInt(Constants.INTENT_ORIGIN);
}
- if (num == 1) {
- loadUrlInCurrentView(url);
+ if (tabHashCode != 0) {
+ LightningView tab = mTabsModel.getTabForHashCode(tabHashCode);
+ if (tab != null) {
+ tab.loadUrl(url);
+ }
} else if (url != null) {
if (url.startsWith(Constants.FILE)) {
mView.showBlockedLocalFileDialog(new DialogInterface.OnClickListener() {
@@ -239,7 +240,7 @@ public void onClick(DialogInterface dialog, int which) {
mShouldClose = true;
LightningView tab = mTabsModel.lastTab();
if (tab != null) {
- tab.setTag(true);
+ tab.setIsNewTab(true);
}
}
});
@@ -248,7 +249,7 @@ public void onClick(DialogInterface dialog, int which) {
mShouldClose = true;
LightningView tab = mTabsModel.lastTab();
if (tab != null) {
- tab.setTag(true);
+ tab.setIsNewTab(true);
}
}
}
@@ -317,7 +318,7 @@ public synchronized void tabChanged(int position) {
*/
public synchronized boolean newTab(@Nullable String url, boolean show) {
// Limit number of tabs for limited version of app
- if (!Constants.FULL_VERSION && mTabsModel.size() >= 10) {
+ if (!BuildConfig.FULL_VERSION && mTabsModel.size() >= 10) {
mView.showSnackbar(R.string.max_tabs);
return false;
}
diff --git a/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java b/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java
deleted file mode 100644
index a2f8ca3d2..000000000
--- a/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package acr.browser.lightning.bus;
-
-import acr.browser.lightning.database.HistoryItem;
-
-public final class BookmarkEvents {
-
- private BookmarkEvents() {
- // No instances
- }
-
- /**
- * The user ask to delete the selected bookmark
- */
- public static class Deleted {
- public final HistoryItem item;
-
- public Deleted(final HistoryItem item) {
- this.item = item;
- }
- }
-
- /**
- * Sended when a bookmark is edited
- */
- public static class BookmarkChanged {
-
- public final HistoryItem oldBookmark;
- public final HistoryItem newBookmark;
-
- public BookmarkChanged(final HistoryItem oldItem, final HistoryItem newItem) {
- oldBookmark = oldItem;
- newBookmark = newItem;
- }
- }
-}
diff --git a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java
deleted file mode 100644
index e0a281f58..000000000
--- a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package acr.browser.lightning.bus;
-
-public final class BrowserEvents {
-
- private BrowserEvents() {
- // No instances
- }
-
- public final static class OpenHistoryInCurrentTab {
- }
-
- /**
- * The user ask to open the given url as new tab
- */
- public final static class OpenUrlInNewTab {
-
- public enum Location {
- NEW_TAB,
- BACKGROUND,
- INCOGNITO
- }
-
- public final String url;
-
- public final Location location;
-
- public OpenUrlInNewTab(final String url) {
- this.url = url;
- this.location = Location.NEW_TAB;
- }
-
- public OpenUrlInNewTab(final String url, Location location) {
- this.url = url;
- this.location = location;
- }
- }
-}
diff --git a/app/src/main/java/acr/browser/lightning/constant/BookmarkPage.java b/app/src/main/java/acr/browser/lightning/constant/BookmarkPage.java
index c6d64ddf0..e4179329f 100644
--- a/app/src/main/java/acr/browser/lightning/constant/BookmarkPage.java
+++ b/app/src/main/java/acr/browser/lightning/constant/BookmarkPage.java
@@ -6,27 +6,32 @@
import android.app.Activity;
import android.app.Application;
import android.graphics.Bitmap;
-import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import com.anthonycr.bonsai.Single;
+import com.anthonycr.bonsai.SingleAction;
+import com.anthonycr.bonsai.SingleOnSubscribe;
+import com.anthonycr.bonsai.SingleSubscriber;
+
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
-import java.lang.ref.WeakReference;
import java.util.List;
+import javax.inject.Inject;
+
import acr.browser.lightning.R;
import acr.browser.lightning.app.BrowserApp;
-import acr.browser.lightning.database.BookmarkManager;
import acr.browser.lightning.database.HistoryItem;
+import acr.browser.lightning.database.bookmark.BookmarkModel;
+import acr.browser.lightning.utils.Preconditions;
import acr.browser.lightning.utils.ThemeUtils;
import acr.browser.lightning.utils.Utils;
-import acr.browser.lightning.view.LightningView;
-public final class BookmarkPage extends AsyncTask {
+public final class BookmarkPage {
/**
* The bookmark page standard suffix
@@ -42,8 +47,14 @@ public final class BookmarkPage extends AsyncTask {
private static final String HEADING_2 = "\n" +
"\n" +
- "\n" +
+ "\n" +
"