<commit_before>// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, 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.

goog.provide('FirefoxDriver');

goog.require('Utils');
goog.require('WebLoadingListener');
goog.require('bot.ErrorCode');
goog.require('bot.appcache');
goog.require('bot.dom');
goog.require('bot.frame');
goog.require('bot.locators');
goog.require('bot.userAgent');
goog.require('bot.window');
goog.require('fxdriver.Timer');
goog.require('fxdriver.events');
goog.require('fxdriver.io');
goog.require('fxdriver.logging');
goog.require('fxdriver.modals');
goog.require('fxdriver.preconditions');
goog.require('fxdriver.screenshot');
goog.require('fxdriver.utils');
goog.require('goog.array');
goog.require('goog.dom');
goog.require('goog.dom.selection');
goog.require('goog.log');
goog.require('goog.math.Coordinate');
goog.require('goog.math.Size');


FirefoxDriver = function(server, win, opt_pageLoadStrategy) {
  this.server = server;
  this.window = win;
  this.pageLoadStrategy = opt_pageLoadStrategy || 'normal';

  // Default to a two second timeout.
  this.alertTimeout = 2000;

  this.currentX = 0;
  this.currentY = 0;

  // This really shouldn't be here, but the firefoxdriver isn't compiled with closure, so the atoms
  // aren't exported into global scope
  FirefoxDriver.prototype.dismissAlert.preconditions =
      [function() { fxdriver.preconditions.alertPresent(this) }];
  FirefoxDriver.prototype.acceptAlert.preconditions =
      [function() { fxdriver.preconditions.alertPresent(this) }];
  FirefoxDriver.prototype.getAlertText.preconditions =
      [function() { fxdriver.preconditions.alertPresent(this) }];
  FirefoxDriver.prototype.setAlertValue.preconditions =
      [function() { fxdriver.preconditions.alertPresent(this) }];


  FirefoxDriver.listenerScript = Utils.loadUrl('resource://fxdriver/evaluate.js');

  this.jsTimer = new fxdriver.Timer();
  this.mouse = Utils.newInstance('@googlecode.com/webdriver/syntheticmouse;1', 'wdIMouse');
  // Current state of modifier keys (for synthenized events).
  this.modifierKeysState = Utils.newInstance('@googlecode.com/webdriver/modifierkeys;1', 'wdIModifierKeys');
  this.mouse.initialize(this.modifierKeysState);
};

/**
 * @private {goog.log.Logger}
 * @const
 */
FirefoxDriver.LOG_ = fxdriver.logging.getLogger('fxdriver.FirefoxDriver');


FirefoxDriver.prototype.__defineGetter__('id', function() {
  if (!this.id_) {
    this.id_ = this.server.getNextId();
  }

  return this.id_;
});


FirefoxDriver.prototype.getCurrentWindowHandle = function(respond) {
  respond.value = this.id;
  respond.send();
};


FirefoxDriver.prototype.getCurrentUrl = function(respond) {
  respond.value = '' + respond.session.getBrowser().contentWindow.location;
  respond.send();
};


FirefoxDriver.prototype.get = function(respond, parameters) {
  var url = parameters.url;
  // Check to see if the given url is the same as the current one, but
  // with a different anchor tag.
  var current = respond.session.getWindow().location;
  var loadEventExpected;
  try {
    loadEventExpected = fxdriver.io.isLoadExpected(current, url);
  } catch (e) {
    goog.log.warning(FirefoxDriver.LOG_, e);
    var converted = e.QueryInterface ?
                    e.QueryInterface(Components.interfaces['nsIException']) : e;
    if ('NS_ERROR_MALFORMED_URI' == converted.name) {
      goog.log.warning(FirefoxDriver.LOG_, converted.name);
      respond.sendError(new WebDriverError(
          bot.ErrorCode.UNKNOWN_ERROR,
          'Target URL '+url+' is not well-formed.'));
      return;
    }
  }

  if (loadEventExpected) {
    Utils.initWebLoadingListener(respond, respond.session.getWindow());
  }

  respond.session.getBrowser().loadURI(url);

  if (!loadEventExpected) {
    goog.log.info(FirefoxDriver.LOG_, 'No load event expected');
    respond.send();
  }
};


