This repository has been archived by the owner. It is now read-only.
Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
with
306 additions
and 1 deletion.
- +36 −0 Client.xcodeproj/project.pbxproj
- +5 −0 Client/Application/AppDelegate.swift
- +19 −0 Cliqz/Extensions/BrowserViewController/BrowserViewController+GhosteryMigration.swift
- +2 −1 Cliqz/Settings/CliqzAppSettingsTableViewController.swift
- +38 −0 Cliqz/Storage/GhosteryMigration/BookmarkMirrorItemExtension.swift
- +136 −0 Cliqz/Storage/GhosteryMigration/GhosteryMigrationManager.swift
- +49 −0 Cliqz/Storage/GhosteryMigration/GhosterySQLiteFactories.swift
- +21 −0 Cliqz/Storage/GhosteryMigration/GhosteryTab.swift
| @@ -0,0 +1,19 @@ | ||
| // | ||
| // BrowserViewController+GhosteryMigration.swift | ||
| // Storage | ||
| // | ||
| // Created by Mahmoud Adam on 4/26/18. | ||
| // Copyright © 2018 Cliqz. All rights reserved. | ||
| // | ||
| import UIKit | ||
| import Storage | ||
|
|
||
| extension BrowserViewController : GhosteryMigrationDelegate { | ||
|
|
||
| func openMigratedGhosteryTab(_ url: URL) { | ||
| DispatchQueue.main.async { | ||
| self.openURLInNewTab(url, isPrivileged: false) | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,38 @@ | ||
| // | ||
| // BookmarkMirrorItemExtension.swift | ||
| // Client | ||
| // | ||
| // Created by Mahmoud Adam on 4/30/18. | ||
| // Copyright © 2018 Cliqz. All rights reserved. | ||
| // | ||
| import UIKit | ||
| import Shared | ||
|
|
||
| extension BookmarkMirrorItem { | ||
| public func copyWithChildrenn(_ children: [GUID]) -> BookmarkMirrorItem { | ||
| return BookmarkMirrorItem( | ||
| guid: self.guid, | ||
| type: self.type, | ||
| dateAdded: self.dateAdded, | ||
| serverModified: self.serverModified, | ||
| isDeleted: self.isDeleted, | ||
| hasDupe: self.hasDupe, | ||
| parentID: self.parentID, | ||
| parentName: self.parentName, | ||
| feedURI: self.feedURI, | ||
| siteURI: self.siteURI, | ||
| pos: self.pos, | ||
| title: self.title, | ||
| description: self.description, | ||
| bookmarkURI: self.bookmarkURI, | ||
| tags: self.tags, | ||
| keyword: self.keyword, | ||
| folderName: self.folderName, | ||
| queryID: self.queryID, | ||
| children: children, | ||
| faviconID: self.faviconID, | ||
| localModified: self.localModified, | ||
| syncStatus: self.syncStatus) | ||
| } | ||
| } |
| @@ -0,0 +1,136 @@ | ||
| // | ||
| // GhosteryMigrationManager.swift | ||
| // Client | ||
| // | ||
| // Created by Mahmoud Adam on 4/24/18. | ||
| // Copyright © 2018 Cliqz. All rights reserved. | ||
| // | ||
| import UIKit | ||
| import Shared | ||
| import Deferred | ||
|
|
||
| public protocol GhosteryMigrationDelegate: class { | ||
| func openMigratedGhosteryTab(_ url: URL) | ||
| } | ||
|
|
||
| public class GhosteryMigrationManager { | ||
|
|
||
| open static var shared = GhosteryMigrationManager() | ||
| open weak var delegate: GhosteryMigrationDelegate? | ||
|
|
||
| private static let migrationKey = "GhosteryMigrationKey" | ||
| private static let databaseFilename = "Ghostery.sqlite" | ||
|
|
||
| private var ghosteryDB: BrowserDB? | ||
| private var bookmarkBuffer: BookmarkBufferStorage? | ||
| private var bookmarkFolders: [BookmarkMirrorItem]? | ||
| private var bookmarks: [BookmarkMirrorItem]? | ||
|
|
||
| init() { | ||
| guard UserDefaults.standard.object(forKey: GhosteryMigrationManager.migrationKey) == nil else { | ||
| return | ||
| } | ||
|
|
||
| let rootPath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]) | ||
| let files = FileAccessor(rootPath: rootPath) | ||
| let file = URL(fileURLWithPath: (try! files.getAndEnsureDirectory())).appendingPathComponent(GhosteryMigrationManager.databaseFilename).path | ||
| if FileManager.default.fileExists(atPath: file) { | ||
| self.ghosteryDB = BrowserDB(filename: GhosteryMigrationManager.databaseFilename, schema: BrowserSchema(), files: files) | ||
| } | ||
| } | ||
|
|
||
| public func startMigration(_ bookmarkBuffer: BookmarkBufferStorage, migrationDelegate : GhosteryMigrationDelegate) { | ||
| self.bookmarkBuffer = bookmarkBuffer | ||
| self.delegate = migrationDelegate | ||
|
|
||
| guard self.ghosteryDB != nil else { | ||
| return | ||
| } | ||
|
|
||
| DispatchQueue.global().async { [weak self] in | ||
| self?.migrateOpenTabs() | ||
| self?.migrateFoldersAndBookmarks() | ||
| } | ||
| } | ||
|
|
||
| private func migrateFoldersAndBookmarks() { | ||
| let folders = self.fetchBookmarkFolders() | ||
| if folders.value.isSuccess { | ||
| let bookmarks = self.fetchBookmarks() | ||
| if bookmarks.value.isSuccess { | ||
| self.performBookmarkMigration() | ||
| self.cleanup() | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private func migrateOpenTabs() { | ||
| let sql = "SELECT * from \(TableGhosteryTabs) order by ZORDER" | ||
| ghosteryDB!.runQuery(sql, args: [], factory: GhosterySQLiteFactories.tabFactory) >>== { [weak self] tabs in | ||
| for tab in tabs.asArray() { | ||
| if let url = URL(string: tab.url) { | ||
| self?.delegate?.openMigratedGhosteryTab(url) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private func fetchBookmarkFolders() -> Deferred<Maybe<Cursor<BookmarkMirrorItem>>> { | ||
| let sql = "SELECT * from \(TableGhosteryBookmarkFolders)" | ||
| return ghosteryDB!.runQuery(sql, args: [], factory: GhosterySQLiteFactories.bookmarkFolderFactory) >>== { [weak self] bookmarkFolders in | ||
| self?.bookmarkFolders = bookmarkFolders.asArray() | ||
| return deferMaybe(bookmarkFolders) | ||
| } | ||
| } | ||
|
|
||
| private func fetchBookmarks() -> Deferred<Maybe<Cursor<BookmarkMirrorItem>>> { | ||
| let sql = "SELECT * from \(TableGhosteryBookmarks)" | ||
| return ghosteryDB!.runQuery(sql, args: [], factory: GhosterySQLiteFactories.bookmarkFactory) >>== { [weak self] bookmarks in | ||
| self?.bookmarks = bookmarks.asArray() | ||
| return deferMaybe(bookmarks) | ||
| } | ||
| } | ||
|
|
||
| private func performBookmarkMigration() { | ||
|
|
||
| var records = [BookmarkMirrorItem]() | ||
| // Add mobile record at the start of the array | ||
| let mobileRecord = BookmarkMirrorItem.folder(BookmarkRoots.MobileFolderGUID, dateAdded: Date.now(), modified: Date.now(), hasDupe: false, parentID: BookmarkRoots.RootGUID, parentName: "<Root>", title: "Mobile Bookmarks", description: nil, children: []) | ||
| records.append(mobileRecord) | ||
|
|
||
| // Append bookmark folders | ||
| if let bookmarkFolders = self.bookmarkFolders { | ||
| records.append(contentsOf: bookmarkFolders) | ||
| } | ||
|
|
||
| // Append bookmarks | ||
| if let bookmarks = bookmarks { | ||
| records.append(contentsOf: bookmarks) | ||
| } | ||
|
|
||
| // Fill in the childern attribute | ||
| let fixedRecords = self.fixupChildern(records) | ||
|
|
||
| // Insert the bookmarks into the database | ||
| _ = self.bookmarkBuffer?.applyRecords(fixedRecords) | ||
| } | ||
|
|
||
| private func fixupChildern(_ bookmarks: [BookmarkMirrorItem]) -> [BookmarkMirrorItem] { | ||
| var records = [BookmarkMirrorItem]() | ||
| for bookmark in bookmarks { | ||
| let childern = bookmarks.filter { bookmark.guid == $0.parentID } | ||
| let childernGUIDs = childern.map { $0.guid } | ||
| let fixedBookmark = bookmark.copyWithChildrenn(childernGUIDs) | ||
| records.append(fixedBookmark) | ||
| } | ||
| return records | ||
| } | ||
|
|
||
| private func cleanup() { | ||
| DispatchQueue.main.async { [weak self] in | ||
| self?.ghosteryDB?.forceClose() | ||
| UserDefaults.standard.set(true, forKey: GhosteryMigrationManager.migrationKey) | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,49 @@ | ||
| // | ||
| // GhosterySQLiteFactories.swift | ||
| // Client | ||
| // | ||
| // Created by Mahmoud Adam on 4/26/18. | ||
| // Copyright © 2018 Cliqz. All rights reserved. | ||
| // | ||
| import UIKit | ||
| import Shared | ||
|
|
||
| let TableGhosteryBookmarkFolders = "zfolder" | ||
| let TableGhosteryBookmarks = "zbookmark" | ||
| let TableGhosteryTabs = "ztab" | ||
|
|
||
| class GhosterySQLiteFactories { | ||
|
|
||
| class func bookmarkFolderFactory(_ row: SDRow) -> BookmarkMirrorItem { | ||
| let id = row["Z_PK"] as! Int | ||
| let parentId = row["ZPARENT"] as? Int | ||
| let name = row["ZNAME"] as! String | ||
|
|
||
| let parentGUID = parentId != nil ? String("GhosteryFolder-\(parentId!)") : BookmarkRoots.MobileFolderGUID | ||
|
|
||
| let bookmarkFolder = BookmarkMirrorItem.folder(String("GhosteryFolder-\(id)"), dateAdded: Date.now(), modified: Date.now(), hasDupe: false, parentID: parentGUID, parentName: nil, title: name, description: name, children: []) | ||
| return bookmarkFolder | ||
| } | ||
|
|
||
| class func bookmarkFactory(_ row: SDRow) -> BookmarkMirrorItem { | ||
| let id = row["Z_PK"] as! Int | ||
| let name = row["ZNAME"] as! String | ||
| let url = row["ZURL"] as! String | ||
| let folderId = row["ZFOLDER"] as? Int | ||
|
|
||
| let parentId = folderId != nil ? String("GhosteryFolder-\(folderId!)") : BookmarkRoots.MobileFolderGUID | ||
|
|
||
| let bookmark = BookmarkMirrorItem.bookmark(String("GhosteryBookmark-\(id)"), dateAdded: Date.now(), modified: Date.now(), hasDupe: false, parentID: parentId, parentName: nil, title: name, description: name, URI: url, tags: "", keyword: nil) | ||
| return bookmark | ||
| } | ||
|
|
||
|
|
||
| class func tabFactory(_ row: SDRow) -> GhosteryTab { | ||
| let id = row["Z_PK"] as! Int | ||
| let order = row["ZORDER"] as! Int | ||
| let url = row["ZURL"] as! String | ||
| let tab = GhosteryTab(id, order: order, url: url) | ||
| return tab | ||
| } | ||
| } |
| @@ -0,0 +1,21 @@ | ||
| // | ||
| // GhosteryTab.swift | ||
| // Storage | ||
| // | ||
| // Created by Mahmoud Adam on 4/26/18. | ||
| // Copyright © 2018 Cliqz. All rights reserved. | ||
| // | ||
| import UIKit | ||
|
|
||
| class GhosteryTab { | ||
| let id: Int | ||
| let order: Int | ||
| let url: String | ||
|
|
||
| init(_ id: Int, order: Int, url: String) { | ||
| self.id = id | ||
| self.order = order | ||
| self.url = url | ||
| } | ||
| } |