public class BaiduBrowser extends BasicBrowser {
    private static final String TAG = "Baidu";
    private static final String packageName = "com.baidu.browser.apps";
    private final static String[] columns = new String[]{"title", "url", "parent_uuid", "sync_uuid"};
    private List<Bookmark> bookmarks;

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_baidu));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_baidu));
    }


    private static final String fileName_origin = "dbbrowser.db";
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "Baidu" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            List<Bookmark> bookmarksList = fetchBookmarksList(filePath_cp, fileName_origin);
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    private List<Bookmark> fetchBookmarksList(String dir, String fileName) {
        String targetFilePath = dir + fileName;
        LogHelper.v(TAG + ":targetFilePath is:" + targetFilePath);
        List<Bookmark> result = new LinkedList<>();
        try {
            ExternalStorageUtil.copyFile(filePath_origin + fileName_origin, targetFilePath, this.getName());
        } catch (Exception e) {
            LogHelper.e(e.getMessage());
            return result;
        }
        result.addAll(fetchBookmarksList(false, targetFilePath, "bookmark", null, null, "create_time asc"));
        result.addAll(fetchBookmarksList(false, targetFilePath, "homepage", null, null, "create_time asc"));
        result.addAll(fetchBookmarksList(false, targetFilePath, "pc_bookmark", null, null, "create_time asc"));
        return result;
    }

    private List<Bookmark> fetchBookmarksList(boolean needThrowException, String dbFilePath, String tableName, String where, String[] whereArgs, String orderBy) {
        return fetchBookmarksList(needThrowException, dbFilePath, tableName, columns, where, whereArgs, orderBy);
    }

    private List<Bookmark> fetchBookmarksList(boolean needThrowException, String dbFilePath, String tableName, String[] columns, String where, String[] whereArgs, String orderBy) {
        LogHelper.v(TAG + ":读取SQLite数据库开始,dbFilePath:" + dbFilePath + ",tableName:" + tableName);
        List<Bookmark> result = new LinkedList<>();
        SQLiteDatabase sqLiteDatabase = null;
        Cursor cursor = null;
        boolean tableExist;
        try {
            sqLiteDatabase = DBHelper.openReadOnlyDatabase(dbFilePath);
            tableExist = DBHelper.checkTableExist(sqLiteDatabase, tableName);
            if (!tableExist) {
                LogHelper.v(TAG + ":database table " + tableName + " not exist.");
                if (needThrowException) {
                    throw new ConverterException(ContextUtil.buildReadBookmarksTableNotExistErrorMessage(this.getName()));
                } else {
                    return result;
                }
            }
            cursor = sqLiteDatabase.query(false, tableName, columns, where, whereArgs, null, null, orderBy, null);
            if (cursor != null && cursor.getCount() > 0) {
                parseBookmarkWithFolder(cursor, result);
            }

        } finally {
            if (cursor != null) {
                cursor.close();
            }
            if (sqLiteDatabase != null) {
                sqLiteDatabase.close();
            }
            LogHelper.v(TAG + ":读取SQLite数据库结束,dbFilePath:" + dbFilePath);
        }
        return result;
    }

    private void parseBookmarkWithFolder(Cursor cursor, List<Bookmark> result) {
        List<BaiduBookmark> bookmarks = parseBookmark(cursor);
        Map<String, BaiduBookmark> folders = new HashMap<>();
        for (BaiduBookmark item : bookmarks) {
            String url = item.getUrl();
            String sync_uuid = item.getSync_uuid();
            if (url == null || url.isEmpty() && !(sync_uuid == null || sync_uuid.isEmpty())) {
                folders.put(item.getSync_uuid(), item);
            }
        }

        for (BaiduBookmark item : bookmarks) {
            String url = item.getUrl();
            String parent_uuid = item.getParent_uuid();
            if (!(url == null || url.isEmpty())) {
                String folderPath = null;
                if (!(parent_uuid == null || parent_uuid.isEmpty())) {
                    folderPath = trim(parseFolderPath(folders, parent_uuid));
                }
                Bookmark bookmark = new Bookmark();
                bookmark.setTitle(item.getTitle());
                bookmark.setUrl(item.getUrl());
                bookmark.setFolder(folderPath == null ? "" : folderPath);
                result.add(bookmark);
            }
        }
    }

    private String parseFolderPath(Map<String, BaiduBookmark> folders, String parent_uuid) {
        BaiduBookmark parent = folders.get(parent_uuid);
        if (parent == null) {
            return null;
        }
        return parseFolderPath(folders, parent_uuid, "");
    }

    private String parseFolderPath(Map<String, BaiduBookmark> folders, String parent_uuid, String path) {
        BaiduBookmark parent = folders.get(parent_uuid);
        if (parent == null) {
            return path;
        }
        String title = parent.getTitle();
        if (!(title == null || title.isEmpty())) {
            path = title + Path.FILE_SPLIT + path;
        }
        return parseFolderPath(folders, parent.getParent_uuid(), path);
    }

    private List<BaiduBookmark> parseBookmark(Cursor cursor) {
        List<BaiduBookmark> result = new LinkedList<>();
        while (cursor.moveToNext()) {
            BaiduBookmark item = new BaiduBookmark();
            item.setTitle(cursor.getString(cursor.getColumnIndex("title")));
            item.setUrl(cursor.getString(cursor.getColumnIndex("url")));
            item.setParent_uuid(cursor.getString(cursor.getColumnIndex("parent_uuid")));
            item.setSync_uuid(cursor.getString(cursor.getColumnIndex("sync_uuid")));
            result.add(item);
        }
        return result;
    }

    private class BaiduBookmark extends Bookmark {
        @Getter
        @Setter
        private String parent_uuid;
        @Getter
        @Setter
        private String sync_uuid;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class Flyme5Browser extends DefaultBrowserAble {
    private String TAG = "Flyme5";
    private List<Bookmark> bookmarks;

    public Flyme5Browser() {
        super.TAG = this.TAG;
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_flyme5));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_flyme5));
    }


    private static final String fileName_origin = "browser2.db";
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "Flyme5" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String filePath_origin = Path.INNER_PATH_DATA + super.packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> bookmarksList = fetchBookmarksList(filePath_cp + fileName_origin);
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class MiuiBrowser extends DefaultBrowserAble {
    private String TAG = "Miui";
    private List<Bookmark> bookmarks;

    public MiuiBrowser() {
        super.TAG = this.TAG;
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_miui));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_miui));
    }


    private static final String fileName_origin = "browser2.db";
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "Miui" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String filePath_origin = Path.INNER_PATH_DATA + super.packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> bookmarksList = fetchBookmarksList(filePath_cp + fileName_origin);
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class FirefoxBrowser extends BasicBrowser {
    private static final String TAG = "Firefox";
    //    private static final String packageName = "org.mozilla.fennec";//每夜版
    private static final String packageName = "org.mozilla.firefox";//正式版
    private List<Bookmark> bookmarks;

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_firefox));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_firefox));
    }


    private static final String fileName_origin = "browser.db";
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "files" + Path.FILE_SPLIT + "mozilla" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "Firefox" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            List<Bookmark> bookmarksList = fetchBookmarksList(filePath_origin);
            LogHelper.v(TAG + ":书签数据:" + JsonUtil.toJson(bookmarksList));
            LogHelper.v(TAG + ":书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    private final static String[] columns = new String[]{"_id", "title", "url", "type", "parent"};

    private List<Bookmark> fetchBookmarksList(String dir) {
        List<Bookmark> result = new LinkedList<>();
        List<String> dirs = InternalStorageUtil.lsDir(dir);
        if (dirs == null || dirs.isEmpty()) {
            LogHelper.v(TAG + ":没有找到目标文件夹");
            return result;
        }
        String targetDir = null;
        String rule = "[a-z0-9]{8}";
        String endKey = ".default";
        for (String item : dirs) {
            if (item != null) {
                if (endKey.endsWith(endKey)) {
                    String tmp = item.replace(endKey, "");
                    if (tmp.matches(rule)) {
                        targetDir = item;
                        break;
                    }
                }
            }
        }
        if (targetDir == null || targetDir.isEmpty()) {
            LogHelper.v(TAG + ":真的没有找到目标文件夹");
            return result;
        } else {
            LogHelper.v(TAG + ":targetDir:" + targetDir);
        }
        dir += targetDir + Path.FILE_SPLIT;
        String sourceFilePath = dir + fileName_origin;
        LogHelper.v(TAG + ":sourceFilePath:" + sourceFilePath);
        ExternalStorageUtil.copyFile(sourceFilePath, filePath_cp + fileName_origin, this.getName());
        LogHelper.v(TAG + ":targetFilePath:" + filePath_cp + fileName_origin);
        return fetchBookmarksList(filePath_cp, fileName_origin);
    }

    private List<Bookmark> fetchBookmarksList(String dir, String fileName) {
        String dbFilePath = dir + fileName;
        LogHelper.v(TAG + ":开始读取书签SQLite数据库:" + dbFilePath);
        List<Bookmark> result = new LinkedList<>();
        SQLiteDatabase sqLiteDatabase = null;
        Cursor cursor = null;
        String tableName = "bookmarks";
        boolean tableExist;
        try {
            sqLiteDatabase = DBHelper.openReadOnlyDatabase(dbFilePath);
            tableExist = DBHelper.checkTableExist(sqLiteDatabase, tableName);
            if (!tableExist) {
                LogHelper.v(TAG + ":database table " + tableName + " not exist.");
                throw new ConverterException(ContextUtil.buildReadBookmarksTableNotExistErrorMessage(this.getName()));
            }
            cursor = sqLiteDatabase.query(false, tableName, columns, null, null, null, null, null, null);
            if (cursor != null && cursor.getCount() > 0) {
                parseBookmarkWithFolder(cursor, result);
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            if (sqLiteDatabase != null) {
                sqLiteDatabase.close();
            }
            LogHelper.v(TAG + ":读取书签SQLite数据库结束");
        }
        return result;
    }

    private void parseBookmarkWithFolder(Cursor cursor, List<Bookmark> result) {
        List<FirefoxBookmark> bookmarks = parseBookmark(cursor);
        Map<Long, FirefoxBookmark> folders = new HashMap<>();
        for (FirefoxBookmark item : bookmarks) {
            int type = item.getType();
            String title = item.getTitle();
            if (title != null && !title.isEmpty() && type == 0) {
                folders.put(item.getId(), item);
            }
        }

        for (FirefoxBookmark item : bookmarks) {
            int type = item.getType();
            if (type == 1) {
                String folderPath = trim(parseFolderPath(folders, item.getParent()));
                Bookmark bookmark = new Bookmark();
                bookmark.setTitle(item.getTitle());
                bookmark.setUrl(item.getUrl());
                bookmark.setFolder(folderPath == null ? "" : folderPath);
                result.add(bookmark);
            }
        }
    }

    private String parseFolderPath(Map<Long, FirefoxBookmark> folders, long parent_uuid) {
        FirefoxBookmark parent = folders.get(parent_uuid);
        if (parent == null) {
            return null;
        }
        return parseFolderPath(folders, parent_uuid, "");
    }

    private String parseFolderPath(Map<Long, FirefoxBookmark> folders, long parent_uuid, String path) {
        FirefoxBookmark parent = folders.get(parent_uuid);
        if (parent == null) {
            return path;
        }
        String title = parent.getTitle();
        if (!(title == null || title.isEmpty() || "root".equals(title))) {
            path = title + Path.FILE_SPLIT + path;
        }
        return parseFolderPath(folders, parent.getParent(), path);
    }

    private List<FirefoxBookmark> parseBookmark(Cursor cursor) {
        List<FirefoxBookmark> result = new LinkedList<>();
        while (cursor.moveToNext()) {
            FirefoxBookmark item = new FirefoxBookmark();
            item.setTitle(cursor.getString(cursor.getColumnIndex("title")));
            item.setUrl(cursor.getString(cursor.getColumnIndex("url")));
            item.setId(cursor.getLong(cursor.getColumnIndex("_id")));
            item.setParent(cursor.getLong(cursor.getColumnIndex("parent")));
            item.setType(cursor.getInt(cursor.getColumnIndex("type")));
            result.add(item);
        }
        return result;
    }

    private class FirefoxBookmark extends Bookmark {
        @Getter
        @Setter
        private long id;
        @Getter
        @Setter
        private long parent;
        @Getter
        @Setter
        private int type;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class H5Browser extends BasicBrowser {
    private static final String TAG = "H5";
    private static final String packageName = "org.noear.h5";
    private List<Bookmark> bookmarks;

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_h5));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_h5));
    }


    private static final String fileName_origin = "h5db.db";
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "H5" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> bookmarksList = fetchBookmarksList(filePath_cp + fileName_origin);
            LogHelper.v(TAG + ":书签数据:" + JsonUtil.toJson(bookmarksList));
            LogHelper.v(TAG + ":书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
            LogHelper.v("result:" + JsonUtil.toJson(bookmarks));
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    private final static String[] columns = new String[]{"title", "url"};

    private List<Bookmark> fetchBookmarksList(String dbFilePath) {
        LogHelper.v(TAG + ":开始读取书签SQLite数据库:" + dbFilePath);
        List<Bookmark> result = new LinkedList<>();
        SQLiteDatabase sqLiteDatabase = null;
        Cursor cursor = null;
        String tableName = "favorites";
        boolean tableExist;
        try {
            sqLiteDatabase = DBHelper.openReadOnlyDatabase(dbFilePath);
            tableExist = DBHelper.checkTableExist(sqLiteDatabase, tableName);
            if (!tableExist) {
                LogHelper.v(TAG + ":database table " + tableName + " not exist.");
                throw new ConverterException(ContextUtil.buildReadBookmarksTableNotExistErrorMessage(this.getName()));
            }
            cursor = sqLiteDatabase.query(false, tableName, columns, null, null, null, null, null, null);
            if (cursor != null && cursor.getCount() > 0) {
                while (cursor.moveToNext()) {
                    Bookmark item = new Bookmark();
                    item.setTitle(cursor.getString(cursor.getColumnIndex("title")));
                    item.setUrl(cursor.getString(cursor.getColumnIndex("url")));
                    result.add(item);
                }
            }

        } finally {
            if (cursor != null) {
                cursor.close();
            }
            if (sqLiteDatabase != null) {
                sqLiteDatabase.close();
            }
            LogHelper.v(TAG + ":读取书签SQLite数据库结束");
        }
        return result;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class LiebaoBrowser extends BasicBrowser {
    private static final String TAG = "Liebao";
    private static final String packageName = "com.ijinshan.browser_fast";
    private List<Bookmark> bookmarks;

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_liebao));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_liebao));
    }

    private static final String fileName_origin = "browser.db";
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "Liebao" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> bookmarksList = fetchBookmarksList(filePath_cp + fileName_origin);
            LogHelper.v(TAG + ":书签数据:" + JsonUtil.toJson(bookmarksList));
            LogHelper.v(TAG + ":书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            LogHelper.e(converterException);
            converterException.printStackTrace();
            throw converterException;
        } catch (Exception e) {
            LogHelper.e(e);
            e.printStackTrace();
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    private final static String[] columns_boomark = new String[]{"title", "url", "folder_id"};
    private final static String[] columns_folder = new String[]{"_id", "title", "parent"};

    private List<Bookmark> fetchBookmarksList(String dbFilePath) {
        LogHelper.v(TAG + ":开始读取书签SQLite数据库:" + dbFilePath);
        List<Bookmark> result = new LinkedList<>();
        SQLiteDatabase sqLiteDatabase = null;
        Cursor cursor = null;
        String tableName = "bookmarks";
        boolean tableExist;
        try {
            sqLiteDatabase = DBHelper.openReadOnlyDatabase(dbFilePath);
            Map<Integer, LiebaoFolder> folders = fetchAllFolder(sqLiteDatabase);
            tableExist = DBHelper.checkTableExist(sqLiteDatabase, tableName);
            if (!tableExist) {
                LogHelper.v(TAG + ":database table " + tableName + " not exist.");
                throw new ConverterException(ContextUtil.buildReadBookmarksTableNotExistErrorMessage(this.getName()));
            }
            cursor = sqLiteDatabase.query(false, tableName, columns_boomark, "bookmark=?", new String[]{"1"}, null, null, null, null);
            if (cursor != null && cursor.getCount() > 0) {
                while (cursor.moveToNext()) {
                    Bookmark item = new Bookmark();
                    item.setTitle(cursor.getString(cursor.getColumnIndex("title")));
                    item.setUrl(cursor.getString(cursor.getColumnIndex("url")));
                    Integer folderId = cursor.getInt(cursor.getColumnIndex("folder_id"));
                    String folderPath = trim(parseFolderPath(folderId, folders));
                    item.setFolder(folderPath == null ? "" : folderPath);
                    result.add(item);
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            if (sqLiteDatabase != null) {
                sqLiteDatabase.close();
            }
            LogHelper.v(TAG + ":读取书签SQLite数据库结束");
        }
        return result;
    }

    private String parseFolderPath(Integer folderId, Map<Integer, LiebaoFolder> folders) {
        if (folderId == null || folderId <= 0) {
            return null;
        }
        return parseFolderPath(folders, folderId, "");
    }

    private String parseFolderPath(Map<Integer, LiebaoFolder> folders, Integer parentId, String path) {
        if (parentId == null || parentId <= 0) {
            return path;
        }
        LiebaoFolder parent = folders.get(parentId);
        if (parent == null) {
            return path;
        }
        String title = parent.getTitle();
        if (!(title == null || title.isEmpty())) {
            path = title + Path.FILE_SPLIT + path;
        }
        return parseFolderPath(folders, parent.getParent(), path);
    }

    private Map<Integer, LiebaoFolder> fetchAllFolder(SQLiteDatabase sqLiteDatabase) {
        Map<Integer, LiebaoFolder> result = new HashMap<>();
        Cursor cursor = null;
        String tableName = "folders";
        boolean tableExist;
        try {
            tableExist = DBHelper.checkTableExist(sqLiteDatabase, tableName);
            if (!tableExist) {
                LogHelper.v(TAG + ":database table " + tableName + " not exist.");
                throw new ConverterException(ContextUtil.buildReadBookmarksTableNotExistErrorMessage(this.getName()));
            }
            cursor = sqLiteDatabase.query(false, tableName, columns_folder, null, null, null, null, null, null);
            if (cursor != null && cursor.getCount() > 0) {
                while (cursor.moveToNext()) {
                    LiebaoFolder item = new LiebaoFolder();
                    item.setId(cursor.getInt(cursor.getColumnIndex("_id")));
                    item.setParent(cursor.getInt(cursor.getColumnIndex("parent")));
                    item.setTitle(cursor.getString(cursor.getColumnIndex("title")));
                    result.put(item.getId(), item);
                }
            }

        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return result;
    }

    private class LiebaoFolder {
        @Getter
        @Setter
        private int id;
        @Getter
        @Setter
        private String title;
        @Getter
        @Setter
        private int parent;

    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class OupengBrowser extends BasicBrowser {
    private static final String TAG = "Oupeng";
    private static final String packageName = "com.oupeng.mini.android";
    private List<Bookmark> bookmarks;

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_oupeng));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_oupeng));
    }


    private static final String fileName_origin = "bookmark.db";
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "Oupeng" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> bookmarksList = fetchBookmarksList(filePath_cp + fileName_origin);
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            LogHelper.e(converterException);
            converterException.printStackTrace();
            throw converterException;
        } catch (Exception e) {
            LogHelper.e(e);
            e.printStackTrace();
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    private final static String[] columns = new String[]{"_id", "parent", "isfolder", "title", "url"};

    private List<Bookmark> fetchBookmarksList(String dbFilePath) {
        LogHelper.v(TAG + ":开始读取书签SQLite数据库:" + dbFilePath);
        List<Bookmark> result = new LinkedList<>();
        SQLiteDatabase sqLiteDatabase = null;
        Cursor cursor = null;
        String tableName = "bookmark";
        boolean tableExist;
        try {
            sqLiteDatabase = DBHelper.openReadOnlyDatabase(dbFilePath);
            tableExist = DBHelper.checkTableExist(sqLiteDatabase, tableName);
            if (!tableExist) {
                LogHelper.v(TAG + ":database table " + tableName + " not exist.");
                throw new ConverterException(ContextUtil.buildReadBookmarksTableNotExistErrorMessage(this.getName()));
            }
            cursor = sqLiteDatabase.query(false, tableName, columns, null, null, null, null, null, null);
            if (cursor != null && cursor.getCount() > 0) {
                parseBookmarkWithFolder(cursor, result);
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            if (sqLiteDatabase != null) {
                sqLiteDatabase.close();
            }
            LogHelper.v(TAG + ":读取书签SQLite数据库结束");
        }
        return result;
    }

    private void parseBookmarkWithFolder(Cursor cursor, List<Bookmark> result) {
        List<OupengBookmark> bookmarks = parseBookmark(cursor);
        Map<Long, OupengBookmark> folders = new HashMap<>();
        for (OupengBookmark item : bookmarks) {
            int isfolder = item.getIsfolder();
            if (isfolder == 1) {
                folders.put(item.getId(), item);
            }
        }

        for (OupengBookmark item : bookmarks) {
            int isfolder = item.getIsfolder();
            if (isfolder == 0) {
                String folderPath = trim(parseFolderPath(folders, item.getParent()));
                Bookmark bookmark = new Bookmark();
                bookmark.setTitle(item.getTitle());
                bookmark.setUrl(item.getUrl());
                bookmark.setFolder(folderPath == null ? "" : folderPath);
                result.add(bookmark);
            }
        }
    }

    private String parseFolderPath(Map<Long, OupengBookmark> folders, long parent_uuid) {
        OupengBookmark parent = folders.get(parent_uuid);
        if (parent == null) {
            return null;
        }
        return parseFolderPath(folders, parent_uuid, "");
    }

    private String parseFolderPath(Map<Long, OupengBookmark> folders, long parent_uuid, String path) {
        OupengBookmark parent = folders.get(parent_uuid);
        if (parent == null) {
            return path;
        }
        String title = parent.getTitle();
        if (!(title == null || title.isEmpty() || "root".equals(title))) {
            path = title + Path.FILE_SPLIT + path;
        }
        return parseFolderPath(folders, parent.getParent(), path);
    }

    private List<OupengBookmark> parseBookmark(Cursor cursor) {
        List<OupengBookmark> result = new LinkedList<>();
        while (cursor.moveToNext()) {
            OupengBookmark item = new OupengBookmark();
            item.setTitle(cursor.getString(cursor.getColumnIndex("title")));
            item.setUrl(cursor.getString(cursor.getColumnIndex("url")));
            item.setIsfolder(cursor.getInt(cursor.getColumnIndex("isfolder")));
            item.setId(cursor.getLong(cursor.getColumnIndex("_id")));
            item.setParent(cursor.getLong(cursor.getColumnIndex("parent")));
            result.add(item);
        }
        return result;
    }

    private class OupengBookmark extends Bookmark {
        @Getter
        @Setter
        private long id;
        @Getter
        @Setter
        private long parent;
        @Getter
        @Setter
        private int isfolder;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class OupengClassicBrowser extends BasicBrowser {
    private static final String TAG = "OupengClassic";
    private static final String packageName = "com.oupeng.mini.classic";
    private List<Bookmark> bookmarks;

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_oupeng_classic));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_oupeng_classic));
    }

    private static final String fileName_origin = "contentprovider.db";
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "OupengClassic" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> bookmarksList = fetchBookmarksList(filePath_cp + fileName_origin);
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            LogHelper.e(converterException);
            converterException.printStackTrace();
            throw converterException;
        } catch (Exception e) {
            LogHelper.e(e);
            e.printStackTrace();
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    private final static String[] columns = new String[]{"title", "url"};

    private List<Bookmark> fetchBookmarksList(String dbFilePath) {
        List<Bookmark> result = new LinkedList<>();
        result.addAll(fetchBookmarksList(dbFilePath, "bks"));
        result.addAll(fetchBookmarksList(dbFilePath, "spds"));
        return result;
    }

    private List<Bookmark> fetchBookmarksList(String dbFilePath, String tableName) {
        LogHelper.v(TAG + ":开始读取书签SQLite数据库:" + dbFilePath + ",tableName:" + tableName);
        List<Bookmark> result = new LinkedList<>();
        SQLiteDatabase sqLiteDatabase = null;
        Cursor cursor = null;
        boolean tableExist;
        try {
            sqLiteDatabase = DBHelper.openReadOnlyDatabase(dbFilePath);
            tableExist = DBHelper.checkTableExist(sqLiteDatabase, tableName);
            if (!tableExist) {
                LogHelper.v(TAG + ":database table " + tableName + " not exist.");
                return result;
            }
            cursor = sqLiteDatabase.query(false, tableName, columns, null, null, null, null, null, null);
            if (cursor != null && cursor.getCount() > 0) {
                while (cursor.moveToNext()) {
                    Bookmark item = new Bookmark();
                    item.setTitle(cursor.getString(cursor.getColumnIndex("title")));
                    item.setUrl(cursor.getString(cursor.getColumnIndex("url")));
                    result.add(item);
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            if (sqLiteDatabase != null) {
                sqLiteDatabase.close();
            }
            LogHelper.v(TAG + ":读取书签SQLite数据库结束");
        }
        return result;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class QiyuBrowser extends BasicBrowser {
    private static final String TAG = "Qiyu";
    private static final String packageName = "com.ruanmei.qiyubrowser";
    private List<Bookmark> bookmarks;

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_qiyu));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_qiyu));
    }


    private static final String fileJsonName_origin = Path.FILE_SPLIT + "local_bm.json";
    private static final String dirJsonName_origin = "files";
    private static final String fileUserDBName_origin = Path.FILE_SPLIT + "bookmarkhistory";
    private static final String fileHomepageDBName_origin = Path.FILE_SPLIT + "homepage";
    private static final String dirDBName_origin = "databases";
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "Qiyu" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            List<Bookmark> bookmarksList = new LinkedList<>();
            List<Bookmark> bookmarksListPart1 = fetchBookmarksListByUserHasLogined();
            List<Bookmark> bookmarksListPart2 = fetchBookmarksListByNoUserLogined();
            List<Bookmark> bookmarksListPart3 = fetchBookmarksListByHomepage();
            LogHelper.v(TAG + ":已登录用户书签数据:" + JsonUtil.toJson(bookmarksListPart1));
            LogHelper.v(TAG + ":已登录用户书签条数:" + bookmarksListPart1.size());
            LogHelper.v(TAG + ":未登录的用户书签数据:" + JsonUtil.toJson(bookmarksListPart2));
            LogHelper.v(TAG + ":未登录的用户书签条数:" + bookmarksListPart2.size());
            LogHelper.v(TAG + ":首页的书签数据:" + JsonUtil.toJson(bookmarksListPart3));
            LogHelper.v(TAG + ":首页的书签条数:" + bookmarksListPart3.size());
            bookmarksList.addAll(bookmarksListPart1);
            bookmarksList.addAll(bookmarksListPart2);
            bookmarksList.addAll(bookmarksListPart3);
            LogHelper.v(TAG + ":总的书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    private List<Bookmark> fetchBookmarksListByHomepage() {
        String origin_dir = filePath_origin + dirDBName_origin;
        String origin_file = origin_dir + fileHomepageDBName_origin;
        String cp_file = filePath_cp + fileHomepageDBName_origin;
        LogHelper.v(TAG + ":开始读取首页的书签sqlite数据库:" + origin_dir);
        List<Bookmark> result = new LinkedList<>();
        LogHelper.v(TAG + ":origin file path:" + origin_file);
        LogHelper.v(TAG + ":tmp file path:" + cp_file);
        try {
            ExternalStorageUtil.copyFile(origin_file, cp_file, this.getName());
        } catch (Exception e) {
            LogHelper.e(e.getMessage());
            return result;
        }
        SQLiteDatabase sqLiteDatabase = null;
        Cursor cursor = null;
        String tableName = "customnavigations";
        boolean tableExist;
        String[] columns = new String[]{"name", "url", "imageurl"};
        try {
            sqLiteDatabase = DBHelper.openReadOnlyDatabase(cp_file);
            tableExist = DBHelper.checkTableExist(sqLiteDatabase, tableName);
            if (!tableExist) {
                LogHelper.v(TAG + ":database table " + tableName + " not exist.");
                return result;
            }
            cursor = sqLiteDatabase.query(false, tableName, columns, null, null, null, null, null, null);
            if (cursor != null && cursor.getCount() > 0) {
                while (cursor.moveToNext()) {
                    String imageurl = cursor.getString(cursor.getColumnIndex("imageurl"));
                    if (imageurl == null || imageurl.isEmpty()) {
                        Bookmark item = new Bookmark();
                        item.setTitle(cursor.getString(cursor.getColumnIndex("name")));
                        item.setUrl(cursor.getString(cursor.getColumnIndex("url")));
                        result.add(item);
                    }
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            if (sqLiteDatabase != null) {
                sqLiteDatabase.close();
            }
        }
        LogHelper.v(TAG + ":读取首页的书签sqlite数据库结束");
        return result;
    }

    private List<Bookmark> fetchBookmarksListByUserHasLogined() {
        List<Bookmark> result = new LinkedList<>();
        String origin_dir = filePath_origin + dirJsonName_origin + Path.FILE_SPLIT + "profiles" + Path.FILE_SPLIT;
        LogHelper.v(TAG + ":开始读取已登录用户的书签json文件:" + origin_dir);
        if (!InternalStorageUtil.isExistDir(origin_dir)) {
            LogHelper.v(origin_dir + " is not existed.skip");
            return result;
        }
        List<String> dirs = InternalStorageUtil.lsDir(origin_dir);
        if (dirs == null || dirs.isEmpty()) {
            LogHelper.v(TAG + ":没有找到目标文件夹");
            return result;
        }
        String targetDir = null;
        String rule = "[0-9]{6,10}";
        for (String item : dirs) {
            if (item != null) {
                if (item.matches(rule)) {
                    targetDir = item;
                    break;
                }
            }
        }
        if (targetDir == null || targetDir.isEmpty()) {
            LogHelper.v(TAG + ":真的没有找到目标文件夹");
            return result;
        } else {
            LogHelper.v(TAG + ":targetDir:" + targetDir);
        }
        String fileName_origin = "Bookmarks";
        origin_dir += targetDir + Path.FILE_SPLIT;
        String sourceFilePath = origin_dir + fileName_origin;
        LogHelper.v(TAG + ":sourceFilePath:" + sourceFilePath);
        try {
            if (InternalStorageUtil.isExistFile(sourceFilePath)) {
                List<Bookmark> part1 = fetchBookmarksByJsonFile(ExternalStorageUtil.copyFile(sourceFilePath, filePath_cp + fileName_origin, this.getName()), true);
                LogHelper.v(TAG + ":" + fileName_origin + " part size:" + part1.size());
                result.addAll(part1);
            }
        } catch (Exception e) {
            LogHelper.e(e.getMessage());
            return result;
        }

        fileName_origin = "pc_bm.json";
        sourceFilePath = origin_dir + fileName_origin;
        LogHelper.v(TAG + ":sourceFilePath:" + sourceFilePath);
        try {
            if (InternalStorageUtil.isExistFile(sourceFilePath)) {
                List<Bookmark> part2 = fetchBookmarksByJsonFileWithChrome(ExternalStorageUtil.copyFile(sourceFilePath, filePath_cp + fileName_origin, this.getName()));
                LogHelper.v(TAG + ":" + fileName_origin + " part size:" + part2.size());
                result.addAll(part2);
            }
        } catch (Exception e) {
            LogHelper.e(e.getMessage());
            return result;
        }

        fileName_origin = "user_bm.json";
        sourceFilePath = origin_dir + fileName_origin;
        LogHelper.v(TAG + ":sourceFilePath:" + sourceFilePath);
        try {
            if (InternalStorageUtil.isExistFile(sourceFilePath)) {
                List<Bookmark> part2 = fetchBookmarksByJsonFile(ExternalStorageUtil.copyFile(sourceFilePath, filePath_cp + fileName_origin, this.getName()), true);
                LogHelper.v(TAG + ":" + fileName_origin + " part size:" + part2.size());
                result.addAll(part2);
            }
        } catch (Exception e) {
            LogHelper.e(e.getMessage());
            return result;
        }
        LogHelper.v(TAG + ":读取已登录用户的书签json文件结束");
        return result;
    }

    private List<Bookmark> fetchBookmarksByJsonFileWithChrome(java.io.File file) throws FileNotFoundException {
        JSONReader jsonReader = null;
        List<Bookmark> result = new LinkedList<>();
        try {
            jsonReader = new JSONReader(new FileReader(file));
            ChromeBookmark qiyuJsonBookmark;
            qiyuJsonBookmark = jsonReader.readObject(ChromeBookmark.class);
            if (qiyuJsonBookmark == null) {
                LogHelper.v("qiyuJsonBookmark is null.");
                return result;
            }
            File fileShow = FileUtil.formatFileSize(file);
            if (fileShow.isOver10KB()) {
                LogHelper.v("书签数据文件大小超过10KB,skip print.size:" + fileShow.toString());
            } else {
                LogHelper.v("书签数据:" + JsonUtil.toJson(qiyuJsonBookmark));
            }
            List<Bookmark> bookmarks = qiyuJsonBookmark.fetchAll();
            if (bookmarks == null) {
                LogHelper.v("bookmarks is null.");
                return result;
            }
            LogHelper.v("书签条数:" + bookmarks.size());
            return bookmarks;
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (jsonReader != null) {
                jsonReader.close();
            }
        }
    }

    private List<Bookmark> fetchBookmarksListByNoUserLogined() {
        List<Bookmark> result = new LinkedList<>();
        List<Bookmark> part1 = fetchBookmarksListByNoUserLoginedWithDB();
        List<Bookmark> part2 = fetchBookmarksListByNoUserLoginedWithJson();
        LogHelper.v(TAG + ":未登录的用户书签，json部分，条数:" + part1.size());
        LogHelper.v(TAG + ":未登录的用户书签，sqlite部分，条数:" + part2.size());
        result.addAll(part1);
        result.addAll(part2);
        return result;
    }

    private List<Bookmark> fetchBookmarksListByNoUserLoginedWithDB() {
        String origin_dir = filePath_origin + dirDBName_origin;
        String origin_file = origin_dir + fileUserDBName_origin;
        String cp_file = filePath_cp + fileUserDBName_origin;
        LogHelper.v(TAG + ":开始读取已登录用户的书签sqlite数据库:" + origin_dir);
        List<Bookmark> result = new LinkedList<>();
        LogHelper.v(TAG + ":origin file path:" + origin_file);
        LogHelper.v(TAG + ":tmp file path:" + cp_file);
        try {
            ExternalStorageUtil.copyFile(origin_file, cp_file, this.getName());
        } catch (Exception e) {
            LogHelper.e(e.getMessage());
            return result;
        }
        SQLiteDatabase sqLiteDatabase = null;
        Cursor cursor = null;
        String tableName = "bookmark";
        boolean tableExist;
        String[] columns = new String[]{"title", "url"};
        try {
            sqLiteDatabase = DBHelper.openReadOnlyDatabase(cp_file);
            tableExist = DBHelper.checkTableExist(sqLiteDatabase, tableName);
            if (!tableExist) {
                LogHelper.v(TAG + ":database table " + tableName + " not exist.");
                return result;
            }
            cursor = sqLiteDatabase.query(false, tableName, columns, null, null, null, null, null, null);
            if (cursor != null && cursor.getCount() > 0) {
                while (cursor.moveToNext()) {
                    Bookmark item = new Bookmark();
                    item.setTitle(cursor.getString(cursor.getColumnIndex("title")));
                    item.setUrl(cursor.getString(cursor.getColumnIndex("url")));
                    result.add(item);
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            if (sqLiteDatabase != null) {
                sqLiteDatabase.close();
            }
        }
        LogHelper.v(TAG + ":读取已登录用户书签sqlite数据库结束");
        return result;
    }

    private List<Bookmark> fetchBookmarksListByNoUserLoginedWithJson() {
        String origin_dir = filePath_origin + dirJsonName_origin;
        String origin_file = origin_dir + fileJsonName_origin;
        String cp_file = filePath_cp + fileJsonName_origin;
        LogHelper.v(TAG + ":开始读取未登录用户的书签Json文件:" + origin_dir);
        List<Bookmark> result = new LinkedList<>();
        LogHelper.v(TAG + ":origin file path:" + origin_file);
        LogHelper.v(TAG + ":tmp file path:" + cp_file);
        java.io.File file;
        try {
            file = ExternalStorageUtil.copyFile(origin_file, cp_file, this.getName());
            result.addAll(fetchBookmarksByJsonFile(file, false));
        } catch (Exception e) {
            LogHelper.e(e.getMessage());
            return result;
        }
        LogHelper.v(TAG + ":读取未登录用户书签Json文件结束");
        return result;
    }

    private List<Bookmark> fetchBookmarksByJsonFile(java.io.File file, boolean isLogined) throws FileNotFoundException {
        JSONReader jsonReader = null;
        List<Bookmark> result = new LinkedList<>();
        try {
            jsonReader = new JSONReader(new FileReader(file));
            QiyuBookmark qiyuJsonBookmark;
            if (isLogined) {
                qiyuJsonBookmark = jsonReader.readObject(QiyuHasLoginedBookmark.class);
            } else {
                qiyuJsonBookmark = jsonReader.readObject(QiyuBookmark.class);
            }
            if (qiyuJsonBookmark == null) {
                LogHelper.v("qiyuJsonBookmark is null.");
                return result;
            }
            File fileShow = FileUtil.formatFileSize(file);
            if (fileShow.isOver10KB()) {
                LogHelper.v("书签数据文件大小超过10KB,skip print.size:" + fileShow.toString());
            } else {
                LogHelper.v("书签数据:" + JsonUtil.toJson(qiyuJsonBookmark));
            }
            List<Bookmark> bookmarks = qiyuJsonBookmark.fetchAll();
            if (bookmarks == null) {
                LogHelper.v("bookmarks is null.");
                return result;
            }
            LogHelper.v("书签条数:" + bookmarks.size());
            return bookmarks;
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (jsonReader != null) {
                jsonReader.close();
            }
        }
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class SogouBrowser extends BasicBrowser {
    private static final String TAG = "Sogou";
    private static final String packageName = "sogou.mobile.explorer";
    private final static String[] columns = new String[]{"f_server_id", "f_server_pid", "f_title", "f_url", "f_is_folder"};
    private List<Bookmark> bookmarks;

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_sougou));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_sougou));
    }


    private static final String fileName_origin = "sogou_cloud_default.db";
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "Sogou" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            List<Bookmark> bookmarksList = new LinkedList<>();
            List<Bookmark> bookmarksListPart1 = fetchBookmarksListByUserHasLogined(filePath_origin);
            List<Bookmark> bookmarksListPart2 = fetchBookmarksListByNoUserLogined(filePath_cp + fileName_origin);
            LogHelper.v(TAG + ":已登录用户书签数据:" + JsonUtil.toJson(bookmarksListPart1));
            LogHelper.v(TAG + ":已登录用户书签条数:" + bookmarksListPart1.size());
            LogHelper.v(TAG + ":未登录的用户书签数据:" + JsonUtil.toJson(bookmarksListPart2));
            LogHelper.v(TAG + ":未登录的用户书签条数:" + bookmarksListPart2.size());
            bookmarksList.addAll(bookmarksListPart1);
            bookmarksList.addAll(bookmarksListPart2);
            LogHelper.v(TAG + ":总的书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            LogHelper.e(converterException);
            converterException.printStackTrace();
            throw converterException;
        } catch (Exception e) {
            LogHelper.e(e);
            e.printStackTrace();
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    private List<Bookmark> fetchBookmarksListByUserHasLogined(String appRootDir) {
        LogHelper.v(TAG + ":开始读取已登录用户书签,appRootDir:" + appRootDir);
        List<Bookmark> result = new LinkedList<>();
        if (!InternalStorageUtil.isExistDir(appRootDir)) {
            LogHelper.v(TAG + ":不存在已登录用户书签,根目录缺失");
            return result;
        }
        String regularRule = "[a-z0-9\\-]{33}";
        String searchRule = "*.db";
        List<String> fileNames = InternalStorageUtil.lsFileAndSortByRegular(appRootDir, searchRule);
        if (fileNames == null || fileNames.isEmpty()) {
            LogHelper.v(TAG + ":已登录用户没有书签数据");
            return result;
        }
        String targetFileNames = null;
        String startKey = "sogou_cloud_";
        for (String item : fileNames) {
            LogHelper.v(TAG + ":item:" + item);
            if (item == null) {
                LogHelper.v(TAG + ":item is null.");
                break;
            }
            item = getFileNameByTrimPath(appRootDir, item);
            String tmp = item;
            if (tmp.startsWith(startKey)) {
                tmp = tmp.replaceAll(startKey, "");
                tmp = tmp.replaceAll(".db", "");
                LogHelper.v(TAG + ":tmp:" + tmp);
                if (tmp.matches(regularRule)) {
                    LogHelper.v(TAG + ":match success regularRule.");
                    targetFileNames = item;
                    break;
                }
            }
            LogHelper.v(TAG + ":not match.");
        }
        if (targetFileNames == null || targetFileNames.isEmpty()) {
            LogHelper.v(TAG + ":已登录用户真的没有书签数据");
            return result;
        }
        result.addAll(fetchBookmarksListByUserHasLogined(appRootDir, targetFileNames));
        LogHelper.v(TAG + ":完成读取已登录用户书签,appRootDir:" + appRootDir);
        return result;
    }

    private List<Bookmark> fetchBookmarksListByUserHasLogined(String dir, String fileName) {
        String targetFilePath = dir + fileName;
        LogHelper.v(TAG + ":targetFilePath is:" + targetFilePath);
        List<Bookmark> result = new LinkedList<>();
        String tmpFilePath = filePath_cp + fileName;
        try {
            ExternalStorageUtil.copyFile(targetFilePath, tmpFilePath, this.getName());
        } catch (Exception e) {
            LogHelper.e(e.getMessage());
            return result;
        }
        result.addAll(fetchBookmarksList(false, tmpFilePath, "cloud_favorite", null, null, null));
        result.addAll(fetchBookmarksList(false, tmpFilePath, "cloud_favorite_base", null, null, null));
        return result;
    }

    private List<Bookmark> fetchBookmarksListByNoUserLogined(String dbFilePath) {
        LogHelper.v(TAG + ":开始读取未登录用户的书签SQLite数据库:" + dbFilePath);
        List<Bookmark> result = new LinkedList<>();
        String originFilePathFull = filePath_origin + fileName_origin;
        LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
        LogHelper.v(TAG + ":tmp file path:" + dbFilePath);
        try {
            ExternalStorageUtil.copyFile(originFilePathFull, dbFilePath, this.getName());
        } catch (Exception e) {
            LogHelper.e(e.getMessage());
            return result;
        }
        result.addAll(fetchBookmarksList(dbFilePath, "cloud_favorite", null, null, null));
        result.addAll(fetchBookmarksList(dbFilePath, "cloud_favorite_base", null, null, null));
        LogHelper.v(TAG + ":读取未登录用户书签SQLite数据库结束");
        return result;
    }

    private List<Bookmark> fetchBookmarksList(String dbFilePath, String tableName, String where, String[] whereArgs, String orderBy) {
        return fetchBookmarksList(true, dbFilePath, tableName, columns, where, whereArgs, orderBy);
    }

    private List<Bookmark> fetchBookmarksList(boolean needThrowException, String dbFilePath, String tableName, String where, String[] whereArgs, String orderBy) {
        return fetchBookmarksList(needThrowException, dbFilePath, tableName, columns, where, whereArgs, orderBy);
    }

    private List<Bookmark> fetchBookmarksList(boolean needThrowException, String dbFilePath, String tableName, String[] columns, String where, String[] whereArgs, String orderBy) {
        LogHelper.v(TAG + ":读取SQLite数据库开始,dbFilePath:" + dbFilePath + ",tableName:" + tableName);
        List<Bookmark> result = new LinkedList<>();
        SQLiteDatabase sqLiteDatabase = null;
        Cursor cursor = null;
        boolean tableExist;
        try {
            sqLiteDatabase = DBHelper.openReadOnlyDatabase(dbFilePath);
            tableExist = DBHelper.checkTableExist(sqLiteDatabase, tableName);
            if (!tableExist) {
                LogHelper.v(TAG + ":database table " + tableName + " not exist.");
                if (needThrowException) {
                    throw new ConverterException(ContextUtil.buildReadBookmarksTableNotExistErrorMessage(this.getName()));
                } else {
                    return result;
                }
            }
            cursor = sqLiteDatabase.query(false, tableName, columns, where, whereArgs, null, null, orderBy, null);
            if (cursor != null && cursor.getCount() > 0) {
                parseBookmarkWithFolder(cursor, result);
            }

        } finally {
            if (cursor != null) {
                cursor.close();
            }
            if (sqLiteDatabase != null) {
                sqLiteDatabase.close();
            }
            LogHelper.v(TAG + ":读取SQLite数据库结束,dbFilePath:" + dbFilePath);
        }
        return result;
    }

    private void parseBookmarkWithFolder(Cursor cursor, List<Bookmark> result) {
        List<SogouBookmark> bookmarks = parseBookmark(cursor);
        Map<String, SogouBookmark> folders = new HashMap<>();
        for (SogouBookmark item : bookmarks) {
            int folder = item.getF_is_folder();
            if (folder == 1) {
                folders.put(item.getF_server_id(), item);
            }
        }

        for (SogouBookmark item : bookmarks) {
            int folder = item.getF_is_folder();
            if (folder == 0) {
                String folderPath = trim(parseFolderPath(folders, item.getF_server_pid()));
                Bookmark bookmark = new Bookmark();
                bookmark.setTitle(item.getTitle());
                bookmark.setUrl(item.getUrl());
                bookmark.setFolder(folderPath == null ? "" : folderPath);
                result.add(bookmark);
            }
        }
    }

    private String parseFolderPath(Map<String, SogouBookmark> folders, String parent_uuid) {
        SogouBookmark parent = folders.get(parent_uuid);
        if (parent == null) {
            return null;
        }
        return parseFolderPath(folders, parent_uuid, "");
    }

    private String parseFolderPath(Map<String, SogouBookmark> folders, String parent_uuid, String path) {
        SogouBookmark parent = folders.get(parent_uuid);
        if (parent == null) {
            return path;
        }
        String title = parent.getTitle();
        if (!(title == null || title.isEmpty())) {
            path = title + Path.FILE_SPLIT + path;
        }
        return parseFolderPath(folders, parent.getF_server_pid(), path);
    }

    private List<SogouBookmark> parseBookmark(Cursor cursor) {
        List<SogouBookmark> result = new LinkedList<>();
        while (cursor.moveToNext()) {
            SogouBookmark item = new SogouBookmark();
            item.setTitle(cursor.getString(cursor.getColumnIndex("f_title")));
            item.setUrl(cursor.getString(cursor.getColumnIndex("f_url")));
            item.setF_server_id(cursor.getString(cursor.getColumnIndex("f_server_id")));
            item.setF_server_pid(cursor.getString(cursor.getColumnIndex("f_server_pid")));
            item.setF_is_folder(cursor.getInt(cursor.getColumnIndex("f_is_folder")));
            result.add(item);
        }
        return result;
    }

    private class SogouBookmark extends Bookmark {
        @Getter
        @Setter
        private String f_server_id;
        @Getter
        @Setter
        private String f_server_pid;
        @Getter
        @Setter
        private int f_is_folder;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class YandexBrowser extends ChromeBrowserAble {
    private static final String packageName = "com.yandex.browser";
    private List<Bookmark> bookmarks;

    public YandexBrowser() {
        super.TAG = "Yandex";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_yandex));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_yandex));
    }

    private static final String fileName_origin = "Bookmarks";
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "app_chromium" + Path.FILE_SPLIT + "Default" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "Yandex" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            java.io.File file = ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> bookmarks = fetchBookmarks(file);
            this.bookmarks = new LinkedList<>();
            fetchValidBookmarks(this.bookmarks, bookmarks);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException.getMessage());
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class ChromeBetaBrowser extends ChromeBrowserAble {
    private static final String TAG = "ChromeBeta";
    private static final String packageName = "com.chrome.beta";
    private List<Bookmark> bookmarks;

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_chrome_beta));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_chrome_beta));
    }

    private static final String fileName_origin = "Bookmarks";
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "app_chrome" + Path.FILE_SPLIT + "Default" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "ChromeBeta" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            java.io.File file = ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> chromeBookmarks = fetchBookmarks(file);
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, chromeBookmarks);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class ChromeBrowser extends ChromeBrowserAble {
    private static final String packageName = "com.android.chrome";
    private List<Bookmark> bookmarks;

    public ChromeBrowser() {
        super.TAG = "Chrome";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_chrome));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_chrome));
    }

    private static final String fileName_origin = "Bookmarks";
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "app_chrome" + Path.FILE_SPLIT + "Default" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "Chrome" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            java.io.File file = ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> chromeBookmarks = fetchBookmarks(file);
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, chromeBookmarks);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException.getMessage());
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class ChromeCanaryBrowser extends ChromeBrowserAble {
    private static final String TAG = "ChromeCanary";
    private static final String packageName = "com.chrome.canary";
    private List<Bookmark> bookmarks;

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_chrome_canary));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_chrome_canary));
    }

    private static final String fileName_origin = "Bookmarks";
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "app_chrome" + Path.FILE_SPLIT + "Default" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "ChromeCanary" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            java.io.File file = ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> chromeBookmarks = fetchBookmarks(file);
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, chromeBookmarks);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException.getMessage());
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class ChromeDevBrowser extends ChromeBrowserAble {
    private static final String TAG = "ChromeDev";
    private static final String packageName = "com.chrome.dev";
    private List<Bookmark> bookmarks;

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_chrome_dev));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_chrome_dev));
    }

    private static final String fileName_origin = "Bookmarks";
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "app_chrome" + Path.FILE_SPLIT + "Default" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "ChromeDev" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            java.io.File file = ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> chromeBookmarks = fetchBookmarks(file);
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, chromeBookmarks);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException.getMessage());
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class XingchenPhoneBrowser extends XingchenBrowserAble {
    private static final String packageName = "com.chaozhuo.browser_phone";
    private List<Bookmark> bookmarks;

    public XingchenPhoneBrowser() {
        super.TAG = "XingchenPhone";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_xingchen_phone));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_xingchen_phone));
    }

    private static final String fileName_origin = "Bookmarks";
    private static final String fileJsonPath_origin = Path.FILE_SPLIT + "app_chromeshell" + Path.FILE_SPLIT + "Default" + Path.FILE_SPLIT;
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "XingchenPhone" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            List<Bookmark> bookmarks = new LinkedList<>();
            List<Bookmark> bookmarksPart1 = this.fetchBookmarks(filePath_origin + fileJsonPath_origin, fileName_origin, filePath_cp);
            List<Bookmark> bookmarksPart2 = fetchBookmarksByHomePage(filePath_origin, filePath_cp);
            LogHelper.v(TAG + ":Json书签数据:" + JsonUtil.toJson(bookmarksPart1));
            LogHelper.v(TAG + ":Json书签条数:" + bookmarksPart1.size());
            LogHelper.v(TAG + ":sqlite书签数据:" + JsonUtil.toJson(bookmarksPart2));
            LogHelper.v(TAG + ":sqlite书签条数:" + bookmarksPart2.size());
            bookmarks.addAll(bookmarksPart1);
            bookmarks.addAll(bookmarksPart2);
            this.bookmarks = new LinkedList<>();
            fetchValidBookmarks(this.bookmarks, bookmarks);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException.getMessage());
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class XingchenTabletBrowser extends XingchenBrowserAble {
    private static final String packageName = "com.chaozhuo.browser";
    private List<Bookmark> bookmarks;

    public XingchenTabletBrowser() {
        super.TAG = "XingchenTablet";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_xingchen_tablet));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_xingchen_tablet));
    }

    private static final String fileName_origin = "Bookmarks";
    private static final String fileJsonPath_origin = Path.FILE_SPLIT + "app_chromeshell" + Path.FILE_SPLIT + "Default" + Path.FILE_SPLIT;
    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "XingchenTablet" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            List<Bookmark> bookmarks = new LinkedList<>();
            List<Bookmark> bookmarksPart1 = this.fetchBookmarks(filePath_origin + fileJsonPath_origin, fileName_origin, filePath_cp);
            List<Bookmark> bookmarksPart2 = fetchBookmarksByHomePage(filePath_origin, filePath_cp);
            LogHelper.v(TAG + ":Json书签数据:" + JsonUtil.toJson(bookmarksPart1));
            LogHelper.v(TAG + ":Json书签条数:" + bookmarksPart1.size());
            LogHelper.v(TAG + ":sqlite书签数据:" + JsonUtil.toJson(bookmarksPart2));
            LogHelper.v(TAG + ":sqlite书签条数:" + bookmarksPart2.size());
            bookmarks.addAll(bookmarksPart1);
            bookmarks.addAll(bookmarksPart2);
            this.bookmarks = new LinkedList<>();
            fetchValidBookmarks(this.bookmarks, bookmarks);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException.getMessage());
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class Qihoo360Browser extends Qihoo360BrowserAble {
    private static final String packageName = "com.qihoo.browser";
    private List<Bookmark> bookmarks;

    public Qihoo360Browser() {
        super.TAG = "360";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_360));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_360));
    }

    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "360" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            List<Bookmark> bookmarksList = new LinkedList<>();
            List<Bookmark> bookmarksListPart1 = fetchBookmarksListByUserHasLogined(filePath_origin, filePath_cp);
            List<Bookmark> bookmarksListPart2 = fetchBookmarksListByNoUserLogined(filePath_origin, filePath_cp);
            LogHelper.v(TAG + ":已登录用户书签数据:" + JsonUtil.toJson(bookmarksListPart1));
            LogHelper.v(TAG + ":已登录用户书签条数:" + bookmarksListPart1.size());
            LogHelper.v(TAG + ":未登录用户书签数据:" + JsonUtil.toJson(bookmarksListPart2));
            LogHelper.v(TAG + ":未登录用户书签条数:" + bookmarksListPart2.size());
            bookmarksList.addAll(bookmarksListPart1);
            bookmarksList.addAll(bookmarksListPart2);
            LogHelper.v(TAG + ":总的书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            LogHelper.e(converterException);
            converterException.printStackTrace();
            throw converterException;
        } catch (Exception e) {
            LogHelper.e(e);
            e.printStackTrace();
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class Qihoo360FastestBrowser extends Qihoo360BrowserAble {
    private static final String packageName = "com.qihoo.chrome360";
    private List<Bookmark> bookmarks;

    public Qihoo360FastestBrowser() {
        super.TAG = "360Fastest";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_360_fastest));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_360_fastest));
    }

    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "360Fastest" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            List<Bookmark> bookmarksList = new LinkedList<>();
            List<Bookmark> bookmarksListPart1 = fetchBookmarksListByUserHasLogined(filePath_origin, filePath_cp);
            List<Bookmark> bookmarksListPart2 = fetchBookmarksListByNoUserLogined(filePath_origin, filePath_cp);
            LogHelper.v(TAG + ":已登录用户书签数据:" + JsonUtil.toJson(bookmarksListPart1));
            LogHelper.v(TAG + ":已登录用户书签条数:" + bookmarksListPart1.size());
            LogHelper.v(TAG + ":未登录用户书签数据:" + JsonUtil.toJson(bookmarksListPart2));
            LogHelper.v(TAG + ":未登录用户书签条数:" + bookmarksListPart2.size());
            bookmarksList.addAll(bookmarksListPart1);
            bookmarksList.addAll(bookmarksListPart2);
            LogHelper.v(TAG + ":总的书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            LogHelper.e(converterException);
            converterException.printStackTrace();
            throw converterException;
        } catch (Exception e) {
            LogHelper.e(e);
            e.printStackTrace();
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class QQBrowser extends QQBrowserAble {
    private static final String packageName = "com.tencent.mtt";
    private List<Bookmark> bookmarks;

    public QQBrowser() {
        super.TAG = "QQ";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_qq));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_qq));
    }


    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "QQ" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            List<Bookmark> bookmarksList = new LinkedList<>();
            List<Bookmark> bookmarksListPart1 = fetchBookmarksListByUserHasLogined(filePath_origin, filePath_cp);
            List<Bookmark> bookmarksListPart2 = fetchBookmarksListByNoUserLogined(filePath_origin, filePath_cp);
            LogHelper.v(TAG + ":已登录用户书签数据:" + JsonUtil.toJson(bookmarksListPart1));
            LogHelper.v(TAG + ":已登录用户书签条数:" + bookmarksListPart1.size());
            LogHelper.v(TAG + ":未登录的用户书签数据:" + JsonUtil.toJson(bookmarksListPart2));
            LogHelper.v(TAG + ":未登录的用户书签条数:" + bookmarksListPart2.size());
            bookmarksList.addAll(bookmarksListPart1);
            bookmarksList.addAll(bookmarksListPart2);
            LogHelper.v(TAG + ":总的书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class QQWithOnePlusBrowser extends QQBrowserAble {
    private static final String packageName = "com.android.browser";
    private List<Bookmark> bookmarks;

    public QQWithOnePlusBrowser() {
        super.TAG = "QQWithOnePlus";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_qqwithoneplus));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_qqwithoneplus));
    }

    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "QQWithOnePlus" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            List<Bookmark> bookmarksList = new LinkedList<>();
            List<Bookmark> bookmarksListPart1 = fetchBookmarksListByUserHasLogined(filePath_origin, filePath_cp);
            List<Bookmark> bookmarksListPart2 = fetchBookmarksListByNoUserLogined(filePath_origin, filePath_cp);
            LogHelper.v(TAG + ":已登录用户书签数据:" + JsonUtil.toJson(bookmarksListPart1));
            LogHelper.v(TAG + ":已登录用户书签条数:" + bookmarksListPart1.size());
            LogHelper.v(TAG + ":未登录的用户书签数据:" + JsonUtil.toJson(bookmarksListPart2));
            LogHelper.v(TAG + ":未登录的用户书签条数:" + bookmarksListPart2.size());
            bookmarksList.addAll(bookmarksListPart1);
            bookmarksList.addAll(bookmarksListPart2);
            LogHelper.v(TAG + ":总的书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class UCBrowser extends UCBrowserAble {
    private List<Bookmark> bookmarks;


    public UCBrowser() {
        super.TAG = "UC";
        super.packageName = "com.UCMobile";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_uc));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_uc));
    }


    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "UC" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            List<Bookmark> bookmarksList = new LinkedList<>();
            String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
            List<Bookmark> bookmarksListPart1 = fetchBookmarksListByUserHasLogined(filePath_origin, filePath_cp);
            List<Bookmark> bookmarksListPart2 = fetchBookmarksListByNoUserLogined(filePath_origin + fileName_origin, filePath_cp + fileName_origin);
            LogHelper.v(TAG + ":已登录的用户书签数据:" + JsonUtil.toJson(bookmarksListPart1));
            LogHelper.v(TAG + ":已登录的用户书签条数:" + bookmarksListPart1.size());
            LogHelper.v(TAG + ":未登录的用户书签数据:" + JsonUtil.toJson(bookmarksListPart2));
            LogHelper.v(TAG + ":未登录的用户书签条数:" + bookmarksListPart2.size());
            bookmarksList.addAll(bookmarksListPart1);
            bookmarksList.addAll(bookmarksListPart2);
            LogHelper.v(TAG + ":总的书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class UCInternationalBrowser extends UCBrowserAble {
    private List<Bookmark> bookmarks;

    public UCInternationalBrowser() {
        super.TAG = "UCInternational";
        super.packageName = "com.UCMobile.intl";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_ucintl));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_ucintl));
    }

    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "UCInternational" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            List<Bookmark> bookmarksList = new LinkedList<>();
            String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
            List<Bookmark> bookmarksListPart1 = fetchBookmarksListByUserHasLogined(filePath_origin, filePath_cp);
            List<Bookmark> bookmarksListPart2 = fetchBookmarksListByNoUserLogined(filePath_origin + fileName_origin, filePath_cp + fileName_origin);
            LogHelper.v(TAG + ":已登录的用户书签数据:" + JsonUtil.toJson(bookmarksListPart1));
            LogHelper.v(TAG + ":已登录的用户书签条数:" + bookmarksListPart1.size());
            LogHelper.v(TAG + ":未登录的用户书签数据:" + JsonUtil.toJson(bookmarksListPart2));
            LogHelper.v(TAG + ":未登录的用户书签条数:" + bookmarksListPart2.size());
            bookmarksList.addAll(bookmarksListPart1);
            bookmarksList.addAll(bookmarksListPart2);
            LogHelper.v(TAG + ":总的书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    public String getPreExecuteConverterMessage() {
        return ContextUtil.buildNotSupportParseHomepageBookmarksMessage();
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class ViaBrowserAble extends BasicBrowser {
    public static final String packageName = "mark.via";
    protected List<Bookmark> bookmarks;

    public static ViaBrowserAble fetchViaBrowser() {
        App via = AppListUtil.getAppInfo(ViaBrowserAble.packageName);
        ViaBrowserAble viaBrowserable = null;
        if (via != null) {
            viaBrowserable = ViaBrowserAble.fetchViaBrowser(via.getVersionName(), via.getVersionCode());
        }
        if (viaBrowserable == null) {
            viaBrowserable = ViaBrowserAble.chooseDefault();
        }
        return viaBrowserable;
    }

    private static ViaBrowserAble fetchViaBrowser(String versionName, long versionCode) {
        if (versionCode >= ViaStage2Browser.minVersionCode && versionName != null && !versionName.isEmpty()) {
            return new ViaStage2Browser();
        } else {
            return new ViaStage1Browser();
        }
    }


    private static ViaBrowserAble chooseDefault() {
        return fetchViaBrowser(null, 0);
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_via));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_via));
    }
} public class XBrowser extends XBrowserAble {
    private static final String packageName = "com.mmbox.xbrowser";
    private List<Bookmark> bookmarks;


    public XBrowser() {
        super.TAG = "X";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_x));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_x));
    }

    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "X" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> bookmarksList = fetchBookmarksList(filePath_cp + fileName_origin);
            LogHelper.v(TAG + ":书签数据:" + JsonUtil.toJson(bookmarksList));
            LogHelper.v(TAG + ":书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class XWithGooglePlayBrowser extends XBrowserAble {
    private static final String packageName = "com.mmbox.xbrowser.gp";
    private List<Bookmark> bookmarks;


    public XWithGooglePlayBrowser() {
        super.TAG = "XWithGooglePlay";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_x_gp));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_x_gp));
    }

    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "XWithGooglePlay" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> bookmarksList = fetchBookmarksList(filePath_cp + fileName_origin);
            LogHelper.v(TAG + ":书签数据:" + JsonUtil.toJson(bookmarksList));
            LogHelper.v(TAG + ":书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class XWithMaskBrowser extends XBrowserAble {
    private static final String packageName = "com.mmbox.browser";
    private List<Bookmark> bookmarks;


    public XWithMaskBrowser() {
        super.TAG = "XWithMask";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_x_mask));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_x_mask));
    }

    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "XWithMask" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> bookmarksList = fetchBookmarksList(filePath_cp + fileName_origin);
            LogHelper.v(TAG + ":书签数据:" + JsonUtil.toJson(bookmarksList));
            LogHelper.v(TAG + ":书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class XWithProBrowser extends XBrowserAble {
    private static final String packageName = "com.mmbox.xbrowser.pro";
    private List<Bookmark> bookmarks;


    public XWithProBrowser() {
        super.TAG = "XWithPro";
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int readBookmarkSum() {
        if (bookmarks == null) {
            readBookmark();
        }
        return bookmarks.size();
    }

    @Override
    public void fillDefaultIcon(Context context) {
        this.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_x_pro));
    }

    @Override
    public void fillDefaultAppName(Context context) {
        this.setName(context.getString(R.string.browser_name_show_x_pro));
    }

    private static final String filePath_origin = Path.INNER_PATH_DATA + packageName + Path.FILE_SPLIT + "databases" + Path.FILE_SPLIT;
    private static final String filePath_cp = Path.SDCARD_ROOTPATH + Path.SDCARD_APP_ROOTPATH + Path.SDCARD_TMP_ROOTPATH + Path.FILE_SPLIT + "XWithPro" + Path.FILE_SPLIT;

    @Override
    public List<Bookmark> readBookmark() {
        if (bookmarks != null) {
            LogHelper.v(TAG + ":bookmarks cache is hit.");
            return bookmarks;
        }
        LogHelper.v(TAG + ":bookmarks cache is miss.");
        LogHelper.v(TAG + ":开始读取书签数据");
        try {
            String originFilePathFull = filePath_origin + fileName_origin;
            LogHelper.v(TAG + ":origin file path:" + originFilePathFull);
            ExternalStorageUtil.mkdir(filePath_cp, this.getName());
            LogHelper.v(TAG + ":tmp file path:" + filePath_cp + fileName_origin);
            ExternalStorageUtil.copyFile(originFilePathFull, filePath_cp + fileName_origin, this.getName());
            List<Bookmark> bookmarksList = fetchBookmarksList(filePath_cp + fileName_origin);
            LogHelper.v(TAG + ":书签数据:" + JsonUtil.toJson(bookmarksList));
            LogHelper.v(TAG + ":书签条数:" + bookmarksList.size());
            bookmarks = new LinkedList<>();
            fetchValidBookmarks(bookmarks, bookmarksList);
        } catch (ConverterException converterException) {
            converterException.printStackTrace();
            LogHelper.e(converterException);
            throw converterException;
        } catch (Exception e) {
            e.printStackTrace();
            LogHelper.e(e);
            throw new ConverterException(ContextUtil.buildReadBookmarksErrorMessage(this.getName()));
        } finally {
            LogHelper.v(TAG + ":读取书签数据结束");
        }
        return bookmarks;
    }

    @Override
    public int appendBookmark(List<Bookmark> bookmarks) {
        return 0;
    }
} public class Rule {
    @Setter
    @Getter
    private int id;
    @Setter
    @Getter
    private BasicBrowser source;
    @Setter
    @Getter
    private BasicBrowser target;
    @Setter
    @Getter
    private boolean canUse;

    public Rule(int id, Context context, BasicBrowser source, BasicBrowser target) {
        boolean sourceInstalled = false, targetInstalled = false;
        if (source.isInstalled(context, source)) {
            sourceInstalled = true;
            source.fillVersion(context);
        } else {
            source.fillDefaultIcon(context);
        }
        if (source.getIcon() == null) {
            source.fillDefaultIcon(context);
        }
        source.fillName(context);
        if (target.isInstalled(context, target)) {
            targetInstalled = true;
            target.fillVersion(context);
        } else {
            target.fillDefaultIcon(context);
        }
        if (target.getIcon() == null) {
            target.fillDefaultIcon(context);
        }
        if (sourceInstalled && targetInstalled) {
            canUse = true;
        }
        target.fillName(context);
        this.id = id;
        this.source = source;
        this.target = target;
    }

    @Override
    public String toString() {
        return "{\"id\":" + id + ",\"source\":{" + source.toString() + "},\"target\":{" + target.toString() + "},\"canUse\":" + canUse + "}";
    }
} public class AppListUtil {
    private static Map<String, App> installedAllApp;
    public static String thisAppInfo;
    public static String thisAppPackageName;

    private static Map<String, App> getInstalledAllApp(Context context) {
        if (installedAllApp == null) {
            init(context);
        }
        return installedAllApp;
    }

    public static void reInit(Context context) {
        LogHelper.v("AppListUtil reInit begining.");
        installedAllApp = null;
        init(context);
        LogHelper.v("AppListUtil reInit completed.");
    }

    public static void init(Context context) {
        LogHelper.v("AppListUtil init begining.");
        String globalMsg = context.getResources().getString(R.string.notPermissionForReadInstalledAppList);
        if (installedAllApp != null) {
            LogHelper.v("AppListUtil init is not necessary.");
            return;
        }
        installedAllApp = new TreeMap<>();
        PackageManager packageManager = context.getPackageManager();
        if (packageManager == null) {
            LogHelper.v("AppListUtil init failure,context.getPackageManager is null.");
            throw new InitException(globalMsg);
        }
        List<PackageInfo> packages = packageManager.getInstalledPackages(0);
        if (packages == null || packages.isEmpty()) {
            LogHelper.v("AppListUtil init failure,packageManager.getInstalledPackages(0) is null or empty.");
            throw new InitException(globalMsg);
        }
        String mePackageName = context.getPackageName();
        thisAppPackageName = mePackageName;
        for (PackageInfo packageInfo : packages) {
            ApplicationInfo applicationInfo = packageInfo.applicationInfo;
            App app = new App();
            app.setName(applicationInfo.loadLabel(packageManager).toString());
            app.setPackageName(packageInfo.packageName);
            if (mePackageName != null && mePackageName.equals(packageInfo.packageName) && thisAppInfo == null) {
                thisAppInfo = "App name:" + context.getString(R.string.app_name) + ",packageName:" + mePackageName + ",versionName:" + packageInfo.versionName + ",versionCode:" + packageInfo.versionCode;
                LogHelper.v(thisAppInfo);
            }
            app.setVersionName(packageInfo.versionName);
            app.setVersionCode(packageInfo.versionCode);
//            app.setIcon(applicationInfo.loadIcon(packageManager));
            installedAllApp.put(app.getPackageName(), app);
            /**
             Only display the non-system app info
             if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
             appList.add(tmpInfo);//如果非系统应用，则添加至appList
             }
             */
        }
        if (installedAllApp == null) {
            LogHelper.e("AppListUtil init failure,installedAllApp is null.");
            throw new InitException("无法获取应用列表，请确认权限.");
        }
        LogHelper.v("AppListUtil init success.");
    }

    public static boolean isInstalled(Context context, String packageName) {
        return getInstalledAllApp(context).keySet().contains(packageName);
    }

//    public static Drawable getIcon(String packageName) {
//        if (isInstalled(packageName)) {
//            return installedAllApp.get(packageName).getIcon();
//        }
//        return null;
//    }

    public static String getAppName(Context context, String packageName) {
        if (isInstalled(context, packageName)) {
            return getInstalledAllApp(context).get(packageName).getName();
        }
        return "ERROR";
    }

    public static App getAppInfo(Context context, String packageName) {
        if (isInstalled(context, packageName)) {
            return getInstalledAllApp(context).get(packageName);
        }
        return null;
    }

    public static App getAppInfo(String packageName) {
        if (installedAllApp != null) {
            return installedAllApp.get(packageName);
        }
        return null;
    }
}
import android.content.Context;
import java.util.LinkedList;
import java.util.List;
import lombok.Getter;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.BaiduBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.Default.impl.Flyme5Browser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.Default.impl.MiuiBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.FirefoxBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.H5Browser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.LiebaoBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.OupengBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.OupengClassicBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.QiyuBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.SogouBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.chrome.impl.YandexBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.chrome.impl.chrome.impl.ChromeBetaBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.chrome.impl.chrome.impl.ChromeBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.chrome.impl.chrome.impl.ChromeCanaryBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.chrome.impl.chrome.impl.ChromeDevBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.chrome.impl.xingchen.impl.XingchenPhoneBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.chrome.impl.xingchen.impl.XingchenTabletBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.qihoo360.impl.Qihoo360Browser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.qihoo360.impl.Qihoo360FastestBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.qq.impl.QQBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.qq.impl.QQWithOnePlusBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.uc.impl.UCBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.uc.impl.UCInternationalBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.via.ViaBrowserAble;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.x.impl.XBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.x.impl.XWithGooglePlayBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.x.impl.XWithMaskBrowser;
import pro.kisscat.www.bookmarkhelper.converter.support.impl.x.impl.XWithProBrowser;
import pro.kisscat.www.bookmarkhelper.entry.rule.Rule;
import pro.kisscat.www.bookmarkhelper.util.appList.AppListUtil;
package pro.kisscat.www.bookmarkhelper.converter.support;




/**
 * Created with Android Studio.
 * Project:BookmarkHelper
 * User:ChengLiang
 * Mail:stevenchengmask@gmail.com
 * Date:2016/10/12
 * Time:11:12
 */

public class ConverterMaster {
    @Getter
    private transient static List<Rule> supportRule;

    public static void init(Context context) {
        AppListUtil.init(context);
        if (supportRule == null) {
            supportRule = new LinkedList<>();
            ViaBrowserAble viaBrowserAble = ViaBrowserAble.fetchViaBrowser();
            supportRule.add(new Rule(supportRule.size() + 1, context, new ChromeBrowser(), viaBrowserAble));
            supportRule.add(new Rule(supportRule.size() + 1, context, new ChromeCanaryBrowser(), viaBrowserAble));
            supportRule.add(new Rule(supportRule.size() + 1, context, new ChromeBetaBrowser(), viaBrowserAble));