Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/test/base/module_system_test.h"
      6 
      7 #include "grit/renderer_resources.h"
      8 
      9 namespace extensions {
     10 namespace {
     11 
     12 class EventUnittest : public ModuleSystemTest {
     13   virtual void SetUp() OVERRIDE {
     14     ModuleSystemTest::SetUp();
     15 
     16     RegisterModule("event_bindings", IDR_EVENT_BINDINGS_JS);
     17     RegisterModule("json_schema", IDR_JSON_SCHEMA_JS);
     18     RegisterModule("schemaUtils", IDR_SCHEMA_UTILS_JS);
     19     RegisterModule("unload_event", IDR_UNLOAD_EVENT_JS);
     20     RegisterModule("utils", IDR_UTILS_JS);
     21 
     22     // Mock out the native handler for event_bindings. These mocks will fail if
     23     // any invariants maintained by the real event_bindings are broken.
     24     OverrideNativeHandler("event_natives",
     25         "var assert = requireNative('assert');"
     26         "var attachedListeners = exports.attachedListeners = {};"
     27         "var attachedFilteredListeners = "
     28         "    exports.attachedFilteredListeners = {};"
     29         "var nextId = 0;"
     30         "var idToName = {};"
     31 
     32         "exports.AttachEvent = function(eventName) {"
     33         "  assert.AssertFalse(!!attachedListeners[eventName]);"
     34         "  attachedListeners[eventName] = 1;"
     35         "};"
     36 
     37         "exports.DetachEvent = function(eventName) {"
     38         "  assert.AssertTrue(!!attachedListeners[eventName]);"
     39         "  delete attachedListeners[eventName];"
     40         "};"
     41 
     42         "exports.IsEventAttached = function(eventName) {"
     43         "  return !!attachedListeners[eventName];"
     44         "};"
     45 
     46         "exports.AttachFilteredEvent = function(name, filters) {"
     47         "  var id = nextId++;"
     48         "  idToName[id] = name;"
     49         "  attachedFilteredListeners[name] ="
     50         "    attachedFilteredListeners[name] || [];"
     51         "  attachedFilteredListeners[name][id] = filters;"
     52         "  return id;"
     53         "};"
     54 
     55         "exports.DetachFilteredEvent = function(id, manual) {"
     56         "  var i = attachedFilteredListeners[idToName[id]].indexOf(id);"
     57         "  attachedFilteredListeners[idToName[id]].splice(i, 1);"
     58         "};"
     59 
     60         "exports.HasFilteredListener = function(name) {"
     61         "  return attachedFilteredListeners[name].length;"
     62         "};");
     63     OverrideNativeHandler("sendRequest",
     64         "exports.sendRequest = function() {};");
     65     OverrideNativeHandler("apiDefinitions",
     66         "exports.GetExtensionAPIDefinitionsForTest = function() {};");
     67     OverrideNativeHandler("logging",
     68         "exports.DCHECK = function() {};");
     69     OverrideNativeHandler("schema_registry",
     70         "exports.GetSchema = function() {};");
     71   }
     72 };
     73 
     74 TEST_F(EventUnittest, TestNothing) {
     75   ExpectNoAssertionsMade();
     76 }
     77 
     78 TEST_F(EventUnittest, AddRemoveTwoListeners) {
     79   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
     80   RegisterModule("test",
     81       "var assert = requireNative('assert');"
     82       "var Event = require('event_bindings').Event;"
     83       "var eventNatives = requireNative('event_natives');"
     84       "var myEvent = new Event('named-event');"
     85       "var cb1 = function() {};"
     86       "var cb2 = function() {};"
     87       "myEvent.addListener(cb1);"
     88       "myEvent.addListener(cb2);"
     89       "myEvent.removeListener(cb1);"
     90       "assert.AssertTrue(!!eventNatives.attachedListeners['named-event']);"
     91       "myEvent.removeListener(cb2);"
     92       "assert.AssertFalse(!!eventNatives.attachedListeners['named-event']);");
     93   module_system_->Require("test");
     94 }
     95 
     96 TEST_F(EventUnittest, OnUnloadDetachesAllListeners) {
     97   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
     98   RegisterModule("test",
     99       "var assert = requireNative('assert');"
    100       "var Event = require('event_bindings').Event;"
    101       "var eventNatives = requireNative('event_natives');"
    102       "var myEvent = new Event('named-event');"
    103       "var cb1 = function() {};"
    104       "var cb2 = function() {};"
    105       "myEvent.addListener(cb1);"
    106       "myEvent.addListener(cb2);"
    107       "require('unload_event').dispatch();"
    108       "assert.AssertFalse(!!eventNatives.attachedListeners['named-event']);");
    109   module_system_->Require("test");
    110 }
    111 
    112 TEST_F(EventUnittest, OnUnloadDetachesAllListenersEvenDupes) {
    113   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
    114   RegisterModule("test",
    115       "var assert = requireNative('assert');"
    116       "var Event = require('event_bindings').Event;"
    117       "var eventNatives = requireNative('event_natives');"
    118       "var myEvent = new Event('named-event');"
    119       "var cb1 = function() {};"
    120       "myEvent.addListener(cb1);"
    121       "myEvent.addListener(cb1);"
    122       "require('unload_event').dispatch();"
    123       "assert.AssertFalse(!!eventNatives.attachedListeners['named-event']);");
    124   module_system_->Require("test");
    125 }
    126 
    127 TEST_F(EventUnittest, EventsThatSupportRulesMustHaveAName) {
    128   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
    129   RegisterModule("test",
    130       "var Event = require('event_bindings').Event;"
    131       "var eventOpts = {supportsRules: true};"
    132       "var assert = requireNative('assert');"
    133       "var caught = false;"
    134       "try {"
    135       "  var myEvent = new Event(undefined, undefined, eventOpts);"
    136       "} catch (e) {"
    137       "  caught = true;"
    138       "}"
    139       "assert.AssertTrue(caught);");
    140   module_system_->Require("test");
    141 }
    142 
    143 TEST_F(EventUnittest, NamedEventDispatch) {
    144   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
    145   RegisterModule("test",
    146       "var Event = require('event_bindings').Event;"
    147       "var dispatchEvent = require('event_bindings').dispatchEvent;"
    148       "var assert = requireNative('assert');"
    149       "var e = new Event('myevent');"
    150       "var called = false;"
    151       "e.addListener(function() { called = true; });"
    152       "dispatchEvent('myevent', []);"
    153       "assert.AssertTrue(called);");
    154   module_system_->Require("test");
    155 }
    156 
    157 TEST_F(EventUnittest, AddListenerWithFiltersThrowsErrorByDefault) {
    158   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
    159   RegisterModule("test",
    160       "var Event = require('event_bindings').Event;"
    161       "var assert = requireNative('assert');"
    162       "var e = new Event('myevent');"
    163       "var filter = [{"
    164       "  url: {hostSuffix: 'google.com'},"
    165       "}];"
    166       "var caught = false;"
    167       "try {"
    168       "  e.addListener(function() {}, filter);"
    169       "} catch (e) {"
    170       "  caught = true;"
    171       "}"
    172       "assert.AssertTrue(caught);");
    173   module_system_->Require("test");
    174 }
    175 
    176 TEST_F(EventUnittest, FilteredEventsAttachment) {
    177   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
    178   RegisterModule("test",
    179       "var Event = require('event_bindings').Event;"
    180       "var assert = requireNative('assert');"
    181       "var bindings = requireNative('event_natives');"
    182       "var eventOpts = {supportsListeners: true, supportsFilters: true};"
    183       "var e = new Event('myevent', undefined, eventOpts);"
    184       "var cb = function() {};"
    185       "var filters = {url: [{hostSuffix: 'google.com'}]};"
    186       "e.addListener(cb, filters);"
    187       "assert.AssertTrue(bindings.HasFilteredListener('myevent'));"
    188       "e.removeListener(cb);"
    189       "assert.AssertFalse(bindings.HasFilteredListener('myevent'));");
    190   module_system_->Require("test");
    191 }
    192 
    193 TEST_F(EventUnittest, DetachFilteredEvent) {
    194   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
    195   RegisterModule("test",
    196       "var Event = require('event_bindings').Event;"
    197       "var assert = requireNative('assert');"
    198       "var bindings = requireNative('event_natives');"
    199       "var eventOpts = {supportsListeners: true, supportsFilters: true};"
    200       "var e = new Event('myevent', undefined, eventOpts);"
    201       "var cb1 = function() {};"
    202       "var cb2 = function() {};"
    203       "var filters = {url: [{hostSuffix: 'google.com'}]};"
    204       "e.addListener(cb1, filters);"
    205       "e.addListener(cb2, filters);"
    206       "e.detach_();"
    207       "assert.AssertFalse(bindings.HasFilteredListener('myevent'));");
    208   module_system_->Require("test");
    209 }
    210 
    211 TEST_F(EventUnittest, AttachAndRemoveSameFilteredEventListener) {
    212   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
    213   RegisterModule("test",
    214       "var Event = require('event_bindings').Event;"
    215       "var assert = requireNative('assert');"
    216       "var bindings = requireNative('event_natives');"
    217       "var eventOpts = {supportsListeners: true, supportsFilters: true};"
    218       "var e = new Event('myevent', undefined, eventOpts);"
    219       "var cb = function() {};"
    220       "var filters = {url: [{hostSuffix: 'google.com'}]};"
    221       "e.addListener(cb, filters);"
    222       "e.addListener(cb, filters);"
    223       "assert.AssertTrue(bindings.HasFilteredListener('myevent'));"
    224       "e.removeListener(cb);"
    225       "assert.AssertTrue(bindings.HasFilteredListener('myevent'));"
    226       "e.removeListener(cb);"
    227       "assert.AssertFalse(bindings.HasFilteredListener('myevent'));");
    228   module_system_->Require("test");
    229 }
    230 
    231 TEST_F(EventUnittest, AddingFilterWithUrlFieldNotAListThrowsException) {
    232   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
    233   RegisterModule("test",
    234       "var Event = require('event_bindings').Event;"
    235       "var assert = requireNative('assert');"
    236       "var eventOpts = {supportsListeners: true, supportsFilters: true};"
    237       "var e = new Event('myevent', undefined, eventOpts);"
    238       "var cb = function() {};"
    239       "var filters = {url: {hostSuffix: 'google.com'}};"
    240       "var caught = false;"
    241       "try {"
    242       "  e.addListener(cb, filters);"
    243       "} catch (e) {"
    244       "  caught = true;"
    245       "}"
    246       "assert.AssertTrue(caught);");
    247   module_system_->Require("test");
    248 }
    249 
    250 TEST_F(EventUnittest, MaxListeners) {
    251   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
    252   RegisterModule("test",
    253       "var Event = require('event_bindings').Event;"
    254       "var assert = requireNative('assert');"
    255       "var eventOpts = {supportsListeners: true, maxListeners: 1};"
    256       "var e = new Event('myevent', undefined, eventOpts);"
    257       "var cb = function() {};"
    258       "var caught = false;"
    259       "try {"
    260       "  e.addListener(cb);"
    261       "} catch (e) {"
    262       "  caught = true;"
    263       "}"
    264       "assert.AssertTrue(!caught);"
    265       "try {"
    266       "  e.addListener(cb);"
    267       "} catch (e) {"
    268       "  caught = true;"
    269       "}"
    270       "assert.AssertTrue(caught);");
    271   module_system_->Require("test");
    272 }
    273 
    274 }  // namespace
    275 }  // namespace extensions
    276