Skip to content

Commit 018fe8b

Browse files
committed
Refactor bookmark-service - getNativeContainerIds into a shared webext- impl.
Created two new abstract methods: getNativeContainerInfo() -> returns browser-specific info (id + throwIfNotFound) for a given BookmarkContainer getDefaultNativeContainerCandidates() -> returns the candidates for being the default containers for creation of unsupported containers Field unsupportedContainers was refactored into getUnsupportedContainers() method. Added getSupportedContainers(). NativeContainersInfo.platformDefaultBookmarksNodeId renamed to .defaultNativeContainerId Refactored and moved ensureContainersExist(...) to webext- impl. It uses the getSupportedContainers() Created a new webext- impl. method identifySupportedContainers(). This method initializes the supported containers cache. This method must be called at least once after the extension is loaded, before a call to getSupportedContainers(), getUnsupportedContainers() or ensureContainersExist (...) is attempted. Currently, identifySupportedContainers() is called before any process*Sync() in bookmark-sync-provider can take place, but should be probably moved to some module/extension init code. Maybe the whole "supported-containers" logic should be moved to different (new?) service.
1 parent 7cc1b74 commit 018fe8b

File tree

8 files changed

+259
-239
lines changed

8 files changed

+259
-239
lines changed

src/modules/android/android-shared/android-bookmark/android-bookmark.service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ export default class AndroidBookmarkService implements BookmarkService {
3030
return bookmarks;
3131
}
3232

