eu.static.mega.co.nz Open in urlscan Pro
2a0b:e40:3::11  Public Scan

URL: https://eu.static.mega.co.nz/4/js/mega-7_d79bc997b93e25507c5264f05f027738a1d710d5da3931f12e92ebdd7857f5cd.js
Submission: On June 18 via manual from CA — Scanned from NZ

Form analysis 0 forms found in the DOM

Text Content

/* Bundle Includes:
 *   js/ui/passwordReminderDialog.js
 *   js/metatags.js
 *   js/vendor/verge.js
 */

(function(scope) {
    "use strict";

    var DEBUG = localStorage.debugPasswordReminderDialog || false;

    // all values are in seconds.
    var DAY = 86400;
    var SHOW_AFTER_LASTLOGIN = 14 * DAY;
    var SHOW_AFTER_LASTSKIP = 90 * DAY;
    // var SHOW_AFTER_LASTSKIP_LOGOUT = 30 * DAY;
    var SHOW_AFTER_ACCOUNT_AGE = 7 * DAY;
    var SHOW_AFTER_LASTSUCCESS = 90 * DAY;
    var RECHECK_INTERVAL = 15 * 60;

    if (DEBUG) {
        SHOW_AFTER_LASTLOGIN = 15;
        SHOW_AFTER_LASTSKIP = 30;
        // SHOW_AFTER_LASTSKIP_LOGOUT = 5;
        SHOW_AFTER_LASTSUCCESS = 45;
        SHOW_AFTER_ACCOUNT_AGE = DAY;
        RECHECK_INTERVAL = 15;
    }

    /** bindable events **/
    var MouseDownEvent = 'mousedown.prd';

    var PasswordReminderAttribute = function(dialog, changedCb, str) {
        var self = this;
        self.dialog = dialog;
        self._queuedSetPropOps = [];

        if (changedCb) {
            this.changedCb = changedCb;
        }
        PasswordReminderAttribute.PROPERTIES.forEach(function(prop) {
            self["_" + prop] = 0;

            Object.defineProperty(self, prop, {
                get: function() { return self["_" + prop]; },
                set: function(newValue) {
                    if (!self.loading) {
                        self._queuedSetPropOps.push([prop, newValue]);
                    }
                    else if (self.loading && self.loading.state() === 'pending') {
                        self.loading.always(function() {
                            self["_" + prop] = newValue;
                            self.hasChanged(prop);
                        });
                    }
                    else {
                        self["_" + prop] = newValue;
                        self.hasChanged(prop);
                    }
                },
                enumerable: true,
                configurable: true
            });
        });


        if (str) {
            self.mergeFromString(str);
        }
    };

    PasswordReminderAttribute.prototype.mergeFromString = function(str) {
        var self = this;

        var vals = str.split(":");
        var wasMerged = false;
        PasswordReminderAttribute.PROPERTIES.forEach(function(prop, index) {
            var val = typeof vals[index] !== 'undefined' ? parseInt(vals[index]) : 0;

            if (Number.isNaN(val)) {
                val = 0;
            }

            if (self["_" + prop] !== val) {
                self["_" + prop] = val;
                wasMerged = true;
            }
        });
        if (wasMerged) {
            self.hasBeenMerged();
        }
    };

    PasswordReminderAttribute.prototype.hasChanged = function(prop) {
        // Update ui?
        if (this.changedCb) {
            this.changedCb(prop);
        }

        // Save via mega.attr
        this.savingPromise = this.save();

        var self = this;
        self.savingPromise.always(function() {
            delete self.savingPromise;
        });
    };

    PasswordReminderAttribute.prototype.hasBeenMerged = function() {
        // update ui?
        if (this.changedCb) {
            this.changedCb();
        }
    };

    PasswordReminderAttribute.prototype.toString = function() {
        var self = this;
        var vals = [];
        PasswordReminderAttribute.PROPERTIES.forEach(function(prop) {
            vals.push(self["_" + prop]);
        });
        return vals.join(":");
    };

    PasswordReminderAttribute.prototype.save = function() {
        var proxyPromise = new MegaPromise();
        var self = this;

        delay('pra_save', function() {
            proxyPromise.linkDoneAndFailTo(
                mega.attr.set(
                    "prd",
                    self.toString(),
                    -2,
                    true
                )
            );
        }, 500);

        return proxyPromise;
    };

    PasswordReminderAttribute.prototype.loadFromAttribute = function() {
        var self = this;

        if (self.loading) {
            return;
        }

        self.loading = mega.attr.get(u_handle, 'prd', -2, true)
            .done(function (r) {
                if (isString(r)) {
                    self.dialog._initFromString(r);
                }
                else {
                    self.dialog._initFromString("");
                }
            })
            .fail(function (e) {
                if (e === ENOENT) {
                    self.dialog._initFromString("");
                }
            })
            .always(function() {
                if (self._queuedSetPropOps.length > 0) {
                    self._queuedSetPropOps.forEach(function(op) {
                        self[op[0]] = op[1];
                    });
                    self._queuedSetPropOps = [];
                }
                if (self.changedCb) {
                    self.changedCb();
                }
            });
    };

    PasswordReminderAttribute.prototype.attributeUpdatedViaAp = function() {
        if (this.loading) {
            this.loading.reject();
            this.loading = false;
        }

        this.loadFromAttribute();
    };

    /**
     * Those properties are intentionally stored in an array, they are ordered and that order is important for when
     * saving/retrieving data from mega.attr.*.
     * In case a new key is added, please append it at the end of the list.
     * Never remove a key from the array above.
     *
     * @type {Array}
     */
    PasswordReminderAttribute.PROPERTIES = [
        'lastSuccess',
        'lastSkipped',
        'masterKeyExported',
        'dontShowAgain',
        'lastLogin'
    ];



    var PasswordReminderDialog = function() {
        var self = this;
        self.isLogout = false;
        self.passwordReminderAttribute = new PasswordReminderAttribute(self, function(prop) {
            self.recheck(prop !== "lastSuccess" && prop !== "dontShowAgain" ? true : false);
        });
    };

    PasswordReminderDialog.prototype.bindEvents = function() {
        var self = this;

        $(this.dialog.querySelectorAll(is_mobile
            ? '.button-prd-confirm, .button-prd-skip, .change-password-button, .button-prd-backup'
            : 'button.mega-button'
        )).rebind('click.prd', function(e) {
            self.onButtonClicked(this, e);
        });

        $(self.passwordField).rebind('keypress.prd', function(e) {
            if (!self.dialog) {
                console.warn('This event should no longer be reached...');
                return;
            }
            if (e.which === 13 || e.keyCode === 13) {
                $(self.dialog.querySelector('.button-prd-confirm')).triggerHandler('click');
                return false;
            }
        });

        $(self.dialog.querySelectorAll('.fm-dialog-close, button.js-close')).rebind('click.prd', () => {
            self.dismiss();
            return false;
        });

        // Handle forgot password button.
        $(self.dialog.querySelector('.forgot-password')).rebind('click.prd', function() {
            self.onChangePassClicked();
            return false;
        });

        uiCheckboxes(
            $(this.dialog.querySelector(is_mobile ? '.content-cell' : 'aside')),
            undefined,
            function(newState) {
                if (newState === true) {
                    self.passwordReminderAttribute.dontShowAgain = 1;
                }
                else {
                    self.passwordReminderAttribute.dontShowAgain = 0;
                }
            },
            self.passwordReminderAttribute.dontShowAgain === 1
        );

        $('.pass-visible', this.dialog).rebind('click.togglePassV', function() {

            if (this.classList.contains('icon-eye-reveal')) {

                self.passwordField.type = 'text';
                if (self.passwordField.style.webkitTextSecurity) {
                    self.passwordField.style.webkitTextSecurity = 'none';
                }
                this.classList.remove('icon-eye-reveal');
                this.classList.add('icon-eye-hidden');
            }
            else {
                self.passwordField.type = 'password';
                if (self.passwordField.style.webkitTextSecurity) {
                    self.passwordField.style.webkitTextSecurity = 'disc';
                }
                this.classList.add('icon-eye-reveal');
                this.classList.remove('icon-eye-hidden');
            }
        });
    };

    /**
     * Dismiss the dialog, rejecting the action promise and hide from view.
     * @return {false}
     */
    PasswordReminderDialog.prototype.dismiss = function() {
        if (self._dialogActionPromise && self._dialogActionPromise.state() === 'pending') {
            self._dialogActionPromise.reject();
        }
        this.hide();
    };

    PasswordReminderDialog.prototype.onButtonClicked = function(element, evt) {
        if (element.classList.contains('button-prd-confirm')) {
            this.onConfirmClicked(element, evt);
        }
        else if (element.classList.contains('button-prd-skip')) {
            this.onSkipClicked(element, evt);
        }
        else if (element.classList.contains('button-prd-backup')) {
            this.onBackupClicked(element, evt);
        }
        else if (element.classList.contains('change-pass')) {
            this.onChangePassClicked(element, evt);
        }
    };

    PasswordReminderDialog.prototype.onConfirmClicked = function(element, evt) {

        var enteredPassword = this.passwordField.value;
        var self = this;

        this.resetUI();

        // Derive the keys from the password
        security.getDerivedEncryptionKey(enteredPassword)
            .then(function(derivedKey) {
                self.completeOnConfirmClicked(derivedKey);
            })
            .catch(function(ex) {
                console.warn(ex);
                self.completeOnConfirmClicked('');
            });
    };

    PasswordReminderDialog.prototype.completeOnConfirmClicked = function(derivedEncryptionKeyArray32) {

        if (checkMyPassword(derivedEncryptionKeyArray32)) {
            if (this.correctLabel) {
                this.correctLabel.classList.remove('hidden');
            }
            this.passwordReminderAttribute.lastSuccess = unixtime();

            var skipButtonSpan = this.dialog.querySelector('.button-prd-skip span');
            if (skipButtonSpan) {
                skipButtonSpan.innerText = l[967];
                this.succeeded = true;
            }
        }
        else {
            if (this.dialog) {
                this.dialog.classList.add('wrong');
            }
            if (this.wrongLabel) {
                this.wrongLabel.classList.remove('hidden');
            }
            if (this.correctLabel) {
                this.correctLabel.classList.add('hidden');
            }
            if (this.passwordField) {
                this.passwordField.value = "";
                $(this.passwordField).focus();
            }

            if (is_mobile) {
                this.exportButton.classList.remove('green-button');
                this.exportButton.classList.add('red-button');
            }
        }
    };

    PasswordReminderDialog.prototype.onSkipClicked = function(element, evt) {
        if (!this.succeeded) {
            this.passwordReminderAttribute.lastSkipped = unixtime();
        }
        else {
            this.hideIcon();
        }
        if (this.passwordField) {
            this.passwordField.classList.add('hidden');
        }

        this.hide();
        delete $.dialog;

        this.onLogoutDialogUserAction();
    };

    PasswordReminderDialog.prototype.onLogoutDialogUserAction = function() {
        var self = this;

        if (self.passwordReminderAttribute.savingPromise) {
            if (self._dialogActionPromise && self._dialogActionPromise.state() === 'pending') {
                loadingDialog.show();
                self._dialogActionPromise.always(function() {
                    loadingDialog.hide();
                });
            }
            self.passwordReminderAttribute.savingPromise.always(function() {
                if (self._dialogActionPromise && self._dialogActionPromise.state() === 'pending') {
                    self._dialogActionPromise.resolve();
                }
            });
        }
        else {
            if (self._dialogActionPromise && self._dialogActionPromise.state() === 'pending') {
                self._dialogActionPromise.resolve();
            }
        }
    };

    PasswordReminderDialog.prototype.onKeyExported = function() {
        this.passwordReminderAttribute.masterKeyExported = 1;
    };

    PasswordReminderDialog.prototype.onBackupClicked = function(element, evt) {
        this.hide();

        if (this._dialogActionPromise && this._dialogActionPromise.state() === 'pending') {
            this._dialogActionPromise.reject();
        }

        if (this.passwordField) {
            // clear the password field, so that if it was filled in the dialog would hide
            this.passwordField.value = "";
        }

        delete $.dialog;

        loadSubPage('keybackup');
    };

    PasswordReminderDialog.prototype.onChangePassClicked = function(element, evt) {
        this.hide();

        if (this._dialogActionPromise && this._dialogActionPromise.state() === 'pending') {
            this._dialogActionPromise.reject();
        }

        if (this.passwordField) {
            // clear the password field, so that if it was filled in the dialog would hide
            this.passwordField.value = "";
        }

        delete $.dialog;

        loadSubPage(is_mobile ? '/fm/account/email-and-pass' : '/fm/account/security');
    };

    PasswordReminderDialog.prototype.init = function() {
        var self = this;

        if (!self.initialised) {
            self.initialised = true;
        }

        if (!self.passwordReminderAttribute.loading) {
            self.passwordReminderAttribute.loadFromAttribute();
        }
        else {
            self.recheck();
        }
    };

    PasswordReminderDialog.prototype.onTopmenuReinit = function () {
        if (this.topIcon && !document.body.contains(this.topIcon)) {
            // reinit if the this.topIcon is detached from the DOM.
            if (this.isShown) {
                this.hide();
            }
            this.initialised = false;
            this.topIcon = null;
            this.dialog = null;
            this.wrongLabel = null;
            this.correctLabel = null;
        }
        this.prepare();
    };

    /**
     * Prepare the PRD.
     * @returns {void}
     */
    PasswordReminderDialog.prototype.prepare = function() {
        if (this.initialised) {
            this.resetUI();
        }
        else {
            this.init();
        }
    };

    PasswordReminderDialog.prototype._initFromString = function(str) {
        var self = this;

        self.passwordReminderAttribute.mergeFromString(str);

        if (self.recheckInterval) {
            clearInterval(self.recheckInterval);
        }

        if (!self.passwordReminderAttribute.dontShowAgain) {
            self.recheckInterval = setInterval(function () {
                self.recheck();
            }, RECHECK_INTERVAL * 1000);

            self.recheck();
        }
    };

    PasswordReminderDialog.prototype.recheck = function(hideIfShown) {
        var self = this;
        if (!u_handle) {
            // user is in the middle of a logout...
            return;
        }

        // skip any re-checks in case this is the 'cancel' page
        if (window.location.toString().indexOf("/cancel") > -1) {
            return;
        }


        // console.error([
        //     "checks",
        //     self.passwordReminderAttribute.toString(),
        //     !self.passwordReminderAttribute.masterKeyExported,
        //     !self.passwordReminderAttribute.dontShowAgain,
        //     unixtime() - u_attr.since > SHOW_AFTER_ACCOUNT_AGE,
        //     unixtime() - self.passwordReminderAttribute.lastSuccess > SHOW_AFTER_LASTSUCCESS,
        //     unixtime() - self.passwordReminderAttribute.lastLogin > SHOW_AFTER_LASTLOGIN
        // ]);


        // account is older then > SHOW_AFTER_ACCOUNT_AGE and lastLogin > SHOW_AFTER_LASTLOGIN
        if (
            u_type === 3 &&
            !self.passwordReminderAttribute.masterKeyExported &&
            !self.passwordReminderAttribute.dontShowAgain &&
            unixtime() - u_attr.since > SHOW_AFTER_ACCOUNT_AGE &&
            unixtime() - self.passwordReminderAttribute.lastSuccess > SHOW_AFTER_LASTSUCCESS &&
            unixtime() - self.passwordReminderAttribute.lastLogin > SHOW_AFTER_LASTLOGIN
        ) {
            // skip recheck in case:
            // - there is no top-icon, i.e. we are on a custom page
            // - there is a visible .dropdown
            // - the user had a textarea, input or select field focused
            // - there is a visible/active dialog
            var skipShowingDialog = !self.showIcon()
                || $(
                    'textarea:focus, input:focus, select:focus, .dropdown:visible:first, .mega-dialog:visible:first'
                ).length > 0;

            if (
                !skipShowingDialog &&
                is_fm() &&
                !pfid &&
                (
                    !self.passwordReminderAttribute.lastSkipped ||
                    unixtime() - self.passwordReminderAttribute.lastSkipped > SHOW_AFTER_LASTSKIP
                )
            ) {
                self.isLogout = false;
                self.show();
            }
            else {
                if (hideIfShown && (!self.passwordField || self.passwordField.value === "")) {
                    self.hide();
                }
            }
        }
        else {
            // only hide if the passwordField was not just entered with some value.
            if (hideIfShown && (!self.passwordField || self.passwordField.value === "")) {
                self.hideIcon();
                if (self.isShown) {
                    self.hide();
                }
            }
        }
    };

    PasswordReminderDialog.prototype.topIconClicked = function() {
        this[this.isShown ? 'hideDialog' : 'showDialog']();
    };

    PasswordReminderDialog.prototype.showIcon = function() {
        if (!this.topIcon || this.topIcon.classList.contains('hidden') || !document.body.contains(this.topIcon)) {
            // because, we have plenty of top menus, that may not be visible/active
            this.topIcon = $('.js-pass-reminder', '.top-head')[0];
            if (this.topIcon) {
                this.topIcon.classList.remove('hidden');
                $(this.topIcon).rebind('click.prd', this.topIconClicked.bind(this));
            }
        }
        return !!this.topIcon;
    };

    PasswordReminderDialog.prototype._initInternals = function() {
        this.dialog = document.querySelector(is_mobile
            ? '.mobile.password-reminder-overlay'
            : '.mega-dialog.pass-reminder'
        );
        assert(this.dialog, 'this.dialog not found');
        this.passwordField = this.dialog.querySelector('input#test-pass');
        $(this.passwordField).rebind('focus.hack', function() {
            if (this.type === 'password') {
                if (ua.details.browser === "Chrome") {
                    $(this).attr('style', '-webkit-text-security: disc;');
                }
                else {
                    $(this).attr('type', 'password');
                }
            }
            $(this).removeAttr('readonly');
            $(this).attr('autocomplete', 'section-off' + rand_range(1, 123244) + ' off disabled nope no none');
        });
        this.passwordField.classList.remove('hidden');
        this.passwordField.value = "";

        this.wrongLabel = this.dialog.querySelector('.pass-reminder.wrong');
        this.correctLabel = this.dialog.querySelector('.pass-reminder.accepted');

        this.exportButton = this.dialog.querySelector('.button-prd-backup');

        this.firstText = this.dialog.querySelector('.pass-reminder.info-txt');

        if (this.firstText) {

            $(this.firstText).html(
                escapeHTML(!this.isLogout ? l[16900] : l[20633])
                    .replace('[A]', '<a \n' +
                        'href="https://mega.io/security" target="_blank" class="red">')
                    .replace('[/A]', '</a>')
            );
        }
        this.resetUI();

        this.bindEvents();

        if (is_mobile) {
            mobile.initPasswordVisibleToggle($(this.dialog));
        }
    };

    PasswordReminderDialog.prototype.show = function() {
        if (this.isShown) {
            return;
        }
        this.isShown = true;

        this._initInternals();

        assert(this.dialog, 'dialog not defined.');

        if (is_mobile) {
            this.dialog.classList.add('overlay');
        }
        else {
            assert(this.topIcon, 'topIcon not defined.');
            $(document.body).rebind(MouseDownEvent, this.onGenericClick.bind(this));
        }

        this.dialog.classList.remove('hidden');
    };


    PasswordReminderDialog.prototype.resetUI = function() {
        $('.button-prd-skip span', $(this.dialog)).text(l[1379]);
        if (this.dialog) {
            this.dialog.classList.remove('wrong');
        }
        if (this.wrongLabel) {
            this.wrongLabel.classList.add('hidden');
        }
        if (this.correctLabel) {
            this.correctLabel.classList.add('hidden');
        }

        if (this.exportButton) {
            this.exportButton.classList.remove('red-button');
            this.exportButton.classList.add('green-button');
        }

        $('i.pass-visible', this.dialog).removeClass('icon-eye-hidden').addClass('icon-eye-reveal');
        $('#test-pass').attr({'style': '', 'type': 'password', 'readonly': true});
    };

    PasswordReminderDialog.prototype.hide = function() {
        if (this.dialogShown) {
            return this.hideDialog();
        }
        if (!this.isShown) {
            return;
        }

        this.isShown = false;
        assert(this.dialog, 'dialog not defined.');

        this.resetUI();

        this.dialog.classList.add('hidden');

        $(window).off('resize.prd');
        $(document.body).off(MouseDownEvent);
    };

    PasswordReminderDialog.prototype.onGenericClick = function(e) {
        if (this.dialogShown) {
            // in case this is the dialog shown (not the popup), don't hide it when the user clicks on the overlay
            return;
        }

        if (
            $(e.target).parents('.pass-reminder').length === 0 &&
            !$(e.target).is('.pass-reminder')
        ) {
            if (this.isShown) {
                this.onSkipClicked();
            }
        }
    };

    PasswordReminderDialog.prototype.hideIcon = function() {
        if (!this.topIcon) {
            return;
        }

        this.topIcon.classList.add('hidden');
        $(this.topIcon).off('click.prd');
    };

    PasswordReminderDialog.prototype.showDialog = function(promise) {
        if (this.dialogShown) {
            return;
        }

        $.dialog = "prd";
        this.dialogShown = true;

        this._initInternals();

        if (is_mobile) {
            this.dialog.classList.add('overlay');
            if (page === 'fm/account') {
                $('.mobile.my-account-page').addClass('hidden');
            }
        }
        else {
            fm_showoverlay();
        }

        this.dialog.classList.remove('hidden');

        if (promise) {
            this._dialogActionPromise = promise;
        }
    };

    PasswordReminderDialog.prototype.hideDialog = function() {
        this.dialogShown = false;

        fm_hideoverlay();

        this.dialog.classList.add('hidden');
        if (is_mobile) {
            this.dialog.classList.remove('overlay');
            if (page === 'fm/account') {
                $('.mobile.my-account-page').removeClass('hidden');
            }
        }

        this.resetUI();

        $(window).off('resize.prd');
        $(document.body).off(MouseDownEvent);
        $(this.passwordField).off('keypress.prd');
        delete $.dialog;
    };

    PasswordReminderDialog.prototype.recheckLogoutDialog = function() {
        var self = this;
        if (!u_handle) {
            // user is in the middle of a logout...
            return MegaPromise.resolve();
        }

        // skip any re-checks in case this is the 'cancel' page
        if (window.location.toString().indexOf("/cancel") > -1) {
            return MegaPromise.resolve();
        }

        var returnedPromise = new MegaPromise();


        // console.error([
        //     "checks",
        //     self.passwordReminderAttribute.toString(),
        //     !self.passwordReminderAttribute.masterKeyExported,
        //     !self.passwordReminderAttribute.dontShowAgain,
        //     unixtime() - u_attr.since > SHOW_AFTER_ACCOUNT_AGE,
        //     unixtime() - self.passwordReminderAttribute.lastSuccess > SHOW_AFTER_LASTSUCCESS,
        //     unixtime() - self.passwordReminderAttribute.lastLogin > SHOW_AFTER_LASTLOGIN
        // ]);

        // Intentionally copying the logic from .recheck, so that we can alter it for the logout action

        // account is older then > SHOW_AFTER_ACCOUNT_AGE and lastLogin > SHOW_AFTER_LASTLOGIN
        if (
            u_type === 3 &&
            /*!self.passwordReminderAttribute.masterKeyExported &&*/
            !self.passwordReminderAttribute.dontShowAgain/* &&
            unixtime() - u_attr.since > SHOW_AFTER_ACCOUNT_AGE &&
            unixtime() - self.passwordReminderAttribute.lastSuccess > SHOW_AFTER_LASTSUCCESS &&
            unixtime() - self.passwordReminderAttribute.lastLogin > SHOW_AFTER_LASTLOGIN*/
        ) {
            if (
                page !== 'start' && is_fm() &&
                !pfid/* &&
                (
                    !self.passwordReminderAttribute.lastSkipped ||
                    unixtime() - self.passwordReminderAttribute.lastSkipped > SHOW_AFTER_LASTSKIP_LOGOUT
                )*/
            ) {

                self.isLogout = true;
                self.showDialog(returnedPromise);
            }
            else {
                returnedPromise.resolve();
            }
        }
        else {
            returnedPromise.resolve();
        }

        return returnedPromise;
    };

    var passwordReminderDialog = new PasswordReminderDialog();
    scope.mega.ui.passwordReminderDialog = passwordReminderDialog;

    mBroadcaster.once('login', function() {
        // cancel page can trigger a login event, which should NOT trigger PRD attribute update.
        if (window.location.toString().indexOf("/cancel") > -1) {
            return;
        }

        // since u_type is not available yet, assuming that 'login' would only be triggered by a normal user login
        // e.g. u_type === 3
        passwordReminderDialog.passwordReminderAttribute.lastLogin = unixtime();
    });

    mBroadcaster.addListener('keyexported', function() {
        passwordReminderDialog.onKeyExported();
    });

    mBroadcaster.addListener('attr:passwordReminderDialog', function() {
        passwordReminderDialog.passwordReminderAttribute.attributeUpdatedViaAp();
    });

})(window);

