chromium/chrome/test/data/extensions/api_test/declarative/api/background.js

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var declarative = chrome.declarative;

var RequestMatcher = chrome.declarativeWebRequest.RequestMatcher;
var CancelRequest = chrome.declarativeWebRequest.CancelRequest;
var RedirectRequest = chrome.declarativeWebRequest.RedirectRequest;
var SetRequestHeader = chrome.declarativeWebRequest.SetRequestHeader;

var inputRule0 = {
  // No 'id', this should be filled by the API.
  conditions: [new RequestMatcher({url: {hostPrefix: "test1"}}),
               new RequestMatcher({url: {hostPrefix: "test2"}})],
  actions: [new CancelRequest(),
            new RedirectRequest({redirectUrl: "http://foobar.com"})]
  // No 'priority', this should be filled by the API.
}

var outputRule0 = {
  id: "_0_",
  conditions: [new RequestMatcher({url: {hostPrefix: "test1"}}),
               new RequestMatcher({url: {hostPrefix: "test2"}})],
  actions: [new CancelRequest(),
            new RedirectRequest({redirectUrl: "http://foobar.com"})],
  priority: 100
}

var inputRule1 = {
  id: "my_rule_id",
  conditions: [],
  actions: [],
  priority: 10
}

var outputRule1 = inputRule1;

var inputRule2 = {
  // No 'id', this should be filled by the API.
  conditions: [new RequestMatcher({url: {hostPrefix: "test3"}})],
  actions: [new CancelRequest()]
  // No 'priority', this should be filled by the API.
}

var outputRule2 = {
  id: "_1_",
  conditions: [new RequestMatcher({url: {hostPrefix: "test3"}})],
  actions: [new CancelRequest()],
  priority: 100
}

var invalidRule0 = {
  conditions: [new RequestMatcher({url: {hostPrefix: "test1"}})]
  // "actions" is missing but not optional.
};

var invalidRule1 = {
  conditions: [new RequestMatcher({url: {hostPrefix: "test1"}})],
  // "actions" contains an invalid action (separate test because this validation
  // happens on a different code path).
  actions: [{key: "value"}]
};
var invalidRule2 = {
  conditions: [new RequestMatcher({url: {hostPrefix: "test1"}})],
  actions: [new SetRequestHeader({name: '\x00', value: 'whatever'})]
};

var testEvent = chrome.declarativeWebRequest.onRequest;