33+
identifySupportedContainers(): ng.IPromise<void> {
34+
return this.methodNotApplicable();
35+
}
36+
3337
methodNotApplicable(): ng.IPromise<any> {
3438
// Unused for this platform
3539
return this.$q.resolve();

src/modules/shared/bookmark/bookmark.enum.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,11 @@ enum BookmarkContainer {
1313
Toolbar = '[xbs] Toolbar'
1414
}
1515

16-
// TODO: maybe remove this new code and use solely (un)supported bookmark detection at runtime
17-
// OR! always create all containers, so that merging in the future is simpler?
18-
const MandatoryBookmarkContainers: Array<BookmarkContainer> = [
19-
BookmarkContainer.Other,
20-
BookmarkContainer.Mobile,
21-
BookmarkContainer.Toolbar
22-
];
23-
2416
enum BookmarkType {
2517
Bookmark = 'bookmark',
2618
Container = 'container',
2719
Folder = 'folder',
2820
Separator = 'separator'
2921
}
3022

31-
export { BookmarkChangeType, BookmarkContainer, BookmarkType, MandatoryBookmarkContainers };
23+
export { BookmarkChangeType, BookmarkContainer, BookmarkType };

src/modules/shared/bookmark/bookmark.interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export interface BookmarkService {
4141
clearNativeBookmarks: () => ng.IPromise<void>;
4242
createNativeBookmarksFromBookmarks: (bookmarks: Bookmark[]) => ng.IPromise<number>;
4343
ensureContainersExist: (bookmarks: Bookmark[]) => Bookmark[];
44+
identifySupportedContainers(): ng.IPromise<void>;
4445
processNativeChangeOnBookmarks: (changeInfo: BookmarkChange, bookmarks: Bookmark[]) => ng.IPromise<Bookmark[]>;
4546
processChangeOnNativeBookmarks: (
4647
id: number,

src/modules/shared/sync/bookmark-sync-provider/bookmark-sync-provider.service.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -137,24 +137,26 @@ export default class BookmarkSyncProviderService implements SyncProvider {
137137
}
138138

139139
processSync(sync: Sync): ng.IPromise<ProcessSyncResult> {
140-
// Process sync
141-
switch (sync.type) {
142-
// Sync native bookmarks to service
143-
case SyncType.Remote:
144-
return this.processRemoteSync(sync);
145-
// Overwrite native bookmarks with synced bookmarks
146-
case SyncType.Local:
147-
return this.processLocalSync(sync);
148-
// Sync bookmarks to service and overwrite native bookmarks
149-
case SyncType.LocalAndRemote:
150-
return this.processLocalAndRemoteSync(sync);
151-
// Upgrade sync to current version
152-
case SyncType.Upgrade:
153-
return this.processUpgradeSync();
154-
// Ambiguous sync
155-
default:
156-
throw new Exceptions.AmbiguousSyncRequestException();
157-
}
140+
return this.bookmarkSvc.identifySupportedContainers().then(() => {
141+
// Process sync
142+
switch (sync.type) {
143+
// Sync native bookmarks to service
144+
case SyncType.Remote:
145+
return this.processRemoteSync(sync);
146+
// Overwrite native bookmarks with synced bookmarks
147+
case SyncType.Local:
148+
return this.processLocalSync(sync);
149+
// Sync bookmarks to service and overwrite native bookmarks
150+
case SyncType.LocalAndRemote:
151+
return this.processLocalAndRemoteSync(sync);
152+
// Upgrade sync to current version
153+
case SyncType.Upgrade:
154+
return this.processUpgradeSync();
155+
// Ambiguous sync
156+
default:
157+
throw new Exceptions.AmbiguousSyncRequestException();
158+
}
159+
});
158160
}
159161

160162
processLocalAndRemoteSync(sync: Sync): ng.IPromise<ProcessSyncResult> {

src/modules/webext/chromium/shared/chromium-bookmark/chromium-bookmark.service.ts

Lines changed: 72 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,21 @@ import angular from 'angular';
22
import { Injectable } from 'angular-ts-decorators';
33
import autobind from 'autobind-decorator';
44
import { Bookmarks as NativeBookmarks, browser } from 'webextension-polyfill-ts';
5-
import {
6-
BookmarkChangeType,
7-
BookmarkContainer,
8-
BookmarkType,
9-
MandatoryBookmarkContainers
10-
} from '../../../../shared/bookmark/bookmark.enum';
5+
import { BookmarkChangeType, BookmarkContainer, BookmarkType } from '../../../../shared/bookmark/bookmark.enum';
116
import {
127
AddNativeBookmarkChangeData,
13-
Bookmark,
148
BookmarkChange,
159
ModifyNativeBookmarkChangeData,
1610
MoveNativeBookmarkChangeData
1711
} from '../../../../shared/bookmark/bookmark.interface';
1812
import * as Exceptions from '../../../../shared/exception/exception';
1913
import Globals from '../../../../shared/global-shared.constants';
2014
import { WebpageMetadata } from '../../../../shared/global-shared.interface';
21-
import { NativeContainersInfo } from '../../../shared/webext-bookmark/NativeContainersInfo';
2215
import WebExtBookmarkService from '../../../shared/webext-bookmark/webext-bookmark.service';
2316

2417
@autobind
2518
@Injectable('BookmarkService')
2619
export default class ChromiumBookmarkService extends WebExtBookmarkService {
27-
otherBookmarksNodeTitle = 'Other bookmarks';
28-
toolbarBookmarksNodeTitle = 'Bookmarks bar';
29-
menuBookmarksNodeTitle = 'Menu bookmarks';
30-
mobileBookmarksNodeTitle = 'Mobile bookmarks';
31-
unsupportedContainers = [BookmarkContainer.Menu, BookmarkContainer.Mobile];
32-
3320
convertNativeBookmarkToSeparator(
3421
bookmark: NativeBookmarks.BookmarkTreeNode
3522
): ng.IPromise<NativeBookmarks.BookmarkTreeNode> {
@@ -134,32 +121,6 @@ export default class ChromiumBookmarkService extends WebExtBookmarkService {
134121
});
135122
}
136123

137-
// TODO: unify with firefox somehow?
138-
// probably auto-detect all supported containers in getNativeContainer (maybe call it explicitely for detection?)
139-
// and then ensure that all supported containers are created
140-
ensureContainersExist(bookmarks: Bookmark[]): Bookmark[] {
141-
if (angular.isUndefined(bookmarks)) {
142-
return;
143-
}
144-
145-
// Add supported containers
146-
const bookmarksToReturn = angular.copy(bookmarks);
147-
MandatoryBookmarkContainers.forEach((element) => {
148-
this.bookmarkHelperSvc.getContainer(element, bookmarksToReturn, true);
149-
});
150-
151-
// Return sorted containers
152-
return bookmarksToReturn.sort((x, y) => {
153-
if (x.title < y.title) {
154-
return -1;
155-
}
156-
if (x.title > y.title) {
157-
return 1;
158-
}
159-
return 0;
160-
});
161-
}
162-
163124
getNativeBookmarksWithSeparators(
164125
nativeBookmarks: NativeBookmarks.BookmarkTreeNode[]
165126
): NativeBookmarks.BookmarkTreeNode[] {
@@ -172,90 +133,83 @@ export default class ChromiumBookmarkService extends WebExtBookmarkService {
172133
return nativeBookmarks;
173134
}
174135

175-
// TODO: unify/share more code with firefox
176-
getNativeContainerIds(): ng.IPromise<NativeContainersInfo> {
177-
const containerIds = new NativeContainersInfo();
178-
// Populate container ids
179-
return browser.bookmarks.getTree().then((tree) => {
180-
// Get the root child nodes
181-
let otherBookmarksNode = tree[0].children.find((x) => {
182-
return x.title === this.otherBookmarksNodeTitle;
183-
});
184-
let toolbarBookmarksNode = tree[0].children.find((x) => {
185-
return x.title === this.toolbarBookmarksNodeTitle;
186-
});
187-
let menuBookmarksNode = tree[0].children.find((x) => {
188-
return x.title === this.menuBookmarksNodeTitle;
189-
});
190-
let mobileBookmarksNode = tree[0].children.find((x) => {
191-
return x.title === this.mobileBookmarksNodeTitle;
192-
});
136+
browserDetection: { isOpera: boolean };
137+
getBrowserDetection() {
138+
if (this.browserDetection) return this.browserDetection;
193139

194-
// TODO: improve this logic
195-
const defaultBookmarksNode = otherBookmarksNode || mobileBookmarksNode;
196-
if (!defaultBookmarksNode) {
197-
// coulnd not find a default container to create folders to place other containers in
198-
throw new Exceptions.ContainerNotFoundException();
199-
}
140+
const browserDetection: any = {};
141+
browserDetection.isChromeLike = this.utilitySvc.isChromeLikeBrowser();
142+
browserDetection.isOpera = this.utilitySvc.isOperaBrowser();
143+
browserDetection.isEdgeChromium = this.utilitySvc.isEdgeChromiumBrowser();
200144

201-
// TODO: FINISH THIS!
202-
// is related to createNativeBookmarksFromBookmarks
203-
// HACK!!!!
204-
this.unsupportedContainers = [];
145+
this.browserDetection = browserDetection;
146+
return this.browserDetection;
147+
}
205148

206-
// Check for unsupported containers
207-
if (!otherBookmarksNode) {
208-
this.logSvc.logWarning('Unsupported container: other bookmarks');
209-
// HACK!!!!
210-
this.unsupportedContainers.push(BookmarkContainer.Other);
211-
otherBookmarksNode = defaultBookmarksNode.children.find((x) => {
212-
return x.title === BookmarkContainer.Other;
213-
});
214-
}
215-
if (!toolbarBookmarksNode) {
216-
this.logSvc.logWarning('Unsupported container: toolbar bookmarks');
217-
// HACK!!!!
218-
this.unsupportedContainers.push(BookmarkContainer.Toolbar);
219-
toolbarBookmarksNode = defaultBookmarksNode.children.find((x) => {
220-
return x.title === BookmarkContainer.Toolbar;
221-
});
222-
}
223-
if (!menuBookmarksNode) {
224-
this.logSvc.logWarning('Unsupported container: menu bookmarks');
225-
// HACK!!!!
226-
this.unsupportedContainers.push(BookmarkContainer.Menu);
227-
menuBookmarksNode = defaultBookmarksNode.children.find((x) => {
228-
return x.title === BookmarkContainer.Menu;
229-
});
230-
}
231-
if (!mobileBookmarksNode) {
232-
this.logSvc.logWarning('Unsupported container: mobile bookmarks');
233-
// HACK!!!!
234-
this.unsupportedContainers.push(BookmarkContainer.Mobile);
235-
mobileBookmarksNode = defaultBookmarksNode.children.find((x) => {
236-
return x.title === BookmarkContainer.Mobile;
149+
chromiumSupportedContainersInfo = {
150+
map: new Map<BookmarkContainer, { id: string; throwIfNotFound: boolean }>([
151+
[BookmarkContainer.Toolbar, { id: '1', throwIfNotFound: false }],
152+
[BookmarkContainer.Other, { id: '2', throwIfNotFound: false }],
153+
[BookmarkContainer.Mobile, { id: '3', throwIfNotFound: false }]
154+
]),
155+
default: [BookmarkContainer.Other, BookmarkContainer.Mobile]
156+
};
157+
158+
operaSupportedContainersInfo = {
159+
map: new Map<BookmarkContainer, { id: string; throwIfNotFound: boolean }>([
160+
[BookmarkContainer.Toolbar, { id: 'bookmarks_bar', throwIfNotFound: false }],
161+
[BookmarkContainer.Other, { id: 'other', throwIfNotFound: true }]
162+
// [, { id: 'unsorted', throwIfNotFound: false }],
163+
// [, { id: 'user_root', throwIfNotFound: false }],
164+
// [, { id: 'shared', throwIfNotFound: false }],
165+
// [, { id: 'trash', throwIfNotFound: false }],
166+
// [, { id: 'speed_dial', throwIfNotFound: false }],
167+
]),
168+
default: [BookmarkContainer.Other]
169+
};
170+
171+
getNativeContainerInfo(containerName: BookmarkContainer): ng.IPromise<{ id?: string; throwIfNotFound: boolean }> {
172+
const browserDetection = this.getBrowserDetection();
173+
if (browserDetection.isOpera) {
174+
const getByName: (
175+
id: string,
176+
callback: (node: NativeBookmarks.BookmarkTreeNode) => void
177+
) => void = (browser as any).bookmarks.getRootByName;
178+
179+
const baseInfo = this.operaSupportedContainersInfo.map.get(containerName);
180+
if (baseInfo) {
181+
return this.$q((resolve) => {
182+
getByName(baseInfo.id, (node) => {
183+
resolve({ id: node.id, throwIfNotFound: baseInfo.throwIfNotFound });
184+
});
237185
});
186+
// eslint-disable-next-line no-else-return
187+
} else {
188+
return this.$q.resolve({ id: undefined, throwIfNotFound: false });
238189
}
190+
// eslint-disable-next-line no-else-return
191+
} else {
192+
return browser.bookmarks.getTree().then((tree) => {
193+
const baseInfo = this.chromiumSupportedContainersInfo.map.get(containerName);
194+
let info: { id?: string; throwIfNotFound: boolean };
195+
if (baseInfo && tree[0].children!.find((x) => x.id === baseInfo.id)) {
196+
info = { ...baseInfo }; // make a copy
197+
} else {
198+
info = { id: undefined, throwIfNotFound: false };
199+
}
200+
return info;
201+
});
202+
}
203+
}
239204

240-
// Add container ids to result
241-
{
242-
// must be always defined!
243-
containerIds.platformDefaultBookmarksNodeId = defaultBookmarksNode.id;
244-
}
245-
if (!angular.isUndefined(otherBookmarksNode)) {
246-
containerIds.set(BookmarkContainer.Other, otherBookmarksNode.id);
247-
}
248-
if (!angular.isUndefined(toolbarBookmarksNode)) {
249-
containerIds.set(BookmarkContainer.Toolbar, toolbarBookmarksNode.id);
250-
}
251-
if (!angular.isUndefined(menuBookmarksNode)) {
252-
containerIds.set(BookmarkContainer.Menu, menuBookmarksNode.id);
253-
}
254-
if (!angular.isUndefined(mobileBookmarksNode)) {
255-
containerIds.set(BookmarkContainer.Mobile, mobileBookmarksNode.id);
256-
}
257-
return containerIds;
258-
});
205+
getDefaultNativeContainerCandidates(): BookmarkContainer[] {
206+
const browserDetection = this.getBrowserDetection();
207+
if (browserDetection.isOpera) {
208+
return this.operaSupportedContainersInfo.default;
209+
// eslint-disable-next-line no-else-return
210+
} else {
211+
return this.chromiumSupportedContainersInfo.default;
212+
}
259213
}
260214

261215
isSeparator(nativeBookmark: NativeBookmarks.BookmarkTreeNode): boolean {

0 commit comments

Comments
 (0)