FirefoxDriver.prototype.close = function(respond) {
  // Grab all the references we'll need. Once we call close all this might go away
  var wm = fxdriver.moz.getService(
      '@mozilla.org/appshell/window-mediator;1', 'nsIWindowMediator');
  var appService = fxdriver.moz.getService(
      '@mozilla.org/toolkit/app-startup;1', 'nsIAppStartup');
  var forceQuit = Components.interfaces.nsIAppStartup.eForceQuit;

  var numOpenWindows = 0;
  var allWindows = wm.getEnumerator('navigator:browser');
  while (allWindows.hasMoreElements()) {
    numOpenWindows += 1;
    allWindows.getNext();
  }

  // If we're on a Mac we may close all the windows but not quit, so
  // ensure that we do actually quit. For Windows, if we don't quit,
  // Firefox will crash. So, whatever the case may be, if that's the last
  // window - just quit Firefox.
  if (numOpenWindows == 1) {
    respond.send();

    // Use an nsITimer to give the response time to go out.
    var event = function(timer) {
        appService.quit(forceQuit);
    };

    FirefoxDriver.nstimer = new fxdriver.Timer();
    FirefoxDriver.nstimer.setTimeout(event, 500);
    return;  // The client should catch the fact that the socket suddenly closes
  }

  // Here we go!
  try {
    var browser = respond.session.getBrowser();
    browser.contentWindow.close();
  } catch (e) {
    goog.log.warning(FirefoxDriver.LOG_, 'Error closing window', e);
  }

  // Send the response so the client doesn't get a connection refused socket
  // error.
  respond.send();
};


/**
 * Clones objects from this privileged scope into a less-privileged scope.
 * Returns the original object for Gecko < 29, which does not support cloning.
 * Note, this is required for Gecko 35+.
 *
 * @param {!Object} origianlObject The object to clone.
 * @param {!Object} targetScope The object to attach to.
 * @return {!Object} The cloned object.<commit_msg>Legacy Firefox driver: Explicitly closing last window before quiting session. Fixes #2100<commit_after>// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, 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.

goog.provide('FirefoxDriver');

goog.require('Utils');
goog.require('WebLoadingListener');
goog.require('bot.ErrorCode');
goog.require('bot.appcache');
goog.require('bot.dom');
goog.require('bot.frame');
goog.require('bot.locators');
goog.require('bot.userAgent');
goog.require('bot.window');
goog.require('fxdriver.Timer');
goog.require('fxdriver.events');
goog.require('fxdriver.io');
goog.require('fxdriver.logging');
goog.require('fxdriver.modals');
goog.require('fxdriver.preconditions');
goog.require('fxdriver.screenshot');
goog.require('fxdriver.utils');
goog.require('goog.array');
goog.require('goog.dom');
goog.require('goog.dom.selection');
goog.require('goog.log');
goog.require('goog.math.Coordinate');
goog.require('goog.math.Size');


FirefoxDriver = function(server, win, opt_pageLoadStrategy) {
  this.server = server;
  this.window = win;
  this.pageLoadStrategy = opt_pageLoadStrategy || 'normal';

  // Default to a two second timeout.
  this.alertTimeout = 2000;

  this.currentX = 0;
  this.currentY = 0;

  // This really shouldn't be here, but the firefoxdriver isn't compiled with closure, so the atoms
  // aren't exported into global scope
  FirefoxDriver.prototype.dismissAlert.preconditions =
      [function() { fxdriver.preconditions.alertPresent(this) }];
  FirefoxDriver.prototype.acceptAlert.preconditions =
      [function() { fxdriver.preconditions.alertPresent(this) }];
  FirefoxDriver.prototype.getAlertText.preconditions =
      [function() { fxdriver.preconditions.alertPresent(this) }];
  FirefoxDriver.prototype.setAlertValue.preconditions =
      [function() { fxdriver.preconditions.alertPresent(this) }];


  FirefoxDriver.listenerScript = Utils.loadUrl('resource://fxdriver/evaluate.js');

  this.jsTimer = new fxdriver.Timer();
  this.mouse = Utils.newInstance('@googlecode.com/webdriver/syntheticmouse;1', 'wdIMouse');
  // Current state of modifier keys (for synthenized events).
  this.modifierKeysState = Utils.newInstance('@googlecode.com/webdriver/modifierkeys;1', 'wdIModifierKeys');
  this.mouse.initialize(this.modifierKeysState);
};

/**
 * @private {goog.log.Logger}
 * @const
 */
