WWW-Mechanize-PhantomJS

 view release on metacpan or  search on metacpan

lib/WWW/Mechanize/PhantomJS/ghostdriver/session.js  view on Meta::CPAN

        "platform" : ghostdriver.system.os.name + '-' + ghostdriver.system.os.version + '-' + ghostdriver.system.os.architecture,
        "javascriptEnabled" : true,
        "takesScreenshot" : true,
        "handlesAlerts" : false,            //< TODO
        "databaseEnabled" : false,          //< TODO
        "locationContextEnabled" : false,   //< TODO Target is 1.1
        "applicationCacheEnabled" : false,  //< TODO Support for AppCache (?)
        "browserConnectionEnabled" : false, //< TODO
        "cssSelectorsEnabled" : true,
        "webStorageEnabled" : false,        //< TODO support for LocalStorage/SessionStorage
        "rotatable" : false,                //< TODO Target is 1.1
        "acceptSslCerts" : false,           //< TODO
        "nativeEvents" : true,              //< TODO Only some commands are Native Events currently
        "unhandledPromptBehavior" : null,
        "proxy" : {                         //< TODO Support more proxy options - PhantomJS does allow setting from command line
            "proxyType" : _const.PROXY_TYPES.DIRECT
        },
        "webSecurityEnabled" : true
    },
    _negotiatedCapabilities = {
        "browserName"               : _defaultCapabilities.browserName,
        "version"                   : _defaultCapabilities.version,
        "driverName"                : _defaultCapabilities.driverName,
        "driverVersion"             : _defaultCapabilities.driverVersion,
        "platform"                  : _defaultCapabilities.platform,
        "javascriptEnabled"         : _defaultCapabilities.javascriptEnabled,
        "takesScreenshot"           : typeof(desiredCapabilities.takesScreenshot) === "undefined" ?
            _defaultCapabilities.takesScreenshot :
            desiredCapabilities.takesScreenshot,
        "handlesAlerts"             : _defaultCapabilities.handlesAlerts,
        "databaseEnabled"           : _defaultCapabilities.databaseEnabled,
        "locationContextEnabled"    : _defaultCapabilities.locationContextEnabled,
        "applicationCacheEnabled"   : _defaultCapabilities.applicationCacheEnabled,
        "browserConnectionEnabled"  : _defaultCapabilities.browserConnectionEnabled,
        "cssSelectorsEnabled"       : _defaultCapabilities.cssSelectorsEnabled,
        "webStorageEnabled"         : _defaultCapabilities.webStorageEnabled,
        "rotatable"                 : _defaultCapabilities.rotatable,
        "acceptSslCerts"            : _defaultCapabilities.acceptSslCerts,
        "nativeEvents"              : _defaultCapabilities.nativeEvents,
        "unhandledPromptBehavior"   : typeof(desiredCapabilities.unhandledPromptBehavior) === "undefined" ?
            _defaultCapabilities.unhandledPromptBehavior :
            desiredCapabilities.unhandledPromptBehavior,
        "proxy"                     : typeof(desiredCapabilities.proxy) === "undefined" ?
            _defaultCapabilities.proxy :
            desiredCapabilities.proxy,
        "webSecurityEnabled"        : typeof(desiredCapabilities.webSecurityEnabled) === "undefined" ?
            _defaultCapabilities.webSecurityEnabled :
            desiredCapabilities.webSecurityEnabled
    },
    // NOTE: This value is needed for Timeouts Upper-bound limit.
    // "setTimeout/setInterval" accept only 32 bit integers, even though Number are all Doubles (go figure!)
    // Interesting details here: {@link http://stackoverflow.com/a/4995054}.
    _max32bitInt = Math.pow(2, 31) -1,      //< Max 32bit Int
    _timeouts = {
        "script"            : 30000,
        "implicit"          : 0,
        "page load"         : 300000,
    },
    _windows = {},  //< NOTE: windows are "webpage" in Phantom-dialect
    _currentWindowHandle = null,
    _cookieJar = require('cookiejar').create(),
    _id = require("./third_party/uuid.js").v1(),
    _inputs = ghostdriver.Inputs(),
    _capsPageSettingsPref = "phantomjs.page.settings.",
    _capsPageCustomHeadersPref = "phantomjs.page.customHeaders.",
    _capsPageZoomFactor = "phantomjs.page.zoomFactor",
    _capsPageBlacklistPref = "phantomjs.page.blacklist",
    _capsPageWhitelistPref = "phantomjs.page.whitelist",
    _capsUnhandledPromptBehavior = "unhandledPromptBehavior",
    _capsLoggingPref = "loggingPrefs",
    _capsBrowserLoggerPref = "OFF",
    _capsHarLoggerPref = "OFF",
    _pageBlacklistFilter,
    _pageWhitelistFilter,
    _capsPageSettingsProxyPref = "proxy",
    _pageSettings = {},
    _pageZoomFactor = 1,
    _additionalPageSettings = {
        resourceTimeout: null,
        userName: null,
        password: null
    },
    _pageCustomHeaders = {},
    _log = ghostdriver.logger.create("Session [" + _id + "]"),
    k, settingKey, headerKey, proxySettings;

    var
    /**
     * Parses proxy JSON object and return proxy settings for phantom
     *
     * @param proxyCapability proxy JSON Object: @see https://code.google.com/p/selenium/wiki/DesiredCapabilities
     */
    _getProxySettingsFromCapabilities = function(proxyCapability) {
        var proxySettings = {};
        if (proxyCapability["proxyType"].toLowerCase() == _const.PROXY_TYPES.MANUAL) {      //< TODO: support other options
            if (proxyCapability["httpProxy"] !== "null") {                                  //< TODO: support other proxy types
                var urlParts = proxyCapability["httpProxy"].split(':');
                proxySettings["ip"] = urlParts[0];
                proxySettings["port"] = urlParts[1];
                proxySettings["proxyType"] = "http";
                proxySettings["user"] = "";
                proxySettings["password"] = "";

                return proxySettings;
            }
        }
        return proxySettings;
    };

    // Searching for `phantomjs.settings.* and phantomjs.customHeaders.* phantomjs.page.zoomFactor` in the Desired Capabilities and merging with the Negotiated Capabilities
    // Possible values for settings: @see http://phantomjs.org/api/webpage/property/settings.html.
    // Possible values for customHeaders: @see http://phantomjs.org/api/webpage/property/custom-headers.html.
    for (k in desiredCapabilities) {
        if (k.indexOf(_capsPageSettingsPref) === 0) {
            settingKey = k.substring(_capsPageSettingsPref.length);
            if (settingKey.length > 0) {
                _negotiatedCapabilities[k] = desiredCapabilities[k];
                _pageSettings[settingKey] = desiredCapabilities[k];
            }
        }
        if (k.indexOf(_capsPageCustomHeadersPref) === 0) {
            headerKey = k.substring(_capsPageCustomHeadersPref.length);

lib/WWW/Mechanize/PhantomJS/ghostdriver/session.js  view on Meta::CPAN

        var _unhandledPromptBehavior = _negotiatedCapabilities["unhandledPromptBehavior"],
            confirmValue;

        if (_unhandledPromptBehavior !== "accept" && _unhandledPromptBehavior !== "dismiss") {
            return;
        }

        _log.info("_decoratePromptBehavior");

        newPage.onAlert = function(msg) {
            _log.debug("ALERT: " + msg);
        }

        newPage.onPrompt = function(msg, val) {
            _log.debug("PROMPT: " + msg);
            return val;
        }

        if (_unhandledPromptBehavior === "accept") {
            confirmValue = true;
        } else {
            confirmValue = false;
        }

        newPage.onConfirm = function(msg) {
            _log.debug("CONFIRM: " + msg);
            return confirmValue;
        }
    },

    // Add any new page to the "_windows" container of this session
    _addNewPage = function(newPage) {
        _log.debug("_addNewPage");

        // decorate the new Window/Page
        newPage = _decorateNewWindow(newPage);
        // set session-specific CookieJar
        newPage.cookieJar = _cookieJar;
        // store the Window/Page by WindowHandle
        _windows[newPage.windowHandle] = newPage;
    },

    // Delete any closing page from the "_windows" container of this session
    _deleteClosingPage = function(closingPage) {
        _log.debug("_deleteClosingPage");

        // Need to be defensive, as the "closing" can be cause by Client Commands
        if (_windows.hasOwnProperty(closingPage.windowHandle)) {
            delete _windows[closingPage.windowHandle];
        }
    },

    _decorateNewWindow = function(page) {
        var k;

        // Decorating:
        // 0. Pages lifetime will be managed by Driver, not the pages
        page.ownsPages = false;

        // 1. Random Window Handle
        page.windowHandle = require("./third_party/uuid.js").v1();

        // 2. Initialize the One-Shot Callbacks
        page["onUrlChanged"] = _oneShotCallbackFactory(page, "onUrlChanged");
        page["onFilePicker"] = _oneShotCallbackFactory(page, "onFilePicker");
        page["onCallback"] = _oneShotCallbackFactory(page, "onCallback");

        // 3. Utility methods
        page.execFuncAndWaitForLoad = _execFuncAndWaitForLoadDecorator;
        page.setOneShotCallback = _setOneShotCallbackDecorator;
        page.waitIfLoading = _waitIfLoadingDecorator;

        // 4. Store every newly created page
        page.onPageCreated = _addNewPage;

        // 5. Remove every closing page
        page.onClosing = _deleteClosingPage;

        // 6. Applying Page settings received via capabilities
        for (k in _pageSettings) {
            // Apply setting only if really supported by PhantomJS
            if (page.settings.hasOwnProperty(k) || _additionalPageSettings.hasOwnProperty(k)) {
                page.settings[k] = _pageSettings[k];
            }
        }

        // 7. Applying Page custom headers received via capabilities
        // fix custom headers per ariya/phantomjs#13621 and detro/ghostdriver#489
        if ("Accept-Encoding" in _pageCustomHeaders) {
            _log.warn("Custom header \"Accept-Encoding\" is not supported.  see ariya/phantomjs#13621");
            delete _pageCustomHeaders["Accept-Encoding"]
        }
        page.customHeaders = _pageCustomHeaders;

        // 8. Applying Page zoomFactor
        page.zoomFactor = _pageZoomFactor;

        // 9. Log Page internal errors
        page.browserLog = ghostdriver.webdriver_logger.create(_capsBrowserLoggerPref);
        page.onError = function(errorMsg, errorStack) {
            var stack = '';

            // Prep the "stack" part of the message
            errorStack.forEach(function (stackEntry, idx, arr) {
                stack += "  " //< a bit of indentation
                    + (stackEntry.function || "(anonymous function)")
                    + " (" + stackEntry.file + ":" + stackEntry.line + ")";
                stack += idx < arr.length - 1 ? "\n" : "";
            });

            // Log as error
            _log.error("page.onError", "msg: " + errorMsg);
            _log.error("page.onError", "stack:\n" + stack);

            // Register as part of the "browser" log
            page.browserLog.push(_createLogEntry("WARNING", errorMsg + "\n" + stack));
        };

        // 10. Log Page console messages
        page.onConsoleMessage = function(msg, lineNum, sourceId) {
            // Log as debug

lib/WWW/Mechanize/PhantomJS/ghostdriver/session.js  view on Meta::CPAN

            "level"     : level,
            "message"   : message,
            "timestamp" : (new Date()).getTime()
        };
    },

    /**
     * Is any window in this Session Loading?
     * @returns "true" if at least 1 window is loading.
     */
    _isLoading = function() {
        var wHandle, _window;

        for (wHandle in _windows) {
            _window = _windows[wHandle];
            if (_window._onLoadLatch || (_window.loadingProgress > 0 && _window.loadingProgress < 100)) {
                return true;
            }
        }

        return false;
    },

    /**
     * According to log method specification we have to clear log after each page refresh.
     * https://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/log
     * @param {Object} page
     * @private
     */
    _clearPageLog = function (page) {
        page.resources.log = [];
        page.browserLog.log = [];
    },

    _getWindow = function(handleOrName) {
        var page = null,
            k;

        if (_isValidWindowHandle(handleOrName)) {
            // Search by "handle"
            page = _windows[handleOrName];
        } else {
            // Search by "name"
            for (k in _windows) {
                if (_windows[k].windowName === handleOrName) {
                    page = _windows[k];
                    break;
                }
            }
        }

        return page;
    },

    _init = function() {
        var page;

        // Ensure a Current Window is available, if it's found to be `null`
        if (_currentWindowHandle === null) {
            // Create the first Window/Page
            page = require("webpage").create();
            // Decorate it with listeners and helpers
            page = _decorateNewWindow(page);
            // set session-specific CookieJar
            page.cookieJar = _cookieJar;
            // Make the new Window, the Current Window
            _currentWindowHandle = page.windowHandle;
            // Store by WindowHandle
            _windows[_currentWindowHandle] = page;
        }
    },

    _getCurrentWindow = function() {
        var page = null;

        if (_windows.hasOwnProperty(_currentWindowHandle)) {
            page = _windows[_currentWindowHandle];
        }

        // TODO Handle "null" cases throwing a "no such window" error

        return page;
    },

    _switchToWindow = function(handleOrName) {
        var page = _getWindow(handleOrName);

        if (page !== null) {
            // Switch current window and return "true"
            _currentWindowHandle = page.windowHandle;
            // Switch to the Main Frame of that window
            page.switchToMainFrame();
            return true;
        }

        // Couldn't find the window, so return "false"
        return false;
    },

    _closeCurrentWindow = function() {
        if (_currentWindowHandle !== null) {
            return _closeWindow(_currentWindowHandle);
        }
        return false;
    },

    _closeWindow = function(handleOrName) {
        var page = _getWindow(handleOrName),
            handle;

        if (page !== null) {
            handle = page.windowHandle;
            _windows[handle].close();
            delete _windows[handle];
            return true;
        }
        return false;
    },

    _getWindowsCount = function() {
        return Object.keys(_windows).length;

lib/WWW/Mechanize/PhantomJS/ghostdriver/session.js  view on Meta::CPAN

    },

    _getTimeout = function(type) {
        return _timeouts[type];
    },

    _getScriptTimeout = function() {
        return _getTimeout(_const.TIMEOUT_NAMES.SCRIPT);
    },

    _getImplicitTimeout = function() {
        return _getTimeout(_const.TIMEOUT_NAMES.IMPLICIT);
    },

    _getPageLoadTimeout = function() {
        return _getTimeout(_const.TIMEOUT_NAMES.PAGE_LOAD);
    },

    _setScriptTimeout = function(ms) {
        _setTimeout(_const.TIMEOUT_NAMES.SCRIPT, ms);
    },

    _setImplicitTimeout = function(ms) {
        _setTimeout(_const.TIMEOUT_NAMES.IMPLICIT, ms);
    },

    _setPageLoadTimeout = function(ms) {
        _setTimeout(_const.TIMEOUT_NAMES.PAGE_LOAD, ms);
    },

    _executePhantomJS = function(page, script, args) {
        try {
            var code = new Function(script);
            return code.apply(page, args);
        } catch (e) {
            return e;
        }
    },

    _aboutToDelete = function() {
        var k;

        // Close current window first
        _closeCurrentWindow();

        // Releasing page resources and deleting the objects
        for (k in _windows) {
            _closeWindow(k);
        }

        // Release CookieJar resources
        _cookieJar.close();
    },

    _getLog = function (type) {
        var har, i, entry, attrName,
            page, tmp, tmpResMap;

        // Return "HAR" as Log Type "har"
        if (type === _const.LOG_TYPES.HAR) {
            har = require('./third_party/har.js');
            page = _getCurrentWindow();

            tmpResMap = {};
            for (i = 0; i < page.resources.log.length; i++) {
                entry = page.resources.log[i];
                if (!tmpResMap[entry.id]) {
                    tmpResMap[entry.id] = {
                        id: entry.id,
                        request: null,
                        startReply: null,
                        endReply: null,
                        error: null
                    }
                }
                for (attrName in entry) {
                    tmpResMap[entry.id][attrName] = entry[attrName];
                }
            }
            page.resources.log = [];
            tmp = Object.keys(tmpResMap).sort();
            for (i in tmp) {
                page.resources.push(tmpResMap[tmp[i]]);
            }

            tmp = [];
            tmp.push(_createLogEntry(
                "INFO",
                JSON.stringify(har.createHar(page, page.resources.log))));
            page.resources.log = [];
            return tmp;
        }

        // Return Browser Console Log
        if (type === _const.LOG_TYPES.BROWSER) {
            page = _getCurrentWindow();
            tmp = page.browserLog.log;
            page.browserLog.log = [];
            return tmp;
        }

        // Return empty Log
        return [];
    },

    _getLogTypes = function () {
        var logTypes = [], k;

        for (k in _const.LOG_TYPES) {
            logTypes.push(_const.LOG_TYPES[k]);
        }

        return logTypes;
    },

    _getFrameOffset = function(page) {
        return page.evaluate(function() {
            var win = window,
                offset = {top: 0, left: 0},
                style,
                rect;



( run in 0.735 second using v1.01-cache-2.11-cpan-39bf76dae61 )