addon-sdk/source/python-lib/mozrunner/qijo.py

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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/.
     5 from ctypes import c_void_p, POINTER, sizeof, Structure, windll, WinError, WINFUNCTYPE, addressof, c_size_t, c_ulong
     6 from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LARGE_INTEGER
     8 LPVOID = c_void_p
     9 LPDWORD = POINTER(DWORD)
    10 SIZE_T = c_size_t
    11 ULONG_PTR = POINTER(c_ulong)
    13 # A ULONGLONG is a 64-bit unsigned integer.
    14 # Thus there are 8 bytes in a ULONGLONG.
    15 # XXX why not import c_ulonglong ?
    16 ULONGLONG = BYTE * 8
    18 class IO_COUNTERS(Structure):
    19     # The IO_COUNTERS struct is 6 ULONGLONGs.
    20     # TODO: Replace with non-dummy fields.
    21     _fields_ = [('dummy', ULONGLONG * 6)]
    23 class JOBOBJECT_BASIC_ACCOUNTING_INFORMATION(Structure):
    24     _fields_ = [('TotalUserTime', LARGE_INTEGER),
    25                 ('TotalKernelTime', LARGE_INTEGER),
    26                 ('ThisPeriodTotalUserTime', LARGE_INTEGER),
    27                 ('ThisPeriodTotalKernelTime', LARGE_INTEGER),
    28                 ('TotalPageFaultCount', DWORD),
    29                 ('TotalProcesses', DWORD),
    30                 ('ActiveProcesses', DWORD),
    31                 ('TotalTerminatedProcesses', DWORD)]
    33 class JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION(Structure):
    34     _fields_ = [('BasicInfo', JOBOBJECT_BASIC_ACCOUNTING_INFORMATION),
    35                 ('IoInfo', IO_COUNTERS)]
    37 # see http://msdn.microsoft.com/en-us/library/ms684147%28VS.85%29.aspx
    38 class JOBOBJECT_BASIC_LIMIT_INFORMATION(Structure):
    39     _fields_ = [('PerProcessUserTimeLimit', LARGE_INTEGER),
    40                 ('PerJobUserTimeLimit', LARGE_INTEGER),
    41                 ('LimitFlags', DWORD),
    42                 ('MinimumWorkingSetSize', SIZE_T),
    43                 ('MaximumWorkingSetSize', SIZE_T),
    44                 ('ActiveProcessLimit', DWORD),
    45                 ('Affinity', ULONG_PTR),
    46                 ('PriorityClass', DWORD),
    47                 ('SchedulingClass', DWORD)
    48                 ]
    50 # see http://msdn.microsoft.com/en-us/library/ms684156%28VS.85%29.aspx
    51 class JOBOBJECT_EXTENDED_LIMIT_INFORMATION(Structure):
    52     _fields_ = [('BasicLimitInformation', JOBOBJECT_BASIC_LIMIT_INFORMATION),
    53                 ('IoInfo', IO_COUNTERS),
    54                 ('ProcessMemoryLimit', SIZE_T),
    55                 ('JobMemoryLimit', SIZE_T),
    56                 ('PeakProcessMemoryUsed', SIZE_T),
    57                 ('PeakJobMemoryUsed', SIZE_T)]
    59 # XXX Magical numbers like 8 should be documented
    60 JobObjectBasicAndIoAccountingInformation = 8
    62 # ...like magical number 9 comes from
    63 # http://community.flexerasoftware.com/archive/index.php?t-181670.html
    64 # I wish I had a more canonical source
    65 JobObjectExtendedLimitInformation = 9
    67 class JobObjectInfo(object):
    68     mapping = { 'JobObjectBasicAndIoAccountingInformation': 8,
    69                 'JobObjectExtendedLimitInformation': 9
    70                 }
    71     structures = { 8: JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION,
    72                    9: JOBOBJECT_EXTENDED_LIMIT_INFORMATION
    73                    }
    74     def __init__(self, _class):
    75         if isinstance(_class, basestring):
    76             assert _class in self.mapping, 'Class should be one of %s; you gave %s' % (self.mapping, _class)
    77             _class = self.mapping[_class]
    78         assert _class in self.structures, 'Class should be one of %s; you gave %s' % (self.structures, _class)
    79         self.code = _class
    80         self.info = self.structures[_class]()
    83 QueryInformationJobObjectProto = WINFUNCTYPE(
    84     BOOL,        # Return type
    85     HANDLE,      # hJob
    86     DWORD,       # JobObjectInfoClass
    87     LPVOID,      # lpJobObjectInfo
    88     DWORD,       # cbJobObjectInfoLength
    89     LPDWORD      # lpReturnLength
    90     )
    92 QueryInformationJobObjectFlags = (
    93     (1, 'hJob'),
    94     (1, 'JobObjectInfoClass'),
    95     (1, 'lpJobObjectInfo'),
    96     (1, 'cbJobObjectInfoLength'),
    97     (1, 'lpReturnLength', None)
    98     )
   100 _QueryInformationJobObject = QueryInformationJobObjectProto(
   101     ('QueryInformationJobObject', windll.kernel32),
   102     QueryInformationJobObjectFlags
   103     )
   105 class SubscriptableReadOnlyStruct(object):
   106     def __init__(self, struct):
   107         self._struct = struct
   109     def _delegate(self, name):
   110         result = getattr(self._struct, name)
   111         if isinstance(result, Structure):
   112             return SubscriptableReadOnlyStruct(result)
   113         return result
   115     def __getitem__(self, name):
   116         match = [fname for fname, ftype in self._struct._fields_
   117                  if fname == name]
   118         if match:
   119             return self._delegate(name)
   120         raise KeyError(name)
   122     def __getattr__(self, name):
   123         return self._delegate(name)
   125 def QueryInformationJobObject(hJob, JobObjectInfoClass):
   126     jobinfo = JobObjectInfo(JobObjectInfoClass)
   127     result = _QueryInformationJobObject(
   128         hJob=hJob,
   129         JobObjectInfoClass=jobinfo.code,
   130         lpJobObjectInfo=addressof(jobinfo.info),
   131         cbJobObjectInfoLength=sizeof(jobinfo.info)
   132         )
   133     if not result:
   134         raise WinError()
   135     return SubscriptableReadOnlyStruct(jobinfo.info)
   137 def test_qijo():
   138     from killableprocess import Popen
   140     popen = Popen('c:\\windows\\notepad.exe')
   142     try:
   143         result = QueryInformationJobObject(0, 8)
   144         raise AssertionError('throw should occur')
   145     except WindowsError, e:
   146         pass
   148     try:
   149         result = QueryInformationJobObject(0, 1)
   150         raise AssertionError('throw should occur')
   151     except NotImplementedError, e:
   152         pass
   154     result = QueryInformationJobObject(popen._job, 8)
   155     if result['BasicInfo']['ActiveProcesses'] != 1:
   156         raise AssertionError('expected ActiveProcesses to be 1')
   157     popen.kill()
   159     result = QueryInformationJobObject(popen._job, 8)
   160     if result.BasicInfo.ActiveProcesses != 0:
   161         raise AssertionError('expected ActiveProcesses to be 0')
   163 if __name__ == '__main__':
   164     print "testing."
   165     test_qijo()
   166     print "success!"

mercurial