chrome.test.runTests([
  // Test validation
  function testInvalidAddRules() {
    try {
      testEvent.addRules();
      chrome.test.fail();
    } catch(e) {
      chrome.test.succeed();
    }
  },
  function testInvalidGetRules() {
    try {
      testEvent.getRules(1, function() {});
      chrome.test.fail();
    } catch(e) {
      chrome.test.succeed();
    }
  },
  function testInvalidRemoveRules() {
    try {
      testEvent.removeRules(1, function() {});
      chrome.test.fail();
    } catch(e) {
      chrome.test.succeed();
    }
  },
  // Add adding two simple rules and check that their optional fields are set
  // correctly in the call back function.
  function testAddRules() {
    var callback = function(rules) {
      chrome.test.assertNoLastError();
      chrome.test.assertEq(2, rules.length);
      // API should have generated id and priority fields.
      chrome.test.assertTrue("id" in rules[0]);
      chrome.test.assertEq([outputRule0, outputRule1], rules);
      chrome.test.succeed();
    };
    testEvent.addRules([inputRule0, inputRule1], callback);
  },
  // Check that getRules() returns all rules if no filter is passed.
  function testGetRules() {
    var callback = function(rules) {
      chrome.test.assertNoLastError();
      // We are not given any guarantee on the order in which rules are
      // returned.
      chrome.test.assertTrue(
          chrome.test.checkDeepEq([outputRule0, outputRule1], rules) ||
          chrome.test.checkDeepEq([outputRule1, outputRule0], rules));
      chrome.test.succeed();
    }
    testEvent.getRules(null, callback);
  },
  // Check that getRules() returns all rules if no filter is passed.
  function testGetRules2() {
    var callback = function(rules) {
      chrome.test.assertNoLastError();
      // We are not given any guarantee on the order in which rules are
      // returned.
      chrome.test.assertTrue(
          chrome.test.checkDeepEq([outputRule0, outputRule1], rules) ||
          chrome.test.checkDeepEq([outputRule1, outputRule0], rules));
      chrome.test.succeed();
    }
    testEvent.getRules(undefined, callback);
  },
  // Check that getRules() returns no rules if empty filter is passed.
  function testGetRules3() {
    var callback = function(rules) {
      chrome.test.assertNoLastError();
      chrome.test.assertEq([], rules);
      chrome.test.succeed();
    }
    testEvent.getRules([], callback);
  },
  // TODO(devlin): The documentation for event.getRules() states that the
  // filter parameter is optional. However, with JS bindings, we throw an error
  // if it's omitted. This is fixed with native bindings.
  // Check that getRules() returns all rules if the filter is omitted.
  // function testGetRules4() {
  //   var callback = function(rules) {
  //     chrome.test.assertNoLastError();
  //     // We are not given any guarantee on the order in which rules are
  //     // returned.
  //     chrome.test.assertTrue(
  //         chrome.test.checkDeepEq([outputRule0, outputRule1], rules) ||
  //         chrome.test.checkDeepEq([outputRule1, outputRule0], rules));
  //     chrome.test.succeed();
  //   }
  //   testEvent.getRules(callback);
  // },
  // Check that getRules() returns matching rules if rules are filtered by ID.
  function testSelectiveGetRules() {
    var callback = function(rules) {
      chrome.test.assertNoLastError();
      chrome.test.assertEq([outputRule1], rules);
      chrome.test.succeed();
    }
    testEvent.getRules(["my_rule_id"], callback);
  },
  // Check that we can remove individual rules.
  function testSelectiveRemoveRules() {
    var callback = function(rules) {
      chrome.test.assertNoLastError();
      chrome.test.succeed();
    }
    testEvent.removeRules(["my_rule_id"], callback);
  },
  // Check that after removal, the rules are really gone.
  function testGetRemainingRules() {
    var callback = function(rules) {
      chrome.test.assertNoLastError();
      chrome.test.assertEq([outputRule0], rules);
      chrome.test.succeed();
    }
    testEvent.getRules(null, callback);
  },
  // Check that rules are assigned unique IDs.
  function testIdGeneration() {
    var callback = function(rules) {
      chrome.test.assertNoLastError();
      chrome.test.assertEq(1, rules.length);
      // API should have generated id and priority fields.
      chrome.test.assertTrue("id" in rules[0]);
      // The IDs should be distinct.
      chrome.test.assertNe(rules[0]["id"], outputRule0["id"]);
      chrome.test.succeed();
    };
    testEvent.addRules([inputRule2], callback);
  },
  // Check that we can remove all rules at once.
  function testRemovingAllRules() {
    var callback = function() {
      chrome.test.assertNoLastError();
      chrome.test.succeed();
    }
    testEvent.removeRules(null, callback);
  },
  // Check that the rules are actually gone.
  function testAllRulesRemoved() {
    var callback = function(rules) {
      chrome.test.assertNoLastError();
      chrome.test.assertEq(0, rules.length);
      chrome.test.succeed();
    }
    testEvent.getRules(null, callback);
  },
  // Check that validation is performed.
  function testValidation() {
    var fail = function() {
      chrome.test.fail("An exception was expected");
    };
    try {
      testEvent.addRules([invalidRule0], fail);
      fail();
    } catch (e) {}
    try {
      testEvent.addRules([invalidRule1], fail);
      fail();
    } catch (e) {}
    // None of these rules should have been registered.
    var callback = function(rules) {
      chrome.test.assertNoLastError();
      chrome.test.assertEq(0, rules.length);
      chrome.test.succeed();
    };
    testEvent.getRules(null, callback);
  },
  // Check that errors are propagated
  function testValidationAsync() {
    var callback = function() {
      chrome.test.assertLastError('Invalid header name.');
      chrome.test.succeed();
    };
    testEvent.addRules([invalidRule2], callback);
  },
  // Finally we add one additional rule, to check that is is removed
  // on page unload.
  function testAddRules() {
    var callback = function(rules) {
      chrome.test.assertNoLastError();
      chrome.test.assertEq(1, rules.length);
      chrome.test.succeed();
    };
    testEvent.addRules([inputRule0], callback);
  },
  ]);