tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

constants.js (15523B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 const actionTypes = {
      8  ADD_REQUEST: "ADD_REQUEST",
      9  SET_EVENT_STREAM_FLAG: "SET_EVENT_STREAM_FLAG",
     10  ADD_TIMING_MARKER: "ADD_TIMING_MARKER",
     11  ADD_BLOCKED_URL: "ADD_BLOCKED_URL",
     12  BATCH_ACTIONS: "BATCH_ACTIONS",
     13  BATCH_ENABLE: "BATCH_ENABLE",
     14  BATCH_FLUSH: "BATCH_FLUSH",
     15  BLOCK_SELECTED_REQUEST_DONE: "BLOCK_SELECTED_REQUEST_DONE",
     16  CLEAR_REQUESTS: "CLEAR_REQUESTS",
     17  CLEAR_TIMING_MARKERS: "CLEAR_TIMING_MARKERS",
     18  CLONE_REQUEST: "CLONE_REQUEST",
     19  CLONE_SELECTED_REQUEST: "CLONE_SELECTED_REQUEST",
     20  ENABLE_REQUEST_FILTER_TYPE_ONLY: "ENABLE_REQUEST_FILTER_TYPE_ONLY",
     21  OPEN_NETWORK_DETAILS: "OPEN_NETWORK_DETAILS",
     22  OPEN_ACTION_BAR: "OPEN_ACTION_BAR",
     23  RESIZE_NETWORK_DETAILS: "RESIZE_NETWORK_DETAILS",
     24  RIGHT_CLICK_REQUEST: "RIGHT_CLICK_REQUEST",
     25  ENABLE_PERSISTENT_LOGS: "ENABLE_PERSISTENT_LOGS",
     26  DISABLE_BROWSER_CACHE: "DISABLE_BROWSER_CACHE",
     27  OPEN_STATISTICS: "OPEN_STATISTICS",
     28  PERSIST_CHANGED: "PERSIST_CHANGED",
     29  PRESELECT_REQUEST: "PRESELECT_REQUEST",
     30  REMOVE_SELECTED_CUSTOM_REQUEST: "REMOVE_SELECTED_CUSTOM_REQUEST",
     31  RESET_COLUMNS: "RESET_COLUMNS",
     32  SELECT_REQUEST: "SELECT_REQUEST",
     33  SELECT_DETAILS_PANEL_TAB: "SELECT_DETAILS_PANEL_TAB",
     34  SELECT_ACTION_BAR_TAB: "SELECT_ACTION_BAR_TAB",
     35  SEND_CUSTOM_REQUEST: "SEND_CUSTOM_REQUEST",
     36  SET_REQUEST_FILTER_TEXT: "SET_REQUEST_FILTER_TEXT",
     37  SORT_BY: "SORT_BY",
     38  SYNCED_BLOCKED_URLS: "SYNCED_BLOCKED_URLS",
     39  TOGGLE_BLOCKING_ENABLED: "TOGGLE_BLOCKING_ENABLED",
     40  REMOVE_BLOCKED_URL: "REMOVE_BLOCKED_URL",
     41  REMOVE_ALL_BLOCKED_URLS: "REMOVE_ALL_BLOCKED_URLS",
     42  ENABLE_ALL_BLOCKED_URLS: "ENABLE_ALL_BLOCKED_URLS",
     43  DISABLE_ALL_BLOCKED_URLS: "DISABLE_ALL_BLOCKED_URLS",
     44  TOGGLE_BLOCKED_URL: "TOGGLE_BLOCKED_URL",
     45  UPDATE_BLOCKED_URL: "UPDATE_BLOCKED_URL",
     46  DISABLE_MATCHING_URLS: "DISABLE_MATCHING_URLS",
     47  REQUEST_BLOCKING_UPDATE_COMPLETE: "REQUEST_BLOCKING_UPDATE_COMPLETE",
     48  TOGGLE_COLUMN: "TOGGLE_COLUMN",
     49  SET_RECORDING_STATE: "SET_RECORDING_STATE",
     50  TOGGLE_REQUEST_FILTER_TYPE: "TOGGLE_REQUEST_FILTER_TYPE",
     51  UNBLOCK_SELECTED_REQUEST_DONE: "UNBLOCK_SELECTED_REQUEST_DONE",
     52  UPDATE_REQUEST: "UPDATE_REQUEST",
     53  WATERFALL_RESIZE: "WATERFALL_RESIZE",
     54  SET_COLUMNS_WIDTH: "SET_COLUMNS_WIDTH",
     55  MSG_ADD: "MSG_ADD",
     56  MSG_SELECT: "MSG_SELECT",
     57  MSG_OPEN_DETAILS: "MSG_OPEN_DETAILS",
     58  MSG_CLEAR: "MSG_CLEAR",
     59  MSG_TOGGLE_FILTER_TYPE: "MSG_TOGGLE_FILTER_TYPE",
     60  MSG_TOGGLE_CONTROL: "MSG_TOGGLE_CONTROL",
     61  MSG_SET_FILTER_TEXT: "MSG_SET_FILTER_TEXT",
     62  MSG_TOGGLE_COLUMN: "MSG_TOGGLE_COLUMN",
     63  MSG_RESET_COLUMNS: "MSG_RESET_COLUMNS",
     64  MSG_CLOSE_CONNECTION: "MSG_CLOSE_CONNECTION",
     65  SET_HEADERS_URL_PREVIEW_EXPANDED: "SET_HEADERS_URL_PREVIEW_EXPANDED",
     66  SET_DEFAULT_RAW_RESPONSE: "SET_DEFAULT_RAW_RESPONSE",
     67 
     68  // Search
     69  ADD_SEARCH_QUERY: "ADD_SEARCH_QUERY",
     70  ADD_SEARCH_RESULT: "ADD_SEARCH_RESULT",
     71  CLEAR_SEARCH_RESULTS: "CLEAR_SEARCH_RESULTS",
     72  ADD_ONGOING_SEARCH: "ADD_ONGOING_SEARCH",
     73  TOGGLE_SEARCH_CASE_SENSITIVE_SEARCH: "TOGGLE_SEARCH_CASE_SENSITIVE_SEARCH",
     74  UPDATE_SEARCH_STATUS: "UPDATE_SEARCH_STATUS",
     75  SET_TARGET_SEARCH_RESULT: "SET_TARGET_SEARCH_RESULT",
     76 };
     77 
     78 // Search status types
     79 const SEARCH_STATUS = {
     80  INITIAL: "INITIAL",
     81  FETCHING: "FETCHING",
     82  CANCELED: "CANCELED",
     83  DONE: "DONE",
     84  ERROR: "ERROR",
     85 };
     86 
     87 const CHANNEL_TYPE = {
     88  WEB_SOCKET: "WEB_SOCKET",
     89  EVENT_STREAM: "EVENT_STREAM",
     90 };
     91 
     92 // Descriptions for what this frontend is currently doing.
     93 const ACTIVITY_TYPE = {
     94  // Standing by and handling requests normally.
     95  NONE: 0,
     96 
     97  // Forcing the target to reload with cache enabled or disabled.
     98  RELOAD: {
     99    WITH_CACHE_ENABLED: 1,
    100    WITH_CACHE_DISABLED: 2,
    101    WITH_CACHE_DEFAULT: 3,
    102  },
    103 
    104  // Enabling or disabling the cache without triggering a reload.
    105  ENABLE_CACHE: 3,
    106  DISABLE_CACHE: 4,
    107 };
    108 
    109 // The panel's window global is an EventEmitter firing the following events:
    110 const EVENTS = {
    111  // When a network event is added to the view
    112  REQUEST_ADDED: "NetMonitor:RequestAdded",
    113 
    114  // When request headers begin receiving.
    115  UPDATING_REQUEST_HEADERS: "NetMonitor:NetworkEventUpdating:RequestHeaders",
    116 
    117  // When request cookies begin receiving.
    118  UPDATING_REQUEST_COOKIES: "NetMonitor:NetworkEventUpdating:RequestCookies",
    119 
    120  // When request post data begins receiving.
    121  UPDATING_REQUEST_POST_DATA: "NetMonitor:NetworkEventUpdating:RequestPostData",
    122 
    123  // When security information begins receiving.
    124  UPDATING_SECURITY_INFO: "NetMonitor:NetworkEventUpdating:SecurityInfo",
    125 
    126  // When response headers begin receiving.
    127  UPDATING_RESPONSE_HEADERS: "NetMonitor:NetworkEventUpdating:ResponseHeaders",
    128 
    129  // When response cookies begin receiving.
    130  UPDATING_RESPONSE_COOKIES: "NetMonitor:NetworkEventUpdating:ResponseCookies",
    131 
    132  // When event timings begin and finish receiving.
    133  UPDATING_EVENT_TIMINGS: "NetMonitor:NetworkEventUpdating:EventTimings",
    134  RECEIVED_EVENT_TIMINGS: "NetMonitor:NetworkEventUpdated:EventTimings",
    135 
    136  // When response content updates receiving.
    137  UPDATING_RESPONSE_CONTENT: "NetMonitor:NetworkEventUpdating:ResponseContent",
    138 
    139  UPDATING_RESPONSE_CACHE: "NetMonitor:NetworkEventUpdating:ResponseCache",
    140 
    141  // Fired once the connection is established
    142  CONNECTED: "connected",
    143 
    144  // When request payload (HTTP details data) are fetched from the backend.
    145  PAYLOAD_READY: "NetMonitor:PayloadReady",
    146 };
    147 
    148 const TEST_EVENTS = {
    149  // When a network or timeline event is received.
    150  // See https://firefox-source-docs.mozilla.org/devtools-user/web_console/remoting/ for
    151  // more information about what each packet is supposed to deliver.
    152  NETWORK_EVENT: "NetMonitor:NetworkEvent",
    153  NETWORK_EVENT_UPDATED: "NetMonitor:NetworkEventUpdated",
    154  TIMELINE_EVENT: "NetMonitor:TimelineEvent",
    155 
    156  // When response content begins receiving.
    157  STARTED_RECEIVING_RESPONSE: "NetMonitor:NetworkEventUpdating:ResponseStart",
    158 
    159  // When request headers finish receiving.
    160  RECEIVED_REQUEST_HEADERS: "NetMonitor:NetworkEventUpdated:RequestHeaders",
    161 
    162  // When early hints response headers finish receiving.
    163  RECEIVED_EARLY_HINTS_RESPONSE_HEADERS:
    164    "NetMonitor:NetworkEventUpdated:EarlyHintsResponseHeaders",
    165 
    166  // When response headers finish receiving.
    167  RECEIVED_RESPONSE_HEADERS: "NetMonitor:NetworkEventUpdated:ResponseHeaders",
    168 
    169  // When request cookies finish receiving.
    170  RECEIVED_REQUEST_COOKIES: "NetMonitor:NetworkEventUpdated:RequestCookies",
    171 
    172  // When request post data finishes receiving.
    173  RECEIVED_REQUEST_POST_DATA: "NetMonitor:NetworkEventUpdated:RequestPostData",
    174 
    175  // When security information finishes receiving.
    176  RECEIVED_SECURITY_INFO: "NetMonitor:NetworkEventUpdated:SecurityInfo",
    177 
    178  // When response cookies finish receiving.
    179  RECEIVED_RESPONSE_COOKIES: "NetMonitor:NetworkEventUpdated:ResponseCookies",
    180 
    181  RECEIVED_RESPONSE_CACHE: "NetMonitor:NetworkEventUpdated:ResponseCache",
    182 
    183  // When response content finishes receiving.
    184  RECEIVED_RESPONSE_CONTENT: "NetMonitor:NetworkEventUpdated:ResponseContent",
    185 
    186  // When stack-trace finishes receiving.
    187  RECEIVED_EVENT_STACKTRACE: "NetMonitor:NetworkEventUpdated:StackTrace",
    188 
    189  // When throttling is set on the backend.
    190  THROTTLING_CHANGED: "NetMonitor:ThrottlingChanged",
    191 
    192  // When a long string is resolved
    193  LONGSTRING_RESOLVED: "NetMonitor:LongStringResolved",
    194 };
    195 
    196 const UPDATE_PROPS = [
    197  "method",
    198  "url",
    199  "earlyHintsStatus",
    200  "remotePort",
    201  "remoteAddress",
    202  "status",
    203  "statusText",
    204  "httpVersion",
    205  "isRacing",
    206  "securityState",
    207  "securityInfo",
    208  "securityInfoAvailable",
    209  "mimeType",
    210  "contentSize",
    211  "transferredSize",
    212  "totalTime",
    213  "eventTimings",
    214  "eventTimingsAvailable",
    215  "earlyHintsResponseHeaders",
    216  "earlyHintsResponseHeadersAvailable",
    217  "headersSize",
    218  "customQueryValue",
    219  "requestHeaders",
    220  "requestHeadersAvailable",
    221  "requestHeadersFromUploadStream",
    222  "requestCookies",
    223  "requestCookiesAvailable",
    224  "requestPostData",
    225  "requestPostDataAvailable",
    226  "responseHeaders",
    227  "responseHeadersAvailable",
    228  "responseCookies",
    229  "responseCookiesAvailable",
    230  "responseContent",
    231  "responseContentAvailable",
    232  "responseCache",
    233  "responseCacheAvailable",
    234  "formDataSections",
    235  "stacktrace",
    236  "isThirdPartyTrackingResource",
    237  "isResolvedByTRR",
    238  "referrerPolicy",
    239  "priority",
    240  "blockedReason",
    241  "extension",
    242  "channelId",
    243  "waitingTime",
    244  "proxyHttpVersion",
    245  "proxyStatus",
    246  "proxyStatusText",
    247  "fromCache",
    248  "fromServiceWorker",
    249  "securityFlags",
    250 ];
    251 
    252 const PANELS = {
    253  COOKIES: "cookies",
    254  HEADERS: "headers",
    255  MESSAGES: "messages",
    256  REQUEST: "request",
    257  RESPONSE: "response",
    258  CACHE: "cache",
    259  SECURITY: "security",
    260  STACK_TRACE: "stack-trace",
    261  TIMINGS: "timings",
    262  HTTP_CUSTOM_REQUEST: "network-action-bar-HTTP-custom-request",
    263  SEARCH: "network-action-bar-search",
    264  BLOCKING: "network-action-bar-blocked",
    265 };
    266 
    267 const RESPONSE_HEADERS = [
    268  "Cache-Control",
    269  "Connection",
    270  "Content-Encoding",
    271  "Content-Length",
    272  "ETag",
    273  "Keep-Alive",
    274  "Last-Modified",
    275  "Server",
    276  "Vary",
    277 ];
    278 
    279 const HEADERS = [
    280  {
    281    name: "override",
    282    canFilter: false,
    283  },
    284  {
    285    name: "status",
    286    label: "status3",
    287    canFilter: true,
    288    filterKey: "status-code",
    289  },
    290  {
    291    name: "method",
    292    canFilter: true,
    293  },
    294  {
    295    name: "domain",
    296    canFilter: true,
    297  },
    298  {
    299    name: "file",
    300    canFilter: false,
    301  },
    302  {
    303    name: "path",
    304    canFilter: false,
    305  },
    306  {
    307    name: "url",
    308    canFilter: true,
    309  },
    310  {
    311    name: "protocol",
    312    canFilter: true,
    313  },
    314  {
    315    name: "scheme",
    316    canFilter: true,
    317  },
    318  {
    319    name: "remoteip",
    320    canFilter: true,
    321    filterKey: "remote-ip",
    322  },
    323  {
    324    name: "cause",
    325    canFilter: true,
    326  },
    327  {
    328    name: "initiator",
    329    canFilter: true,
    330  },
    331  {
    332    name: "type",
    333    canFilter: false,
    334  },
    335  {
    336    name: "cookies",
    337    canFilter: false,
    338  },
    339  {
    340    name: "setCookies",
    341    boxName: "set-cookies",
    342    canFilter: false,
    343  },
    344  {
    345    name: "transferred",
    346    canFilter: true,
    347  },
    348  {
    349    name: "contentSize",
    350    boxName: "size",
    351    filterKey: "size",
    352    canFilter: true,
    353  },
    354  {
    355    name: "priority",
    356    boxName: "priority",
    357    canFilter: true,
    358  },
    359  {
    360    name: "startTime",
    361    boxName: "start-time",
    362    canFilter: false,
    363    subMenu: "timings",
    364  },
    365  {
    366    name: "endTime",
    367    boxName: "end-time",
    368    canFilter: false,
    369    subMenu: "timings",
    370  },
    371  {
    372    name: "responseTime",
    373    boxName: "response-time",
    374    canFilter: false,
    375    subMenu: "timings",
    376  },
    377  {
    378    name: "duration",
    379    canFilter: false,
    380    subMenu: "timings",
    381  },
    382  {
    383    name: "latency",
    384    canFilter: false,
    385    subMenu: "timings",
    386  },
    387  ...RESPONSE_HEADERS.map(header => ({
    388    name: header,
    389    boxName: "response-header",
    390    canFilter: false,
    391    subMenu: "responseHeaders",
    392    noLocalization: true,
    393  })),
    394  {
    395    name: "waterfall",
    396    canFilter: false,
    397  },
    398 ];
    399 
    400 const HEADER_FILTERS = HEADERS.filter(h => h.canFilter).map(
    401  h => h.filterKey || h.name
    402 );
    403 
    404 const FILTER_FLAGS = [
    405  ...HEADER_FILTERS,
    406  "set-cookie-domain",
    407  "set-cookie-name",
    408  "set-cookie-value",
    409  "mime-type",
    410  "larger-than",
    411  "transferred-larger-than",
    412  "is",
    413  "has-response-header",
    414  "regexp",
    415 ];
    416 
    417 const FILTER_TAGS = [
    418  "html",
    419  "css",
    420  "js",
    421  "xhr",
    422  "fonts",
    423  "images",
    424  "media",
    425  "ws",
    426  "other",
    427 ];
    428 
    429 const MESSAGE_HEADERS = [
    430  {
    431    name: "data",
    432    width: "40%",
    433  },
    434  {
    435    name: "size",
    436    width: "12%",
    437  },
    438  {
    439    name: "opCode",
    440    width: "9%",
    441  },
    442  {
    443    name: "maskBit",
    444    width: "9%",
    445  },
    446  {
    447    name: "finBit",
    448    width: "9%",
    449  },
    450  {
    451    name: "time",
    452    width: "20%",
    453  },
    454  {
    455    name: "eventName",
    456    width: "9%",
    457  },
    458  {
    459    name: "lastEventId",
    460    width: "9%",
    461  },
    462  {
    463    name: "retry",
    464    width: "9%",
    465  },
    466 ];
    467 
    468 const REQUESTS_WATERFALL = {
    469  BACKGROUND_TICKS_MULTIPLE: 5, // ms
    470  BACKGROUND_TICKS_SCALES: 3,
    471  BACKGROUND_TICKS_SPACING_MIN: 10, // px
    472  BACKGROUND_TICKS_COLOR_RGB: [128, 136, 144],
    473  // 8-bit value of the alpha component of the tick color
    474  BACKGROUND_TICKS_OPACITY_MIN: 32,
    475  BACKGROUND_TICKS_OPACITY_ADD: 32,
    476  // Colors for timing markers (theme colors, see variables.css)
    477  DOMCONTENTLOADED_TICKS_COLOR: "--timing-marker-dom-content-loaded-color",
    478  LOAD_TICKS_COLOR: "--timing-marker-load-color",
    479 
    480  HEADER_TICKS_MULTIPLE: 5, // ms
    481  HEADER_TICKS_SPACING_MIN: 60, // px
    482  // Reserve extra space for rendering waterfall time label
    483  LABEL_WIDTH: 50, // px
    484 };
    485 
    486 const TIMING_KEYS = [
    487  "blocked",
    488  "dns",
    489  "connect",
    490  "ssl",
    491  "send",
    492  "wait",
    493  "receive",
    494 ];
    495 
    496 // Minimal width of Network Monitor column is 30px, for Waterfall 150px
    497 // Default width of columns (which are not defined in DEFAULT_COLUMNS_DATA) is 8%
    498 const MIN_COLUMN_WIDTH = 30; // in px
    499 const DEFAULT_COLUMN_WIDTH = 8; // in %
    500 /**
    501 * A mapping of HTTP status codes.
    502 */
    503 const SUPPORTED_HTTP_CODES = [
    504  "100",
    505  "101",
    506  "103",
    507  "200",
    508  "201",
    509  "202",
    510  "203",
    511  "204",
    512  "205",
    513  "206",
    514  "300",
    515  "301",
    516  "302",
    517  "303",
    518  "304",
    519  "307",
    520  "308",
    521  "400",
    522  "401",
    523  "403",
    524  "404",
    525  "405",
    526  "406",
    527  "407",
    528  "408",
    529  "409",
    530  "410",
    531  "411",
    532  "412",
    533  "413",
    534  "414",
    535  "415",
    536  "416",
    537  "417",
    538  "418",
    539  "422",
    540  "425",
    541  "426",
    542  "428",
    543  "429",
    544  "431",
    545  "451",
    546  "500",
    547  "501",
    548  "502",
    549  "503",
    550  "504",
    551  "505",
    552  "511",
    553 ];
    554 
    555 // Keys are the codes provided by server, values are localization messages
    556 // prefixed by "netmonitor.blocked."
    557 const BLOCKED_REASON_MESSAGES = {
    558  devtools: "Blocked by DevTools",
    559  1001: "CORS disabled",
    560  1002: "CORS Failed",
    561  1003: "CORS Not HTTP",
    562  1004: "CORS Multiple Origin Not Allowed",
    563  1005: "CORS Missing Allow Origin",
    564  1006: "CORS No Allow Credentials",
    565  1007: "CORS Allow Origin Not Matching Origin",
    566  1008: "CORS Missing Allow Credentials",
    567  1009: "CORS Origin Header Missing",
    568  1010: "CORS External Redirect Not Allowed",
    569  1011: "CORS Preflight Did Not Succeed",
    570  1012: "CORS Invalid Allow Method",
    571  1013: "CORS Method Not Found",
    572  1014: "CORS Invalid Allow Header",
    573  1015: "CORS Missing Allow Header",
    574  2001: "Malware",
    575  2002: "Phishing",
    576  2003: "Unwanted",
    577  2004: "Tracking",
    578  2005: "Blocked",
    579  2006: "Harmful",
    580  2007: "Cryptomining",
    581  2008: "Fingerprinting",
    582  2009: "Socialtracking",
    583  2011: "Harmful Add-on Blocked",
    584  3001: "Mixed Block",
    585  4000: "CSP",
    586  4001: "CSP No Data Protocol",
    587  4002: "CSP Web Extension",
    588  4003: "CSP Content Blocked",
    589  4004: "CSP Data Document",
    590  4005: "CSP Web Browser",
    591  4006: "CSP Preload",
    592  5000: "Not same-origin",
    593  6000: "Blocked By Extension",
    594 };
    595 
    596 /** @see {@link https://searchfox.org/mozilla-central/rev/d7a8eadc28298c31381119cbf25c8ba14b8712b3/netwerk/protocol/websocket/nsIWebSocketEventService.idl#30-38} */
    597 const WEB_SOCKET_OPCODE = {
    598  CONTINUATION: 0,
    599  TEXT: 1,
    600  BINARY: 2,
    601  CLOSE: 8,
    602  PING: 9,
    603  PONG: 10,
    604 };
    605 
    606 const general = {
    607  ACTIVITY_TYPE,
    608  EVENTS,
    609  TEST_EVENTS,
    610  FILTER_SEARCH_DELAY: 200,
    611  UPDATE_PROPS,
    612  HEADERS,
    613  MESSAGE_HEADERS,
    614  RESPONSE_HEADERS,
    615  FILTER_FLAGS,
    616  FILTER_TAGS,
    617  REQUESTS_WATERFALL,
    618  PANELS,
    619  TIMING_KEYS,
    620  MIN_COLUMN_WIDTH,
    621  DEFAULT_COLUMN_WIDTH,
    622  SUPPORTED_HTTP_CODES,
    623  BLOCKED_REASON_MESSAGES,
    624  SEARCH_STATUS,
    625  AUTO_EXPAND_MAX_LEVEL: 7,
    626  AUTO_EXPAND_MAX_NODES: 50,
    627  CHANNEL_TYPE,
    628  WEB_SOCKET_OPCODE,
    629  // Arbitrary limit for rendering strings in the netmonitor table.
    630  // Useful for instance for very big data URIs.
    631  MAX_UI_STRING_LENGTH: 10000,
    632 };
    633 
    634 // flatten constants
    635 module.exports = Object.assign({}, general, actionTypes);