diff --git a/react/features/app/components/App.native.js b/react/features/app/components/App.native.js index 198da4b31..5488a86b9 100644 --- a/react/features/app/components/App.native.js +++ b/react/features/app/components/App.native.js @@ -6,6 +6,7 @@ import { Linking } from 'react-native'; import '../../analytics'; import '../../authentication'; +import '../../base/domains'; import { Platform } from '../../base/react'; import { AspectRatioDetector, diff --git a/react/features/base/domains/actionTypes.js b/react/features/base/domains/actionTypes.js new file mode 100644 index 000000000..97f5b9e22 --- /dev/null +++ b/react/features/base/domains/actionTypes.js @@ -0,0 +1,12 @@ +// @flow + +/** + * Action to add new domains to the list of domains known to the feature + * base/domains. + * + * { + * type: ADD_KNOWN_DOMAINS, + * knownDomains: Array + * } + */ +export const ADD_KNOWN_DOMAINS = Symbol('ADD_KNOWN_DOMAINS'); diff --git a/react/features/base/domains/actions.js b/react/features/base/domains/actions.js new file mode 100644 index 000000000..fb8f262fc --- /dev/null +++ b/react/features/base/domains/actions.js @@ -0,0 +1,21 @@ +// @flow + +import { ADD_KNOWN_DOMAINS } from './actionTypes'; + +/** + * Sends an action to add one or an array of known domains if not present yet. + * + * @param {string | Array} knownDomains - The new domain as a string or + * an array of domains. + * @returns {{ + * type: ADD_KNOWN_DOMAINS, + * knownDomains: Array + * }} + */ +export function addKnownDomains(knownDomains: string | Array) { + return { + type: ADD_KNOWN_DOMAINS, + knownDomains: typeof knownDomains === 'string' + ? [ knownDomains ] : knownDomains + }; +} diff --git a/react/features/base/domains/constants.js b/react/features/base/domains/constants.js new file mode 100644 index 000000000..56e7f34e6 --- /dev/null +++ b/react/features/base/domains/constants.js @@ -0,0 +1,15 @@ +// @flow + +/** + * A list of domains we consider jitsi-enabled domains by default. This is in + * line with the app links on iOS and Android, but stands here as retreiving + * those programatically is not straightforward. + */ +export const JITSI_KNOWN_DOMAINS = [ + 'beta.meet.jit.si', + 'beta.hipchat.me', + 'chaos.hipchat.me', + 'enso.me', + 'hipchat.me', + 'meet.jit.si' +]; diff --git a/react/features/base/domains/index.js b/react/features/base/domains/index.js new file mode 100644 index 000000000..f3a2aac65 --- /dev/null +++ b/react/features/base/domains/index.js @@ -0,0 +1,5 @@ +export * from './actions'; +export * from './actionTypes'; + +import './middleware'; +import './reducer'; diff --git a/react/features/base/domains/middleware.js b/react/features/base/domains/middleware.js new file mode 100644 index 000000000..bd807f33b --- /dev/null +++ b/react/features/base/domains/middleware.js @@ -0,0 +1,59 @@ +// @flow + +import { APP_WILL_MOUNT } from '../../app'; +import { SET_ROOM } from '../conference'; +import { MiddlewareRegistry } from '../redux'; +import { parseURIString } from '../util'; + +import { addKnownDomains } from './actions'; +import { JITSI_KNOWN_DOMAINS } from './constants'; + +MiddlewareRegistry.register(store => next => action => { + const result = next(action); + + switch (action.type) { + + case APP_WILL_MOUNT: + _ensureDefaultServer(store); + break; + + case SET_ROOM: + _parseAndAddKnownDomain(store); + break; + } + + return result; +}); + +/** + * Ensures presence of the default server in the known domains list. + * + * @param {Object} store - The redux store. + * @private + * @returns {Promise} + */ +function _ensureDefaultServer({ dispatch, getState }) { + const { app } = getState()['features/app']; + const defaultURL = parseURIString(app._getDefaultURL()); + + dispatch(addKnownDomains([ + defaultURL.host, + ...JITSI_KNOWN_DOMAINS + ])); +} + +/** + * Retrieves the domain name of a room upon join and stores it in the known + * domain list, if not present yet. + * + * @param {Object} store - The redux store. + * @private + * @returns {Promise} + */ +function _parseAndAddKnownDomain({ dispatch, getState }) { + const { locationURL } = getState()['features/base/connection']; + + locationURL + && locationURL.host + && dispatch(addKnownDomains(locationURL.host)); +} diff --git a/react/features/base/domains/reducer.js b/react/features/base/domains/reducer.js new file mode 100644 index 000000000..43ef03379 --- /dev/null +++ b/react/features/base/domains/reducer.js @@ -0,0 +1,49 @@ +// @flow + +import { ReducerRegistry } from '../redux'; +import { PersistenceRegistry } from '../storage'; + +import { ADD_KNOWN_DOMAINS } from './actionTypes'; + +const DEFAULT_STATE = []; + +const STORE_NAME = 'features/base/domains'; + +PersistenceRegistry.register(STORE_NAME); + +ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => { + switch (action.type) { + case ADD_KNOWN_DOMAINS: + return _addKnownDomain(state, action); + + default: + return state; + } +}); + +/** + * Adds an array of new domains to the known domain list if not present yet. + * + * @param {Object} state - The redux state. + * @param {Object} action - The redux action. + * @private + * @returns {Object} + */ +function _addKnownDomain(state, action) { + const { knownDomains: knownDomainsToAdd } = action; + const knownDomains = Array.from(state); + + if (Array.isArray(knownDomainsToAdd)) { + for (let knownDomain of knownDomainsToAdd) { + knownDomain = knownDomain.toLowerCase(); + + if (knownDomains.indexOf(knownDomain) === -1) { + knownDomains.push(knownDomain); + } + } + + return knownDomains; + } + + return state; +}