diff --git a/src/about/index.js b/src/about/index.js
index b816a80e..6d3f7f7e 100644
--- a/src/about/index.js
+++ b/src/about/index.js
@@ -18,29 +18,30 @@ limitations under the License.
import $ from 'jquery';
import ServiceWorkerBridge from '../service-worker-bridge';
-const tabActivator = new ServiceWorkerBridge().serverLocatoor;
-
-$(() => {
- const date = new Date().getFullYear();
- $('#copyright').append(`${date} Nuxeo`);
- $('#apache').click(() => {
- tabActivator.loadNewExtensionTab(
- 'http://www.apache.org/licenses/LICENSE-2.0'
- );
- });
- $('#feedback').click(() => {
- tabActivator.loadNewExtensionTab(
- 'https://portal.prodpad.com/40c295d6-739d-11e7-9e52-06df22ffaf6f'
- );
- });
- $('#apache').click(() => {
- tabActivator.loadNewExtensionTab(
- 'http://www.apache.org/licenses/LICENSE-2.0'
- );
- });
- $('#feedback').click(() => {
- tabActivator.loadNewExtensionTab(
- 'https://portal.prodpad.com/40c295d6-739d-11e7-9e52-06df22ffaf6f'
- );
- });
-});
+new ServiceWorkerBridge()
+ .bootstrap()
+ .then((worker) => worker.tabActivator)
+ .then((tabActivator) => $(() => {
+ const date = new Date().getFullYear();
+ $('#copyright').append(`${date} Nuxeo`);
+ $('#apache').click(() => {
+ tabActivator.loadNewExtensionTab(
+ 'http://www.apache.org/licenses/LICENSE-2.0'
+ );
+ });
+ $('#feedback').click(() => {
+ tabActivator.loadNewExtensionTab(
+ 'https://portal.prodpad.com/40c295d6-739d-11e7-9e52-06df22ffaf6f'
+ );
+ });
+ $('#apache').click(() => {
+ tabActivator.loadNewExtensionTab(
+ 'http://www.apache.org/licenses/LICENSE-2.0'
+ );
+ });
+ $('#feedback').click(() => {
+ tabActivator.loadNewExtensionTab(
+ 'https://portal.prodpad.com/40c295d6-739d-11e7-9e52-06df22ffaf6f'
+ );
+ });
+ }));
diff --git a/src/content/main.js b/src/content/main.js
index d151ea18..31674093 100644
--- a/src/content/main.js
+++ b/src/content/main.js
@@ -19,11 +19,9 @@ limitations under the License.
import ServiceWorkerBridge from '../service-worker-bridge';
-const serviceWorkerBridge = new ServiceWorkerBridge();
-
class Content {
- constructor() {
- this.browserStore = serviceWorkerBridge.browserStore;
+ constructor(store) {
+ this.browserStore = store;
// fetch back the server url from the browser store
this.browserStore.get(['server']).then((data) => {
@@ -60,7 +58,10 @@ class ContentMessageHandler {
}
}
-const content = new Content();
-const handler = new ContentMessageHandler(content);
+new ServiceWorkerBridge().bootstrap().then((worker) => {
+ const content = new Content(worker.browserStore);
+ const handler = new ContentMessageHandler(content);
-chrome.runtime.onMessage.addListener((request, sender, sendResponse) => handler.handle(request, sender, sendResponse));
+ chrome.runtime.onMessage
+ .addListener((request, sender, sendResponse) => handler.handle(request, sender, sendResponse));
+});
diff --git a/src/json/index.js b/src/json/index.js
index e0d93088..da42a6e3 100644
--- a/src/json/index.js
+++ b/src/json/index.js
@@ -13,21 +13,24 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
-import $ from 'jquery';
+import jQuery from 'jquery';
import 'bootstrap';
import hljs from 'highlight.js';
import '../../public/styles/mono-blue.css';
import ServiceWorkerBridge from '../service-worker-bridge';
-$(() => {
- const jsonHighlighter = new ServiceWorkerBridge().jsonHighlighter;
- jsonHighlighter.input().then((input) => {
- document.getElementById('json-string').textContent = input;
- try {
- hljs.highlightAll();
- } catch (e) {
- console.log('Sorry! JSON highlighting only available in Chrome.');
- }
- });
-});
+new ServiceWorkerBridge()
+ .bootstrap()
+ .then((worker) => jQuery(() => {
+ worker.jsonHighlighter
+ .input()
+ .then((input) => {
+ document.getElementById('json-string').textContent = input;
+ try {
+ hljs.highlightAll();
+ } catch (e) {
+ console.log('Sorry! JSON highlighting only available in Chrome.');
+ }
+ });
+ }));
diff --git a/src/main/browser-store.js b/src/main/browser-store.js
index 42d8c7d2..8c00f537 100644
--- a/src/main/browser-store.js
+++ b/src/main/browser-store.js
@@ -1,8 +1,20 @@
-class BrowserStore {
+import ServiceWorkerComponent from './service-worker-component';
+
+class BrowserStore extends ServiceWorkerComponent {
constructor(worker, namespace = 'nuxeo-browser-extension.') {
- this.worker = worker;
+ super(worker);
+
+ // Define propertie
this.namespace = namespace;
+ // Bind methods
+ Object.getOwnPropertyNames(Object.getPrototypeOf(this))
+ .filter((prop) => typeof this[prop] === 'function' && prop !== 'constructor')
+ .forEach((method) => {
+ this[method] = this[method].bind(this);
+ });
+
+ // Define functors
this.keysOf = (data) => {
if (Array.isArray(data)) {
return data;
@@ -31,13 +43,6 @@ class BrowserStore {
// call the function to get the default value
return data[key]();
};
-
- // Bind methods
- Object.getOwnPropertyNames(Object.getPrototypeOf(this))
- .filter((prop) => typeof this[prop] === 'function' && prop !== 'constructor')
- .forEach((method) => {
- this[method] = this[method].bind(this);
- });
}
get(input) {
diff --git a/src/main/connect-locator.js b/src/main/connect-locator.js
index eaa05470..ab81f038 100644
--- a/src/main/connect-locator.js
+++ b/src/main/connect-locator.js
@@ -1,21 +1,24 @@
import CryptoJS from 'crypto-js';
+import ServiceWorkerComponent from './service-worker-component';
-class ConnectLocator {
+class ConnectLocator extends ServiceWorkerComponent {
constructor(worker) {
- this.worker = worker;
- // Declare private methods
- this.credentialsKeyOf = (location) => {
- const hash = CryptoJS
- .SHA512(location.toString())
- .toString();
- return `connect-locator.${hash}`;
- };
+ super(worker);
+
// Bind methods
Object.getOwnPropertyNames(Object.getPrototypeOf(this))
.filter((prop) => typeof this[prop] === 'function' && prop !== 'constructor')
.forEach((method) => {
this[method] = this[method].bind(this);
});
+
+ // Declare functors
+ this.credentialsKeyOf = (location) => {
+ const hash = CryptoJS
+ .SHA512(location.toString())
+ .toString();
+ return `connect-locator.${hash}`;
+ };
}
withUrl(input) {
diff --git a/src/main/declarative-net-engine.js b/src/main/declarative-net-engine.js
index d859797f..3b8b472e 100644
--- a/src/main/declarative-net-engine.js
+++ b/src/main/declarative-net-engine.js
@@ -1,4 +1,5 @@
/* eslint-disable max-classes-per-file */
+import ServiceWorkerComponent from './service-worker-component';
class BaseRule {
constructor() {
@@ -146,9 +147,11 @@ class RedirectRule extends BaseRule {
}
}
-class DeclarativeNetEngine {
+class DeclarativeNetEngine extends ServiceWorkerComponent {
constructor(worker) {
- this.worker = worker;
+ super(worker);
+
+ // Define properties
this.rules = new Map();
this.rulesToAdd = [];
this.rulesToRemove = [];
@@ -160,7 +163,7 @@ class DeclarativeNetEngine {
this[method] = this[method].bind(this);
});
- // Private functions
+ // Define functors
this.requestOf = (rulesToAdd, rulesToRemove) => ({
addRules: rulesToAdd.map((rule) => rule.toJson()),
removeRuleIds: rulesToRemove.map((rule) => rule.hashCode()),
diff --git a/src/main/designer-live-preview.js b/src/main/designer-live-preview.js
index 912365ae..6ddb27b6 100644
--- a/src/main/designer-live-preview.js
+++ b/src/main/designer-live-preview.js
@@ -18,16 +18,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { resolve } from 'nuxeo/lib/deps/promise';
import DeclarativeNetComponents from './declarative-net-engine';
+import ServiceWorkerComponent from './service-worker-component';
const BasicAuthenticationHeaderRule = DeclarativeNetComponents.BasicAuthenticationHeaderRule;
const RedirectRule = DeclarativeNetComponents.RedirectRule;
-class DesignerLivePreview {
+class DesignerLivePreview extends ServiceWorkerComponent {
// eslint-disable-next-line no-unused-vars
constructor(worker) {
- this.worker = worker;
+ super(worker);
// Set defaukt properties for the class
this.undoByProjectNames = new Map();
@@ -124,12 +124,12 @@ class DesignerLivePreview {
modifyUrlForUIPath(url) {
const fragments = url.pathname.split('/');
if (fragments[2] !== 'ui') {
- return resolve(url);
+ return Promise.resolve(url);
}
fragments.splice(3, 0, ''); // Insert an empty string after 'ui'
const newUrl = new URL(url);
newUrl.pathname = fragments.join('/');
- return resolve(newUrl);
+ return Promise.resolve(newUrl);
}
toggle(projectName) {
diff --git a/src/main/desktop-notifier.js b/src/main/desktop-notifier.js
index 4685b196..b1e49d45 100644
--- a/src/main/desktop-notifier.js
+++ b/src/main/desktop-notifier.js
@@ -15,11 +15,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
+import ServiceWorkerComponent from './service-worker-component';
+
const namespacedIdOf = (id) => `nuxeo-web-extension-${id}`;
-class DesktopNotifier {
+class DesktopNotifier extends ServiceWorkerComponent {
constructor(worker) {
- this.worker = worker;
+ super(worker);
// Bind methods
Object.getOwnPropertyNames(Object.getPrototypeOf(this))
diff --git a/src/main/document-browser.js b/src/main/document-browser.js
index 5114d7f3..3215ca16 100644
--- a/src/main/document-browser.js
+++ b/src/main/document-browser.js
@@ -1,14 +1,15 @@
/* eslint-disable comma-dangle */
import DOMPurify from 'dompurify';
+import ServiceWorkerComponent from './service-worker-component';
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
const pathPattern = /^\//;
const selectFromPattern = /SELECT .* FROM /i;
const webuiPattern = /nuxeo\/ui\/#!\//;
-class DocumentBrowser {
+class DocumentBrowser extends ServiceWorkerComponent {
constructor(worker) {
- this.worker = worker;
+ super(worker);
// Bind methods
Object.getOwnPropertyNames(Object.getPrototypeOf(this))
@@ -18,51 +19,67 @@ class DocumentBrowser {
});
}
- listenToChromeEvents() {
- const cleanupFunctions = [];
+ // eslint-disable-next-line no-unused-vars
+ activate(self) {
+ return Promise
+ .resolve([])
+ .then((undoStack) => {
+ chrome.omnibox.onInputEntered.addListener(this.openDocument);
+ undoStack.push(() => chrome.omnibox.onInputEntered.removeListener(this.openDocument));
- chrome.omnibox.onInputEntered.addListener(this.openDocument);
- cleanupFunctions.push(() => chrome.omnibox.onInputEntered.removeListener(this.openDocument));
+ chrome.omnibox.onInputChanged.addListener(this.suggestDocument);
+ undoStack.push(() => chrome.omnibox.onInputChanged.removeListener(this.suggestDocument));
- chrome.omnibox.onInputChanged.addListener(this.suggestDocument);
- cleanupFunctions.push(() => chrome.omnibox.onInputChanged.removeListener(this.suggestDocument));
-
- return () => {
- while (cleanupFunctions.length > 0) {
- const cleanupFunction = cleanupFunctions.pop();
- cleanupFunction();
- }
- };
+ return undoStack;
+ })
+ .then((undoStack) => () => undoStack.forEach((undo) => undo()));
}
onWebUI() {
- return webuiPattern.exec(this.worker.serverConnector._nuxeo._baseURL);
+ return Promise.resolve(
+ webuiPattern.exec(this.worker.serverConnector._nuxeo._baseURL)
+ );
}
openDocument(input) {
- if (uuidPattern.test(input)) {
- this.openDocFromId(input);
- } else if (pathPattern.test(input)) {
- this.openDocFromPath(input);
- } else {
- console.error(`Invalid input ${input}`);
- }
+ return Promise.resolve(input)
+ .then((text) => {
+ if (!uuidPattern.test(input)) {
+ return { text, promise: null };
+ }
+ return { text, promise: this.openDoc(text) };
+ })
+ .then(({ text, promise }) => {
+ if (promise !== null) {
+ return { text, promise };
+ }
+ if (!pathPattern.test(input)) {
+ return { text, promise: null };
+ }
+ return { text, promise: this.openDoc(text) };
+ })
+ .then(({ text, promise }) => {
+ if (promise == null) {
+ return Promise.reject(new Error(`Invalid input ${text}`));
+ }
+ return promise;
+ });
}
openDocFromId(id) {
- this.worker.serverConnector.withNuxeo()
+ return this.worker.serverConnector.withNuxeo()
.then((nuxeo) => nuxeo.request(`/id/${id}`))
.then((request) => this.doOpenDoc(request));
}
openDocFromPath(path) {
- this.worker.serverConnector.withNuxeo()
+ return this.worker.serverConnector.withNuxeo()
.then((nuxeo) => nuxeo.request(`/path/${path}`))
.then((request) => this.doOpenDoc(request));
}
doOpenDoc(request) {
- request
+ return request
.schemas('*')
.enrichers({ document: ['acls', 'permissions'] })
.get()
@@ -73,60 +90,73 @@ class DocumentBrowser {
}
return `nxdoc/default/${uid}/view_documents`;
}
- this.browserNavigator.loadNewExtensionTab(pathOf(doc.uid), true);
+ this.tabNavigationHandler.loadNewExtensionTab(pathOf(doc.uid), true);
})
.catch((error) => {
console.log(error);
});
}
- suggestDocument(text, suggest) {
- if (uuidPattern.test(text)) {
- this.openDocFromId(text);
- return;
- }
- if (pathPattern.test(text)) {
- this.openDocFromPath(text);
- return;
- }
- const jsonQueryOf = (query) => {
- if (selectFromPattern.test(query)) {
- return text;
- }
- return `SELECT * FROM Document WHERE ecm:fulltext = "${text}"`;
- };
- const query = jsonQueryOf(text).replace(/'/g, '"');
- const suggestions = [];
- this.nuxeo
- .repository()
- .schemas(['dublincore', 'common', 'uid'])
- .query({
- query,
- sortBy: 'dc:modified',
+ suggestDocument(input, suggest) {
+ return Promise.resolve({ text: input, pronise: null })
+ .then(({ text, promise }) => {
+ if (promise || !uuidPattern.test(text)) {
+ return { text, promise };
+ }
+ // document selection using UUID
+ return { text, promise: this.openDocFromId(text) };
})
- .then((res) => {
- if (res.entries.length > 0) {
- res.entries.forEach((doc) => {
- const sanitizedDoc = DOMPurify.sanitize(
- `${doc.title} ${doc.path}`,
- { ALLOWED_TAGS: ['match', 'dim'] }
- );
- suggestions.push({
- content: doc.uid,
- description: sanitizedDoc,
- });
- });
+ .then(({ text, promise }) => {
+ if (promise || !pathPattern.test(text)) {
+ return { text, promise };
}
- if (res.entries.length > 5) {
- const sanitizedDoc = DOMPurify.sanitize(
- 'Want more results? Try the fulltext searchbox from the Nuxeo Dev Tools extension window.',
- { ALLOWED_TAGS: ['match', 'dim'] }
- );
- chrome.omnibox.setDefaultSuggestion({
- description: sanitizedDoc,
- });
+ // document selection using path
+ return { text, promise: this.openDocFromPath(text) };
+ })
+ .then(({ text, promise }) => {
+ if (promise) {
+ return promise;
}
- suggest(suggestions);
+ // document selection using NXQL
+ const jsonQueryOf = (query) => {
+ if (selectFromPattern.test(query)) {
+ return text;
+ }
+ return `SELECT * FROM Document WHERE ecm:fulltext = "${text}"`;
+ };
+ const query = jsonQueryOf(text).replace(/'/g, '"');
+ const suggestions = [];
+ return this.nuxeo
+ .repository()
+ .schemas(['dublincore', 'common', 'uid'])
+ .query({
+ query,
+ sortBy: 'dc:modified',
+ })
+ .then((res) => {
+ if (res.entries.length > 0) {
+ res.entries.forEach((doc) => {
+ const sanitizedDoc = DOMPurify.sanitize(
+ `${doc.title} ${doc.path}`,
+ { ALLOWED_TAGS: ['match', 'dim'] }
+ );
+ suggestions.push({
+ content: doc.uid,
+ description: sanitizedDoc,
+ });
+ });
+ }
+ if (res.entries.length > 5) {
+ const sanitizedDoc = DOMPurify.sanitize(
+ 'Want more results? Try the fulltext searchbox from the Nuxeo Dev Tools extension window.',
+ { ALLOWED_TAGS: ['match', 'dim'] }
+ );
+ chrome.omnibox.setDefaultSuggestion({
+ description: sanitizedDoc,
+ });
+ }
+ suggest(suggestions);
+ });
});
}
diff --git a/src/main/json-highlighter.js b/src/main/json-highlighter.js
index 30d1bf63..322b2b99 100644
--- a/src/main/json-highlighter.js
+++ b/src/main/json-highlighter.js
@@ -1,6 +1,10 @@
-class JsonHighlighter {
+import ServiceWorkerComponent from './service-worker-component';
+
+class JsonHighlighter extends ServiceWorkerComponent {
// eslint-disable-next-line no-unused-vars
constructor(worker) {
+ super(worker);
+
this._input = '';
// Bind methods
diff --git a/src/main/main-firefox.js b/src/main/main-firefox.js
index db683652..8ed508e0 100644
--- a/src/main/main-firefox.js
+++ b/src/main/main-firefox.js
@@ -28,4 +28,4 @@ console.log(`Service Worker: ${buildTime} - ${buildVersion} - ${browserVendor} -
const serviceWorker = new ServiceWorker(developmentMode, buildTime, buildVersion, browserVendor);
// eslint-disable-next-line no-unused-vars
-const undoListeningHandler = serviceWorker.listenToChromeEvents();
+const undoListeningHandler = serviceWorker.activate();
diff --git a/src/main/manifest-chrome.json b/src/main/manifest-chrome.json
index ca2984d9..9fadf04d 100644
--- a/src/main/manifest-chrome.json
+++ b/src/main/manifest-chrome.json
@@ -13,7 +13,7 @@
},
"permissions": [
"storage",
- "cookies",
+ "contextMenus",
"tabs",
"activeTab",
"notifications",
diff --git a/src/main/repository-indexer.js b/src/main/repository-indexer.js
index b0fdc1b3..0577930f 100644
--- a/src/main/repository-indexer.js
+++ b/src/main/repository-indexer.js
@@ -14,9 +14,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-class RepositoryIndexer {
+import ServiceWorkerComponent from './service-worker-component';
+
+class RepositoryIndexer extends ServiceWorkerComponent {
constructor(worker) {
- this.worker = worker;
+ super(worker);
+
this.waiting = undefined;
// Bind methods
diff --git a/src/main/runtime-build-info.js b/src/main/runtime-build-info.js
index 6c5c86a0..b777b3c2 100644
--- a/src/main/runtime-build-info.js
+++ b/src/main/runtime-build-info.js
@@ -1,17 +1,21 @@
/* eslint-disable max-classes-per-file */
+import ServiceWorkerComponent from './service-worker-component';
+
+class RuntimeBuildInfo extends ServiceWorkerComponent {
+ constructor(worker, buildTime, buildVersion, browserVendor) {
+ super(worker);
-class RuntimeBuildInfo {
- constructor(buildTime, buildVersion, browserVendor) {
this._developer = 'NOS Team ';
this._browserVendor = browserVendor;
this._buildTime = buildTime;
this._buildVersion = buildVersion;
- // binds methods to this
- this.developer = this.developer.bind(this);
- this.browserVendor = this.browserVendor.bind(this);
- this.buildTime = this.buildTime.bind(this);
- this.buildVersion = this.buildVersion.bind(this);
+ // Bind methods
+ Object.getOwnPropertyNames(Object.getPrototypeOf(this))
+ .filter((prop) => typeof this[prop] === 'function' && prop !== 'constructor')
+ .forEach((method) => {
+ this[method] = this[method].bind(this);
+ });
}
developer() {
@@ -31,8 +35,9 @@ class RuntimeBuildInfo {
}
}
-class DevelopmentMode {
- constructor(isEnabled) {
+class DevelopmentMode extends ServiceWorkerComponent {
+ constructor(worker, isEnabled) {
+ super(worker);
this._isEnabled = isEnabled;
// bind this methods
diff --git a/src/main/server-connector.js b/src/main/server-connector.js
index 4dd40ece..ab0c3fb0 100644
--- a/src/main/server-connector.js
+++ b/src/main/server-connector.js
@@ -1,12 +1,16 @@
/* eslint-disable comma-dangle */
/* eslint-disable max-classes-per-file */
import Nuxeo from 'nuxeo';
+import ServiceWorkerComponent from './service-worker-component';
-class ServerConnector {
+class ServerConnector extends ServiceWorkerComponent {
constructor(worker) {
- this.worker = worker;
- this.rootUrl = undefined;
+ super(worker);
+
+ // Define properties
+ this.disconnect = () => {};
this.nuxeo = undefined;
+ this.rootUrl = undefined;
// Bind methods
Object.getOwnPropertyNames(Object.getPrototypeOf(this))
@@ -14,66 +18,56 @@ class ServerConnector {
.forEach((method) => {
this[method] = this[method].bind(this);
});
-
- // listeners
- this.onInputChanged = null;
}
onNewServer(rootUrl) {
- return new Promise((resolve, reject) => {
- try {
- if (rootUrl) {
- if (this.isConnected()) {
- this.disconnect();
- }
- this.connect(rootUrl, resolve, reject);
- } else {
- this.disconnect();
- resolve();
- }
- } catch (error) {
- reject(error);
- }
- });
+ if (!rootUrl) {
+ return this.disconnect();
+ }
+ return this.isConnected()
+ .then((connected) => {
+ if (connected) return this.disconnect();
+ return true;
+ })
+ .then(() => this.connect(rootUrl));
}
- connect(rootUrl, resolve, reject) {
+ connect(rootUrl) {
this.rootUrl = rootUrl;
this.nuxeo = new Nuxeo({ baseURL: this.rootUrl });
- this.nuxeo.login()
+ return this.nuxeo
+ .login()
.then(() => {
chrome.omnibox.onInputChanged.addListener(this.onInputChanged = this.suggestDocument);
})
- .then(() => resolve())
- .catch((error) => {
- if (error.response) {
- this.handleErrors(error, this.defaultServerError);
- return null;
+ .then(() => () => {
+ this.disconnect = undefined;
+ this.rootUrl = undefined;
+ this.nuxeo = undefined;
+ chrome.omnibox.onInputChanged.removeListener(this.suggestDocument);
+ })
+ .then((disconnect) => {
+ this.disconnect = disconnect.bind(this);
+ return this.disconnect;
+ })
+ .catch((cause) => {
+ if (cause.response) {
+ this.handleErrors(cause, this.defaultServerError);
+ return () => {};
}
- return reject(error);
+ throw cause;
});
}
- disconnect() {
- chrome.omnibox.onInputChanged.removeListener(this.onInputChanged);
-
- this.nuxeo = null;
- this.rootUrl = null;
- this.onInputChanged = null;
- }
-
isConnected() {
- return this.rootUrl != null;
+ return Promise.resolve(this.rootUrl != null);
}
runtimeInfo() {
- return { rootUrl: this.rootUrl, nuxeo: this.nuxeo };
- // return this.worker.browserStore
- // .get('serverInfo')
- // // eslint-disable-next-line arrow-body-style
- // .then((store) => {
- // return store.serverInfo;
- // });
+ return Promise.resolve({
+ rootUrl: this.rootUrl,
+ nuxeo: this.nuxeo
+ });
}
withNuxeo() {
@@ -193,6 +187,18 @@ class ServerConnector {
});
}
+ listStudioProjects() {
+ return this.withNuxeo().then((nuxeo) => nuxeo
+ .operation('Studio.ListProjects')
+ .execute()
+ .catch((cause) => {
+ if (!cause.response) {
+ throw cause;
+ }
+ return this.handleErrors(cause, this.defaultServerError);
+ }));
+ }
+
restart() {
const notifyRestart = (context) => new Promise((resolve) => {
this.worker.desktopNotifier.notify('reload', {
@@ -201,7 +207,7 @@ class ServerConnector {
iconUrl: '../images/nuxeo-128.png',
requireInteraction: false,
})
- .then(() => this.worker.browserNavigator.reloadServerTab(context, 10000))
+ .then(() => this.worker.tabNavigationHandler.reloadServerTab(context, 10000))
.then(() => this.worker.desktopNotifier.cancel('reload'))
.then(() => resolve());
});
@@ -219,7 +225,7 @@ class ServerConnector {
const rootUrl = this.rootUrl;
const restartUrl = `${this.rootUrl}/site/connectClient/uninstall/restart`;
- return this.worker.browserNavigator.disableTabExtension()
+ return this.worker.tabNavigationHandler.disableTabExtension()
.then((tabInfo) => this
.withNuxeo()
.then((nuxeo) => nuxeo
diff --git a/src/main/service-worker-component.js b/src/main/service-worker-component.js
new file mode 100644
index 00000000..d95fbab3
--- /dev/null
+++ b/src/main/service-worker-component.js
@@ -0,0 +1,42 @@
+class ServiceWorkerComponent {
+ constructor(worker = this) {
+ this.worker = worker;
+ }
+
+ // eslint-disable-next-line no-unused-vars
+ walkComponents(object = this, path = '', recursive = false, action = (componentInput, pathInput) => {}) {
+ Object.getOwnPropertyNames(object)
+ .filter((prop) => prop !== 'worker' && object[prop] instanceof ServiceWorkerComponent)
+ .forEach((prop) => {
+ const component = object[prop];
+ const newPath = path ? `${path}.${prop}` : prop;
+ action(component, newPath);
+ if (recursive) {
+ this.walkComponents(component, newPath, true, action);
+ }
+ });
+ }
+
+ componentsOf(object = this, recursive = false) {
+ const components = [];
+ this.walkComponents(object, '', recursive, (component) => {
+ components.push(component);
+ });
+ return components;
+ }
+
+ componentNamesOf(object = this, recursive = false) {
+ const componentNames = [];
+ this.walkComponents(object, '', recursive, (component, path) => {
+ componentNames.push(path);
+ });
+ return componentNames;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ toJSON() {
+ return {}; // avoid circular dependencies on components
+ }
+}
+
+export default ServiceWorkerComponent;
diff --git a/src/main/service-worker.js b/src/main/service-worker.js
index c3657b22..0b173149 100644
--- a/src/main/service-worker.js
+++ b/src/main/service-worker.js
@@ -1,6 +1,6 @@
/* eslint-disable max-classes-per-file */
/* eslint-disable comma-dangle */
-import BrowserNavigator from './browser-navigator';
+import TabNavigationHandler from './tab-navigation-handler';
import BrowserStore from './browser-store';
import ConnectLocator from './connect-locator';
import DeclararactiveNetCompoments from './declarative-net-engine';
@@ -11,13 +11,14 @@ import JSONHighlighter from './json-highlighter';
import RepositoryIndexer from './repository-indexer';
import RuntimeBuildComponent from './runtime-build-info';
import ServerConnector from './server-connector';
+import ServiceWorkerComponent from './service-worker-component';
import StudioHotReloader from './studio-hot-reloader';
const DeclarativeNetEngine = DeclararactiveNetCompoments.DeclarativeNetEngine;
-class ServiceWorkerMessageHandler {
+class ServiceWorkerMessageHandler extends ServiceWorkerComponent {
constructor(worker) {
- this.worker = worker;
+ super(worker);
// Bind methods
Object.getOwnPropertyNames(Object.getPrototypeOf(this))
@@ -45,11 +46,11 @@ class ServiceWorkerMessageHandler {
function getNestedProperty(obj, path) {
return path.split('.').reduce((prev, curr) => (prev ? prev[curr] : null), obj);
}
- const service = getNestedProperty(worker, request.service);
- if (!service) {
- return Promise.reject(new Error(`Invalid service ${JSON.stringify(request)}`));
+ const component = getNestedProperty(worker, request.component);
+ if (!component) {
+ return Promise.reject(new Error(`Invalid component ${JSON.stringify(request)}`));
}
- if (typeof service[request.action] !== 'function') {
+ if (typeof component[request.action] !== 'function') {
return Promise.reject(new Error(`Invalid action ${JSON.stringify(request)}`));
}
this.worker.developmentMode
@@ -57,7 +58,7 @@ class ServiceWorkerMessageHandler {
.then((console) => console
.log(`ServiceWorkerMessageHandler.handle(${JSON.stringify(request)}) called`));
return Promise
- .resolve(service[request.action](...request.params))
+ .resolve(component[request.action](...request.params))
.then((response) => {
this.worker.developmentMode
.asConsole()
@@ -85,25 +86,34 @@ class ServiceWorkerMessageHandler {
}
}
-class ServiceWorker {
+class ServiceWorkerComponentInventory extends ServiceWorkerComponent {
+ list(recursive = false) {
+ const componentNames = this.componentNamesOf(this.worker, recursive);
+ return Promise.resolve(componentNames);
+ }
+}
+
+class ServiceWorker extends ServiceWorkerComponent {
constructor(developmentMode, buildTime, buildVersion, browserVendor) {
+ super();
// sub-componments takes reference to the worker
// in order to invoke other services. The order is important as
// services may be invoked while constructing.
this.buildInfo = new RuntimeBuildComponent
- .RuntimeBuildInfo(buildTime, buildVersion, browserVendor);
- this.browserNavigator = new BrowserNavigator(this);
+ .RuntimeBuildInfo(this, buildTime, buildVersion, browserVendor);
this.browserStore = new BrowserStore(this);
+ this.componentInventory = new ServiceWorkerComponentInventory(this);
this.connectLocator = new ConnectLocator(this);
this.declarativeNetEngine = new DeclarativeNetEngine(this);
this.designerLivePreview = new DesignerLivePreview(this);
this.desktopNotifier = new DesktopNotifier(this);
- this.developmentMode = new RuntimeBuildComponent.DevelopmentMode(developmentMode);
+ this.developmentMode = new RuntimeBuildComponent.DevelopmentMode(this, developmentMode);
this.documentBrowser = new DocumentBrowser(this);
this.jsonHighlighter = new JSONHighlighter(this);
this.repositoryIndexer = new RepositoryIndexer(this);
this.serverConnector = new ServerConnector(this);
this.studioHotReloader = new StudioHotReloader(this);
+ this.tabNavigationHandler = new TabNavigationHandler(this);
// Bind methods
Object.getOwnPropertyNames(Object.getPrototypeOf(this))
@@ -121,8 +131,8 @@ class ServiceWorker {
return this.asPromise()
.then((worker) => {
// Initialize the cleanup stack
- const cleanupFunctions = [];
- if (typeof cleanupFunctions.push !== 'function') {
+ const deactivateStack = [];
+ if (typeof deactivateStack.push !== 'function') {
throw new Error('cleanupFunctions must have a push method');
}
@@ -134,21 +144,42 @@ class ServiceWorker {
// install the service worker message handler
const messageHandle = new ServiceWorkerMessageHandler(worker).handle;
chrome.runtime.onMessage.addListener(messageHandle);
- cleanupFunctions.push(() => chrome.runtime.onMessage.removeListener(messageHandle));
-
- cleanupFunctions.push(worker.browserNavigator.listenToChromeEvents());
- cleanupFunctions.push(worker.documentBrowser.listenToChromeEvents());
- cleanupFunctions.push(() => worker.designerLivePreview.disable());
+ deactivateStack.push(() => chrome.runtime.onMessage.removeListener(messageHandle));
+
+ // activate all sub-components
+ this.componentsOf(worker)
+ .map((component) => {
+ if (typeof component.activate !== 'function') return () => {};
+ return component
+ .activate(self)
+ .then((cleanup) => worker.developmentMode.asConsole()
+ .then((console) => console
+ .log(`ServiceWorkerComponent.activate(${component.constructor.name}) called`))
+ .then(() => cleanup));
+ })
+ .filter((cleanup) => typeof cleanup === 'function')
+ .forEach((cleanup) => {
+ deactivateStack.push(cleanup);
+ });
// can be used in development mode from the console for now
- worker.deactivate = () => {
- while (cleanupFunctions.length > 0) {
- const cleanupFunction = cleanupFunctions.pop();
- cleanupFunction();
+ self.nuxeoWebExtension = worker;
+
+ return {
+ worker,
+ undo: () => {
+ self['nuxeo-web-extension'] = undefined;
+ while (deactivateStack.length > 0) {
+ const deactivate = deactivateStack.pop();
+ deactivate(self);
+ }
}
};
- return worker;
- });
+ })
+ // eslint-disable-next-line no-return-assign
+ .then(({ worker, undo }) => (
+ worker.deactivate = undo.bind(worker)
+ ));
}
}
diff --git a/src/main/studio-hot-reloader.js b/src/main/studio-hot-reloader.js
index 707a5775..4a970588 100644
--- a/src/main/studio-hot-reloader.js
+++ b/src/main/studio-hot-reloader.js
@@ -16,6 +16,7 @@ limitations under the License.
*/
import NuxeoServerVersion from 'nuxeo/lib/server-version';
+import ServiceWorkerComponent from './service-worker-component';
const checkDependencies = `import groovy.json.JsonOutput;
import org.nuxeo.connect.packages.PackageManager;
@@ -39,9 +40,9 @@ def dependencies = snapshotPkg == null ? null : snapshotPkg.getDependencies();
println JsonOutput.toJson([studio: pkgName, nx: nxInstance, studioDistrib: targetPlatform, match: match, deps: dependencies]);`;
-class StudioHotReloader {
+class StudioHotReloader extends ServiceWorkerComponent {
constructor(worker) {
- this.worker = worker;
+ super(worker);
// Bind methods
Object.getOwnPropertyNames(Object.getPrototypeOf(this))
@@ -184,7 +185,7 @@ class StudioHotReloader {
message: 'A Hot Reload has successfully been completed.',
iconUrl: '../images/nuxeo-128.png',
});
- this.worker.browserNavigator.reloadServerTab();
+ return this.worker.tabNavigationHandler.reloadServerTab();
})
.catch((er) => {
this.handleErrors(er, this.worker.serverConnector.defasultServerError);
diff --git a/src/main/browser-navigator.js b/src/main/tab-navigation-handler.js
similarity index 53%
rename from src/main/browser-navigator.js
rename to src/main/tab-navigation-handler.js
index edb6cc42..3d4e55d1 100644
--- a/src/main/browser-navigator.js
+++ b/src/main/tab-navigation-handler.js
@@ -1,7 +1,11 @@
/* eslint-disable comma-dangle */
-class Navigator {
+import ServiceWorkerComponent from './service-worker-component';
+
+class TabNavigationHandler extends ServiceWorkerComponent {
constructor(worker) {
- this.worker = worker;
+ super(worker);
+
+ // Define properties
this.tabInfo = null;
// Bind methods
@@ -40,88 +44,98 @@ class Navigator {
return Promise.resolve(input)
.then((tabInfo) => {
this.tabInfo = tabInfo;
- chrome.action.enable(tabInfo.id);
return tabInfo;
})
- .then((tabInfo) => {
- this.worker.developmentMode.asConsole()
- .then((console) => console.log(`Enabled TabExtension for ${JSON.stringify(tabInfo)}`));
- return tabInfo;
- });
+ .then((tabInfo) => Promise.resolve(tabInfo.id)
+ .then((tabId) => chrome.action
+ .enable(tabId)
+ .then(() => chrome.action
+ .setBadgeText({ tabId, text: 'C' }))
+ .then(() => chrome.action
+ .setBadgeBackgroundColor({ tabId, color: '#4688F1' }))
+ .then(() => tabInfo)))
+ .then((tabInfo) => this.worker.developmentMode
+ .asConsole()
+ .then((console) => console.log(`Enabled TabExtension for ${JSON.stringify(tabInfo)}`))
+ .then(() => tabInfo));
}
disableTabExtension() {
if (!this.tabInfo) Promise.reject(new Error('No tab info found'));
return Promise.resolve(this.tabInfo)
.then((tabInfo) => {
- chrome.action.disable(this.tabInfo.id);
this.tabInfo = null;
return tabInfo;
})
- .then((tabInfo) => {
- this.worker.developmentMode.asConsole()
- .then((console) => console.log(`Disabled TabExtension for ${JSON.stringify(tabInfo)}`));
- return tabInfo;
- });
+ .then((tabInfo) => Promise.resolve(tabInfo.id)
+ .then((tabId) => chrome.action
+ .disable(tabId)
+ .then(() => chrome.action
+ .setBadgeText({ tabId, text: 'D' }))
+ .then(() => chrome.action
+ .setBadgeBackgroundColor({ tabId, color: '#FF0000' })))
+ .then(() => tabInfo))
+ .then((tabInfo) => this.worker.developmentMode
+ .asConsole()
+ .then((console) => console.log(`Disabled TabExtension for ${JSON.stringify(tabInfo)}`))
+ .then(() => tabInfo));
}
- listenToChromeEvents() {
- const cleanupFunctions = [];
-
+ // eslint-disable-next-line no-unused-vars
+ activate(self) {
// disable extension by default
chrome.action.disable();
- // onInstalled event
- const onInstalledHandle = () => chrome.action.disable();
- chrome.runtime.onInstalled.addListener(onInstalledHandle);
- cleanupFunctions.push(() => chrome.runtime.onInstalled.removeListener(onInstalledHandle));
-
- // tab activation handle
- const tabActivatedHandle = (activeInfo) => chrome
- .tabs.get(activeInfo.tabId, (tabInfo) => this
- .enableExtensionIfNuxeoServerTab(tabInfo));
- chrome.tabs.onActivated.addListener(tabActivatedHandle);
- cleanupFunctions.push(() => chrome.tabs.onActivated.removeListener(tabActivatedHandle));
-
- // tab update handle
- const tabUpdatedHandle = (tabId, changeInfo, tab) => {
- if (changeInfo.status !== 'complete') return;
-
- this.enableExtensionIfNuxeoServerTab(tab);
- };
- chrome.tabs.onUpdated.addListener(tabUpdatedHandle);
- cleanupFunctions.push(() => chrome.tabs.onUpdated.removeListener(tabUpdatedHandle));
-
- // windows focus handle
- const windowFocusHandle = (windowId) => {
- if (windowId === chrome.windows.WINDOW_ID_NONE) return;
- chrome.tabs.query({ active: true, windowId }, (tabs) => {
- if (!tabs || tabs.length === 0) return;
-
- this.enableExtensionIfNuxeoServerTab(tabs[0]);
- });
- };
- chrome.windows.onFocusChanged.addListener(windowFocusHandle);
- cleanupFunctions.push(() => chrome.windows.onFocusChanged.removeListener(windowFocusHandle));
+ return Promise.resolve([])
+ .then((undoStack) => {
+ // tab activation handle
+ const tabActivatedHandle = (activeInfo) => chrome
+ .tabs.get(activeInfo.tabId, (tabInfo) => this
+ .enableExtensionIfNuxeoServerTab(tabInfo));
+ chrome.tabs.onActivated.addListener(tabActivatedHandle);
+ undoStack.push(() => chrome.tabs.onActivated.removeListener(tabActivatedHandle));
+ return undoStack;
+ })
+ .then((undoStack) => {
+ // tab update handle
+ const tabUpdatedHandle = (tabId, changeInfo, tab) => {
+ if (changeInfo.status !== 'complete') return;
- // tab removed handle
- // eslint-disable-next-line no-unused-vars
- const tabRemovedHandle = (tabId, removeInfo) => {
- chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
- if (!tabs || tabs.length === 0) return;
+ this.enableExtensionIfNuxeoServerTab(tab);
+ };
+ chrome.tabs.onUpdated.addListener(tabUpdatedHandle);
+ undoStack.push(() => chrome.tabs.onUpdated.removeListener(tabUpdatedHandle));
+ return undoStack;
+ })
+ .then((undoStack) => {
+ // windows focus handle
+ const windowFocusHandle = (windowId) => {
+ if (windowId === chrome.windows.WINDOW_ID_NONE) return;
+ chrome.tabs.query({ active: true, windowId }, (tabs) => {
+ if (!tabs || tabs.length === 0) return;
- this.enableExtensionIfNuxeoServerTab(tabs[0]);
- });
- };
- chrome.tabs.onRemoved.addListener(tabRemovedHandle);
- cleanupFunctions.push(() => chrome.tabs.onRemoved.removeListener(tabRemovedHandle));
+ this.enableExtensionIfNuxeoServerTab(tabs[0]);
+ });
+ };
+ chrome.windows.onFocusChanged.addListener(windowFocusHandle);
+ undoStack.push(() => chrome.windows.onFocusChanged.removeListener(windowFocusHandle));
+ return undoStack;
+ })
+ .then((undoStack) => {
+ // tab removed handle
+ // eslint-disable-next-line no-unused-vars
+ const tabRemovedHandle = (tabId, removeInfo) => {
+ chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
+ if (!tabs || tabs.length === 0) return;
- return () => {
- while (cleanupFunctions.length > 0) {
- const cleanupFunction = cleanupFunctions.pop();
- cleanupFunction();
- }
- };
+ this.enableExtensionIfNuxeoServerTab(tabs[0]);
+ });
+ };
+ chrome.tabs.onRemoved.addListener(tabRemovedHandle);
+ undoStack.push(() => chrome.tabs.onRemoved.removeListener(tabRemovedHandle));
+ return undoStack;
+ })
+ .then((undoStack) => () => undoStack.forEach((cleanup) => cleanup()));
}
enableExtensionIfNuxeoServerTab(info) {
@@ -130,7 +144,6 @@ class Navigator {
if (rootUrl) return rootUrl;
return chrome.action
.disable(info.tabId)
- .then(() => chrome.action.isEnabled(info.id))
.then(() => undefined);
})
.then((rootUrl) => {
@@ -150,10 +163,10 @@ class Navigator {
.then((rootUrl) => chrome.action.isEnabled(info.id)
.then((isEnabled) => this.worker.developmentMode.asConsole()
.then((console) => console
- .log(`Handled activation of ${JSON.stringify(info)} <- rootUrl=${rootUrl}, extension=${isEnabled ? 'enabled' : 'disabled'}`))))
- .catch((error) => this.worker.developmentMode.asConsole((console) => {
- console.warn(error);
- console.warn(`Caught error (see previous error) <- Navigator.enableExtensionIfNuxeoServerTab(${JSON.stringify(info)})`);
+ .log(`Handled activation of ${JSON.stringify(info)} <- rootUrl=${rootUrl}, extension=${isEnabled ? 'enabled' : 'disabled'}`)))
+ .then(() => rootUrl))
+ .catch((cause) => this.worker.developmentMode.asConsole((console) => {
+ console.warn(`Caught error (see previous error) <- Navigator.enableExtensionIfNuxeoServerTab(${JSON.stringify(info)})`, cause);
}));
}
@@ -172,8 +185,7 @@ class Navigator {
message: 'You are not authenticated. Please log in and try again.',
iconUrl: '../images/access_denied.png',
});
- this.reloadServerTab({ rootUrl, tabInfo }, 0);
- throw new Error(`Not logged in : ${tabInfo.url}...`);
+ return this.reloadServerTab({ rootUrl, tabInfo }, 0);
})
.then((response) => {
if (response.ok) return response;
@@ -201,36 +213,31 @@ class Navigator {
if (!tabInfo) {
throw new Error('No nuxeo server tab info selected');
}
- return new Promise((resolve, reject) => {
- const maxAttempts = 10;
- let attempts = 0;
-
- const checkStatus = () => {
- attempts += 1;
- if (attempts > maxAttempts) {
- reject(new Error('Maximum number of attempts reached'));
- return;
- }
-
- fetch(rootUrl)
- .then((response) => {
- if (response.ok) {
- chrome.tabs.reload(tabInfo.id);
- resolve(tabInfo);
- } else {
- // If the status page is not available, check again after a delay
- setTimeout(checkStatus, waitingTime);
- }
- })
- .catch(() => {
- // If the request failed, check again after a delay
- setTimeout(checkStatus, waitingTime);
- });
- };
-
- // Start checking the status
- checkStatus();
- });
+ return { rootUrl, tabInfo };
+ }).then(({ rootUrl, tabInfo }) => {
+ const runnningstatusUrl = `${rootUrl}/runningstatus`;
+ const maxAttempts = 10;
+ let attempts = 0;
+ const checkStatus = () => {
+ attempts += 1;
+ if (attempts > maxAttempts) {
+ throw new Error(`Maximum number of attempts reached on ${rootUrl}...`);
+ }
+ return fetch(runnningstatusUrl)
+ .then((response) => {
+ if (!response.ok) {
+ // If the status page is not available, check again after a delay
+ return new Promise((resolve) => setTimeout(resolve, waitingTime))
+ .then(checkStatus);
+ }
+ chrome.tabs.reload(tabInfo.id);
+ return tabInfo;
+ })
+ .catch(() => new Promise((resolve) => setTimeout(resolve, waitingTime))
+ .then(checkStatus));
+ };
+ // Start checking the status
+ return checkStatus();
});
}
@@ -260,4 +267,4 @@ class Navigator {
}
}
-export default Navigator;
+export default TabNavigationHandler;
diff --git a/src/popup/index.js b/src/popup/index.js
index 4c161405..8acfecf7 100644
--- a/src/popup/index.js
+++ b/src/popup/index.js
@@ -95,11 +95,9 @@ function loadPage(worker) {
$('#designer-live-preview-button').toggleClass('enabled', isEnabled);
$('#designer-live-preview-button').toggleClass('disabled', !isEnabled);
};
- const toogleDesignerLivePreviewMessage = () => {
+ const toogleDesignerLivePreviewMessage = (cause) => {
$('#designer-livepreview-message').css('display', 'block');
- // setTimeout(() => {
- // $('#designer-livepreview-message').css('display', 'none');
- // }, 5000);
+ $('#designer-livepreview-message a').text(cause.message);
};
$('#no-studio-buttons').css('display', 'none');
$('#studio').css('display', 'flex');
@@ -107,9 +105,9 @@ function loadPage(worker) {
worker.designerLivePreview
.isEnabled(packageName)
.then((isEnabled) => toogleDesignerLivePreviewButton(isEnabled))
- .catch((error) => {
- console.log('Error getting designer live preview status', error);
- toogleDesignerLivePreviewMessage();
+ .catch((cause) => {
+ console.log('Error getting designer live preview status', cause);
+ toogleDesignerLivePreviewMessage(cause);
});
const packageLocation = new URL(
@@ -121,18 +119,20 @@ function loadPage(worker) {
new URL(packageLocation, connectUrl.href).toString()
);
$('#studio').click(() => {
- worker.browserNavigator.loadNewExtensionTab(packageLocation);
+ worker.tabNavigationHandler.loadNewExtensionTab(packageLocation);
});
$('#hot-reload-button').click(() => {
startLoadingHR()
.then(() => worker.studioHotReloader.reload())
.then(stopLoading)
+ .then(() => worker.tabNavigationHandler.reloadServerTab())
.catch(stopLoading);
});
$('#designer-live-preview-button').click(() => {
worker.designerLivePreview
.toggle(packageName)
.then((isEnabled) => toogleDesignerLivePreviewButton(isEnabled))
+ .then(() => worker.tabNavigationHandler.reloadServerTab())
.catch(() => toogleDesignerLivePreviewMessage());
});
$('#force-hot-reload-button').click(() => {
@@ -171,7 +171,7 @@ function loadPage(worker) {
const registerLink = (element, url) => {
$(element).click(() => {
- worker.browserNavigator.loadNewExtensionTab(url);
+ worker.tabNavigationHandler.loadNewExtensionTab(url);
});
};
@@ -329,7 +329,7 @@ function loadPage(worker) {
.then(openJsonWindow);
} else {
const jsonPath = `api/v1/repo/${repository}/${path}?enrichers.document=acls,permissions&properties=*`;
- worker.browserNavigator.loadNewExtensionTab(jsonPath, true);
+ worker.tabNavigationHandler.loadNewExtensionTab(jsonPath, true);
}
});
}
@@ -594,7 +594,7 @@ function loadPage(worker) {
});
$('.doc-title').click((event) => {
const docPath = onUI ? `ui/#!/doc/${event.currentTarget.id}` : `nxdoc/default/${event.currentTarget.id}/view_documents`;
- worker.browserNavigator.loadNewExtensionTab(docPath, true);
+ worker.tabNavigationHandler.loadNewExtensionTab(docPath, true);
});
$('.json-icon').click((event) => {
event.preventDefault();
@@ -626,7 +626,7 @@ function loadPage(worker) {
let openJsonWindow = (jsonObject) => {
const jsonString = JSON.stringify(jsonObject, undefined, 2);
worker.jsonHighlighter.input(DOMPurify.sanitize(jsonString));
- worker.browserNavigator.loadNewExtensionTab('json/index.html');
+ worker.tabNavigationHandler.loadNewExtensionTab('json/index.html');
};
$('#restart-button').on('click', () => {
@@ -817,13 +817,13 @@ function loadPage(worker) {
}
new ServiceWorkerBridge()
- .asPromise()
+ .bootstrap()
.then((worker) => {
worker.developmentMode
.asPromise().then(() => {
- window.nuxeoWebExensions = worker;
- window.nuxeoWebExensions.reloadPopup = () => worker.asPromise().then(loadPage);
- window.worker = worker;
+ // can be used in development mode from the console for now
+ worker.reloadPopup = () => worker.asPromise().then(loadPage);
+ window.nuxeoWebExtension = worker;
})
.catch((error) => console.error(error));
return worker;
diff --git a/src/service-worker-bridge.js b/src/service-worker-bridge.js
index 0596afe5..e0135f9d 100644
--- a/src/service-worker-bridge.js
+++ b/src/service-worker-bridge.js
@@ -1,30 +1,37 @@
/* eslint-disable comma-dangle */
class ServiceWorkerBridge {
- constructor() {
- const services = [
- 'buildInfo',
- 'browserNavigator',
- 'browserStore',
- 'chromeNotifier',
- 'connectLocator',
- 'declarativeNetEngine',
- 'designerLivePreview',
- 'developmentMode',
- 'jsonHighlighter',
- 'repositoryIndexer',
- 'serverConnector',
- 'studioHotReloader',
- 'documentBrowser'
- ];
+ bootstrap() {
+ return new Promise((resolve, reject) => {
+ chrome.runtime.sendMessage(
+ {
+ extension: 'nuxeo-web-extension',
+ component: 'componentInventory',
+ action: 'list',
+ params: [],
+ },
+ (response) => {
+ if (chrome.runtime.lastError) {
+ return reject(chrome.runtime.lastError);
+ }
+ if (response && response.error) {
+ return reject(response.error);
+ }
+ this.createProxies(response);
+ return resolve(this);
+ }
+ );
+ });
+ }
- services.forEach((service) => {
- this[service] = new Proxy({}, {
+ createProxies(components) {
+ components.forEach((component) => {
+ this[component] = new Proxy({}, {
get: (target, action) => (...params) => new Promise((resolve, reject) => {
chrome.runtime.sendMessage(
{
extension: 'nuxeo-web-extension',
- service: `${service}`,
+ component: `${component}`,
action,
params,
},
@@ -46,10 +53,6 @@ class ServiceWorkerBridge {
});
});
}
-
- asPromise() {
- return new Promise((resolve) => resolve(this));
- }
}
export default ServiceWorkerBridge;