mega.metatags = new function() {
    'use strict';

    /**
     * Private function to check if the page is excluded and not missing
     * @param {String} page     Page name
     * @returns {Boolean}       true/false is excluded.
     */
    var isPageExcluded = function(page) {
        // XXX: add new items sorted alphabetically.
        var excludedPages = [
            'keybackup', 'businessinvite', 'businesssignup', 'cancel', 'confirm', 'debug',
            'discount', 'download', 'emailverify', 'key', 'filerequest', 'payment', 'recover',
            'recoverybykey', 'recoverybypark', 'recoveryenterkey',
            'recoverykeychangepass', 'recoveryparkchangepass',
            'redeem', 'repay', 'reset', 'sms', 'special', 'start', 'test', 'thanks', 'twofactor',
            'unsub', 'verify', 'voucher', 'wiretransfer'
        ];

        if (!page) {
            return true;
        }

        for (var i = excludedPages.length; i--;) {
            var ep = excludedPages[i];

            if (page.substr(0, ep.length) === ep) {
                return ep.length === page.length ? -1 : ep.length;
            }
        }

        return false;
    };

    var stopBots = function(metaRobots, noReporting) {
        if (!noReporting && !isPageExcluded(page) && !is_fm() && !is_extension) {
            if (d) {
                console.error('A page without title. Please handle. Page: ' + page);
            }
            api_req({ a: 'log', e: 99735, m: 'page without title: ' + page });
        }

        metaRobots = document.createElement('meta');
        metaRobots.name = 'robots';
        metaRobots.content = 'noindex';
        document.head.appendChild(metaRobots);
    };

    var setMeta = function(attr, val, content) {
        var meta = document.head.querySelector('meta[' + attr + '="' + val + '"]');
        if (!meta) {
            meta = document.createElement('meta');
            meta.setAttribute(attr, val);
            document.head.appendChild(meta);
        }
        meta.content = content;
    };

    var insertOgTwitterMetas = function(title, desc, url, image) {
        setMeta('property', 'og:title', title);
        setMeta('property', 'og:description', desc);
        setMeta('property', 'og:url', url);
        setMeta('property', 'og:image', image);
        // ----- Twitter
        var meta = document.head.querySelector('meta[property="twitter:card"]');
        if (!meta) {
            meta = document.createElement('meta');
            meta.setAttribute('property', 'twitter:card');
            meta.content = 'summary';
            document.head.appendChild(meta);
        }
        setMeta('property', 'twitter:title', title);
        setMeta('property', 'twitter:description', desc);
        setMeta('property', 'twitter:url', url);
        setMeta('property', 'twitter:image', image);
    };

    var addCanonical = function(link) {
        if (lang && lang !== 'en') {
            link += `/lang_${lang}`;
        }
        var canonical = document.createElement('link');
        canonical.setAttribute('rel', 'canonical');
        canonical.setAttribute('href', link);
        document.head.appendChild(canonical);
    };

    var ucFirst = function(s) {
        s = String(s || '');
        return s.charAt(0).toUpperCase() + s.slice(1);
    };

    /* eslint-disable complexity */
    this.addStrucuturedData = function(type, data) {

        if (!type || !data) {
            return;
        }

        var supportedTypes = ['Product', 'SoftwareApplication', 'FAQPage', 'NewsArticle', 'Organization'];
        if (supportedTypes.indexOf(type) === -1) {
            return;
        }

        if (
            !(type === 'Product' && data.offers && data.description && data.name) &&
            !(type === 'SoftwareApplication' && data.offers && data.operatingSystem && data.name) &&
            !(type === 'FAQPage' && data.mainEntity && Object.keys(data.mainEntity).length) &&
            !(type === 'NewsArticle' && data.headline && data.image && data.datePublished && data.dateModified) &&
            !(type === 'Organization' && data.url && data.logo)
        ) {
            return;
        }

        var prepareMetaStruct = function() {
            var structData = document.head.querySelector('script[type="application/ld+json"]');
            if (!structData) {
                structData = document.createElement('script');
                structData.setAttribute('type', 'application/ld+json');
                document.head.appendChild(structData);
            }
            return structData;
        };

        var metaStruct = prepareMetaStruct();
        if (!metaStruct) {
            return;
        }

        var structContent = Object.create(null);
        structContent['@context'] = 'https://schema.org/';
        structContent['@type'] = type;

        if (type === 'Product') {
            structContent['name'] = data.name;
            structContent['image'] = [data.image || 'https://cms2.mega.nz/b41537c0eae056cfe5ab05902fca322b.png'];
            structContent['description'] = data.description;
            structContent['brand'] = { '@type': 'Brand', 'name': 'MEGA' };
            structContent['offers'] = {
                '@type': 'Offer',
                'url': data.offers.url || '',
                'priceCurrency': 'EUR',
                'price': data.offers.price
            };

        }
        else if (type === 'SoftwareApplication') {
            structContent['name'] = data.name;
            structContent['operatingSystem'] = data.operatingSystem;
            if (data.applicationCategory) {
                structContent['applicationCategory'] = data.applicationCategory;
            }
            structContent['offers'] = {
                '@type': 'Offer',
                'priceCurrency': 'EUR',
                'price': data.offers.price
            };
        }
        else if (type === 'FAQPage') {
            var mainE = [];
            for (var entity in data.mainEntity) {
                if (data.mainEntity[entity]) {
                    var temp = {
                        '@type': 'Question',
                        'name': entity,
                        'acceptedAnswer': {
                            '@type': 'Answer',
                            'text': data.mainEntity[entity]
                        }
                    };
                    mainE.push(temp);
                }
            }
            if (mainE.length) {
                structContent['mainEntity'] = mainE;
            }
            else {
                document.head.removeChild(metaStruct);
                return;
            }
        }
        else if (type === 'NewsArticle') {
            structContent['headline'] = data.headline;
            structContent['image'] = [data.image];
            structContent['datePublished'] = data.datePublished;
            structContent['dateModified'] = data.dateModified;
        }
        else if (type === 'Organization') {
            structContent['url'] = data.url;
            structContent['logo'] = data.logo;
        }
        else {
            return;
        }
        metaStruct.textContent = JSON.stringify(structContent, null, 3);
    };

    this.disableBots = function() {
        var metaRobots = document.head.querySelector('meta[name="robots"]');
        if (!metaRobots) {
            metaRobots = document.createElement('meta');
            document.head.appendChild(metaRobots);
        }
        metaRobots.name = 'robots';
        metaRobots.content = 'noindex';
    };

    /**
     * Get Page meta tags.
     * @param {String} page     Page name
     * @returns {Object}        Object contains needed tags
     */
    this.getPageMetaTags = function(page) {
        var mTags = Object.create(null);
        var metaRobots = document.head.querySelector('meta[name="robots"]');
        if (metaRobots) {
            document.head.removeChild(metaRobots);
        }
        var metaCanonical = document.head.querySelector('link[rel="canonical"]');
        if (metaCanonical) {
            document.head.removeChild(metaCanonical);
        }
        var metaStruct = document.head.querySelector('script[type="application/ld+json"]');
        if (metaStruct) {
            document.head.removeChild(metaStruct);
        }

        if (page === 'refer') {
            mTags.en_title = 'MEGA Referral Program - MEGA';
            mTags.en_desc = 'Refer your contacts to MEGA and earn 20 percent commission for each paid plan sign up.';
            mTags.mega_title = l[23963] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_refer || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/07834c8d2b3b05bc352966fe02fe597b.png';
        }
        else if (page === 'mobile' || page === 'android' || page === 'ios') {
            mTags.en_title = 'Cloud Storage at Your Fingertips - MEGA Mobile Apps - MEGA';
            mTags.en_desc = 'Download the MEGA app to securely upload, access and stream your files across your ' +
                'devices, or communicate with our end-to-end encrypted chat.';
            mTags.mega_title = l[23965] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_mobile || mTags.en_desc;
            if (page !== 'mobile') {
                addCanonical(getBaseUrl() + '/mobile');
            }
        }
        else if (page === 'nas') {
            mTags.en_title = 'Network Attached Storage (NAS) - MEGA';
            mTags.en_desc = 'Access your MEGA account directly on your QNAP and Synology Network Attached Storage' +
                ' (NAS) with our MEGA CMD tool.';
            mTags.mega_title = l[23966] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_nas || mTags.en_desc;
        }
        else if (page === 'desktop') {
            mTags.en_title = 'Desktop App - MEGA';
            mTags.en_desc = 'Our MEGA Desktop App allows you to easily automate synchronisation between your ' +
                'computer and your MEGA Cloud Storage. Available for macOS, Windows, and Linux.';
            mTags.mega_title = l[23967] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_sync || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/0723d3ca8f856c90f39480c66b4f2646.png';
        }
        else if (page === 'extensions' || page === 'chrome' || page === 'firefox' || page === 'edge') {
            mTags.en_title = 'Improve Performance and Security - Browser Extensions - MEGA';
            mTags.en_desc = 'Install the MEGA extension for your browser to reduce load times, improve performance' +
                ' and strengthen security.';
            mTags.mega_title = l[23968] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_extensions || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/b9a5ee1bd8935e2eb8659b1b7b87f0ae.png';
            if (page !== 'extensions') {
                addCanonical(getBaseUrl() + '/extensions');
            }
        }
        else if (page === 'bird') {
            mTags.en_title = 'MEGAbird - MEGA';
            mTags.en_desc = 'Send large files by email through MEGA';
            mTags.mega_title = l[23969] || mTags.en_title;
            mTags.mega_desc = l[20931] || mTags.en_desc;
        }
        else if (page === 'cmd') {
            mTags.en_title = 'Unleash MEGA\'s Full Potential with MEGA CMD - MEGA';
            mTags.en_desc = 'System administrators can automate MEGA account access by integrating scripts with ' +
                'the MEGA CMD tool.';
            mTags.mega_title = l[23970] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_cmd || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/75bc1e26149f8962b723a42205434feb.png';
        }
        else if (page === 'pro' || page.substr(0, 6) === 'propay') {
            mTags.en_title = 'Compare Plans and Pricing - MEGA';
            mTags.en_desc = 'Compare MEGA\'s pricing plans. Get 16% off if you purchase an annual plan. ' +
                'Start using MEGA\'s secure cloud storage and fast transfers today.';
            mTags.mega_title = l[23971] || mTags.en_title;
            mTags.mega_desc = l[23972] || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/559d084a50ad7283acb6f1c433136952.png';
        }
        else if (page === 'register') {
            mTags.en_title = 'Create Your Account - MEGA';
            mTags.en_desc = 'Get started with MEGA, the world\'s largest fully-featured free cloud storage and ' +
                'communications provider with secure, user-controlled end-to-end encryption.';
            mTags.mega_title = l[23973] || mTags.en_title;
            mTags.mega_desc = l[23974] || mTags.en_desc;
        }
        else if (page === 'login') {
            mTags.en_title = 'Login - MEGA';
            mTags.en_desc = 'Log in to your MEGA account. Access the world\'s most trusted, protected cloud storage.';
            mTags.mega_title = l[23975] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_login || mTags.en_desc;
        }
        else if (page === 'recovery') {
            mTags.en_title = 'Recovery - MEGA';
            mTags.en_desc = 'Forgot your MEGA password? Start your recovery process here.';
            mTags.mega_title = l[23976] || mTags.en_title;
            mTags.mega_desc = l[23977] || mTags.en_desc;
        }
        else if (page === 'terms') {
            mTags.en_title = 'Terms of Service - MEGA';
            mTags.en_desc = 'Please read our Terms of Service that cover how you may access our services, website ' +
                'domains, and client software.';
            mTags.mega_title = l[23978] || mTags.en_title;
            mTags.mega_desc = l[23979] || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/4548c0ab90a611b8b7c5a940811e23b5975b4ba8.png';
        }
        else if (page === 'dispute') {
            mTags.en_title = 'For Copyright Claims and Disputes - MEGA';
            mTags.en_desc = 'If you believe that access to a file you have uploaded has been wrongly disabled, ' +
                'please file a counter-notice.';
            mTags.mega_title = l[24967] || mTags.en_title;
            mTags.mega_desc = l[24968] || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/4548c0ab90a611b8b7c5a940811e23b5975b4ba8.png';
        }
        else if (page === 'privacy' || page === 'gdpr') {
            mTags.en_title = 'Privacy and Data Policy - GDPR - MEGA';
            mTags.en_desc = 'MEGA takes privacy very seriously. We are committed to ensuring continued compliance ' +
                'with data protection regulations including GDPR.';
            mTags.mega_title = l[23980] || mTags.en_title;
            mTags.mega_desc = l[23981] || mTags.en_desc;
            if (page !== 'privacy') {
                addCanonical(getBaseUrl() + '/privacy');
            }
        }
        else if (page === 'copyright') {
            mTags.en_title = 'Copyright - MEGA';
            mTags.en_desc = 'We respect copyright and require that users of our services comply with applicable' +
                ' intellectual property laws. Learn more or submit a notice here.';
            mTags.mega_title = l[23983] || mTags.en_title;
            mTags.mega_desc = l[23984] || mTags.en_desc;
        }
        else if (page === 'copyrightnotice') {
            mTags.en_title = 'Copyright Notice - MEGA';
            mTags.en_desc = 'Copyright. Notice of Alleged Infringement "Notice" submit';
            mTags.mega_title = l[23985] || mTags.en_title;
            mTags.mega_desc = l[23986] || mTags.en_desc;
        }
        else if (page === 'disputenotice') {
            mTags.en_title = 'Copyright Counter-Notification - MEGA';
            mTags.en_desc = 'Copyright Counter-Notification';
            mTags.mega_title = l[23987] || mTags.en_title;
            mTags.mega_desc = l[8789] || mTags.en_desc;
        }
        else if (page === 'takedown') {
            mTags.en_title = 'Takedown Guidance Policy - MEGA';
            mTags.en_desc = 'MEGA Takedown Policy. Guidance on requesting user information or "takedown" of' +
                ' user data.';
            mTags.mega_title = l[23988] || mTags.en_title;
            mTags.mega_desc = l[23989] || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/c449150b27444c9cc8eb3cad8ab02319744dd61d.png';
        }
        else if (page === 'cookie') {
            mTags.en_title = 'Cookie Policy - MEGA';
            mTags.en_desc = 'We value your privacy. Learn about the necessary data MEGA collects through cookies ' +
                'and similar technologies.';
            mTags.mega_title = l[24639] || mTags.en_title;
            mTags.mega_desc = l[24640] || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/e5cebb274552eb5e5408db5e834d5ff3ec8c66ef.png'
        }
        else if (page === 'contact') {
            mTags.en_title = 'Contact Us - MEGA';
            mTags.en_desc = 'Need help with your account or want to report an issue? Contact our support staff.';
            mTags.mega_title = l[23990] || mTags.en_title;
            mTags.mega_desc = l[23991] || mTags.en_desc;
        }
        else if (page === 'resellers') {
            mTags.en_title = 'Resellers - MEGA';
            mTags.en_desc = 'Conveniently purchase a MEGA Pro membership from one of our authorised resellers: ' +
                'CloudBasedBackup, 6Media, Pay.mobi or VoucherReseller';
            mTags.mega_title = l[23992] || mTags.en_title;
            mTags.mega_desc = l[23993] || mTags.en_desc;
            stopBots(metaRobots);
        }
        else if (page === 'securechat') {
            mTags.en_title = 'Private and Secure Communication - MEGA';
            mTags.en_desc = 'Exchange messages, share your files and have audio and/or video calls with MEGA\'s ' +
                'end-to-end encrypted chat.';
            mTags.mega_title = l[24608] || mTags.en_title;
            mTags.mega_desc = l[24611] || mTags.en_desc;
        }
        else if (page === 'storage') {
            mTags.en_title = 'Secure Cloud Storage and Fast Transfers - MEGA';
            mTags.en_desc = 'Work remotely and never run out of storage. With MEGA, you\'ll have access to one of ' +
                'the most generous and secure cloud storage services currently available.';
            mTags.mega_title = l[24606] || mTags.en_title;
            mTags.mega_desc = l[24609] || mTags.en_desc;
        }
        else if (page === 'megabackup') {
            mTags.en_title = 'Back Up Your Files - MEGA';
            mTags.en_desc = 'Get peace of mind when you back up data, such as important documents and files, ' +
                'from your computer to MEGA.';
            mTags.mega_title = l.ft_backup_metatag_title || mTags.en_title;
            mTags.mega_desc = l.ft_backup_metatag_desc || mTags.en_desc;
        }
        else if (page === 'collaboration') {
            mTags.en_title = 'Work From Anywhere and Stay Connected - MEGA';
            mTags.en_desc = 'Securely store files, stay in contact and collaborate in one easy place with MEGA.';
            mTags.mega_title = l[24607] || mTags.en_title;
            mTags.mega_desc = l[24610] || mTags.en_desc;
        }
        else if (page === 'security') {
            mTags.en_title = 'Security and Why It Matters - MEGA';
            mTags.en_desc = 'Your files and chats are end-to-end encrypted with keys controlled by you and ' +
                'nobody else.';
            mTags.mega_title = l[23994] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_security || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/c964ddb7dd27f1acd727747862787486.png';
        }
        else if (page === 'objectstorage') {
            mTags.en_title = 'S4 Object Storage Beta Registration - MEGA';
            mTags.en_desc = 'MEGA\'s S4 beta program starts soon, for a limited number of participants. ' +
                'Sign up to become a beta tester and get &#8364 1,000 worth of storage for free.';
            mTags.mega_title = l.ri_s4_metatag_title || mTags.en_title;
            mTags.mega_desc = l.ri_s4_metatag_desc || mTags.en_desc;
        }
        else if (page === 'security/bug-bounty') {
            mTags.en_title = 'We Welcome Security And Bug Reports - MEGA';
            mTags.en_desc = 'Earn Bounties For Finding Bugs And Other Issues At MEGA';
            mTags.mega_title = l.mtags_title_security_bugbounty || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_security_bugbounty || mTags.en_desc;
        }
        else if (page === 'dev' || page === 'developers') {
            mTags.en_title = 'Documentation for Developers - MEGA';
            mTags.en_desc = 'Check out the MEGA C++ client access engine with full documentation including ' +
                'integration guides, data structures and more.';
            mTags.mega_title = l[23996] || mTags.en_title;
            mTags.mega_desc = l[23997] || mTags.en_desc;
            if (page === 'dev') {
                addCanonical(getBaseUrl() + '/developers');
            }
        }
        else if (page === 'doc') {
            mTags.en_title = 'Software Developer Documentation - MEGA';
            mTags.en_desc = 'MEGA provides an API accessible with our software development kit (SDK), with a ' +
                'full library of developer documentation.';
            mTags.mega_title = l[23998] || mTags.en_title;
            mTags.mega_desc = l[23999] || mTags.en_desc;
        }
        else if (page === 'sdk') {
            mTags.en_title = 'SDK - MEGA';
            mTags.en_desc =
                'MEGA SDK for C++, providing essential abstraction to your application\'s secure cloud storage access.';
            mTags.mega_title = l[24000] || mTags.en_title;
            mTags.mega_desc = l[24001] || mTags.en_desc;
        }
        else if (page === 'sdkterms') {
            mTags.en_title = 'SDK Terms and Conditions - Developers - MEGA';
            mTags.en_desc = 'Check MEGA\'s Terms of Service and Privacy Policy for our API and SDK.';
            mTags.mega_title = l[24002] || mTags.en_title;
            mTags.mega_desc = l[24003] || mTags.en_desc;
        }
        else if (page === 'about/main' || page === 'about') {
            mTags.en_title = 'About Us - Encrypted Cloud Storage - MEGA';
            mTags.en_desc = 'MEGA launched in 2013 as the world\'s first zero-knowledge, easy to use cloud ' +
                'storage provider with user-controlled end-to-end encryption.';
            mTags.mega_title = l[24004] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_about || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/0fcca13fc3baaf74cd6bdc51850c19c3.png';
            if (page === 'about/main') {
                addCanonical(getBaseUrl() + '/about');
            }
            this.addStrucuturedData('Organization', {
                url: getBaseUrl(),
                logo: 'https://cms2.mega.nz/b41537c0eae056cfe5ab05902fca322b.png',
            });
        }
        else if (page === 'about/jobs') {
            mTags.en_title = 'Career Opportunities - MEGA';
            mTags.en_desc = 'Join the world\'s largest fully-featured cloud storage and privacy company. Check out' +
                ' our latest job listings and apply today.';
            mTags.mega_title = l[24005] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_about_jobs || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/659cd40a308f29a025c2d3b42944a0c9.png';
        }
        else if (page === 'about/privacy') {
            mTags.en_title = 'About MEGA and Our End-to-End Encrypted Cloud Storage - MEGA';
            mTags.en_desc = 'MEGA is the world\'s leading fully-featured end-to-end encrypted cloud storage provider.' +
                ' We strive to offer the highest levels of privacy possible.';
            mTags.mega_title = l[24006] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_about_priv || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/753f59a51ed56feda0644a1be74c1671.png';
        }
        else if (page === 'about/reliability') {
            mTags.en_title = 'How Reliable is MEGA\'s End-to-End Encrypted Storage? - MEGA';
            mTags.en_desc = 'MEGA\'s CloudRAID technology means files are split into equal-sized parts and stored' +
                ' in different countries for additional service robustness.';
            mTags.mega_title = l[24007] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_about_rel || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/f1d60e5822b4d755de9be2d0441b9a3b.png';
        }
        else if (page === 'sourcecode') {
            mTags.en_title = 'Transparency and Public Source Code - MEGA';
            mTags.en_desc = 'We publish the full source code for our client apps and welcome independent ' +
                'verification and integrity checks.';
            mTags.mega_title = l[24008] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_srccode || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/147ddec6fa35a6084030513d1ccd2eed.png';
        }
        else if (page === 'credits') {
            mTags.en_title = 'What Powers MEGA? - Credits - MEGA';
            mTags.en_desc = 'MEGA would like to thank the authors of the following open source components that ' +
                'have contributed to the functionality of our site.';
            mTags.mega_title = l[24009] || mTags.en_title;
            mTags.mega_desc = l[24010] || mTags.en_desc;
        }
        else if (page === 'business') {
            mTags.en_title = 'The Secure Cloud Storage Solution for Your Business - MEGA';
            mTags.en_desc = 'Massive storage, secure sharing across devices and 24/7 support make MEGA Business ' +
                'the obvious choice for your team.';
            mTags.mega_title = l[24011] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_business || mTags.en_desc;
            mTags.image = 'https://cms2.mega.nz/730b119f030d91dacb5dc349726e6c17.png';
        }
        else if (page === 'registerb') {
            mTags.en_title = 'Business Account - MEGA';
            mTags.en_desc = 'With our user-controlled end-to-end encryption, your data and communications have never ' +
                'been safer. MEGA is the secure solution for your business.';
            mTags.mega_title = l[24012] || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_registerb || mTags.en_desc;
        }
        else if (page === 'corporate' || page === 'corporate/media') {
            mTags.en_title = 'Media Assets - MEGA';
            mTags.en_desc = 'Are you a journalist or technology reviewer? Download our MEGA media resources or ' +
                'contact us for enquiries.';
            mTags.mega_title = l[24015] || mTags.en_title;
            mTags.mega_desc = l[24089] || mTags.en_desc;
            if (page === 'corporate') {
                addCanonical(getBaseUrl() + '/corporate/media');
            }
        }
        else if (page === 'corporate/reviews') {
            mTags.en_title = 'Reviews - MEGA';
            mTags.en_desc = 'MEGA is the largest secure, fully-featured cloud storage provider in the world. ' +
                'Check out some of our top reviews and product comparisons.';
            mTags.mega_title = l[24086] || mTags.en_title;
            mTags.mega_desc = l[24087] || mTags.en_desc;
        }
        else if (typeof Object(window.dlmanager).isStreaming === 'object') {
            mTags.mega_title = dlmanager.isStreaming._megaNode.name + ' - MEGA';
            mTags.dynamic = true;
        }
        else if (page === 'recoveryparkchangepass') {
            mTags.mega_title = 'Park Change Password - MEGA';
            stopBots(metaRobots);
        }
        else if (page === 'recoverykeychangepass') {
            mTags.mega_title = 'Key Change Password - MEGA';
            stopBots(metaRobots);
        }
        else if (page === 'recoveryenterkey') {
            mTags.mega_title = 'Recovery Key - MEGA';
            stopBots(metaRobots);
        }
        else if (page === 'recoverybypark') {
            mTags.mega_title = 'Park Recovery - MEGA';
            stopBots(metaRobots);
        }
        else if (page === 'recoverybykey') {
            mTags.mega_title = 'Recover by Key - MEGA';
            stopBots(metaRobots);
        }
        else if (page === 'wiretransfer') {
            mTags.mega_title = 'Wire Transfer - MEGA';
            stopBots(metaRobots);
        }
        else if (page === 'twofactor') {
            mTags.mega_title = 'Two Factor - MEGA';
            stopBots(metaRobots);
        }
        else if (page.substr(0, 11) === 'emailverify') {
            mTags.mega_title = 'Email Verify - MEGA';
            mTags.mega_desc = 'Email verification';
            stopBots(metaRobots, true);
        }
        else if (page === 'businessinvite') {
            mTags.mega_title = 'Business Invite - MEGA';
            stopBots(metaRobots);
        }
        else if (page === 'businesssignup') {
            mTags.mega_title = 'Business Signup - MEGA';
            stopBots(metaRobots);
        }
        else if (page === 'achievements') {
            mTags.en_title = 'Achievements - MEGA';
            mTags.en_desc = 'Free additional cloud storage - 5 GB per achievement, valid for 365 days.';
            mTags.mega_title = l.achievement_meta_title || mTags.en_title;
            mTags.mega_desc = l.achievement_meta_desc || mTags.en_desc;
        }
        else if (page === 'support') {
            mTags.en_title = 'Support - MEGA';
            mTags.en_desc = 'Get support';
            mTags.mega_title = l.support_meta_tag || mTags.en_title;
            mTags.mega_desc = l[516] || mTags.en_desc;
        }
        else if (page === 'start') {
            mTags.en_title = 'The Most Trusted, Best-Protected Cloud Storage - MEGA';
            mTags.en_desc = 'MEGA understands the importance of keeping data and conversations private. We provide ' +
                'a fantastic user experience that protects users\' right to privacy.';
            mTags.mega_title = l.mtags_title_start || mTags.en_title;
            mTags.mega_desc = l.mtags_desc_start || mTags.en_desc;
            if (getCleanSitePath().substr(0, 5) === 'start') {
                addCanonical(getBaseUrl());
            }
        }
        else if (page.startsWith('special')) {
            mTags.mega_title = 'Special - MEGA';
            mTags.mega_desc = 'MEGA\'s Special Page';

            if (page.endsWith('/pro')) {
                mTags.mega_title = 'Special - PRO - MEGA';
            }
            else if (page.endsWith('/business')) {
                mTags.mega_title = 'Special - Business - MEGA';
            }

            stopBots(metaRobots);
        }
        else if (page && (mTags.excluded = isPageExcluded(page))) {
            mTags.mega_title = page.charAt(0).toUpperCase() + page.slice(1) + ' - MEGA';
            stopBots(metaRobots);
        }
        else {
            mTags.mega_title = 'MEGA';
            stopBots(metaRobots);
        }
        if (!mTags.mega_desc) {
            mTags.mega_desc = l[24023] || mega.whoami;
            if (!isPageExcluded(page) && !is_fm() && !is_extension) {
                if (d) {
                    console.error('A page without Description. Please handle. Page: ' + page);
                }
                api_req({ a: 'log', e: 99736, m: 'page without desc: ' + page });
            }
        }

        mTags.image = mTags.image || 'https://cms2.mega.nz/b41537c0eae056cfe5ab05902fca322b.png';
        insertOgTwitterMetas(
            mTags.mega_title,
            mTags.mega_desc,
            getBaseUrl() + (page && page !== 'start' ? '/' + page : ''),
            mTags.image
        );

        mTags.page = page;
        this.lastSetMetaTags = mTags;

        return mTags;
    };
    /* eslint-enable complexity */

    this.checkPageMatchesURL = function() {
        if (page !== (getCleanSitePath() || 'start')) {
            var metaRobots = document.head.querySelector('meta[name="robots"]');
            if (!metaRobots) {
                stopBots(metaRobots);
            }
        }
    };
};