FirefoxDriver.LOG_ = fxdriver.logging.getLogger('fxdriver.FirefoxDriver');


FirefoxDriver.prototype.__defineGetter__('id', function() {
  if (!this.id_) {
    this.id_ = this.server.getNextId();
  }

  return this.id_;
});


FirefoxDriver.prototype.getCurrentWindowHandle = function(respond) {
  respond.value = this.id;
  respond.send();
};


FirefoxDriver.prototype.getCurrentUrl = function(respond) {
  respond.value = '' + respond.session.getBrowser().contentWindow.location;
  respond.send();
};


FirefoxDriver.prototype.get = function(respond, parameters) {
  var url = parameters.url;
  // Check to see if the given url is the same as the current one, but
  // with a different anchor tag.
  var current = respond.session.getWindow().location;
  var loadEventExpected;
  try {
    loadEventExpected = fxdriver.io.isLoadExpected(current, url);
  } catch (e) {
    goog.log.warning(FirefoxDriver.LOG_, e);
    var converted = e.QueryInterface ?
                    e.QueryInterface(Components.interfaces['nsIException']) : e;
    if ('NS_ERROR_MALFORMED_URI' == converted.name) {
      goog.log.warning(FirefoxDriver.LOG_, converted.name);
      respond.sendError(new WebDriverError(
          bot.ErrorCode.UNKNOWN_ERROR,
          'Target URL '+url+' is not well-formed.'));
      return;
    }
  }

  if (loadEventExpected) {
    Utils.initWebLoadingListener(respond, respond.session.getWindow());
  }

  respond.session.getBrowser().loadURI(url);

  if (!loadEventExpected) {
    goog.log.info(FirefoxDriver.LOG_, 'No load event expected');
    respond.send();
  }
};


FirefoxDriver.prototype.close = function(respond) {
  // Grab all the references we'll need. Once we call close all this might go away
  var wm = fxdriver.moz.getService(
      '@mozilla.org/appshell/window-mediator;1', 'nsIWindowMediator');
  var appService = fxdriver.moz.getService(
      '@mozilla.org/toolkit/app-startup;1', 'nsIAppStartup');
  var forceQuit = Components.interfaces.nsIAppStartup.eForceQuit;

  var numOpenWindows = 0;
  var allWindows = wm.getEnumerator('navigator:browser');
  while (allWindows.hasMoreElements()) {
    numOpenWindows += 1;
    allWindows.getNext();
  }

  // Here we go!
  try {
    var browser = respond.session.getBrowser();
    browser.contentWindow.close();
  } catch (e) {
    goog.log.warning(FirefoxDriver.LOG_, 'Error closing window', e);
  }

  // If we're on a Mac we may close all the windows but not quit, so
  // ensure that we do actually quit. For Windows, if we don't quit,
  // Firefox will crash. So, whatever the case may be, if that's the last
  // window - just quit Firefox.
  if (numOpenWindows == 1) {
    respond.send();

    // Use an nsITimer to give the response time to go out.
    var event = function(timer) {
      appService.quit(forceQuit);
    };

    FirefoxDriver.nstimer = new fxdriver.Timer();
    FirefoxDriver.nstimer.setTimeout(event, 500);
    return;  // The client should catch the fact that the socket suddenly closes
  }

  // Send the response so the client doesn't get a connection refused socket
  // error.
  respond.send();
};


/**
 * Clones objects from this privileged scope into a less-privileged scope.
 * Returns the original object for Gecko < 29, which does not support cloning.
 * Note, this is required for Gecko 35+.
 *
 * @param {!Object} origianlObject The object to clone.
 * @param {!Object} targetScope The object to attach to.
 * @return {!Object} The cloned object.
{'fraction_non_alphanumeric': 0.1276085948369145, 'fraction_numerical': 0.004019168341320142, 'mean_word_length': 4.040514218932606, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1780187', 'n_tokens_mistral': 4007, 'n_tokens_neox': 3840, 'n_words': 1022}