/*!
 * verge 1.9.1+201402130803
 * https://github.com/ryanve/verge
 * MIT License 2013 Ryan Van Etten
 */

(function(root, name, make) {
  if (typeof module != 'undefined' && module['exports']) module['exports'] = make();
  else root[name] = make();
}(this, 'verge', function() {

  var xports = {}
    , win = typeof window != 'undefined' && window
    , doc = typeof document != 'undefined' && document
    , docElem = doc && doc.documentElement
    , matchMedia = win['matchMedia'] || win['msMatchMedia']
    , mq = matchMedia ? function(q) {
        return !!matchMedia.call(win, q).matches;
      } : function() {
        return false;
      }
    , viewportW = xports['viewportW'] = function() {
        var a = docElem['clientWidth'], b = win['innerWidth'];
        return a < b ? b : a;
      }
    , viewportH = xports['viewportH'] = function() {
        var a = docElem['clientHeight'], b = win['innerHeight'];
        return a < b ? b : a;
      };
  
  /** 
   * Test if a media query is active. Like Modernizr.mq
   * @since 1.6.0
   * @return {boolean}
   */  
  xports['mq'] = mq;

  /** 
   * Normalized matchMedia
   * @since 1.6.0
   * @return {MediaQueryList|Object}
   */ 
  xports['matchMedia'] = matchMedia ? function() {
    // matchMedia must be binded to window
    return matchMedia.apply(win, arguments);
  } : function() {
    // Gracefully degrade to plain object
    return {};
  };

  /**
   * @since 1.8.0
   * @return {{width:number, height:number}}
   */
  function viewport() {
    return {'width':viewportW(), 'height':viewportH()};
  }
  xports['viewport'] = viewport;
  
  /** 
   * Cross-browser window.scrollX
   * @since 1.0.0
   * @return {number}
   */
  xports['scrollX'] = function() {
    return win.pageXOffset || docElem.scrollLeft; 
  };

  /** 
   * Cross-browser window.scrollY
   * @since 1.0.0
   * @return {number}
   */
  xports['scrollY'] = function() {
    return win.pageYOffset || docElem.scrollTop; 
  };

  /**
   * @param {{top:number, right:number, bottom:number, left:number}} coords
   * @param {number=} cushion adjustment
   * @return {Object}
   */
  function calibrate(coords, cushion) {
    var o = {};
    cushion = +cushion || 0;
    o['width'] = (o['right'] = coords['right'] + cushion) - (o['left'] = coords['left'] - cushion);
    o['height'] = (o['bottom'] = coords['bottom'] + cushion) - (o['top'] = coords['top'] - cushion);
    return o;
  }

  /**
   * Cross-browser element.getBoundingClientRect plus optional cushion.
   * Coords are relative to the top-left corner of the viewport.
   * @since 1.0.0
   * @param {Element|Object} el element or stack (uses first item)
   * @param {number=} cushion +/- pixel adjustment amount
   * @return {Object|boolean}
   */
  function rectangle(el, cushion) {
    el = el && !el.nodeType ? el[0] : el;
    if (!el || 1 !== el.nodeType) return false;
    return calibrate(el.getBoundingClientRect(), cushion);
  }
  xports['rectangle'] = rectangle;

  /**
   * Get the viewport aspect ratio (or the aspect ratio of an object or element)
   * @since 1.7.0
   * @param {(Element|Object)=} o optional object with width/height props or methods
   * @return {number}
   * @link http://w3.org/TR/css3-mediaqueries/#orientation
   */
  function aspect(o) {
    o = null == o ? viewport() : 1 === o.nodeType ? rectangle(o) : o;
    var h = o['height'], w = o['width'];
    h = typeof h == 'function' ? h.call(o) : h;
    w = typeof w == 'function' ? w.call(o) : w;
    return w/h;
  }
  xports['aspect'] = aspect;

  /**
   * Test if an element is in the same x-axis section as the viewport.
   * @since 1.0.0
   * @param {Element|Object} el
   * @param {number=} cushion
   * @return {boolean}
   */
  xports['inX'] = function(el, cushion) {
    var r = rectangle(el, cushion);
    return !!r && r.right >= 0 && r.left <= viewportW();
  };

  /**
   * Test if an element is in the same y-axis section as the viewport.
   * @since 1.0.0
   * @param {Element|Object} el
   * @param {number=} cushion
   * @return {boolean}
   */
  xports['inY'] = function(el, cushion) {
    var r = rectangle(el, cushion);
    return !!r && r.bottom >= 0 && r.top <= viewportH();
  };

  /**
   * Test if an element is in the viewport.
   * @since 1.0.0
   * @param {Element|Object} el
   * @param {number=} cushion
   * @return {boolean}
   */
  xports['inViewport'] = function(el, cushion) {
    // Equiv to `inX(el, cushion) && inY(el, cushion)` but just manually do both 
    // to avoid calling rectangle() twice. It gzips just as small like this.
    var r = rectangle(el, cushion);
    return !!r && r.bottom >= 0 && r.right >= 0 && r.top <= viewportH() && r.left <= viewportW();
  };

  return xports;
}));