First checkin of the Python XPCOM bindings.
git-svn-id: svn://10.0.0.236/trunk@87331 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
567
mozilla/extensions/python/xpcom/LICENSE.txt
Normal file
567
mozilla/extensions/python/xpcom/LICENSE.txt
Normal file
@@ -0,0 +1,567 @@
|
||||
MOZILLA PUBLIC LICENSE
|
||||
Version 1.1
|
||||
|
||||
---------------
|
||||
|
||||
1. Definitions.
|
||||
|
||||
1.0.1. "Commercial Use" means distribution or otherwise making the
|
||||
Covered Code available to a third party.
|
||||
|
||||
1.1. "Contributor" means each entity that creates or contributes to
|
||||
the creation of Modifications.
|
||||
|
||||
1.2. "Contributor Version" means the combination of the Original
|
||||
Code, prior Modifications used by a Contributor, and the Modifications
|
||||
made by that particular Contributor.
|
||||
|
||||
1.3. "Covered Code" means the Original Code or Modifications or the
|
||||
combination of the Original Code and Modifications, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.4. "Electronic Distribution Mechanism" means a mechanism generally
|
||||
accepted in the software development community for the electronic
|
||||
transfer of data.
|
||||
|
||||
1.5. "Executable" means Covered Code in any form other than Source
|
||||
Code.
|
||||
|
||||
1.6. "Initial Developer" means the individual or entity identified
|
||||
as the Initial Developer in the Source Code notice required by Exhibit
|
||||
A.
|
||||
|
||||
1.7. "Larger Work" means a work which combines Covered Code or
|
||||
portions thereof with code not governed by the terms of this License.
|
||||
|
||||
1.8. "License" means this document.
|
||||
|
||||
1.8.1. "Licensable" means having the right to grant, to the maximum
|
||||
extent possible, whether at the time of the initial grant or
|
||||
subsequently acquired, any and all of the rights conveyed herein.
|
||||
|
||||
1.9. "Modifications" means any addition to or deletion from the
|
||||
substance or structure of either the Original Code or any previous
|
||||
Modifications. When Covered Code is released as a series of files, a
|
||||
Modification is:
|
||||
A. Any addition to or deletion from the contents of a file
|
||||
containing Original Code or previous Modifications.
|
||||
|
||||
B. Any new file that contains any part of the Original Code or
|
||||
previous Modifications.
|
||||
|
||||
1.10. "Original Code" means Source Code of computer software code
|
||||
which is described in the Source Code notice required by Exhibit A as
|
||||
Original Code, and which, at the time of its release under this
|
||||
License is not already Covered Code governed by this License.
|
||||
|
||||
1.10.1. "Patent Claims" means any patent claim(s), now owned or
|
||||
hereafter acquired, including without limitation, method, process,
|
||||
and apparatus claims, in any patent Licensable by grantor.
|
||||
|
||||
1.11. "Source Code" means the preferred form of the Covered Code for
|
||||
making modifications to it, including all modules it contains, plus
|
||||
any associated interface definition files, scripts used to control
|
||||
compilation and installation of an Executable, or source code
|
||||
differential comparisons against either the Original Code or another
|
||||
well known, available Covered Code of the Contributor's choice. The
|
||||
Source Code can be in a compressed or archival form, provided the
|
||||
appropriate decompression or de-archiving software is widely available
|
||||
for no charge.
|
||||
|
||||
1.12. "You" (or "Your") means an individual or a legal entity
|
||||
exercising rights under, and complying with all of the terms of, this
|
||||
License or a future version of this License issued under Section 6.1.
|
||||
For legal entities, "You" includes any entity which controls, is
|
||||
controlled by, or is under common control with You. For purposes of
|
||||
this definition, "control" means (a) the power, direct or indirect,
|
||||
to cause the direction or management of such entity, whether by
|
||||
contract or otherwise, or (b) ownership of more than fifty percent
|
||||
(50%) of the outstanding shares or beneficial ownership of such
|
||||
entity.
|
||||
|
||||
2. Source Code License.
|
||||
|
||||
2.1. The Initial Developer Grant.
|
||||
The Initial Developer hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license, subject to third party intellectual property
|
||||
claims:
|
||||
(a) under intellectual property rights (other than patent or
|
||||
trademark) Licensable by Initial Developer to use, reproduce,
|
||||
modify, display, perform, sublicense and distribute the Original
|
||||
Code (or portions thereof) with or without Modifications, and/or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patents Claims infringed by the making, using or
|
||||
selling of Original Code, to make, have made, use, practice,
|
||||
sell, and offer for sale, and/or otherwise dispose of the
|
||||
Original Code (or portions thereof).
|
||||
|
||||
(c) the licenses granted in this Section 2.1(a) and (b) are
|
||||
effective on the date Initial Developer first distributes
|
||||
Original Code under the terms of this License.
|
||||
|
||||
(d) Notwithstanding Section 2.1(b) above, no patent license is
|
||||
granted: 1) for code that You delete from the Original Code; 2)
|
||||
separate from the Original Code; or 3) for infringements caused
|
||||
by: i) the modification of the Original Code or ii) the
|
||||
combination of the Original Code with other software or devices.
|
||||
|
||||
2.2. Contributor Grant.
|
||||
Subject to third party intellectual property claims, each Contributor
|
||||
hereby grants You a world-wide, royalty-free, non-exclusive license
|
||||
|
||||
(a) under intellectual property rights (other than patent or
|
||||
trademark) Licensable by Contributor, to use, reproduce, modify,
|
||||
display, perform, sublicense and distribute the Modifications
|
||||
created by such Contributor (or portions thereof) either on an
|
||||
unmodified basis, with other Modifications, as Covered Code
|
||||
and/or as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims infringed by the making, using, or
|
||||
selling of Modifications made by that Contributor either alone
|
||||
and/or in combination with its Contributor Version (or portions
|
||||
of such combination), to make, use, sell, offer for sale, have
|
||||
made, and/or otherwise dispose of: 1) Modifications made by that
|
||||
Contributor (or portions thereof); and 2) the combination of
|
||||
Modifications made by that Contributor with its Contributor
|
||||
Version (or portions of such combination).
|
||||
|
||||
(c) the licenses granted in Sections 2.2(a) and 2.2(b) are
|
||||
effective on the date Contributor first makes Commercial Use of
|
||||
the Covered Code.
|
||||
|
||||
(d) Notwithstanding Section 2.2(b) above, no patent license is
|
||||
granted: 1) for any code that Contributor has deleted from the
|
||||
Contributor Version; 2) separate from the Contributor Version;
|
||||
3) for infringements caused by: i) third party modifications of
|
||||
Contributor Version or ii) the combination of Modifications made
|
||||
by that Contributor with other software (except as part of the
|
||||
Contributor Version) or other devices; or 4) under Patent Claims
|
||||
infringed by Covered Code in the absence of Modifications made by
|
||||
that Contributor.
|
||||
|
||||
3. Distribution Obligations.
|
||||
|
||||
3.1. Application of License.
|
||||
The Modifications which You create or to which You contribute are
|
||||
governed by the terms of this License, including without limitation
|
||||
Section 2.2. The Source Code version of Covered Code may be
|
||||
distributed only under the terms of this License or a future version
|
||||
of this License released under Section 6.1, and You must include a
|
||||
copy of this License with every copy of the Source Code You
|
||||
distribute. You may not offer or impose any terms on any Source Code
|
||||
version that alters or restricts the applicable version of this
|
||||
License or the recipients' rights hereunder. However, You may include
|
||||
an additional document offering the additional rights described in
|
||||
Section 3.5.
|
||||
|
||||
3.2. Availability of Source Code.
|
||||
Any Modification which You create or to which You contribute must be
|
||||
made available in Source Code form under the terms of this License
|
||||
either on the same media as an Executable version or via an accepted
|
||||
Electronic Distribution Mechanism to anyone to whom you made an
|
||||
Executable version available; and if made available via Electronic
|
||||
Distribution Mechanism, must remain available for at least twelve (12)
|
||||
months after the date it initially became available, or at least six
|
||||
(6) months after a subsequent version of that particular Modification
|
||||
has been made available to such recipients. You are responsible for
|
||||
ensuring that the Source Code version remains available even if the
|
||||
Electronic Distribution Mechanism is maintained by a third party.
|
||||
|
||||
3.3. Description of Modifications.
|
||||
You must cause all Covered Code to which You contribute to contain a
|
||||
file documenting the changes You made to create that Covered Code and
|
||||
the date of any change. You must include a prominent statement that
|
||||
the Modification is derived, directly or indirectly, from Original
|
||||
Code provided by the Initial Developer and including the name of the
|
||||
Initial Developer in (a) the Source Code, and (b) in any notice in an
|
||||
Executable version or related documentation in which You describe the
|
||||
origin or ownership of the Covered Code.
|
||||
|
||||
3.4. Intellectual Property Matters
|
||||
(a) Third Party Claims.
|
||||
If Contributor has knowledge that a license under a third party's
|
||||
intellectual property rights is required to exercise the rights
|
||||
granted by such Contributor under Sections 2.1 or 2.2,
|
||||
Contributor must include a text file with the Source Code
|
||||
distribution titled "LEGAL" which describes the claim and the
|
||||
party making the claim in sufficient detail that a recipient will
|
||||
know whom to contact. If Contributor obtains such knowledge after
|
||||
the Modification is made available as described in Section 3.2,
|
||||
Contributor shall promptly modify the LEGAL file in all copies
|
||||
Contributor makes available thereafter and shall take other steps
|
||||
(such as notifying appropriate mailing lists or newsgroups)
|
||||
reasonably calculated to inform those who received the Covered
|
||||
Code that new knowledge has been obtained.
|
||||
|
||||
(b) Contributor APIs.
|
||||
If Contributor's Modifications include an application programming
|
||||
interface and Contributor has knowledge of patent licenses which
|
||||
are reasonably necessary to implement that API, Contributor must
|
||||
also include this information in the LEGAL file.
|
||||
|
||||
(c) Representations.
|
||||
Contributor represents that, except as disclosed pursuant to
|
||||
Section 3.4(a) above, Contributor believes that Contributor's
|
||||
Modifications are Contributor's original creation(s) and/or
|
||||
Contributor has sufficient rights to grant the rights conveyed by
|
||||
this License.
|
||||
|
||||
3.5. Required Notices.
|
||||
You must duplicate the notice in Exhibit A in each file of the Source
|
||||
Code. If it is not possible to put such notice in a particular Source
|
||||
Code file due to its structure, then You must include such notice in a
|
||||
location (such as a relevant directory) where a user would be likely
|
||||
to look for such a notice. If You created one or more Modification(s)
|
||||
You may add your name as a Contributor to the notice described in
|
||||
Exhibit A. You must also duplicate this License in any documentation
|
||||
for the Source Code where You describe recipients' rights or ownership
|
||||
rights relating to Covered Code. You may choose to offer, and to
|
||||
charge a fee for, warranty, support, indemnity or liability
|
||||
obligations to one or more recipients of Covered Code. However, You
|
||||
may do so only on Your own behalf, and not on behalf of the Initial
|
||||
Developer or any Contributor. You must make it absolutely clear than
|
||||
any such warranty, support, indemnity or liability obligation is
|
||||
offered by You alone, and You hereby agree to indemnify the Initial
|
||||
Developer and every Contributor for any liability incurred by the
|
||||
Initial Developer or such Contributor as a result of warranty,
|
||||
support, indemnity or liability terms You offer.
|
||||
|
||||
3.6. Distribution of Executable Versions.
|
||||
You may distribute Covered Code in Executable form only if the
|
||||
requirements of Section 3.1-3.5 have been met for that Covered Code,
|
||||
and if You include a notice stating that the Source Code version of
|
||||
the Covered Code is available under the terms of this License,
|
||||
including a description of how and where You have fulfilled the
|
||||
obligations of Section 3.2. The notice must be conspicuously included
|
||||
in any notice in an Executable version, related documentation or
|
||||
collateral in which You describe recipients' rights relating to the
|
||||
Covered Code. You may distribute the Executable version of Covered
|
||||
Code or ownership rights under a license of Your choice, which may
|
||||
contain terms different from this License, provided that You are in
|
||||
compliance with the terms of this License and that the license for the
|
||||
Executable version does not attempt to limit or alter the recipient's
|
||||
rights in the Source Code version from the rights set forth in this
|
||||
License. If You distribute the Executable version under a different
|
||||
license You must make it absolutely clear that any terms which differ
|
||||
from this License are offered by You alone, not by the Initial
|
||||
Developer or any Contributor. You hereby agree to indemnify the
|
||||
Initial Developer and every Contributor for any liability incurred by
|
||||
the Initial Developer or such Contributor as a result of any such
|
||||
terms You offer.
|
||||
|
||||
3.7. Larger Works.
|
||||
You may create a Larger Work by combining Covered Code with other code
|
||||
not governed by the terms of this License and distribute the Larger
|
||||
Work as a single product. In such a case, You must make sure the
|
||||
requirements of this License are fulfilled for the Covered Code.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation.
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Code due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description
|
||||
must be included in the LEGAL file described in Section 3.4 and must
|
||||
be included with all distributions of the Source Code. Except to the
|
||||
extent prohibited by statute or regulation, such description must be
|
||||
sufficiently detailed for a recipient of ordinary skill to be able to
|
||||
understand it.
|
||||
|
||||
5. Application of this License.
|
||||
|
||||
This License applies to code to which the Initial Developer has
|
||||
attached the notice in Exhibit A and to related Covered Code.
|
||||
|
||||
6. Versions of the License.
|
||||
|
||||
6.1. New Versions.
|
||||
Netscape Communications Corporation ("Netscape") may publish revised
|
||||
and/or new versions of the License from time to time. Each version
|
||||
will be given a distinguishing version number.
|
||||
|
||||
6.2. Effect of New Versions.
|
||||
Once Covered Code has been published under a particular version of the
|
||||
License, You may always continue to use it under the terms of that
|
||||
version. You may also choose to use such Covered Code under the terms
|
||||
of any subsequent version of the License published by Netscape. No one
|
||||
other than Netscape has the right to modify the terms applicable to
|
||||
Covered Code created under this License.
|
||||
|
||||
6.3. Derivative Works.
|
||||
If You create or use a modified version of this License (which you may
|
||||
only do in order to apply it to code which is not already Covered Code
|
||||
governed by this License), You must (a) rename Your license so that
|
||||
the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
|
||||
"MPL", "NPL" or any confusingly similar phrase do not appear in your
|
||||
license (except to note that your license differs from this License)
|
||||
and (b) otherwise make it clear that Your version of the license
|
||||
contains terms which differ from the Mozilla Public License and
|
||||
Netscape Public License. (Filling in the name of the Initial
|
||||
Developer, Original Code or Contributor in the notice described in
|
||||
Exhibit A shall not of themselves be deemed to be modifications of
|
||||
this License.)
|
||||
|
||||
7. DISCLAIMER OF WARRANTY.
|
||||
|
||||
COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||||
WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
|
||||
DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
|
||||
THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
|
||||
IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
|
||||
YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
|
||||
COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
|
||||
OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
|
||||
ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
|
||||
|
||||
8. TERMINATION.
|
||||
|
||||
8.1. This License and the rights granted hereunder will terminate
|
||||
automatically if You fail to comply with terms herein and fail to cure
|
||||
such breach within 30 days of becoming aware of the breach. All
|
||||
sublicenses to the Covered Code which are properly granted shall
|
||||
survive any termination of this License. Provisions which, by their
|
||||
nature, must remain in effect beyond the termination of this License
|
||||
shall survive.
|
||||
|
||||
8.2. If You initiate litigation by asserting a patent infringement
|
||||
claim (excluding declatory judgment actions) against Initial Developer
|
||||
or a Contributor (the Initial Developer or Contributor against whom
|
||||
You file such action is referred to as "Participant") alleging that:
|
||||
|
||||
(a) such Participant's Contributor Version directly or indirectly
|
||||
infringes any patent, then any and all rights granted by such
|
||||
Participant to You under Sections 2.1 and/or 2.2 of this License
|
||||
shall, upon 60 days notice from Participant terminate prospectively,
|
||||
unless if within 60 days after receipt of notice You either: (i)
|
||||
agree in writing to pay Participant a mutually agreeable reasonable
|
||||
royalty for Your past and future use of Modifications made by such
|
||||
Participant, or (ii) withdraw Your litigation claim with respect to
|
||||
the Contributor Version against such Participant. If within 60 days
|
||||
of notice, a reasonable royalty and payment arrangement are not
|
||||
mutually agreed upon in writing by the parties or the litigation claim
|
||||
is not withdrawn, the rights granted by Participant to You under
|
||||
Sections 2.1 and/or 2.2 automatically terminate at the expiration of
|
||||
the 60 day notice period specified above.
|
||||
|
||||
(b) any software, hardware, or device, other than such Participant's
|
||||
Contributor Version, directly or indirectly infringes any patent, then
|
||||
any rights granted to You by such Participant under Sections 2.1(b)
|
||||
and 2.2(b) are revoked effective as of the date You first made, used,
|
||||
sold, distributed, or had made, Modifications made by that
|
||||
Participant.
|
||||
|
||||
8.3. If You assert a patent infringement claim against Participant
|
||||
alleging that such Participant's Contributor Version directly or
|
||||
indirectly infringes any patent where such claim is resolved (such as
|
||||
by license or settlement) prior to the initiation of patent
|
||||
infringement litigation, then the reasonable value of the licenses
|
||||
granted by such Participant under Sections 2.1 or 2.2 shall be taken
|
||||
into account in determining the amount or value of any payment or
|
||||
license.
|
||||
|
||||
8.4. In the event of termination under Sections 8.1 or 8.2 above,
|
||||
all end user license agreements (excluding distributors and resellers)
|
||||
which have been validly granted by You or any distributor hereunder
|
||||
prior to termination shall survive termination.
|
||||
|
||||
9. LIMITATION OF LIABILITY.
|
||||
|
||||
UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
|
||||
(INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
|
||||
DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
|
||||
OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
|
||||
ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
|
||||
CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
|
||||
WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
|
||||
COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
|
||||
INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
|
||||
LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
|
||||
RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
|
||||
PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
|
||||
EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
|
||||
THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
|
||||
|
||||
10. U.S. GOVERNMENT END USERS.
|
||||
|
||||
The Covered Code is a "commercial item," as that term is defined in
|
||||
48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
|
||||
software" and "commercial computer software documentation," as such
|
||||
terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
|
||||
C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
|
||||
all U.S. Government End Users acquire Covered Code with only those
|
||||
rights set forth herein.
|
||||
|
||||
11. MISCELLANEOUS.
|
||||
|
||||
This License represents the complete agreement concerning subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. This License shall be governed by
|
||||
California law provisions (except to the extent applicable law, if
|
||||
any, provides otherwise), excluding its conflict-of-law provisions.
|
||||
With respect to disputes in which at least one party is a citizen of,
|
||||
or an entity chartered or registered to do business in the United
|
||||
States of America, any litigation relating to this License shall be
|
||||
subject to the jurisdiction of the Federal Courts of the Northern
|
||||
District of California, with venue lying in Santa Clara County,
|
||||
California, with the losing party responsible for costs, including
|
||||
without limitation, court costs and reasonable attorneys' fees and
|
||||
expenses. The application of the United Nations Convention on
|
||||
Contracts for the International Sale of Goods is expressly excluded.
|
||||
Any law or regulation which provides that the language of a contract
|
||||
shall be construed against the drafter shall not apply to this
|
||||
License.
|
||||
|
||||
12. RESPONSIBILITY FOR CLAIMS.
|
||||
|
||||
As between Initial Developer and the Contributors, each party is
|
||||
responsible for claims and damages arising, directly or indirectly,
|
||||
out of its utilization of rights under this License and You agree to
|
||||
work with Initial Developer and Contributors to distribute such
|
||||
responsibility on an equitable basis. Nothing herein is intended or
|
||||
shall be deemed to constitute any admission of liability.
|
||||
|
||||
13. MULTIPLE-LICENSED CODE.
|
||||
|
||||
Initial Developer may designate portions of the Covered Code as
|
||||
"Multiple-Licensed". "Multiple-Licensed" means that the Initial
|
||||
Developer permits you to utilize portions of the Covered Code under
|
||||
Your choice of the NPL or the alternative licenses, if any, specified
|
||||
by the Initial Developer in the file described in Exhibit A.
|
||||
|
||||
EXHIBIT A -Mozilla Public License.
|
||||
|
||||
``The contents of this file are subject to the Mozilla Public License
|
||||
Version 1.1 (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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS"
|
||||
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing rights and limitations
|
||||
under the License.
|
||||
|
||||
The Original Code is ______________________________________.
|
||||
|
||||
The Initial Developer of the Original Code is ________________________.
|
||||
Portions created by ______________________ are Copyright (C) ______
|
||||
_______________________. All Rights Reserved.
|
||||
|
||||
Contributor(s): ______________________________________.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms
|
||||
of the _____ license (the "[___] License"), in which case the
|
||||
provisions of [______] License are applicable instead of those
|
||||
above. If you wish to allow use of your version of this file only
|
||||
under the terms of the [____] License and not to allow others to use
|
||||
your version of this file under the MPL, indicate your decision by
|
||||
deleting the provisions above and replace them with the notice and
|
||||
other provisions required by the [___] License. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file
|
||||
under either the MPL or the [___] License."
|
||||
|
||||
[NOTE: The text of this Exhibit A may differ slightly from the text of
|
||||
the notices in the Source Code files of the Original Code. You should
|
||||
use the text of this Exhibit A rather than the text found in the
|
||||
Original Code Source Code for Your Modifications.]
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
AMENDMENTS
|
||||
|
||||
The Netscape Public License Version 1.1 ("NPL") consists of the
|
||||
Mozilla Public License Version 1.1 with the following Amendments,
|
||||
including Exhibit A-Netscape Public License. Files identified with
|
||||
"Exhibit A-Netscape Public License" are governed by the Netscape
|
||||
Public License Version 1.1.
|
||||
|
||||
Additional Terms applicable to the Netscape Public License.
|
||||
I. Effect.
|
||||
These additional terms described in this Netscape Public
|
||||
License -- Amendments shall apply to the Mozilla Communicator
|
||||
client code and to all Covered Code under this License.
|
||||
|
||||
II. "Netscape's Branded Code" means Covered Code that Netscape
|
||||
distributes and/or permits others to distribute under one or more
|
||||
trademark(s) which are controlled by Netscape but which are not
|
||||
licensed for use under this License.
|
||||
|
||||
III. Netscape and logo.
|
||||
This License does not grant any rights to use the trademarks
|
||||
"Netscape", the "Netscape N and horizon" logo or the "Netscape
|
||||
lighthouse" logo, "Netcenter", "Gecko", "Java" or "JavaScript",
|
||||
"Smart Browsing" even if such marks are included in the Original
|
||||
Code or Modifications.
|
||||
|
||||
IV. Inability to Comply Due to Contractual Obligation.
|
||||
Prior to licensing the Original Code under this License, Netscape
|
||||
has licensed third party code for use in Netscape's Branded Code.
|
||||
To the extent that Netscape is limited contractually from making
|
||||
such third party code available under this License, Netscape may
|
||||
choose to reintegrate such code into Covered Code without being
|
||||
required to distribute such code in Source Code form, even if
|
||||
such code would otherwise be considered "Modifications" under
|
||||
this License.
|
||||
|
||||
V. Use of Modifications and Covered Code by Initial Developer.
|
||||
V.1. In General.
|
||||
The obligations of Section 3 apply to Netscape, except to
|
||||
the extent specified in this Amendment, Section V.2 and V.3.
|
||||
|
||||
V.2. Other Products.
|
||||
Netscape may include Covered Code in products other than the
|
||||
Netscape's Branded Code which are released by Netscape
|
||||
during the two (2) years following the release date of the
|
||||
Original Code, without such additional products becoming
|
||||
subject to the terms of this License, and may license such
|
||||
additional products on different terms from those contained
|
||||
in this License.
|
||||
|
||||
V.3. Alternative Licensing.
|
||||
Netscape may license the Source Code of Netscape's Branded
|
||||
Code, including Modifications incorporated therein, without
|
||||
such Netscape Branded Code becoming subject to the terms of
|
||||
this License, and may license such Netscape Branded Code on
|
||||
different terms from those contained in this License.
|
||||
|
||||
VI. Litigation.
|
||||
Notwithstanding the limitations of Section 11 above, the
|
||||
provisions regarding litigation in Section 11(a), (b) and (c) of
|
||||
the License shall apply to all disputes relating to this License.
|
||||
|
||||
EXHIBIT A-Netscape Public License.
|
||||
|
||||
"The contents of this file are subject to the Netscape Public
|
||||
License Version 1.1 (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.mozilla.org/NPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS
|
||||
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
rights and limitations under the License.
|
||||
|
||||
The Original Code is Mozilla Communicator client code, released
|
||||
March 31, 1998.
|
||||
|
||||
The Initial Developer of the Original Code is Netscape
|
||||
Communications Corporation. Portions created by Netscape are
|
||||
Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
Rights Reserved.
|
||||
|
||||
Contributor(s): ______________________________________.
|
||||
|
||||
Alternatively, the contents of this file may be used under the
|
||||
terms of the _____ license (the "[___] License"), in which case
|
||||
the provisions of [______] License are applicable instead of
|
||||
those above. If you wish to allow use of your version of this
|
||||
file only under the terms of the [____] License and not to allow
|
||||
others to use your version of this file under the NPL, indicate
|
||||
your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the [___]
|
||||
License. If you do not delete the provisions above, a recipient
|
||||
may use your version of this file under either the NPL or the
|
||||
[___] License."
|
||||
53
mozilla/extensions/python/xpcom/__init__.py
Normal file
53
mozilla/extensions/python/xpcom/__init__.py
Normal file
@@ -0,0 +1,53 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# The XPCOM (Cross Platform COM) package.
|
||||
import exceptions
|
||||
|
||||
#import sys
|
||||
#sys.stdout = open("pystdout.log", "w")
|
||||
|
||||
# A global "verbose" flag - currently used by the
|
||||
# server package to print trace messages
|
||||
verbose = 0
|
||||
hr_map = {}
|
||||
|
||||
# The standard XPCOM exception object.
|
||||
# Instances of this class are raised by the XPCOM extension module.
|
||||
class Exception(exceptions.Exception):
|
||||
def __init__(self, errno, message = None):
|
||||
assert int(errno) == errno, "The errno param must be an integer"
|
||||
self.errno = errno
|
||||
self.message = message
|
||||
exceptions.Exception.__init__(self, errno)
|
||||
def __str__(self):
|
||||
if not hr_map:
|
||||
import nsError
|
||||
for name, val in nsError.__dict__.items():
|
||||
if type(val)==type(0):
|
||||
hr_map[val] = name
|
||||
message = self.message
|
||||
if message is None:
|
||||
message = hr_map.get(self.errno)
|
||||
if message is None:
|
||||
message = ""
|
||||
return "0x%x (%s)" % (self.errno, message)
|
||||
|
||||
# An alias for Exception - allows code to say "from xpcom import COMException"
|
||||
# rather than "Exception" - thereby preventing clashes.
|
||||
COMException = Exception
|
||||
|
||||
# Exceptions thrown by servers. It can be good for diagnostics to
|
||||
# differentiate between a ServerException (which was presumably explicitly thrown)
|
||||
# and a normal exception which may simply be propagating down.
|
||||
# (When ServerException objects are thrown across the XPConnect
|
||||
# gateway they will be converted back to normal client exceptions if
|
||||
# subsequently re-caught by Python
|
||||
class ServerException(Exception):
|
||||
def __init__(self, errno=None, *args, **kw):
|
||||
if errno is None:
|
||||
import nsError
|
||||
errno = nsError.NS_ERROR_FAILURE
|
||||
Exception.__init__(self, errno, *args, **kw)
|
||||
|
||||
# Some global functions.
|
||||
247
mozilla/extensions/python/xpcom/client/__init__.py
Normal file
247
mozilla/extensions/python/xpcom/client/__init__.py
Normal file
@@ -0,0 +1,247 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
import os
|
||||
import new
|
||||
from xpcom import xpt, _xpcom, COMException, nsError
|
||||
|
||||
XPTC_InvokeByIndex = _xpcom.XPTC_InvokeByIndex
|
||||
|
||||
_just_int_interfaces = ["nsISupportsPRInt32", "nsISupportsPRInt16", "nsISupportsPRUint32", "nsISupportsPRUint16", "nsISupportsPRUint8", "nsISupportsPRBool"]
|
||||
_just_long_interfaces = ["nsISupportsPRInt64", "nsISupportsPRUint64"]
|
||||
_just_float_interfaces = ["nsISupportsDouble", "nsISupportsFloat"]
|
||||
# When doing a specific conversion, the order we try the interfaces in.
|
||||
_int_interfaces = _just_int_interfaces + _just_float_interfaces
|
||||
_long_interfaces = _just_long_interfaces + _just_int_interfaces + _just_float_interfaces
|
||||
_float_interfaces = _just_float_interfaces + _just_long_interfaces + _just_int_interfaces
|
||||
|
||||
method_template = """
|
||||
def %s(self, %s):
|
||||
return XPTC_InvokeByIndex(self._comobj_, %d,
|
||||
(%s,
|
||||
(%s)))
|
||||
"""
|
||||
def _MakeMethodCode(method):
|
||||
# Build a declaration
|
||||
param_no = 0
|
||||
param_decls = []
|
||||
param_flags = []
|
||||
param_names = []
|
||||
used_default = 0
|
||||
for param in method.params:
|
||||
param_no = param_no + 1
|
||||
param_name = "Param%d" % (param_no,)
|
||||
param_default = ""
|
||||
if not param.hidden_indicator and param.IsIn() and not param.IsDipper():
|
||||
if param.IsOut() or used_default: # If the param is "inout", provide a useful default for the "in" direction.
|
||||
param_default = " = None"
|
||||
used_default = 1 # Once we have used one once, we must for the rest!
|
||||
param_decls.append(param_name + param_default)
|
||||
param_names.append(param_name)
|
||||
|
||||
type_repr = xpt.MakeReprForInvoke(param)
|
||||
param_flags.append( (param.param_flags,) + type_repr )
|
||||
sep = ", "
|
||||
param_decls = sep.join(param_decls)
|
||||
if len(param_names)==1: # Damn tuple reprs.
|
||||
param_names = param_names[0] + ","
|
||||
else:
|
||||
param_names = sep.join(param_names)
|
||||
# A couple of extra newlines make them easier to read for debugging :-)
|
||||
return method_template % (method.name, param_decls, method.method_index, tuple(param_flags), param_names)
|
||||
|
||||
# Keyed by IID, each item is a tuple of (methods, getters, setters)
|
||||
interface_cache = {}
|
||||
|
||||
# Fully process the interface - generate method code, etc.
|
||||
def BuildInterfaceInfo(iid):
|
||||
ret = interface_cache.get(iid, None)
|
||||
if ret is None:
|
||||
# Build the data for the cache.
|
||||
method_code_blocks = []
|
||||
getters = {}
|
||||
setters = {}
|
||||
method_names = []
|
||||
|
||||
interface = xpt.Interface(iid)
|
||||
for m in interface.methods:
|
||||
if not m.IsNotXPCOM() and \
|
||||
not m.IsHidden() and \
|
||||
not m.IsConstructor():
|
||||
# Yay - a method we can use!
|
||||
if m.IsSetter():
|
||||
param_flags = map(lambda x: (x.param_flags,) + xpt.MakeReprForInvoke(x), m.params)
|
||||
setters[m.name] = m.method_index, param_flags
|
||||
elif m.IsGetter():
|
||||
param_flags = map(lambda x: (x.param_flags,) + xpt.MakeReprForInvoke(x), m.params)
|
||||
getters[m.name] = m.method_index, param_flags
|
||||
else:
|
||||
method_names.append(m.name)
|
||||
method_code_blocks.append(_MakeMethodCode(m))
|
||||
|
||||
# Build the constants.
|
||||
constants = {}
|
||||
for c in interface.constants:
|
||||
constants[c.name] = c.value
|
||||
# Build the methods - We only build function objects here
|
||||
# - they are bound to each instance at instance creation.
|
||||
methods = {}
|
||||
if len(method_code_blocks)!=0:
|
||||
method_code = "\n".join(method_code_blocks)
|
||||
## print "Method Code:"
|
||||
## print method_code
|
||||
codeObject = compile(method_code, "<XPCOMObject method>","exec")
|
||||
# Exec the code object
|
||||
tempNameSpace = {}
|
||||
exec codeObject in globals(), tempNameSpace # self.__dict__, self.__dict__
|
||||
for name in method_names:
|
||||
methods[name] = tempNameSpace[name]
|
||||
ret = methods, getters, setters, constants
|
||||
interface_cache[iid] = ret
|
||||
return ret
|
||||
|
||||
def Component(ob, iid):
|
||||
ob_name = None
|
||||
if not hasattr(ob, "IID"):
|
||||
ob_name = ob
|
||||
cm = _xpcom.NS_GetGlobalComponentManager()
|
||||
ob = cm.CreateInstanceByContractID(ob)
|
||||
return Interface(ob, iid)
|
||||
|
||||
class Interface:
|
||||
"""Implements a dynamic interface using xpcom reflection.
|
||||
"""
|
||||
def __init__(self, ob, iid, object_name = None):
|
||||
ob = ob.QueryInterface(iid, 0) # zero means "no auto-wrap"
|
||||
self.__dict__['_comobj_'] = ob
|
||||
# Hack - the last interface only!
|
||||
methods, getters, setters, constants = BuildInterfaceInfo(iid)
|
||||
self.__dict__['_interface_infos_'] = getters, setters
|
||||
self.__dict__['_interface_methods_'] = methods # Unbound methods.
|
||||
|
||||
self.__dict__.update(constants)
|
||||
# We remember the constant names to prevent the user trying to assign to them!
|
||||
self.__dict__['_constant_names_'] = constants.keys()
|
||||
|
||||
if object_name is None:
|
||||
object_name = "object with interface '%s'" % (iid.name,)
|
||||
self.__dict__['_object_name_'] = object_name
|
||||
|
||||
def __cmp__(self, other):
|
||||
try:
|
||||
other = other._comobj_
|
||||
except AttributeError:
|
||||
pass
|
||||
return cmp(self._comobj_, other)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self._comobj_)
|
||||
|
||||
def __repr__(self):
|
||||
return "<XPCOM interface '%s'>" % (self._comobj_.IID.name,)
|
||||
|
||||
# See if the object support strings.
|
||||
def __str__(self):
|
||||
try:
|
||||
self._comobj_.QueryInterface(_xpcom.IID_nsISupportsString)
|
||||
return str(self._comobj_)
|
||||
except COMException:
|
||||
return self.__repr__()
|
||||
|
||||
# Try the numeric support.
|
||||
def _do_conversion(self, interface_names, cvt):
|
||||
iim = _xpcom.XPTI_GetInterfaceInfoManager()
|
||||
for interface_name in interface_names:
|
||||
iid = iim.GetInfoForName(interface_name).GetIID()
|
||||
try:
|
||||
prim = self._comobj_.QueryInterface(iid)
|
||||
return cvt(prim.data)
|
||||
except COMException:
|
||||
pass
|
||||
raise ValueError, "This object does not support automatic numeric conversion to this type"
|
||||
|
||||
def __int__(self):
|
||||
return self._do_conversion(_int_interfaces, int)
|
||||
|
||||
def __long__(self):
|
||||
return self._do_conversion(_long_interfaces, long)
|
||||
|
||||
def __float__(self):
|
||||
return self._do_conversion(_float_interfaces, float)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
# Allow the underlying interface to provide a better implementation if desired.
|
||||
ret = getattr(self.__dict__['_comobj_'], attr, None)
|
||||
if ret is not None:
|
||||
return ret
|
||||
# Do the function thing first.
|
||||
unbound_method = self.__dict__['_interface_methods_'].get(attr)
|
||||
if unbound_method is not None:
|
||||
return new.instancemethod(unbound_method, self, self.__class__)
|
||||
|
||||
getters, setters = self.__dict__['_interface_infos_']
|
||||
info = getters.get(attr)
|
||||
if info is None:
|
||||
raise AttributeError, "XPCOM component '%s' has no attribute '%s'" % (self._object_name_, attr)
|
||||
method_index, param_infos = info
|
||||
if len(param_infos)!=1: # Only expecting a retval
|
||||
raise RuntimeError, "Can't get properties with this many args!"
|
||||
args = ( param_infos, () )
|
||||
return XPTC_InvokeByIndex(self._comobj_, method_index, args)
|
||||
|
||||
def __setattr__(self, attr, val):
|
||||
# If we already have a __dict__ item of that name, and its not one of
|
||||
# our constants, we just directly set it, and leave.
|
||||
if self.__dict__.has_key(attr) and attr not in self.__dict__['_constant_names_']:
|
||||
self.__dict__[attr] = val
|
||||
return
|
||||
# Start sniffing for what sort of attribute this might be?
|
||||
getters, setters = self.__dict__['_interface_infos_']
|
||||
info = setters.get(attr)
|
||||
if info is None:
|
||||
raise AttributeError, "XPCOM component '%s' can not set attribute '%s'" % (self._object_name_, attr)
|
||||
method_index, param_infos = info
|
||||
if len(param_infos)!=1: # Only expecting a single input val
|
||||
raise RuntimeError, "Can't set properties with this many args!"
|
||||
real_param_infos = ( param_infos, (val,) )
|
||||
return XPTC_InvokeByIndex(self._comobj_, method_index, real_param_infos)
|
||||
|
||||
# Called by the _xpcom C++ framework to wrap interfaces up just
|
||||
# before they are returned.
|
||||
def MakeInterfaceResult(ob, iid):
|
||||
return Interface(ob, iid)
|
||||
|
||||
class WeakReference:
|
||||
"""A weak-reference object. You construct a weak reference by passing
|
||||
any COM object you like. If the object does not support weak
|
||||
refs, you will get a standard NS_NOINTERFACE exception.
|
||||
|
||||
Once you have a weak-reference, you can "call" the object to get
|
||||
back a strong reference. Eg:
|
||||
|
||||
>>> some_ob = components.classes['...]
|
||||
>>> weak_ref = WeakReference(some_ob)
|
||||
>>> new_ob = weak_ref() # new_ob is effectively "some_ob" at this point
|
||||
>>> # EXCEPT: new_ob may be None of some_ob has already died - a
|
||||
>>> # weak reference does not keep the object alive (that is the point)
|
||||
|
||||
You should never hold onto this resulting strong object for a long time,
|
||||
or else you defeat the purpose of the weak-reference.
|
||||
"""
|
||||
def __init__(self, ob, iid = None):
|
||||
swr = Interface(ob, _xpcom.IID_nsISupportsWeakReference)
|
||||
self._comobj_ = Interface(swr.GetWeakReference(), _xpcom.IID_nsIWeakReference)
|
||||
if iid is None:
|
||||
try:
|
||||
iid = ob.IID
|
||||
except AttributeError:
|
||||
iid = _xpcom.IID_nsISupports
|
||||
self._iid_ = iid
|
||||
def __call__(self, iid = None):
|
||||
if iid is None: iid = self._iid_
|
||||
try:
|
||||
return Interface(self._comobj_.QueryReferent(iid), iid)
|
||||
except COMException, details:
|
||||
if details.errno != nsError.NS_ERROR_NULL_POINTER:
|
||||
raise
|
||||
return None
|
||||
183
mozilla/extensions/python/xpcom/components.py
Normal file
183
mozilla/extensions/python/xpcom/components.py
Normal file
@@ -0,0 +1,183 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# This module provides the JavaScript "components" interface
|
||||
import xpt
|
||||
import xpcom, _xpcom
|
||||
import xpcom.client
|
||||
import xpcom.server
|
||||
import types
|
||||
|
||||
StringTypes = [types.StringType, types.UnicodeType]
|
||||
|
||||
# The "manager" object.
|
||||
manager = xpcom.client.Interface(_xpcom.NS_GetGlobalComponentManager(), _xpcom.IID_nsIComponentManager)
|
||||
|
||||
# The "interfaceInfoManager" object - JS doesnt have this.
|
||||
interfaceInfoManager = _xpcom.XPTI_GetInterfaceInfoManager()
|
||||
|
||||
# The "Exception" object
|
||||
Exception = xpcom.Exception
|
||||
|
||||
# Base class for our collections.
|
||||
# It appears that all objects supports "." and "[]" notation.
|
||||
# eg, "interface.nsISupports" or interfaces["nsISupports"]
|
||||
class _ComponentCollection:
|
||||
# Bases are to over-ride 2 methods.
|
||||
# _get_one(self, name) - to return one object by name
|
||||
# _build_dict - to return a dictionary which provide access into
|
||||
def __init__(self):
|
||||
self._dict_data = None
|
||||
def keys(self):
|
||||
if self._dict_data is None:
|
||||
self._dict_data = self._build_dict()
|
||||
return self._dict_data.keys()
|
||||
def items(self):
|
||||
if self._dict_data is None:
|
||||
self._dict_data = self._build_dict()
|
||||
return self._dict_data.items()
|
||||
def values(self):
|
||||
if self._dict_data is None:
|
||||
self._dict_data = self._build_dict()
|
||||
return self._dict_data.values()
|
||||
def has_key(self, key):
|
||||
if self._dict_data is None:
|
||||
self._dict_data = self._build_dict()
|
||||
return self._dict_data.has_key(key)
|
||||
|
||||
def __len__(self):
|
||||
if self._dict_data is None:
|
||||
self._dict_data = self._build_dict()
|
||||
return len(self._dict_data)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if self._dict_data is not None and self._dict_data.has_key(attr):
|
||||
return self._dict_data[attr]
|
||||
return self._get_one(attr)
|
||||
def __getitem__(self, item):
|
||||
if self._dict_data is not None and self._dict_data.has_key(item):
|
||||
return self._dict_data[item]
|
||||
return self._get_one(item)
|
||||
|
||||
|
||||
class _Interface:
|
||||
# An interface object.
|
||||
def __init__(self, name, iid):
|
||||
# Bypass self.__setattr__ when initializing attributes.
|
||||
d = self.__dict__
|
||||
d['_iidobj_'] = iid # Allows the C++ framework to treat this as a native IID.
|
||||
d['name'] = name
|
||||
d['constants'] = None # Built first time an attribute is asked for.
|
||||
def __cmp__(self, other):
|
||||
this_iid = self._iidobj_
|
||||
other_iid = getattr(other, "_iidobj_", other)
|
||||
return cmp(this_iid, other_iid)
|
||||
def __hash__(self):
|
||||
return hash(self._iidobj_)
|
||||
def __str__(self):
|
||||
return str(self._iidobj_)
|
||||
def __getitem__(self, item):
|
||||
raise TypeError, "components.interface objects are not subscriptable"
|
||||
def __setitem__(self, item, value):
|
||||
raise TypeError, "components.interface objects are not subscriptable"
|
||||
def __setattr__(self, attr, value):
|
||||
raise AttributeError, "Can not set attributes on components.Interface objects"
|
||||
def __getattr__(self, attr):
|
||||
# Support constants as attributes.
|
||||
c = self.constants
|
||||
if c is None:
|
||||
c = {}
|
||||
i = xpt.Interface(self._iidobj_)
|
||||
for c_ob in i.constants:
|
||||
c[c_ob.name] = c_ob.value
|
||||
self.__dict__['constants'] = c
|
||||
if c.has_key(attr):
|
||||
return c[attr]
|
||||
raise AttributeError, "'%s' interfaces do not define a constant '%s'" % (self.name, attr)
|
||||
|
||||
|
||||
class _Interfaces(_ComponentCollection):
|
||||
def _get_one(self, name):
|
||||
item = interfaceInfoManager.GetInfoForName(name)
|
||||
return _Interface(item.GetName(), item.GetIID())
|
||||
|
||||
def _build_dict(self):
|
||||
ret = {}
|
||||
enum = interfaceInfoManager.EnumerateInterfaces()
|
||||
while not enum.IsDone():
|
||||
# Call the Python-specific FetchBlock, to keep the loop in C.
|
||||
items = enum.FetchBlock(500, _xpcom.IID_nsIInterfaceInfo)
|
||||
# This shouldnt be necessary, but appears to be so!
|
||||
for item in items:
|
||||
ret[item.GetName()] = _Interface(item.GetName(), item.GetIID())
|
||||
return ret
|
||||
|
||||
# And the actual object people use.
|
||||
interfaces = _Interfaces()
|
||||
|
||||
del _Interfaces # Keep our namespace clean.
|
||||
|
||||
#################################################
|
||||
class _Class:
|
||||
def __init__(self, contractid):
|
||||
self.contractid = contractid
|
||||
def __getattr__(self, attr):
|
||||
if attr == "clsid":
|
||||
rc = manager.contractIDToClassID(self.contractid)
|
||||
# stash it away - it can never change!
|
||||
self.clsid = rc
|
||||
return rc
|
||||
raise AttributeError, "%s class has no attribute '%s'" % (self.contractid, attr)
|
||||
def createInstance(self, iid = None):
|
||||
import xpcom.client
|
||||
if iid is None:
|
||||
iid = _xpcom.IID_nsISupports
|
||||
elif type(iid) in StringTypes and len(iid)>0 and iid[0] != "{":
|
||||
iid = getattr(interfaces, iid)
|
||||
return xpcom.client.Component(self.contractid, iid)
|
||||
def getService(self, iid):
|
||||
return _xpcom.GetGlobalServiceManager().getService(self.contractid, iid)
|
||||
|
||||
class _Classes(_ComponentCollection):
|
||||
def __init__(self):
|
||||
_ComponentCollection.__init__(self)
|
||||
def _get_one(self, name):
|
||||
# XXX - Need to check the contractid is valid!
|
||||
return _Class(name)
|
||||
|
||||
def _build_dict(self):
|
||||
ret = {}
|
||||
enum = manager.EnumerateContractIDs()
|
||||
while not enum.IsDone():
|
||||
# Call the Python-specific FetchBlock, to keep the loop in C.
|
||||
items = enum.FetchBlock(500)
|
||||
for item in items:
|
||||
name = str(item)
|
||||
ret[name] = _Class(name)
|
||||
return ret
|
||||
|
||||
classes = _Classes()
|
||||
|
||||
del _Classes
|
||||
|
||||
del _ComponentCollection
|
||||
|
||||
# The ID function
|
||||
ID = _xpcom.IID
|
||||
|
||||
# A helper to cleanup our namespace as xpcom shuts down.
|
||||
class _ShutdownObserver:
|
||||
_com_interfaces_ = interfaces.nsIObserver
|
||||
def Observe(self, service, topic, extra):
|
||||
global manager
|
||||
global interfaceInfoManager
|
||||
global _shutdownObserver
|
||||
manager = interfaceInfoManager = _shutdownObserver = None
|
||||
|
||||
svc = _xpcom.GetGlobalServiceManager().GetService("@mozilla.org/observer-service;1", interfaces.nsIObserverService)
|
||||
# Observers will be QI'd for a weak-reference, so we must keep the
|
||||
# observer alive ourself, and must keep the COM object alive,
|
||||
# _not_ just the Python instance!!!
|
||||
_shutdownObserver = xpcom.server.WrapObject(_ShutdownObserver(), interfaces.nsIObserver)
|
||||
svc.AddObserver(_shutdownObserver, "xpcom-shutdown")
|
||||
del svc, _ShutdownObserver
|
||||
135
mozilla/extensions/python/xpcom/doc/advanced.html
Normal file
135
mozilla/extensions/python/xpcom/doc/advanced.html
Normal file
@@ -0,0 +1,135 @@
|
||||
<html>
|
||||
<!-- Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. -->
|
||||
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Python XPCOM Advanced Topics</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Python XPCOM Advanced Topics</h1>
|
||||
|
||||
<p>This document contains a series of tidbits that don't fit
|
||||
anywhere else. As the Python XPCOM Package documentation matures, most of
|
||||
these topics will have another home.</p>
|
||||
|
||||
<h2>XPCOM Services</h2>
|
||||
<p>An XPCOM service is simply a singleton registered by name. Python has
|
||||
full support for both using and implementing XPCOM services. To use a
|
||||
service, use <i>xpcom.components.services</i> just like the JavaScript
|
||||
counterpart. There is nothing special about implementing a service in
|
||||
Python; see the standard XPCOM documentation on services for more information.</p>
|
||||
|
||||
<h2>nsISupports Primitives.</h2>
|
||||
|
||||
<p>There is a set of interfaces described in <i>nsISupportsPrimitives.idl</i>, which I
|
||||
term collectively the <i>nsISupports Primitives Interfaces</i>. These
|
||||
are a set of interfaces a component can support to allow automatic conversion to
|
||||
and from many basic types. For example, an interface can define that it
|
||||
supports the <i>nsISupportsString</i> interface, and this could be used by any
|
||||
program that wishes to get a string representation of the object. If an
|
||||
interface wishes to expose itself as a "boolean value", it may choose
|
||||
to support the <i>nsISupportsPRBool</i> interface.</p>
|
||||
<p>When you call an XPCOM object (i.e., you have an XPCOM interface you are
|
||||
calling), you can use
|
||||
the builtin functions <i>str()</i>, <i>int()</i>, <i>long()</i> etc., on the
|
||||
object<i>.</i> In the
|
||||
case of <i>str()</i>, if the object does not support the <i>nsISupportsString</i>
|
||||
or <i>nsISupportsWString</i> interfaces, the default string <i>str()</i> for the
|
||||
object will be returned (i.e., what is normally returned for most XPCOM objects -
|
||||
support for these interface is not very common!). In the case of the numeric functions, a <i>ValueError</i>
|
||||
exception will be raised if the objects do not support any interface that can be
|
||||
used for the conversion. <i>ValueError</i> is used instead of <i>TypeError</i>,
|
||||
as the type itself (i.e., an XPCOM object) can sometimes be used in this context -
|
||||
hence it is the specific <i>value</i> of the object that is the problem.</p>
|
||||
<p>The use of <i>repr()</i> on an XPCOM interface object prevents support
|
||||
attempts for these interfaces, and allows you to see the
|
||||
"real" object, rather than what the object wants you to see!</p>
|
||||
<p>When you implement an XPCOM object, you have two choices for implementation
|
||||
of these interfaces:</p>
|
||||
<ul>
|
||||
<li>You can explicitly handle these interfaces like any other interface.
|
||||
In this case, you have full control. However, if you
|
||||
implement only one of these standard interfaces, then you are only
|
||||
overriding the default behavior for that specific interface - all other
|
||||
interfaces not explicitly listed in your class will still get the behavior
|
||||
described below.<br>
|
||||
</li>
|
||||
<li>If your class does not define support for these interfaces, the framework
|
||||
will use standard Python class semantics to implement them - i.e., if your
|
||||
class provides a <i>__str__</i> method, it will be used to implement <i>nsISupportsString</i>
|
||||
and <i>nsISupportsWString</i>, if you provide <i>__int__</i>, <i>__long__</i>,
|
||||
<i>__float__</i> etc., methods, they will be used to implement the numeric
|
||||
interfaces. If your class defines no such special methods, then the <i>
|
||||
QueryInterface()</i> for those interfaces fails (rather than the QI succeeding
|
||||
and the operation to fetch the data failing).</li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<p>This allows for an interesting feature that would not normally be
|
||||
possible. Consider Python code that does a <i>str()</i> on an XPCOM
|
||||
interface, and where the XPCOM interface itself is implemented in Python and
|
||||
provides a <i>__str__</i> method. The <i>str()</i> on the original
|
||||
interface queries for the <i>nsISupportsString</i> interface. The
|
||||
Python implemented object responds to this interface and delegates to the <i>__str__</i>
|
||||
method. At the end of all this, <i>str()</i> returns the same result
|
||||
as if the objects were native Python objects with no XPCOM layer in between.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<h2>Enumerators</h2>
|
||||
|
||||
<p>The primary enumerator used by XPCOM is <i>nsISimpleEnumerator</i>.
|
||||
Although the Python XPCOM package has full support for <i>nsIEnumerator</i>,
|
||||
since this interface is not "scriptable", you should avoided using it in interfaces
|
||||
you design.</p>
|
||||
|
||||
<p>When you use <i>nsISimpleEnumerator</i> from Python, the following enhancements
|
||||
are available:</p>
|
||||
<ul>
|
||||
<li>The <i>GetNext()</i> method takes an optional IID as a parameter. If
|
||||
this is specified, the returned object will be of this interface. This
|
||||
prevents the manual <i>QueryInterface()</i> generally required from other
|
||||
languages.</li>
|
||||
<li>There is a <i>FetchBlock(num, [iid])</i> method, which fetches the
|
||||
specified number of elements in one operation and returns a Python
|
||||
list. This can be useful for large enumerator sets, so the loop
|
||||
iterating the elements runs at full C++ speed.</li>
|
||||
</ul>
|
||||
<p><i>nsIEnumerator</i> has similar enhancements.</p>
|
||||
<p>When implementing a Python XPCOM object, the Python class <i>xpcom.server.enumerator.SimpleEnumerator()</i>
|
||||
can be used. You can pass a standard Python sequence (list, etc), and it
|
||||
will be correctly wrapped in an <i>nsISimpleEnumerator</i> interface.</p>
|
||||
<h2>Files</h2>
|
||||
<p>The Python XPCOM package provides an <i> xpcom.file</i> module. This implements
|
||||
a Python-like file object on top of the XPCOM/Mozilla stream interfaces.
|
||||
When run from within the Mozilla environment, this allows you to open almost any
|
||||
URL supported by Mozilla (including "chrome://" etc.,).</p>
|
||||
<p>See this module for more information, including test code.</p>
|
||||
<h2>XPCOM Object Identity</h2>
|
||||
<p>XPCOM has defined rules for object identity and for how objects must behave
|
||||
in their <i> QueryInterface()</i> implementations. The Python XPCOM framework
|
||||
manages this for you; your code can return new Python instances etc., when
|
||||
responding to new interfaces, and the framework itself will ensure the XPCOM
|
||||
semantics are followed. Critically, the framework provides no mechanism
|
||||
for breaking these rules.</p>
|
||||
<h2>Policies</h2>
|
||||
<p>The Python XPCOM framework has the concept of "policies" that
|
||||
define how XPCOM semantics are mapped to Python objects. It is the policy
|
||||
that implements delegation of <i> QueryInterface()</i>, translates property
|
||||
references into direct property references, and failing that, "get_name"
|
||||
and "set_name" calls, decides how to handle exceptions in the
|
||||
component, and so on.</p>
|
||||
<p>The default policy is very flexible and suitable for most purposes.
|
||||
Indeed, the Komodo project has never had to implement a custom policy.
|
||||
However, you should be aware the feature exists should you wish to do some
|
||||
bizarre things, such as using Python as a bridge between XPCOM and some other
|
||||
component technology.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
84
mozilla/extensions/python/xpcom/doc/architecture.html
Normal file
84
mozilla/extensions/python/xpcom/doc/architecture.html
Normal file
@@ -0,0 +1,84 @@
|
||||
<html>
|
||||
<!-- Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. -->
|
||||
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Architecture</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Python XPCOM Package Architecture</h1>
|
||||
<h2><a name="Architecture">Architecture</a></h2>
|
||||
<p>Much of the design for the Python XPCOM Package has been borrowed from the Python MS-COM
|
||||
extensions in <i>win32com</i>. Most of the major limitations and drawbacks in the <i>win32com</i>
|
||||
design have been addressed, mainly "auto-wrapping" of
|
||||
interface objects, which is not supported by <i>win32com</i>.</p>
|
||||
<p>Like <i>win32com</i>, this architecture includes the concept of <i>client COM</i> and <i>server
|
||||
COM.</i> </p>
|
||||
<p>Client COM:</p>
|
||||
<ul>
|
||||
<li>calls other interfaces</li>
|
||||
<li>is supported by <i>PyInterfaces</i> implemented in C++, which assists
|
||||
in making the COM calls</li>
|
||||
<li>is supported by <i>PyGateways</i>, which assists in receiving
|
||||
external COM calls and dispatching them to the correct Python object</li>
|
||||
<li> is supported in the <i>xpcom/client</i> package</li>
|
||||
</ul>
|
||||
<p>Server COM:</p>
|
||||
<ul>
|
||||
<li>implements interfaces for use by other XPCOM applications or components</li>
|
||||
<li> is
|
||||
supported in the <i>xpcom/server</i> package</li>
|
||||
</ul>
|
||||
<p>The XPConnect framework is very powerful, and far exceeds what COM's <i>
|
||||
IDispatch</i> can offer. Thus, we are able to get by with far fewer interfaces
|
||||
supported in the C++ level, and defer most things to the Python code that uses
|
||||
XPConnect. As a result, the requirement for a huge number of interfaces to
|
||||
exist in the <i>.pyd</i> does not exist. There are, however, a number of
|
||||
interfaces that do require native C++ support: these are interfaces
|
||||
required to "boot" the XPConnect support (i.e., the interfaces that are
|
||||
used to get information about interfaces), and also two gateways that need to
|
||||
work without interface information available. This last requirement is
|
||||
due to the XPCOM shutdown-ordering - it may be a bug, but is not an unreasonable
|
||||
amount of code anyway.</p>
|
||||
<p><b>Auto-wrapping</b> of COM objects is supported by both client COM and
|
||||
server COM. For client COM, auto-wrapping means that the
|
||||
Python programmer always sees Python "component" objects, rather than
|
||||
raw C++ interface objects; to the user, it all appears to "just
|
||||
work". This is a major source of frustration in the <i>win32com</i>
|
||||
framework.</p>
|
||||
<p>For server COM, auto-wrapping means that you can
|
||||
pass Python instances wherever a COM object is expected. If the Python
|
||||
instance supports COM interfaces, by virtue of having a <i>_com_interfaces_</i>
|
||||
attribute that lists the interface requested, it will be automatically wrapped
|
||||
in the correct COM object. </p>
|
||||
<p><b>Error Handling:</b> The C++ framework has good error handling support,
|
||||
and uses the XPCOM console service to log debug messages, Python exceptions and
|
||||
tracebacks. <i>win32com</i> does not have good exception/traceback support
|
||||
at the C++ level, mainly because COM does not define a service like
|
||||
the console where debug messages can go. This does mean that in Mozilla
|
||||
release builds, these debug messages are likely to be lost, but the <i>--console</i>
|
||||
command line option to a release Mozilla will get them back. Therefore,
|
||||
the other error-support utilities, such as the error callbacks made on the
|
||||
policy object, may be used.</p>
|
||||
<p><b>Component Loader, Modules and Factories:</b> XPCOM has the concept
|
||||
of a component loader - a module used to load all components of a
|
||||
particular type. For example, the <i>moz.jsloader.1</i> component loads all
|
||||
the JavaScript components. Similarly, the <i>moz.pyloader.1</i>
|
||||
component loads all Python components. However, unlike
|
||||
JavaScript, the Python component loader is actually implemented in Python
|
||||
itself! Since the Python component loader can not be used to load
|
||||
itself, this component has some special code, <i>pyloader.dll,</i> to boot-strap itself.</p>
|
||||
<p>This means is that all XPCOM components, including the Python loader itself and all
|
||||
XPCOM module and factory interfaces, are implemented in
|
||||
Python. <b>There are no components or interfaces implemented purely in C++
|
||||
in this entire package!</b></p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
198
mozilla/extensions/python/xpcom/doc/configure.html
Normal file
198
mozilla/extensions/python/xpcom/doc/configure.html
Normal file
@@ -0,0 +1,198 @@
|
||||
<html>
|
||||
<!-- Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. -->
|
||||
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Configuring your Environment</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Building, Configuring and Testing Python XPCOM Package</h1>
|
||||
<p>This document attempts to explain how to build, configure and test the
|
||||
Python XPCOM Package. This document assumes you have already successfully
|
||||
built
|
||||
Mozilla from source and your environment is currently set up for such a build -
|
||||
see the <a href="http://www.mozilla.org/build/">Mozilla build documentation</a>
|
||||
for more information.</p>
|
||||
<p>This section covers:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p align="left"><a href="#ConfigureTheEnvironment">Configuring your
|
||||
Environment</a></li>
|
||||
<li>
|
||||
<p align="left"><a href="#BuildingTheExtensions">Building</a></li>
|
||||
<li>
|
||||
<p align="left"><a href="#RunningTheTests">Testing your Setup</a></li>
|
||||
<li><a href="#Registration">Registering the Loader and Test
|
||||
Component</a></li>
|
||||
<li><a href="#RunningTheTests">Running the test suite</a></li>
|
||||
</ul>
|
||||
<h2><a name="ConfigureTheEnvironment">Configuring your Environment</a></h2>
|
||||
<p>In addition to the existing environment requirements for building Mozilla itself, the
|
||||
Python XPCOM package has the following requirements:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a name="MozillaDirectory"><b>Mozilla Directory</b></a><b> - </b>Ensure the Mozilla
|
||||
<i> bin</i> directory is on your PATH
|
||||
(LD_LIBRARY_PATH
|
||||
on Unix) so Python can locate the <i> xpcom.dll</i> module needed for
|
||||
core XPCOM services.</li>
|
||||
<li><a name="PYTHONPATH"><b>PYTHONPATH</b></a> - <tt>PYTHONPATH</tt> needs to be set appropriately. Ensure
|
||||
the parent to this <i>xpcom</i> directory is on your path so "import
|
||||
xpcom" locates this directory. Note that the Mozilla <i>components</i> directory does not need to be on the <tt>PYTHONPATH</tt>,
|
||||
but any modules used by your components must be set correctly. If anything
|
||||
is wrong here you should get a normal <tt>ImportError</tt>.</li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<p>Note that on Windows, the PYTHONPATH is generally maintained in the
|
||||
Registry; however, you can set this variable at a DOS prompt, and it will still be
|
||||
added to the core PYTHONPATH.
|
||||
</blockquote>
|
||||
<h2><a name="BuildingTheExtensions">Building</a></h2>
|
||||
<p>The initial release of the Python XPCOM package has a very simple, hard-coded
|
||||
build process. The intention is to include this package in the Mozilla
|
||||
source tree, and integrate the build with the Mozilla build. Until this
|
||||
happens, perform the following steps:</p>
|
||||
<ul>
|
||||
<li>Ensure you can successfully build Mozilla itself from source-code.</li>
|
||||
<li>Unpack this source code, and change to the <i>xpcom</i> directory under
|
||||
the root <i>PyXPCOM</i> directory.</li>
|
||||
<li>For Windows, edit <i>makefile.stupid.win</i>, while for Linux, edit <i>makefile.stupid.linux</i></li>
|
||||
<li>As per the instructions at the top of the makefile, edit the MOZ_SRC,
|
||||
INSTALLDIR and PYTHON_SRC definitions appropriately.</li>
|
||||
</ul>
|
||||
<h3>Build Example: Building on Windows</h3>
|
||||
<p>For this example, we will assume that the source-code for Mozilla is in C:\src\mozilla,
|
||||
the source-code for the PyXPCOM package is in <i>c:\src\pyxpcom</i>. Further, we assume
|
||||
that you have Python 2.0 installed in <i>C:\Python20</i>, and wish to install
|
||||
the built Python XPCOM package so it exists in <i>C:\Python20\xpcom</i>.</p>
|
||||
<p>To build the package in this environment, you would perform the following
|
||||
steps:</p>
|
||||
<ul>
|
||||
<li>Unpack the PyXPCOM package source-code into the appropriate directory</li>
|
||||
<li>Edit makefile.stupid.win with the following changes:<br>
|
||||
<i>MOZ_SRC=c:\src<br>
|
||||
INSTALLDIR=C:\Python20<br>
|
||||
PYTHON_SRC=C:\Python20</i></li>
|
||||
<li> From the top-level Python xpcom source directory (i.e., the
|
||||
directory with <i>makefile.stupid.win</i>), execute the command:<br>
|
||||
<i>nmake -f makefile.stupid.win install</i></li>
|
||||
</ul>
|
||||
<p>NOTE: To build a Debug version of the Python XPCOM library, you can add <i>DEBUG=1</i>
|
||||
to the nmake command-line.</p>
|
||||
<p>If everything appears to work and you are brave, you may also like to execute
|
||||
<i>make -f makefile.stupid.win test</i> to execute the test script.
|
||||
Otherwise, continue to the following section where we confirm the installation
|
||||
step-by-step.</p>
|
||||
<h3>Build Example: Building on Linux</h3>
|
||||
<p>For this example, we will assume that the source-code for Mozilla is in ~/src/mozilla,
|
||||
the source-code for the PyXPCOM package is in ~/src/pyxpcom. Further, we assume
|
||||
that you have ActivePython 2.0 installed in <i>/usr/local/ActivePython2.0</i>,
|
||||
and wish to install the built Python XPCOM package so it exists in <i>/usr/local/ActivePython2.0/lib/python2.0/site-packages/xpcom</i>.</p>
|
||||
<p>To build the package in this environment, you would perform the following
|
||||
steps:</p>
|
||||
<ul>
|
||||
<li>Unpack the PyXPCOM package source-code into the appropriate directory</li>
|
||||
<li>Edit makefile.stupid.linux with the following changes (substituting
|
||||
username accordingly):<br>
|
||||
<i>MOZ_SRC=/home/username/src<br>
|
||||
INSTALLDIR=/usr/local/ActivePython-2.0/site-packages<br>
|
||||
PYTHON_SRC=/usr/local/ActivePython-2.0</i></li>
|
||||
<li>Build: As a regular user, from the top-level Python xpcom source
|
||||
directory (i.e., the directory with <i>makefile.stupid.linux</i>), execute
|
||||
the command:<br>
|
||||
<i>make -f makefile.stupid.linux DEBUG=1</i></li>
|
||||
<li>Install: Log in as a user with permissions to install into the relevant directories
|
||||
(usually the root user). From the top-level Python xpcom source
|
||||
directory (i.e., the directory with <i>makefile.stupid.linux</i>), execute
|
||||
the command:<br>
|
||||
<i>make -f makefile.stupid.linux DEBUG=1 install</i></li>
|
||||
<li>Switch back to a regular user, ready for testing!</li>
|
||||
</ul>
|
||||
<p>NOTE: The instructions above are for a Debug build, as this is the default
|
||||
Mozilla build type. If you have configured Mozilla to build a Release
|
||||
version of Mozilla, you can drop the DEBUG=1 option. It is important that
|
||||
PyXPCOM and Mozilla itself are consistent with respect to Release and Debug
|
||||
builds. For more details, please consult the makefile.</p>
|
||||
<p>If everything appears to work and you are brave, you may also like to execute
|
||||
<i>make -f makefile.stupid.linux test</i> to execute the test script.
|
||||
Otherwise, continue to the following section where we confirm the installation
|
||||
step--by-step.</p>
|
||||
<h2><a name="RunningTheTests">Testing your Setup</a></h2>
|
||||
<p>The Python XPCOM Package has a complete test suite. If you are
|
||||
impatient, you can simply execute <i>make -f makefile.stupid.linux test</i> (for
|
||||
Linux) or <i>nmake -f makefile.stupid.linux test</i> (for Windows). If
|
||||
this command indicates that the tests succeeded, then you can ignore the rest of
|
||||
this section.</p>
|
||||
<p>In the rest of this section, we walk through some simpler tests a step at a time,
|
||||
to help diagnose any problems.</p>
|
||||
<p><b>Note:</b> We recommend you do all your testing outside of <i> mozilla.exe</i>; it is far simpler to test all of
|
||||
this using the PyXPCOM package stand-alone.</p>
|
||||
<p><b>Note:</b> On Windows, if you use a debug build of Mozilla (i.e., in <i>dist\WIN32_D.OBJ\bin)</i>,
|
||||
you <b>must</b> use <i>python_d.exe</i>; if you use a release build (i.e., in
|
||||
a <i>dist\WIN32_O.OBJ\bin</i> directory), you must use <i>python.exe</i>.
|
||||
<i>makefile.stupid.win</i> handles this automatically.</p>
|
||||
<p>To test your setup:</p>
|
||||
<ol>
|
||||
<li>Start Python, and check<br>
|
||||
>>> <i>import xpcom</i><br>
|
||||
works. If not, <a href="#PYTHONPATH">check your PYTHONPATH</a> - the
|
||||
main PyXPCOM package can not be located..</li>
|
||||
<li>Check<i><br>
|
||||
>>> import xpcom._xpcom</i><br>
|
||||
|
||||
works. If not, then most likely your <a href="#MozillaDirectory">Mozilla
|
||||
directory is not on your path</a>, or something is wrong with <i>_xpcom(_d).pyd/_xpcommodule.so</i>.</li>
|
||||
|
||||
<li>Next run a simple test: <i>test/test_misc.py</i>. With a Windows debug build, the command may look like:<br>
|
||||
<i>C:\Anywhere> python_d \src\python\xpcom\test\test_misc.py<br>
|
||||
</i>or on Linux<br>
|
||||
<i>/home/user/src/mozilla/dist/bin$ python /home/user/src/python/xpcom/test/test_misc.py</i></li>
|
||||
</ol>
|
||||
<p>If you can't get this going, you won't get much further! If you do, the
|
||||
next step is to register our test component and run our full test suite.</p>
|
||||
<h2><a name="Registration">Registering the Loader and Test Component</a></h2>
|
||||
<p>First register the generic Python loader. For instructions, see the <a href="file:///F:/src/as/Komodo/src/pyxpcom/xpcom/doc/architecture.html">architecture
|
||||
document</a>. Do this only once, regardless of how many
|
||||
Python components you have. Then install the test component itself, and
|
||||
finally you can test it!</p>
|
||||
<h3>Registering the Python Loader and Component</h3>
|
||||
<p>To register the Python Loader and Component:</p>
|
||||
<ol>
|
||||
<li>Ensure the build process has put <i>pyloader.dll </i>(or <i>modpyloader.so</i>
|
||||
for Unix), and the files <i> py_test_component.py </i> and <i> py_test_component.idl</i> into
|
||||
the Mozilla <i>bin/components</i> directory. If not, copy the files
|
||||
there manually.</li>
|
||||
<li>Run <i>regxpcom</i>. <i>regxpcom</i> is a standard Mozilla
|
||||
executable, found in the <i>bin</i> directory, that detects whether the DLL and .py
|
||||
files have been added and registers them accordingly. You should
|
||||
see a few messages that include the following:</li>
|
||||
</ol>
|
||||
<blockquote>
|
||||
<pre>Registering: PythonComponentLoader
|
||||
Registered 1 Python components in pyloader.dll
|
||||
nsNativeComponentLoader: autoregistering succeeded
|
||||
Auto-registering all Python components in F:\src\mozilla\dist\WIN32_D.OBJ\bin\components
|
||||
Registering: PythonTestComponent
|
||||
Registered 1 Python components in py_test_component.py</pre>
|
||||
</blockquote>
|
||||
<p>If so (or you see no message at all), you are ready to run the test suite.</p>
|
||||
<p><b>Note</b>: If you execute this same step a second time, you will not
|
||||
see any of the above mentioned messages. XPCOM knows that nothing has
|
||||
changed since you last ran <i>regxpcom</i>, so nothing is registered. If
|
||||
you do not see these messages the first time you run it, there is the
|
||||
possibility that some other process, possibly the build process, has already
|
||||
executed this step.</p>
|
||||
<h2><b>Running the Test Suite</b></h2>
|
||||
<p>To run the test suite, run <i>xpcom/test/regrtest.py.</i> This runs the
|
||||
tests and ensures that the test output is as expected. If all tests
|
||||
pass, you have a fully functioning Python XPCOM package. Enjoy!</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
54
mozilla/extensions/python/xpcom/doc/credits.html
Normal file
54
mozilla/extensions/python/xpcom/doc/credits.html
Normal file
@@ -0,0 +1,54 @@
|
||||
<html>
|
||||
<!-- Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. -->
|
||||
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-au">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Credits and Acknowledgements</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Credits and Acknowledgements</h1>
|
||||
<h2>ActiveState Tool Corporation</h2>
|
||||
<p>The Python XPCOM Package was developed primarily by <a href="mailto:markh@activestate.com">Mark
|
||||
Hammond</a> of <a href="http://www.ActiveState.com">ActiveState Tool Corporation</a>.</p>
|
||||
<p>The developers on the <a href="http://www.ActiveState.com/Products/Komodo">Komodo
|
||||
project</a> deserve high praise for putting up with early versions when almost
|
||||
nothing worked, and for believing in Python as a viable XPCOM language.
|
||||
Their feedback and patience has allowed the first public release to be amazingly
|
||||
functional and bug-free.</p>
|
||||
<h3>Komodo Development Team (at December 2000)</h3>
|
||||
<p><a href="mailto:davida@activestate.com">David Ascher</a>, <a href="mailto:aaronb@ActiveState.com">Aaron Bingham</a>,
|
||||
<a href="mailto:bindu@activestate.com">Bin Du</a>, <a href="mailto:markh@activestate.com">Mark
|
||||
Hammond</a>, <a href="mailto:trentm@activestate.com">Trent Mick (build god)</a>,
|
||||
<a href="mailto:paulp@activestate.com">Paul Prescod</a>, <a href="mailto:ericp@ActiveState.com">Eric Promislow</a>,
|
||||
<a href="mailto:kens@ActiveState.com">Ken Simpson</a>, <a href="mailto:neilw@ActiveState.com">Neil Watkiss</a>,
|
||||
<a href="mailto:AudreyS@ActiveState.com">Audrey Schumacher</a>.</p>
|
||||
<h2>Mozilla/Netscape</h2>
|
||||
<p>The following people at <a href="http://www.netscape.com">Netscape</a> and <a href="http://www.mozilla.org">Mozilla</a>
|
||||
(or not there but still heavily involved in the project) have provided enormous
|
||||
help in getting things integrated with their build system, answering us on the
|
||||
newsgroup, teaching us the finer points of XPCOM, gently slapping us for accidentally
|
||||
referring to <i>jscript</i>, etc., and otherwise lending us a clue in the
|
||||
Mozilla/Netscape/XPCOM world.</p>
|
||||
<p><a href="mailto:jband@netscape.com">John Bandhauer</a>, <a href="mailto:brendan@meer.net">Brendan
|
||||
Eich</a>, <a href="mailto:shaver@zeroknowledge.com">Mike Shaver</a>, <a href="mailto:evaughan@netscape.com">Eric Vaughan</a>,
|
||||
<a href="mailto:hyatt@netscape.com">David Hyatt</a></p>
|
||||
<h2>External Contributors</h2>
|
||||
<p>The following people have made contributions to the project, simply because
|
||||
they find it useful and enjoy supporting Open Source projects.</p>
|
||||
<p><a href="mailto:cmeerw@web.de">Christof Meerwald</a></p>
|
||||
<h2>Documentation Credits</h2>
|
||||
<p>The following people have contributed to the Python XPCOM Package
|
||||
documentation </p>
|
||||
<p><a href="mailto:markh@activestate.com">Mark
|
||||
Hammond</a>, <a href="mailto:AudreyS@ActiveState.com">Audrey Schumacher</a></p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
240
mozilla/extensions/python/xpcom/doc/tutorial.html
Normal file
240
mozilla/extensions/python/xpcom/doc/tutorial.html
Normal file
@@ -0,0 +1,240 @@
|
||||
<html>
|
||||
<!-- Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. -->
|
||||
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Python XPCOM Package Tutorial</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Python XPCOM Package Tutorial</h1>
|
||||
<p>This is a quick introduction to the Python XPCOM Package. We assume that you have a good understanding of Python and <a href="http://www.mozilla.org/projects/xpcom/">XPCOM</a>,
|
||||
and have experience both using and implementing XPCOM objects in some other
|
||||
language (e.g., C++ or JavaScript). We <b><i>do not</i></b> attempt to
|
||||
provide a tutorial to XPCOM or Python itself, only to using Python <i>and</i>
|
||||
XPCOM.</p>
|
||||
<p>This tutorial contains the following sections:</p>
|
||||
<ul>
|
||||
<li><a href="#Using">Using XPCOM Objects and Interfaces</a> - when you wish to
|
||||
<i>use</i> a component written by anyone else in any XPCOM supported
|
||||
language.</li>
|
||||
<li><a href="#Implementing">Implementing XPCOM Objects and Interfaces</a> -
|
||||
when you wish to implement a component for use by anyone else in any xpcom
|
||||
supported language.</li>
|
||||
<li><a href="#Parameters">Parameters and Types</a> - useful information
|
||||
regarding how Python translates XPCOM types, and handles byref parameters.</li>
|
||||
</ul>
|
||||
<p>For anything not covered here, try the <a href="advanced.html">advanced
|
||||
documentation</a>, and if that fails, use the source, Luke!</p>
|
||||
<h2><a name="Using">Using XPCOM object and interfaces.</a></h2>
|
||||
<p>The techniques for using XPCOM in Python have been borrowed from JavaScript -
|
||||
thus, the model described here should be quite familiar to existing JavaScript
|
||||
XPCOM programmers.</p>
|
||||
<h3>xpcom.components module</h3>
|
||||
<p>When using an XPCOM object, the primary module used is the <u><i>xpcom.components</i></u>
|
||||
module. Using this module, you can get a Python object that supports any
|
||||
scriptable XPCOM interface. Once you have this Python object, you can
|
||||
simply call XPCOM methods on the object, as normal.</p>
|
||||
<p>The <u><i>xpcom.components</i></u> module defines the following public
|
||||
members:</p>
|
||||
<table border="1" width="100%">
|
||||
<tr>
|
||||
<td width="16%"><b>Name</b></td>
|
||||
<td width="84%"><b>Description</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="16%">classes</td>
|
||||
<td width="84%">A mapping (dictionary-like object) used to get XPCOM
|
||||
"classes". These are indexed by XPCOM contract ID, just
|
||||
like the JavaScript object of the same name.
|
||||
<p>Example:</p>
|
||||
<pre>cls = components.classes["@mozilla.org/sample;1"]
|
||||
ob = cls.createInstance() # Now have an nsISupports</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="16%">interfaces</td>
|
||||
<td width="84%">An object that exposes all XPCOM interface IDs (IIDs).
|
||||
Like the JavaScript object of the same name, this object uses
|
||||
"dot" notation, as demonstrated below.
|
||||
<p>Example:</p>
|
||||
<pre>ob = cls.createInstance(components.interfaces.nsISample)
|
||||
# Now have an nsISample</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>For many people, this is all you need to know. Consider the Mozilla Sample Component. The Mozilla Sample
|
||||
Component has a contract ID of <i>@mozilla.org/sample;1</i>,
|
||||
and implements the <i>nsISample</i> interface.</p>
|
||||
<p>Thus, a complete Python program that uses this component is shown below.</p>
|
||||
<pre>from xpcom import components
|
||||
cls = components.classes["@mozilla.org/sample;1"]
|
||||
ob = cls.createInstance(components.interfaces.nsISample)
|
||||
# nsISample defines a "value" property - let's use it!
|
||||
ob.value = "new value"
|
||||
if ob.value != "new value":
|
||||
print "Eeek - what happened?"</pre>
|
||||
<p>And that is it - a complete Python program that uses XPCOM.</p>
|
||||
<h2><a name="Implementing">Implementing XPCOM Objects and Interfaces.</a></h2>
|
||||
<p>Implementing XPCOM objects is almost as simple as using them. The
|
||||
basic strategy is this:</p>
|
||||
<ol>
|
||||
<li>Create a standard Python source file, with a standard Python class.</li>
|
||||
<li>Add some special <a href="#Attributes"> attributes</a> to your class for use by the Python XPCOM
|
||||
framework. This controls the XPCOM behavior of your object.</li>
|
||||
<li>Implement the XPCOM <a href="#Properties"> properties</a> and methods of your classes as normal.</li>
|
||||
<li>Put the Python source file in the Mozilla <i> components</i> directory.</li>
|
||||
<li>Run <i> regxpcom.</i></li>
|
||||
</ol>
|
||||
<p>Your component is now ready to be used.</p>
|
||||
<h3><a name="Attributes">Attributes</a></h3>
|
||||
<p>There are two classes of attributes: those used at runtime to define the object
|
||||
behavior and those used at registration time to control object
|
||||
registration. Not all objects require registration, thus not all
|
||||
Python XPCOM objects will have registration-related attributes.</p>
|
||||
<table border="1" width="100%">
|
||||
<tr>
|
||||
<td width="17%"><b>Attribute</b></td>
|
||||
<td width="83%"><b>Description</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="17%">_com_interfaces_</td>
|
||||
<td width="83%">The interface IDs (IIDs) supported by the component.
|
||||
For simplicity, this may be either a single IID, or a list of IIDs.
|
||||
There is no need to specify base interfaces, as all parent interfaces are
|
||||
automatically supported. Thus, it is never necessary to nominate <i>
|
||||
nsISupports</i> in the list of interfaces.
|
||||
<p>This attribute is required. Objects without such an attribute are
|
||||
deemed unsuitable for use as a XPCOM object.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="17%">_reg_contractid_</td>
|
||||
<td width="83%">The contract ID of the component. Required if the
|
||||
component requires registration (i.e., exists in the components directory).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="17%">_reg_clsid_</td>
|
||||
<td width="83%">The Class ID (CLSID) of the component, as a string in the
|
||||
standard "{XXX-XXX-XXX-XXX}" format. Required if the
|
||||
component requires registration (i.e., exists in the components directory).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="17%">_reg_registrar_</td>
|
||||
<td width="83%">Nominates a function that is called at registration
|
||||
time. The default is for no extra function to be called. This can
|
||||
be useful if a component has special registration requirements and needs
|
||||
to hook into the registration process.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="17%">_reg_desc_</td>
|
||||
<td width="83%">The description of the XPCOM object. This may be used by
|
||||
browsers or other such objects. If not specified, the contract ID
|
||||
is used.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3><a name="Properties">Properties</a></h3>
|
||||
<p>A Python class can support XPCOM properties in one of two ways. Either
|
||||
a standard Python property of the same name can exist - our sample
|
||||
component demonstrates this with the <i>boolean_value</i> property.
|
||||
Alternatively, the class can provide the <i>get_propertyName(self)</i> and <i>set_propertyName(self,
|
||||
value)</i> functions (with <i>propertyName</i> changed to the appropriate value for the
|
||||
property), and these functions will be called instead.</p>
|
||||
<h4>Example: The Python XPCOM Test Component</h4>
|
||||
<p>As an example, examine the Python XPCOM Test Component. This
|
||||
code can be found in <i>py_test_component.py</i>.</p>
|
||||
<pre>from xpcom import components
|
||||
|
||||
class PythonTestComponent:
|
||||
_com_interfaces_ = components.interfaces.nsIPythonTestInterface
|
||||
_reg_clsid_ = "{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}"
|
||||
_reg_contractid_ = "Python.TestComponent"
|
||||
def __init__(self):
|
||||
self.boolean_value = 1
|
||||
...
|
||||
def do_boolean(self, p1, p2):
|
||||
ret = p1 ^ p2
|
||||
return ret, not ret, ret
|
||||
...</pre>
|
||||
<p><b>Note:</b> This component only specifies the mandatory attributes - <i>_com_interfaces</i>,
|
||||
<i>_reg_clsid_</i> and <i>_reg_contractid_</i>.</p>
|
||||
<p>This sample code demonstrates supporting the <i>boolean_value</i> attribute,
|
||||
supported implicitly, as it is defined in the IDL and exists as a real Python
|
||||
attribute of that name, and a method called <i>do_boolean</i>.</p>
|
||||
<h4>Tip: The xpcom/xpt.py Script</h4>
|
||||
<p> The xpcom/xpt.py script is a useful script that can generate the skeleton of a class for
|
||||
any XPCOM interface. Just specify the interface name on the command-line,
|
||||
and paste the output into your source file.</p>
|
||||
<p>This is the output of running this program over the <i>nsISample</i>
|
||||
interface (i.e., assuming we wanted to implement a component that supported this
|
||||
interface):</p>
|
||||
<pre>class nsISample:
|
||||
_com_interfaces_ = xpcom.components.interfaces.nsISample
|
||||
# If this object needs to be registered, the following 2 are also needed.
|
||||
# _reg_clsid_ = {a new clsid generated for this object}
|
||||
# _reg_contractid_ = "The.Object.Name"
|
||||
|
||||
def get_value( self ):
|
||||
# Result: string
|
||||
pass
|
||||
def set_value( self, param0 ):
|
||||
# Result: void - None
|
||||
# In: param0: string
|
||||
pass
|
||||
def writeValue( self, param0 ):
|
||||
# Result: void - None
|
||||
# In: param0: string
|
||||
pass
|
||||
def poke( self, param0 ):
|
||||
# Result: void - None
|
||||
# In: param0: string
|
||||
pass</pre>
|
||||
<p><b>Note:</b> The types of the parameters and the function itself are included in
|
||||
the comments. You need to implement the functions
|
||||
themselves. Another advantage of this script is that the <a href="#HiddenParams">hidden
|
||||
parameters</a> are handled for you; the comments indicate when parameters
|
||||
have been hidden.</p>
|
||||
<h2><a name="Parameters">Parameters and Types</a></h2>
|
||||
<p>This section briefly describes the XPCOM type support in
|
||||
Python.</p>
|
||||
<p>All XPCOM interfaces define parameters of a specific type. There is
|
||||
currently no concept of a variant, or union of all types. Thus, the
|
||||
conversion rules are very straightforward, and generally surprise free: for
|
||||
any given XPCOM method, there is only one possible type for a given parameter.</p>
|
||||
<h3>Type Conversion Rules:</h3>
|
||||
<ul>
|
||||
<li>All numeric types will attempt to be coerced to the correct type.
|
||||
Thus, you can pass a Python float to an XPCOM method expecting an integer,
|
||||
or vice-versa. Specifically, when an integer is required, you can pass
|
||||
any Python object for which <i>int()</i> would succeed; for a Python float,
|
||||
any object for which <i>float()</i> would succeed is acceptable. This
|
||||
means that you can pass a Python string object as an integer, as long as the
|
||||
string was holding a valid integer.</li>
|
||||
<li>Strings and Unicode objects are interchangeable, but no other automatic
|
||||
string conversions are performed. Thus, you can not pass an integer
|
||||
where a string is expected, even though the reverse is true.</li>
|
||||
<li>Any sequence object can be passed as an array. List objects are
|
||||
always returned for arrays.</li>
|
||||
<li>Any Python instance suitable for use as a XPCOM object (i.e., with the
|
||||
<a href="#Implementing">necessary annotations</a>) can be
|
||||
passed as a XPCOM object. No special wrapping step is needed to turn a
|
||||
Python instance into a XPCOM object. Note you must pass a class <i>instance</i>,
|
||||
not the class itself.</li>
|
||||
<li><a name="HiddenParams">Many XPCOM <b> method signatures</b> specify
|
||||
"count" or "size" parameters. For example, every
|
||||
time an array is passed via XPCOM, the method signature will always specify
|
||||
an integer that holds the count of the array. These parameters are
|
||||
always hidden in Python. As the size param can be implied from the
|
||||
length of the Python sequence passed, the Python programmer need never pass
|
||||
these parameters; in contrast, JavaScript requires these redundant parameters.</a></li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
|
||||
298
mozilla/extensions/python/xpcom/file.py
Normal file
298
mozilla/extensions/python/xpcom/file.py
Normal file
@@ -0,0 +1,298 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
"""Implementation of Python file objects for Mozilla/xpcom.
|
||||
|
||||
Introduction:
|
||||
This module defines various class that are implemented using
|
||||
Mozilla streams. This allows you to open Mozilla URI's, and
|
||||
treat them as Python file object.
|
||||
|
||||
Example:
|
||||
>>> file = URIFile("chrome://whatever")
|
||||
>>> data = file.read(5) # Pass no arg to read everything.
|
||||
|
||||
Known Limitations:
|
||||
* Not all URL schemes will work from "python.exe" - most notably
|
||||
"chrome://" and "http://" URLs - this is because a simple initialization of
|
||||
xpcom by Python does not load up the full set of Mozilla URL handlers.
|
||||
If you can work out how to correctly initialize the chrome registry and
|
||||
setup a message queue.
|
||||
|
||||
Known Bugs:
|
||||
* Only read ("r") mode is supported. Although write ("w") mode doesnt make
|
||||
sense for HTTP type URLs, it potentially does for file:// etc type ones.
|
||||
* No concept of text mode vs binary mode. It appears Mozilla takes care of
|
||||
this internally (ie, all "text/???" mime types are text, rest are binary)
|
||||
|
||||
"""
|
||||
|
||||
from xpcom import components, Exception, _xpcom
|
||||
import os
|
||||
import threading # for locks.
|
||||
|
||||
NS_RDONLY = components.interfaces.nsIFileChannel.NS_RDONLY
|
||||
NS_WRONLY = components.interfaces.nsIFileChannel.NS_WRONLY
|
||||
NS_RDWR = components.interfaces.nsIFileChannel.NS_RDWR
|
||||
NS_CREATE_FILE = components.interfaces.nsIFileChannel.NS_CREATE_FILE
|
||||
NS_APPEND = components.interfaces.nsIFileChannel.NS_APPEND
|
||||
NS_TRUNCATE = components.interfaces.nsIFileChannel.NS_TRUNCATE
|
||||
NS_SYNC = components.interfaces.nsIFileChannel.NS_SYNC
|
||||
NS_EXCL = components.interfaces.nsIFileChannel.NS_EXCL
|
||||
|
||||
# A helper function - you pass a progID, an interface, plus optionally the
|
||||
# name of the "constructor" and its args.
|
||||
def _construct(progid, interface, ctor = None, *args):
|
||||
assert (ctor is None and not args) or (ctor is not None and args), \
|
||||
"no point having a ctor with no args, or if you provide args, there must be a ctor!"
|
||||
instance = components.classes[progid] \
|
||||
.createInstance(interface)
|
||||
if ctor is not None:
|
||||
ctor = getattr(instance, ctor)
|
||||
apply(ctor, args)
|
||||
return instance
|
||||
|
||||
# A helper function that may come in useful
|
||||
def LocalFileToURL(localFileName):
|
||||
"Convert a filename to an XPCOM nsIFileURL object."
|
||||
# Create an nsILocalFile
|
||||
localFile = components.classes["@mozilla.org/file/local;1"] \
|
||||
.createInstance(components.interfaces.nsILocalFile)
|
||||
localFile.initWithPath(localFileName)
|
||||
|
||||
# Create a standard URL, but we QI for the FileURL interface!
|
||||
url = components.classes["@mozilla.org/network/standard-url;1"] \
|
||||
.createInstance(components.interfaces.nsIFileURL)
|
||||
# Setting the "file" attribute causes initialization...
|
||||
url.file = localFile
|
||||
return url
|
||||
|
||||
# A base class for file objects.
|
||||
class _File:
|
||||
def __init__(self, name_thingy = None, mode="r"):
|
||||
self.lockob = threading.Lock()
|
||||
self.inputStream = self.outputStream = None
|
||||
if name_thingy is not None:
|
||||
self.init(name_thingy, mode)
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
# The Moz file streams are not thread safe.
|
||||
def _lock(self):
|
||||
self.lockob.acquire()
|
||||
def _release(self):
|
||||
self.lockob.release()
|
||||
def read(self, n = -1):
|
||||
assert self.inputStream is not None, "Not setup for read!"
|
||||
self._lock()
|
||||
try:
|
||||
return str(self.inputStream.read(n))
|
||||
finally:
|
||||
self._release()
|
||||
|
||||
def readlines(self):
|
||||
# Not part of the xpcom interface, but handy for direct Python users.
|
||||
# Not 100% faithful, but near enough for now!
|
||||
lines = self.read().split("\n")
|
||||
if len(lines) and len(lines[-1]) == 0:
|
||||
lines = lines[:-1]
|
||||
return [s+"\n" for s in lines ]
|
||||
|
||||
def write(self, data):
|
||||
assert self.outputStream is not None, "Not setup for write!"
|
||||
self._lock()
|
||||
try:
|
||||
self.outputStream.write(data, len(data))
|
||||
finally:
|
||||
self._release()
|
||||
|
||||
def close(self):
|
||||
self._lock()
|
||||
try:
|
||||
if self.inputStream is not None:
|
||||
self.inputStream.close()
|
||||
self.inputStream = None
|
||||
if self.outputStream is not None:
|
||||
self.outputStream.close()
|
||||
self.outputStream = None
|
||||
self.channel = None
|
||||
# leave self.fileInst alone - it should be available after close.
|
||||
finally:
|
||||
self._release()
|
||||
|
||||
def flush(self):
|
||||
self._lock()
|
||||
try:
|
||||
if self.outputStream is not None: self.outputStream.flush()
|
||||
finally:
|
||||
self._release()
|
||||
|
||||
# A synchronous "file object" used to open a URI.
|
||||
class URIFile(_File):
|
||||
def init(self, url, mode="r"):
|
||||
self.close()
|
||||
if mode != "r":
|
||||
raise ValueError, "only 'r' mode supported'"
|
||||
io_service = components.classes["@mozilla.org/network/io-service;1"] \
|
||||
.createInstance("nsIIOService")
|
||||
if hasattr(url, "queryInterface"):
|
||||
url_ob = url
|
||||
else:
|
||||
url_ob = components.classes["@mozilla.org/network/standard-url;1"] \
|
||||
.createInstance(components.interfaces.nsIURL)
|
||||
url_ob.spec = url
|
||||
# Mozilla asserts and starts saying "NULL POINTER" if this is wrong!
|
||||
if not url_ob.scheme:
|
||||
raise ValueError, ("The URI '%s' is invalid (no scheme)"
|
||||
% (url_ob.spec,))
|
||||
self.channel = io_service.newChannelFromURI(url_ob)
|
||||
self.inputStream = self.channel.openInputStream()
|
||||
|
||||
# A "file object" implemented using Netscape's native file support.
|
||||
# Based on io.js - http://lxr.mozilla.org/seamonkey/source/xpcom/tests/utils/io.js
|
||||
# You open this file using a local file name (as a string) so it really is pointless -
|
||||
# you may as well be using a standard Python file object!
|
||||
class LocalFile(_File):
|
||||
def init(self, name, mode = "r"):
|
||||
name = os.path.abspath(name) # Moz libraries under Linux fail with relative paths.
|
||||
self.close()
|
||||
self.fileInst = _construct('@mozilla.org/file/local;1', "nsILocalFile", "initWithPath", name)
|
||||
self.inputStream = None
|
||||
self.channel = None
|
||||
if mode in ["w","a"]:
|
||||
if mode== "w":
|
||||
if self.fileInst.exists():
|
||||
self.fileInst.delete(0)
|
||||
moz_mode = NS_CREATE_FILE | NS_WRONLY
|
||||
elif mode=="a":
|
||||
moz_mode = NS_APPEND
|
||||
else:
|
||||
assert 0, "Can't happen!"
|
||||
perms = 0644
|
||||
if not self.fileInst.exists():
|
||||
self.fileInst.create(components.interfaces.nsILocalFile.NORMAL_FILE_TYPE, 0644)
|
||||
self.channel = _construct('@mozilla.org/network/local-file-channel;1', "nsIFileChannel", "init",
|
||||
self.fileInst, moz_mode, perms)
|
||||
self.outputStream = self.channel.openOutputStream()
|
||||
self.fileInst.permissions = perms
|
||||
|
||||
elif mode == "r":
|
||||
self.channel = _construct('@mozilla.org/network/local-file-channel;1', "nsIFileChannel", "init",
|
||||
self.fileInst, NS_RDONLY, self.fileInst.permissions)
|
||||
self.inputStream = self.channel.openInputStream()
|
||||
else:
|
||||
raise ValueError, "Unknown mode"
|
||||
|
||||
def read(self, n = -1):
|
||||
if n == -1:
|
||||
n = self.fileInst.fileSize
|
||||
return _File.read(self, n)
|
||||
|
||||
|
||||
##########################################################
|
||||
##
|
||||
## Test Code
|
||||
##
|
||||
##########################################################
|
||||
def _DoTestRead(file, expected):
|
||||
# read in a couple of chunks, just to test that our various arg combinations work.
|
||||
got = file.read(3)
|
||||
got = got + file.read(300)
|
||||
got = got + file.read(0)
|
||||
got = got + file.read()
|
||||
if got != expected:
|
||||
raise RuntimeError, "Reading '%s' failed - got %d bytes, but expected %d bytes" % (file, len(got), len(expected))
|
||||
|
||||
def _DoTestBufferRead(file, expected):
|
||||
# read in a couple of chunks, just to test that our various arg combinations work.
|
||||
buffer = _xpcom.AllocateBuffer(50)
|
||||
got = ''
|
||||
while 1:
|
||||
# Note - we need to reach into the file object so we
|
||||
# can get at the native buffer supported function.
|
||||
num = file.inputStream.read(buffer)
|
||||
if num == 0:
|
||||
break
|
||||
got = got + str(buffer[:num])
|
||||
if got != expected:
|
||||
raise RuntimeError, "Reading '%s' failed - got %d bytes, but expected %d bytes" % (file, len(got), len(expected))
|
||||
|
||||
def _TestLocalFile():
|
||||
import tempfile, os
|
||||
fname = tempfile.mktemp()
|
||||
data = "Hello from Python"
|
||||
test_file = LocalFile(fname, "w")
|
||||
try:
|
||||
test_file.write(data)
|
||||
test_file.close()
|
||||
# Make sure Python can read it OK.
|
||||
f = open(fname, "r")
|
||||
if f.read() != data:
|
||||
print "Eeek - Python could not read the data back correctly!"
|
||||
f.close()
|
||||
# For the sake of the test, try a re-init.
|
||||
test_file.init(fname, "r")
|
||||
got = str(test_file.read())
|
||||
if got != data:
|
||||
print "Read the wrong data back - %r" % (got,)
|
||||
else:
|
||||
print "Read the correct data."
|
||||
test_file.close()
|
||||
# Try reading in chunks.
|
||||
test_file = LocalFile(fname, "r")
|
||||
got = test_file.read(10) + test_file.read()
|
||||
if got != data:
|
||||
print "Chunks the wrong data back - %r" % (got,)
|
||||
else:
|
||||
print "Chunks read the correct data."
|
||||
test_file.close()
|
||||
# XXX - todo - test "a" mode!
|
||||
finally:
|
||||
try:
|
||||
os.unlink(fname)
|
||||
except OSError, details:
|
||||
print "Error removing temp test file:", details
|
||||
|
||||
def _TestAll():
|
||||
# A mini test suite.
|
||||
# Get a test file, and convert it to a file:// URI.
|
||||
# check what we read is the same as when
|
||||
# we read this file "normally"
|
||||
fname = components.__file__
|
||||
if fname[-1] in "cCoO": # fix .pyc/.pyo
|
||||
fname = fname[:-1]
|
||||
expected = open(fname, "rb").read()
|
||||
# convert the fname to a URI.
|
||||
url = LocalFileToURL(fname)
|
||||
# First try passing a URL as a string.
|
||||
_DoTestRead( URIFile( url.spec), expected)
|
||||
print "Open as string test worked."
|
||||
# Now with a URL object.
|
||||
_DoTestRead( URIFile( url ), expected)
|
||||
print "Open as URL test worked."
|
||||
|
||||
_DoTestBufferRead( URIFile( url ), expected)
|
||||
print "File test using buffers worked."
|
||||
|
||||
# For the sake of testing, do our pointless, demo object!
|
||||
_DoTestRead( LocalFile(fname), expected )
|
||||
print "Local file read test worked."
|
||||
|
||||
# Now do the full test of our pointless, demo object!
|
||||
_TestLocalFile()
|
||||
|
||||
def _TestURI(url):
|
||||
test_file = URIFile(url)
|
||||
print "Opened file is", test_file
|
||||
got = test_file.read()
|
||||
print "Read %d bytes of data from %r" % (len(got), url)
|
||||
test_file.close()
|
||||
|
||||
if __name__=='__main__':
|
||||
import sys
|
||||
if len(sys.argv) < 2:
|
||||
print "No URL specified on command line - performing self-test"
|
||||
_TestAll()
|
||||
else:
|
||||
_TestURI(sys.argv[1])
|
||||
217
mozilla/extensions/python/xpcom/makefile.stupid.linux
Normal file
217
mozilla/extensions/python/xpcom/makefile.stupid.linux
Normal file
@@ -0,0 +1,217 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# Dumb makefile to build PyXPCOM on linux
|
||||
#
|
||||
# The build is by no means clean. I just kept shoving in compiler and linker
|
||||
# options until it worked. :)
|
||||
#
|
||||
# USAGE:
|
||||
# 1. edit top section as appropriate
|
||||
# 2. build, install, and test PyXPCOM
|
||||
# > make -f makefile.stupid.linux DEBUG=1
|
||||
# > make -f makefile.stupid.linux DEBUG=1 install
|
||||
# > make -f makefile.stupid.linux DEBUG=1 test
|
||||
# A debug build is suggested (DEBUG=1) by default because a default
|
||||
# mozilla build is a debug build. Exclude the "DEBUG=1" to build for a
|
||||
# release build of mozilla.
|
||||
#
|
||||
|
||||
#-------------------------
|
||||
# You must edit the variables in this section as appropriate for your machine
|
||||
# The most common edits will just be:
|
||||
# MOZ_SRC, INSTALLDIR, and PYTHON_SRC
|
||||
# =========== START OF SECTION FOR COMMON EDITS =====================
|
||||
|
||||
# We expect a "mozilla" directory under this
|
||||
MOZ_SRC=/home/skip/src
|
||||
|
||||
# this will have an "xpcom" subdir on install
|
||||
INSTALLDIR=/usr/local/ActivePython-2.0/lib/python2.0/site-packages
|
||||
|
||||
PYTHON_SRC=/usr/local/ActivePython-2.0
|
||||
|
||||
# =========== START OF SECTION FOR COMMON EDITS =====================
|
||||
|
||||
MOZCOMPONENTSDIR=$(MOZ_SRC)/mozilla/dist/bin/components
|
||||
MOZINCLUDES=-I$(MOZ_SRC)/mozilla/dist/include
|
||||
MOZLIBDIR=$(MOZ_SRC)/mozilla/dist/lib
|
||||
|
||||
# this is setup to use the *installed* Python directory structure
|
||||
# - To use the development Python dir structure some changes are
|
||||
# necessary here *and* below (below, because there two lib dir
|
||||
# to include in LDFLAGS for the dev dir structure)
|
||||
PYTHON_SRC=/usr/local/ActivePython-2.0
|
||||
PYTHONINCLUDES=-I$(PYTHON_SRC)/include/python2.0
|
||||
PYTHONLIBDIR=$(PYTHON_SRC)/lib/python2.0/config
|
||||
|
||||
XPIDL=$(MOZ_SRC)/mozilla/dist/bin/xpidl
|
||||
IDLINCLUDES=-I$(MOZ_SRC)/mozilla/dist/idl
|
||||
|
||||
|
||||
#-------------------------
|
||||
# You should not need to edit anything beyond this point.
|
||||
#
|
||||
|
||||
# the main PyXPCOM engine library
|
||||
ENGINE=src/_xpcommodule.so
|
||||
# the PyXPCOM loader
|
||||
LOADER=src/loader/libpyloader.so
|
||||
|
||||
all:: $(ENGINE) $(LOADER)
|
||||
|
||||
|
||||
#---- build the PyXPCOM loader
|
||||
|
||||
LOADER_CFLAGS=-fpic -fno-rtti -fno-exceptions -Wconversion \
|
||||
-Wpointer-arith -Wbad-function-cast -Wcast-align -Woverloaded-virtual \
|
||||
-Wsynth -pedantic -Wno-long-long -pthread -DTRIMMED
|
||||
ifdef DEBUG
|
||||
LOADER_CFLAGS += -DDEBUG
|
||||
endif
|
||||
|
||||
# NOTE: not sure if using -rpath is the best way to do this
|
||||
LOADER_LDFLAGS=-Xlinker -rpath -Xlinker $(MOZLIBDIR) \
|
||||
-Xlinker -rpath -Xlinker $(MOZLIBDIR)/components \
|
||||
-Xlinker -rpath -Xlinker $(PYTHONLIBDIR) \
|
||||
-L$(MOZLIBDIR) -L$(PYTHONLIBDIR)
|
||||
# NOTE: can't remember if "-shared" is necessary here
|
||||
LOADER_LIBS=-lpython2.0 -ldl -lpthread -ldb -lutil -shared -lxpcom
|
||||
$(LOADER): src/loader/pyloader.cpp
|
||||
c++ $(LOADER_CFLAGS) $(MOZINCLUDES) $(PYTHONINCLUDES) \
|
||||
-c src/loader/pyloader.cpp \
|
||||
-o src/loader/pyloader.o
|
||||
c++ $(LOADER_CFLAGS) $(LOADER_LDFLAGS) $(LOADER_LIBS) \
|
||||
-o $(LOADER) \
|
||||
src/loader/pyloader.o
|
||||
|
||||
|
||||
#---- build the PyXPCOM engine
|
||||
|
||||
ENGINE_CFLAGS=-fpic -fno-rtti -fno-exceptions -Wconversion \
|
||||
-Wpointer-arith -Wbad-function-cast -Wcast-align -Woverloaded-virtual \
|
||||
-Wsynth -pedantic -Wno-long-long -pthread -DTRIMMED -nostdlib
|
||||
ifdef DEBUG
|
||||
ENGINE_CFLAGS += -DDEBUG
|
||||
endif
|
||||
|
||||
# -DXPCOM_EXPORTS
|
||||
XPCOM_SRC_OBJECTS = \
|
||||
src/ErrorUtils.o \
|
||||
src/PyGBase.o \
|
||||
src/PyGModule.o \
|
||||
src/PyGStub.o \
|
||||
src/PyGInputStream.o \
|
||||
src/PyGWeakReference.o \
|
||||
src/PyIComponentManager.o \
|
||||
src/PyIInputStream.o \
|
||||
src/PyIEnumerator.o \
|
||||
src/PyIID.o \
|
||||
src/PyIInterfaceInfo.o \
|
||||
src/PyIInterfaceInfoManager.o \
|
||||
src/PyIServiceManager.o \
|
||||
src/PyISimpleEnumerator.o \
|
||||
src/PyISupports.o \
|
||||
src/Pyxpt_info.o \
|
||||
src/TypeObject.o \
|
||||
src/VariantUtils.o \
|
||||
src/dllmain.o \
|
||||
src/xpcom.o
|
||||
|
||||
%.o: %.cpp
|
||||
c++ $(ENGINE_CFLAGS) $(MOZINCLUDES) $(PYTHONINCLUDES) \
|
||||
-c $< -o $@
|
||||
|
||||
# NOTE: not sure if using -rpath is the best way to do this
|
||||
# NOTE: can't remember if "-shared" is necessary here
|
||||
ENGINE_LDFLAGS=-Xlinker -rpath -Xlinker $(MOZLIBDIR) \
|
||||
-Xlinker -rpath -Xlinker $(MOZLIBDIR)/components \
|
||||
-Xlinker -rpath -Xlinker $(PYTHONLIBDIR) \
|
||||
-Xlinker -shared
|
||||
ENGINE_LIBS=-lpython2.0 -ldl -lpthread -ldb -lutil -lxpcom \
|
||||
-lnspr4 -lgtk -lgdk -rdynamic -lgmodule -lglib -lm -lplc4 \
|
||||
-lpthread -lnsl -lresolv -lm -lc -lgcc
|
||||
|
||||
$(ENGINE): $(XPCOM_SRC_OBJECTS)
|
||||
c++ $(ENGINE_CFLAGS) $(ENGINE_LDFLAGS) -o $(ENGINE) \
|
||||
$(XPCOM_SRC_OBJECTS) -L$(MOZLIBDIR) -L$(PYTHONLIBDIR) $(ENGINE_LIBS)
|
||||
|
||||
|
||||
#---- install PyXPCOM
|
||||
|
||||
XPCOM_PACKAGE_FILES = \
|
||||
__init__.py \
|
||||
components.py \
|
||||
file.py \
|
||||
nsError.py \
|
||||
register.py \
|
||||
xpcom_consts.py \
|
||||
xpt.py \
|
||||
client/__init__.py \
|
||||
server/__init__.py \
|
||||
server/enumerator.py \
|
||||
server/factory.py \
|
||||
server/loader.py \
|
||||
server/module.py \
|
||||
server/policy.py
|
||||
|
||||
# this is a cheasy install
|
||||
# - no attention to permissions
|
||||
# - doesn't explicitly use $(XPCOM_PACKAGE_FILES)
|
||||
install:: all $(XPCOM_PACKAGE_FILES)
|
||||
mkdir -p $(INSTALLDIR)/xpcom/client
|
||||
mkdir -p $(INSTALLDIR)/xpcom/server
|
||||
cp -f *.py $(INSTALLDIR)/xpcom
|
||||
cp -f client/*.py $(INSTALLDIR)/xpcom/client
|
||||
cp -f server/*.py $(INSTALLDIR)/xpcom/server
|
||||
cp -f $(ENGINE) $(INSTALLDIR)/xpcom
|
||||
mkdir -p $(MOZCOMPONENTSDIR)
|
||||
cp -f $(LOADER) $(MOZCOMPONENTSDIR)
|
||||
( \
|
||||
export PYTHONPATH=$(INSTALLDIR):$(PYTHONPATH) ; \
|
||||
export MOZILLA_FIVE_HOME=$(MOZ_SRC)/mozilla/dist/bin ; \
|
||||
export LD_LIBRARY_PATH=$(MOZ_SRC)/mozilla/dist/bin ; \
|
||||
$(MOZ_SRC)/mozilla/dist/bin/regxpcom \
|
||||
)
|
||||
|
||||
|
||||
#---- build and run the PyXPCOM test suite
|
||||
|
||||
all:: test/test_component/py_test_component.xpt
|
||||
|
||||
test/test_component/py_test_component.xpt: test/test_component/py_test_component.idl
|
||||
$(XPIDL) -m typelib -w $(IDLINCLUDES) -o test/test_component/py_test_component $<
|
||||
|
||||
install::
|
||||
mkdir -p $(MOZCOMPONENTSDIR)
|
||||
cp -f test/test_component/py_test_component.xpt $(MOZCOMPONENTSDIR)
|
||||
cp -f test/test_component/py_test_component.py $(MOZCOMPONENTSDIR)
|
||||
( \
|
||||
export PYTHONPATH=$(INSTALLDIR):$(PYTHONPATH) ; \
|
||||
export MOZILLA_FIVE_HOME=$(MOZ_SRC)/mozilla/dist/bin ; \
|
||||
export LD_LIBRARY_PATH=$(MOZ_SRC)/mozilla/dist/bin ; \
|
||||
$(MOZ_SRC)/mozilla/dist/bin/regxpcom \
|
||||
)
|
||||
|
||||
test:: install
|
||||
( \
|
||||
export PYTHONPATH=$(INSTALLDIR):$(PYTHONPATH) ; \
|
||||
export MOZILLA_FIVE_HOME=$(MOZ_SRC)/mozilla/dist/bin ; \
|
||||
export LD_LIBRARY_PATH=$(MOZ_SRC)/mozilla/dist/bin ; \
|
||||
python test/regrtest.py \
|
||||
)
|
||||
|
||||
runpython: install
|
||||
( \
|
||||
export PYTHONPATH=$(INSTALLDIR):$(PYTHONPATH) ; \
|
||||
export MOZILLA_FIVE_HOME=$(MOZ_SRC)/mozilla/dist/bin ; \
|
||||
export LD_LIBRARY_PATH=$(MOZ_SRC)/mozilla/dist/bin ; \
|
||||
python \
|
||||
)
|
||||
|
||||
clean:
|
||||
find . -name "*~" | xargs rm -f
|
||||
find . -name "*.o" | xargs rm -f
|
||||
find . -name "*.pyc" | xargs rm -f
|
||||
find . -name "*.so" | xargs rm -f
|
||||
|
||||
223
mozilla/extensions/python/xpcom/makefile.stupid.win
Normal file
223
mozilla/extensions/python/xpcom/makefile.stupid.win
Normal file
@@ -0,0 +1,223 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# Dumb makefile to build PyXPCOM on Windows
|
||||
#
|
||||
# The build is by no means clean. I just kept shoving in compiler and linker
|
||||
# options until it worked. :)
|
||||
#
|
||||
# USAGE:
|
||||
# 1. edit top section as appropriate
|
||||
# 2. build, install, and test PyXPCOM
|
||||
# > nmake -f makefile.stupid.win
|
||||
# > nmake -f makefile.stupid.win install
|
||||
# > nmake -f makefile.stupid.win test
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# You must edit the variables in this section as appropriate for your machine
|
||||
# The most common edits will just be:
|
||||
# MOZ_SRC, INSTALLDIR, and PYTHON_SRC
|
||||
# ========= START OF SECTION FOR COMMON EDITS ==============
|
||||
|
||||
# We expect a "mozilla" directory under this
|
||||
MOZ_SRC=c:\src
|
||||
|
||||
# this will have an "xpcom" subdir on install
|
||||
INSTALLDIR=C:\Python20
|
||||
|
||||
# this is setup to use the *installed* Python directory structure
|
||||
PYTHON_SRC=C:\Python20
|
||||
|
||||
|
||||
# ========= END OF SECTION FOR COMMON EDITS ==============
|
||||
|
||||
!IF DEFINED(DEBUG)
|
||||
MOZ_BUILD_DIR=$(MOZ_SRC)\mozilla\dist\WIN32_D.OBJ
|
||||
PYTHON_EXE=python_d.exe
|
||||
!ELSE
|
||||
MOZ_BUILD_DIR=$(MOZ_SRC)\mozilla\dist\WIN32_O.OBJ
|
||||
PYTHON_EXE=python.exe
|
||||
!ENDIF
|
||||
|
||||
MOZCOMPONENTSDIR=$(MOZ_BUILD_DIR)\bin\components
|
||||
MOZINCLUDES=/I$(MOZ_SRC)\mozilla\dist\include /I$(MOZ_BUILD_DIR)\include
|
||||
MOZLIBS=/LIBPATH:$(MOZ_BUILD_DIR)\lib
|
||||
|
||||
# this is setup to use the *installed* Python directory structure
|
||||
# - To use the development Python dir structure some changes are
|
||||
# necessary here *and* below (below, because there two lib dir
|
||||
# to include in LDFLAGS for the dev dir structure)
|
||||
PYTHONINCLUDES=/I$(PYTHON_SRC)\include
|
||||
PYTHONLIBS=/LIBPATH:$(PYTHON_SRC)\libs
|
||||
|
||||
MOZ_BIN=$(MOZ_BUILD_DIR)\bin
|
||||
|
||||
XPIDL=$(MOZ_BIN)\xpidl.exe
|
||||
IDLINCLUDES=-I$(MOZ_SRC)\mozilla\dist\idl
|
||||
REGXPCOM=$(MOZ_BIN)\regxpcom.exe
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# You should not need to edit anything beyond this point.
|
||||
#
|
||||
|
||||
# the main PyXPCOM engine library
|
||||
!IF DEFINED(DEBUG)
|
||||
ENGINE=src\_xpcom_d.pyd
|
||||
# the PyXPCOM loader
|
||||
LOADER=src\loader\pyloader_d.dll
|
||||
!ELSE
|
||||
ENGINE=src\_xpcom.pyd
|
||||
# the PyXPCOM loader
|
||||
LOADER=src\loader\pyloader.dll
|
||||
!ENDIF
|
||||
|
||||
|
||||
all:: $(ENGINE) $(LOADER)
|
||||
|
||||
|
||||
#---- build the PyXPCOM loader
|
||||
|
||||
!IF DEFINED(DEBUG)
|
||||
LOADER_CFLAGS_THIS_BUILD=/ZI /MDd /Od /DDEBUG /D_DEBUG
|
||||
LOADER_LDFLAGS_THIS_BUILD=/debug
|
||||
!ELSE
|
||||
LOADER_CFLAGS_THIS_BUILD=/MD /Ox /DNDEBUG /D_NDEBUG
|
||||
LOADER_LDFLAGS_THIS_BUILD=
|
||||
!ENDIF
|
||||
|
||||
LOADER_CFLAGS=/W3 /D WIN32 /D _WINDOWS /D XPCOM_EXPORTS $(LOADER_CFLAGS_THIS_BUILD)
|
||||
LOADER_LDFLAGS=/dll $(LOADER_LDFLAGS_THIS_BUILD)
|
||||
|
||||
$(LOADER): src\loader\pyloader.cpp
|
||||
cl /nologo $(LOADER_CFLAGS) $(MOZINCLUDES) $(PYTHONINCLUDES) \
|
||||
/c src\loader\pyloader.cpp \
|
||||
/Fosrc\loader\pyloader.obj
|
||||
link $(LOADER_LDFLAGS) $(PYTHONLIBS) $(MOZLIBS) \
|
||||
/out:$(LOADER) \
|
||||
src\loader\pyloader.obj \
|
||||
xpcom.lib
|
||||
|
||||
|
||||
#---- build the PyXPCOM engine
|
||||
|
||||
!IF DEFINED(DEBUG)
|
||||
ENGINE_CFLAGS_THIS_BUILD=/ZI /MDd /Od /DDEBUG /D_DEBUG
|
||||
!ELSE
|
||||
ENGINE_CFLAGS_THIS_BUILD=/MD /Ox /DNDEBUG /D_NDEBUG
|
||||
!ENDIF
|
||||
|
||||
ENGINE_CFLAGS=/D _USRDLL /W3 /D WIN32 /D _WINDOWS /D XPCOM_EXPORTS $(ENGINE_CFLAGS_THIS_BUILD)
|
||||
|
||||
XPCOM_SRC_OBJECTS = \
|
||||
src\ErrorUtils.obj \
|
||||
src\PyGBase.obj \
|
||||
src\PyGModule.obj \
|
||||
src\PyGStub.obj \
|
||||
src\PyGInputStream.obj \
|
||||
src\PyGWeakReference.obj \
|
||||
src\PyIComponentManager.obj \
|
||||
src\PyIInputStream.obj \
|
||||
src\PyIEnumerator.obj \
|
||||
src\PyIID.obj \
|
||||
src\PyIInterfaceInfo.obj \
|
||||
src\PyIInterfaceInfoManager.obj \
|
||||
src\PyIServiceManager.obj \
|
||||
src\PyISimpleEnumerator.obj \
|
||||
src\PyISupports.obj \
|
||||
src\Pyxpt_info.obj \
|
||||
src\TypeObject.obj \
|
||||
src\VariantUtils.obj \
|
||||
src\dllmain.obj \
|
||||
src\xpcom.obj
|
||||
|
||||
.cpp.obj:
|
||||
cl /nologo $(ENGINE_CFLAGS) $(MOZINCLUDES) $(PYTHONINCLUDES) -c $< -Fo$@
|
||||
|
||||
!IF DEFINED(DEBUG)
|
||||
ENGINE_LDFLAGS_THIS_BUILD=/debug
|
||||
!ELSE
|
||||
ENGINE_LDFLAGS_THIS_BUILD=
|
||||
!ENDIF
|
||||
|
||||
#XXX for debug: ENGINE_LDFLAGS_DEBUG=/DEBUG
|
||||
ENGINE_LDFLAGS=/dll /export:init_xpcom $(ENGINE_LDFLAGS_THIS_BUILD)
|
||||
|
||||
$(ENGINE): $(XPCOM_SRC_OBJECTS)
|
||||
link $(ENGINE_LDFLAGS) $(XPCOM_SRC_OBJECTS) $(MOZLIBS) $(PYTHONLIBS) /out:$(ENGINE)
|
||||
|
||||
|
||||
#---- install PyXPCOM
|
||||
|
||||
XPCOM_PACKAGE_FILES = \
|
||||
__init__.py \
|
||||
components.py \
|
||||
file.py \
|
||||
nsError.py \
|
||||
register.py \
|
||||
xpcom_consts.py \
|
||||
xpt.py \
|
||||
client\__init__.py \
|
||||
server\__init__.py \
|
||||
server\enumerator.py \
|
||||
server\factory.py \
|
||||
server\loader.py \
|
||||
server\module.py \
|
||||
server\policy.py
|
||||
|
||||
# this is a cheasy install
|
||||
# - no attention to permissions
|
||||
# - doesn't explicitly use $(XPCOM_PACKAGE_FILES)
|
||||
install:: all $(XPCOM_PACKAGE_FILES)
|
||||
if not exist $(INSTALLDIR) mkdir $(INSTALLDIR)
|
||||
if not exist $(INSTALLDIR)\xpcom mkdir $(INSTALLDIR)\xpcom
|
||||
if not exist $(INSTALLDIR)\xpcom\client mkdir $(INSTALLDIR)\xpcom\client
|
||||
if not exist $(INSTALLDIR)\xpcom\server mkdir $(INSTALLDIR)\xpcom\server
|
||||
if not exist $(INSTALLDIR)\xpcom\test mkdir $(INSTALLDIR)\xpcom\test
|
||||
if not exist $(INSTALLDIR)\xpcom\test\output mkdir $(INSTALLDIR)\xpcom\test\output
|
||||
copy /v /y *.py $(INSTALLDIR)\xpcom
|
||||
copy /v /y client\*.py $(INSTALLDIR)\xpcom\client
|
||||
copy /v /y server\*.py $(INSTALLDIR)\xpcom\server
|
||||
copy /v /y test\*.py $(INSTALLDIR)\xpcom\test
|
||||
copy /v /y test\output\* $(INSTALLDIR)\xpcom\test\output
|
||||
copy /v /y $(ENGINE) $(INSTALLDIR)\xpcom
|
||||
if not exist $(MOZCOMPONENTSDIR) mkdir $(MOZCOMPONENTSDIR)
|
||||
copy /v /y $(LOADER) $(MOZCOMPONENTSDIR)
|
||||
set PYTHONPATH=$(INSTALLDIR);$(PYTHONPATH)
|
||||
set PATH=$(MOZ_BIN);$(PATH)
|
||||
$(REGXPCOM)
|
||||
|
||||
|
||||
#---- build and run the PyXPCOM test suite
|
||||
|
||||
all:: test\test_component\py_test_component.xpt
|
||||
|
||||
test\test_component\py_test_component.xpt: test\test_component\py_test_component.idl
|
||||
$(XPIDL) -m typelib -w $(IDLINCLUDES) -o test\test_component\py_test_component test\test_component\py_test_component.idl
|
||||
|
||||
install::
|
||||
if not exist $(MOZCOMPONENTSDIR) mkdir $(MOZCOMPONENTSDIR)
|
||||
copy /v /y test\test_component\py_test_component.xpt $(MOZCOMPONENTSDIR)
|
||||
copy /v /y test\test_component\py_test_component.py $(MOZCOMPONENTSDIR)
|
||||
set PYTHONPATH=$(INSTALLDIR);$(PYTHONPATH)
|
||||
set PATH=$(MOZ_BIN);$(PATH)
|
||||
$(REGXPCOM)
|
||||
|
||||
test:: install
|
||||
set PATH=$(MOZ_BIN);$(PATH)
|
||||
set PYTHONPATH=$(INSTALLDIR);$(PYTHONPATH)
|
||||
$(PYTHON_EXE) test\regrtest.py
|
||||
|
||||
runpython:: install
|
||||
set PATH=$(MOZ_BIN);$(PATH)
|
||||
set PYTHONPATH=$(INSTALLDIR);$(PYTHONPATH)
|
||||
$(PYTHON_EXE)
|
||||
|
||||
clean:
|
||||
-del /f /q src\*.obj
|
||||
-del /f /q src\loader\*.obj
|
||||
-del /f /q *.pyc
|
||||
-del /f /q client\*.pyc
|
||||
-del /f /q server\*.pyc
|
||||
-del /f /q test\*.pyc
|
||||
|
||||
115
mozilla/extensions/python/xpcom/nsError.py
Normal file
115
mozilla/extensions/python/xpcom/nsError.py
Normal file
@@ -0,0 +1,115 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# Generated by h2py from nsError.h
|
||||
# CMD line: h2py.py -i (nsresult) nsError.h
|
||||
|
||||
# XXX - NOTE - some manual code at the end, and all literals moved back to ints
|
||||
NS_ERROR_MODULE_XPCOM = 1
|
||||
NS_ERROR_MODULE_BASE = 2
|
||||
NS_ERROR_MODULE_GFX = 3
|
||||
NS_ERROR_MODULE_WIDGET = 4
|
||||
NS_ERROR_MODULE_CALENDAR = 5
|
||||
NS_ERROR_MODULE_NETWORK = 6
|
||||
NS_ERROR_MODULE_PLUGINS = 7
|
||||
NS_ERROR_MODULE_LAYOUT = 8
|
||||
NS_ERROR_MODULE_HTMLPARSER = 9
|
||||
NS_ERROR_MODULE_RDF = 10
|
||||
NS_ERROR_MODULE_UCONV = 11
|
||||
NS_ERROR_MODULE_REG = 12
|
||||
NS_ERROR_MODULE_FILES = 13
|
||||
NS_ERROR_MODULE_DOM = 14
|
||||
NS_ERROR_MODULE_IMGLIB = 15
|
||||
NS_ERROR_MODULE_MAILNEWS = 16
|
||||
NS_ERROR_MODULE_EDITOR = 17
|
||||
NS_ERROR_MODULE_XPCONNECT = 18
|
||||
NS_ERROR_MODULE_PROFILE = 19
|
||||
def NS_FAILED(_nsresult): return ((_nsresult) & 0x80000000)
|
||||
|
||||
NS_ERROR_SEVERITY_SUCCESS = 0
|
||||
NS_ERROR_SEVERITY_ERROR = 1
|
||||
NS_ERROR_MODULE_BASE_OFFSET = 0x45
|
||||
def NS_ERROR_GET_CODE(err): return ((err) & 0xffff)
|
||||
|
||||
def NS_ERROR_GET_MODULE(err): return (((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 0x1fff))
|
||||
|
||||
def NS_ERROR_GET_SEVERITY(err): return (((err) >> 31) & 0x1)
|
||||
|
||||
NS_OK = 0
|
||||
NS_COMFALSE = 1
|
||||
NS_ERROR_BASE = ( 0xC1F30000)
|
||||
NS_ERROR_NOT_INITIALIZED = (NS_ERROR_BASE + 1)
|
||||
NS_ERROR_ALREADY_INITIALIZED = (NS_ERROR_BASE + 2)
|
||||
NS_ERROR_NOT_IMPLEMENTED = ( 0x80004001)
|
||||
NS_NOINTERFACE = ( 0x80004002)
|
||||
NS_ERROR_NO_INTERFACE = NS_NOINTERFACE
|
||||
NS_ERROR_INVALID_POINTER = ( 0x80004003)
|
||||
NS_ERROR_NULL_POINTER = NS_ERROR_INVALID_POINTER
|
||||
NS_ERROR_ABORT = ( 0x80004004)
|
||||
NS_ERROR_FAILURE = ( 0x80004005)
|
||||
NS_ERROR_UNEXPECTED = ( 0x8000ffff)
|
||||
NS_ERROR_OUT_OF_MEMORY = ( 0x8007000e)
|
||||
NS_ERROR_ILLEGAL_VALUE = ( 0x80070057)
|
||||
NS_ERROR_INVALID_ARG = NS_ERROR_ILLEGAL_VALUE
|
||||
NS_ERROR_NO_AGGREGATION = ( 0x80040110)
|
||||
NS_ERROR_NOT_AVAILABLE = ( 0x80040111)
|
||||
NS_ERROR_FACTORY_NOT_REGISTERED = ( 0x80040154)
|
||||
NS_ERROR_FACTORY_REGISTER_AGAIN = ( 0x80040155)
|
||||
NS_ERROR_FACTORY_NOT_LOADED = ( 0x800401f8)
|
||||
NS_ERROR_FACTORY_NO_SIGNATURE_SUPPORT = \
|
||||
(NS_ERROR_BASE + 0x101)
|
||||
NS_ERROR_FACTORY_EXISTS = (NS_ERROR_BASE + 0x100)
|
||||
NS_ERROR_PROXY_INVALID_IN_PARAMETER = ( 0x80010010)
|
||||
NS_ERROR_PROXY_INVALID_OUT_PARAMETER = ( 0x80010011)
|
||||
|
||||
##### END OF GENERATED CODE
|
||||
#####
|
||||
def NS_ERROR_GENERATE_FAILURE(module,code):
|
||||
return (NS_ERROR_SEVERITY_ERROR<<31) | ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
|
||||
|
||||
NS_BASE_STREAM_CLOSED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 2)
|
||||
NS_BASE_STREAM_OSERROR = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 3)
|
||||
NS_BASE_STREAM_ILLEGAL_ARGS = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 4)
|
||||
NS_BASE_STREAM_NO_CONVERTER = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 5)
|
||||
NS_BASE_STREAM_BAD_CONVERSION = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 6)
|
||||
NS_BASE_STREAM_WOULD_BLOCK = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 7)
|
||||
NS_ERROR_FILE_UNRECOGNIZED_PATH = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 1)
|
||||
NS_ERROR_FILE_UNRESOLVABLE_SYMLINK = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 2)
|
||||
NS_ERROR_FILE_EXECUTION_FAILED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 3)
|
||||
NS_ERROR_FILE_UNKNOWN_TYPE = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 4)
|
||||
NS_ERROR_FILE_DESTINATION_NOT_DIR = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 5)
|
||||
NS_ERROR_FILE_TARGET_DOES_NOT_EXIST = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 6)
|
||||
NS_ERROR_FILE_COPY_OR_MOVE_FAILED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 7)
|
||||
NS_ERROR_FILE_ALREADY_EXISTS = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 8)
|
||||
NS_ERROR_FILE_INVALID_PATH = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 9)
|
||||
NS_ERROR_FILE_DISK_FULL = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 10)
|
||||
NS_ERROR_FILE_CORRUPTED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 11)
|
||||
NS_ERROR_FILE_NOT_DIRECTORY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 12)
|
||||
NS_ERROR_FILE_IS_DIRECTORY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 13)
|
||||
NS_ERROR_FILE_IS_LOCKED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 14)
|
||||
NS_ERROR_FILE_TOO_BIG = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 15)
|
||||
NS_ERROR_FILE_NO_DEVICE_SPACE = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 16)
|
||||
NS_ERROR_FILE_NAME_TOO_LONG = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 17)
|
||||
NS_ERROR_FILE_NOT_FOUND = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 18)
|
||||
NS_ERROR_FILE_READ_ONLY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 19)
|
||||
NS_ERROR_FILE_DIR_NOT_EMPTY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 20)
|
||||
NS_ERROR_FILE_ACCESS_DENIED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 21)
|
||||
|
||||
## from netCore.h
|
||||
NS_ERROR_ALREADY_CONNECTED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 11)
|
||||
|
||||
NS_ERROR_NOT_CONNECTED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 12)
|
||||
NS_ERROR_IN_PROGRESS = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 15)
|
||||
NS_ERROR_OFFLINE = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 16)
|
||||
|
||||
## from nsISocketTransportService.idl
|
||||
NS_ERROR_CONNECTION_REFUSED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 13)
|
||||
|
||||
NS_ERROR_NET_TIMEOUT = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 14)
|
||||
|
||||
# Status nsresult codes: used with nsIProgressEventSink::OnStatus
|
||||
NS_NET_STATUS_RESOLVING_HOST = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 3)
|
||||
NS_NET_STATUS_CONNECTED_TO = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 4)
|
||||
NS_NET_STATUS_SENDING_TO = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 5)
|
||||
NS_NET_STATUS_RECEIVING_FROM = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 6)
|
||||
NS_NET_STATUS_CONNECTING_TO = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 7)
|
||||
91
mozilla/extensions/python/xpcom/readme.html
Normal file
91
mozilla/extensions/python/xpcom/readme.html
Normal file
@@ -0,0 +1,91 @@
|
||||
<html>
|
||||
<!-- Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. -->
|
||||
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Python XPCOM module</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Python XPCOM Package</h1>
|
||||
|
||||
<p>Version 0.91 - January 2001</p>
|
||||
<p>This is the readme for the Python interface to <b>XPCOM</b>.</p>
|
||||
<p><b>XPCOM </b>is an acronym for "Cross Platform COM". It has
|
||||
come out of the <a href="http://www.mozilla.org">Mozilla</a> project, which
|
||||
maintains the <a href="http://www.mozilla.org/projects/xpcom/">main XPCOM
|
||||
project pages.</a> The Python XPCOM package is a set of Python bindings to
|
||||
XPCOM, allowing a Python programmer to both use and implement XPCOM
|
||||
interfaces. If you don't know what <a href="http://www.python.org">Python</a>
|
||||
is, then none of this probably interests you at all!</p>
|
||||
<p>This readme has links to the following information:</p>
|
||||
<ul>
|
||||
<li><a href="doc/configure.html">Building, Configuring and
|
||||
Testing the Python
|
||||
XPCOM Package</a></li>
|
||||
<li><a href="doc/tutorial.html">A tutorial for the Python XPCOM package</a></li>
|
||||
<li>Some <a href="doc/advanced.html">advanced
|
||||
topics and other miscellaneous information</a></li>
|
||||
<li><a href="doc/architecture.html">Information on the architecture</a></li>
|
||||
<li>A list of the <a href="#KnownBugs">known issues and bugs</a>, the <a href="#ReleaseHistory">release
|
||||
history</a> and the <a href="doc/credits.html">PyXPCOM acknowledgements</a></li>
|
||||
</ul>
|
||||
<p>Note: <b>This package requires Python 1.6 or later</b>; we recommend using
|
||||
the latest
|
||||
official Python version (currently 2.0). This package works
|
||||
very well with the latest <a href="http://www.ActiveState.com/Products/ActivePython">ActivePython</a>,
|
||||
and does not require any external modules or packages beyond what is provided in
|
||||
the core Python release for each platform.</p>
|
||||
<h2>About the Python XPCOM Package</h2>
|
||||
<p>The Python XPCOM Package was developed by <a href="http://www.ActiveState.com">ActiveState
|
||||
Tool Corporation</a>, and came out of their <a href="http://www.ActiveState.com/Products/Komodo">Komodo
|
||||
project</a>. The Python XPCOM package is released under the <a href="http://www.mozilla.org/MPL/">Mozilla
|
||||
Public License (MPL)</a></p>
|
||||
<p>Please see the <a href="doc/credits.html">credits file</a> for a list of
|
||||
contributors. </p>
|
||||
<h2><a name="KnownBugs">Known Bugs</a>/Issues</h2>
|
||||
<ul>
|
||||
<li>No attempt is made to recurse sub-directories of the main
|
||||
"components" directory. This is because we may decide on some
|
||||
smart scheme for recursion (similar to Python packages), and don't want people
|
||||
to rely on simple recursive searches.</li>
|
||||
<li>No management of the PythonPath is done by the package. You must
|
||||
arrange for the Python <i>xpcom</i> package to be on your PythonPath.
|
||||
Significantly, the XPCOM <i> components</i> directory is not on the PythonPath and
|
||||
generally cannot be, as Python will often find other DLLs in this directory and
|
||||
attempt to use them as Python modules. This means that Python module
|
||||
files will not be found in the <i> components</i> directory, even when referenced by
|
||||
another component - thus, a component can not import another component
|
||||
source file as a regular module! It is thought that when we know what to
|
||||
do with sub-directories of the <i> components</i> directory (as described above), some
|
||||
automated PythonPath support will be provided, so Python components and regular
|
||||
Python modules the component depends on can exist in the same directory
|
||||
structure.</li>
|
||||
<li>No unregistration support at all. The main Python Component Loader supports
|
||||
unregistration, but the actual Python objects themselves do not support unregistration. It is unclear if the Component Loader
|
||||
unregistration process needs to manually remove each component it is responsible
|
||||
for.</li>
|
||||
<li>All Python-implemented components unconditionally support
|
||||
weak-references. There is no way to disable this feature for any or all
|
||||
components. It is unclear if there is a need to prevent this, but it is
|
||||
documented here just in case!</li>
|
||||
</ul>
|
||||
<h2><a name="ReleaseHistory">Release History</a></h2>
|
||||
<h3>Version 0.90 - January 2001</h3>
|
||||
<ul>
|
||||
<li>First public release.</li>
|
||||
</ul>
|
||||
<h3>Version 0.91 - January 2001</h3>
|
||||
<ul>
|
||||
<li>Fix a seg fault on Linux when PYTHONPATH is not set.</li>
|
||||
<li>Changes to allow building with stand-alone XPCOM.</li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
37
mozilla/extensions/python/xpcom/register.py
Normal file
37
mozilla/extensions/python/xpcom/register.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
import os, sys
|
||||
|
||||
def addSelf(fname):
|
||||
#XXX the path hardcoding and env var reliance limits the usefulness
|
||||
#XXX I don't even know if this is used, or usable, at all anymore.
|
||||
try:
|
||||
mozSrc = os.environ['MOZ_SRC']
|
||||
except KeyError:
|
||||
print "register.py: need MOZ_SRC to be set"
|
||||
sys.exit(-1)
|
||||
try:
|
||||
komododist = os.environ['KOMODO']
|
||||
except KeyError:
|
||||
print "Set KOMODO"
|
||||
sys.exit(-1)
|
||||
|
||||
bindir = os.path.join(mozSrc, "dist", "WIN32_D.OBJ", "bin")
|
||||
idldir = os.path.join(mozSrc, "dist", "idl")
|
||||
idl2dir = os.path.join(komododist, "SciMoz")
|
||||
componentdir = os.path.normpath(os.path.join(bindir, 'components'))
|
||||
|
||||
base, ext = os.path.splitext(fname)
|
||||
idlfile = base+'.idl'
|
||||
pyfile = base+'.py'
|
||||
xptfile = base+'.xpt'
|
||||
if os.path.exists(idlfile):
|
||||
# IDL file of same name exists, assume it needs to be updated
|
||||
print r'%(bindir)s\xpidl -I %(idldir)s -I %(idl2dir)s -m typelib %(idlfile)s' % vars()
|
||||
os.system(r'%(bindir)s\xpidl -I %(idldir)s -I %(idl2dir)s -m typelib %(idlfile)s' % vars())
|
||||
print r'cp %(xptfile)s %(componentdir)s' % vars()
|
||||
os.system(r'cp %(xptfile)s %(componentdir)s' % vars())
|
||||
print 'cp %(pyfile)s %(componentdir)s' % vars()
|
||||
os.system('cp %(pyfile)s %(componentdir)s' % vars())
|
||||
|
||||
38
mozilla/extensions/python/xpcom/server/__init__.py
Normal file
38
mozilla/extensions/python/xpcom/server/__init__.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# The xpcom.server package.
|
||||
|
||||
from policy import DefaultPolicy
|
||||
from xpcom import _xpcom
|
||||
|
||||
# We define the concept of a single "tracer" object - similar to the single
|
||||
# Python "trace hook" for debugging. Someone can set
|
||||
# xpcom.server.tracer to some class/function, and it will be used in place
|
||||
# of the real xpcom object. Presumably this "trace" object will delegate
|
||||
# to the real object, but presumably also taking some other action, such
|
||||
# as calling a profiler or debugger.
|
||||
tracer = None
|
||||
|
||||
# Wrap an instance in an interface (via a policy)
|
||||
def WrapObject(ob, iid, policy = None):
|
||||
"""Called by the framework to attempt to wrap
|
||||
an object in a policy.
|
||||
If iid is None, it will use the first interface the object indicates it supports.
|
||||
"""
|
||||
if policy is None:
|
||||
policy = DefaultPolicy
|
||||
if tracer is not None:
|
||||
ob = tracer(ob)
|
||||
return _xpcom.WrapObject(policy( ob, iid ), iid)
|
||||
|
||||
# Create the main module for the Python loader.
|
||||
# This is a once only init process, and the returned object
|
||||
# if used to load all other Python components.
|
||||
|
||||
# This means that we keep all factories, modules etc implemented in
|
||||
# Python!
|
||||
def NS_GetModule( serviceManager, nsIFile ):
|
||||
import loader
|
||||
iid = _xpcom.IID_nsIModule
|
||||
return WrapObject(loader.MakePythonComponentLoaderModule(serviceManager, nsIFile), iid)
|
||||
24
mozilla/extensions/python/xpcom/server/enumerator.py
Normal file
24
mozilla/extensions/python/xpcom/server/enumerator.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
from xpcom import components
|
||||
|
||||
# This class is created by Python components when it
|
||||
# needs to return an enumerator.
|
||||
# For example, a component may implement a function:
|
||||
# nsISimpleEnumerator enumSomething();
|
||||
# This could could simply say:
|
||||
# return SimpleEnumerator([something1, something2, something3])
|
||||
class SimpleEnumerator:
|
||||
_com_interfaces_ = [components.interfaces.nsISimpleEnumerator]
|
||||
|
||||
def __init__(self, data):
|
||||
self._data = data
|
||||
self._index = 0
|
||||
|
||||
def hasMoreElements(self):
|
||||
return self._index < len(self._data)
|
||||
|
||||
def getNext(self):
|
||||
self._index = self._index + 1
|
||||
return self._data[self._index-1]
|
||||
36
mozilla/extensions/python/xpcom/server/factory.py
Normal file
36
mozilla/extensions/python/xpcom/server/factory.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# Class factory
|
||||
#
|
||||
# Hardly worth its own source file!
|
||||
import xpcom
|
||||
from xpcom import components, nsError, _xpcom
|
||||
|
||||
|
||||
class Factory:
|
||||
_com_interfaces_ = components.interfaces.nsIFactory
|
||||
# This will only ever be constructed via other Python code,
|
||||
# so we can have ctor args.
|
||||
def __init__(self, klass):
|
||||
self.klass = klass
|
||||
|
||||
def createInstance(self, outer, iid):
|
||||
if outer is not None:
|
||||
raise xpcom.ServerException(nsError.NS_ERROR_NO_AGGREGATION)
|
||||
|
||||
if xpcom.verbose:
|
||||
print "Python Factory creating", self.klass.__name__
|
||||
try:
|
||||
return self.klass()
|
||||
except:
|
||||
# An exception here may not be obvious to the user - none
|
||||
# of their code has been called yet. It can be handy on
|
||||
# failure to tell the user what class failed!
|
||||
_xpcom.LogWarning("Creation of class '%r' failed!\nException details follow\n" % (self.klass,))
|
||||
raise
|
||||
|
||||
def lockServer(self, lock):
|
||||
if xpcom.verbose:
|
||||
print "Python Factory LockServer called -", lock
|
||||
|
||||
208
mozilla/extensions/python/xpcom/server/loader.py
Normal file
208
mozilla/extensions/python/xpcom/server/loader.py
Normal file
@@ -0,0 +1,208 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
import xpcom
|
||||
from xpcom import components
|
||||
|
||||
import factory
|
||||
import module
|
||||
|
||||
import glob, os, types
|
||||
|
||||
from xpcom.client import Component
|
||||
|
||||
fileSizeValueName = "FileSize"
|
||||
lastModValueName = "LastModTimeStamp"
|
||||
xpcomKeyName = "software/mozilla/XPCOM/components"
|
||||
|
||||
# Until we get interface constants.
|
||||
When_Startup = 0
|
||||
When_Component = 1
|
||||
When_Timer = 2
|
||||
|
||||
def _has_good_attr(object, attr):
|
||||
# Actually allows "None" to be specified to disable inherited attributes.
|
||||
return getattr(object, attr, None) is not None
|
||||
|
||||
def FindCOMComponents(py_module):
|
||||
# For now, just run over all classes looking for likely candidates.
|
||||
comps = []
|
||||
for name, object in py_module.__dict__.items():
|
||||
if type(object)==types.ClassType and \
|
||||
_has_good_attr(object, "_com_interfaces_") and \
|
||||
_has_good_attr(object, "_reg_clsid_") and \
|
||||
_has_good_attr(object, "_reg_contractid_"):
|
||||
comps.append(object)
|
||||
return comps
|
||||
|
||||
def register_self(compMgr, location, registryLocation, componentType):
|
||||
pcl = PythonComponentLoader
|
||||
from xpcom import _xpcom
|
||||
svc = _xpcom.GetGlobalServiceManager().GetService("@mozilla.org/categorymanager;1", components.interfaces.nsICategoryManager)
|
||||
svc.addCategoryEntry("component-loader", pcl._reg_component_type_, pcl._reg_contractid_, 1, 1)
|
||||
|
||||
class PythonComponentLoader:
|
||||
_com_interfaces_ = components.interfaces.nsIComponentLoader
|
||||
_reg_clsid_ = "{63B68B1E-3E62-45f0-98E3-5E0B5797970C}" # Never copy these!
|
||||
_reg_contractid_ = "moz.pyloader.1"
|
||||
_reg_desc_ = "Python component loader"
|
||||
# Optional function which performs additional special registration
|
||||
# Appears that no special unregistration is needed for ComponentLoaders, hence no unregister function.
|
||||
_reg_registrar_ = (register_self,None)
|
||||
# Custom attributes for ComponentLoader registration.
|
||||
_reg_component_type_ = "script/python"
|
||||
|
||||
def __init__(self):
|
||||
self.com_modules = {} # Keyed by module's FQN as obtained from nsIFile.path
|
||||
|
||||
def _getCOMModuleForLocation(self, componentFile):
|
||||
fqn = componentFile.path
|
||||
mod = self.com_modules.get(fqn)
|
||||
if mod is not None:
|
||||
return mod
|
||||
import ihooks, sys
|
||||
base_name = os.path.splitext(os.path.basename(fqn))[0]
|
||||
loader = ihooks.ModuleLoader()
|
||||
|
||||
module_name_in_sys = "component:%s" % (base_name,)
|
||||
stuff = loader.find_module(base_name, [componentFile.parent.path])
|
||||
assert stuff is not None, "Couldnt find the module '%s'" % (base_name,)
|
||||
py_mod = loader.load_module( module_name_in_sys, stuff )
|
||||
|
||||
# Make and remember the COM module.
|
||||
comps = FindCOMComponents(py_mod)
|
||||
mod = module.Module(comps)
|
||||
|
||||
self.com_modules[fqn] = mod
|
||||
return mod
|
||||
|
||||
def getFactory(self, clsid, location, type):
|
||||
# return the factory
|
||||
assert type == self._reg_component_type_, "Being asked to create an object not of my type:%s" % (type,)
|
||||
file_interface = components.manager.specForRegistryLocation(location)
|
||||
# delegate to the module.
|
||||
m = self._getCOMModuleForLocation(file_interface)
|
||||
return m.getClassObject(components.manager, clsid, components.interfaces.nsIFactory)
|
||||
|
||||
def init(self, comp_mgr, registry):
|
||||
# void
|
||||
registry = registry.QueryInterface(components.interfaces.nsIRegistry)
|
||||
try:
|
||||
self.xpcom_registry_key = registry.getSubtree(
|
||||
components.interfaces.nsIRegistry.Common,
|
||||
xpcomKeyName)
|
||||
# If we worked, we can use the registry!
|
||||
self.registry = registry
|
||||
except xpcom.Exception, details:
|
||||
print "Registry failed", details
|
||||
self.registry = None # no registry ops allowed
|
||||
|
||||
self.comp_mgr = comp_mgr
|
||||
if xpcom.verbose:
|
||||
print "Python component loader init() called"
|
||||
|
||||
# Called when a component of the appropriate type is registered,
|
||||
# to give the component loader an opportunity to do things like
|
||||
# annotate the registry and such.
|
||||
def onRegister (self, clsid, type, className, proId, location, replace, persist):
|
||||
if xpcom.verbose:
|
||||
print "Python component loader - onRegister() called"
|
||||
|
||||
def autoRegisterComponents (self, when, directory):
|
||||
directory_path = directory.path
|
||||
print "Auto-registering all Python components in", directory_path
|
||||
import traceback
|
||||
|
||||
# ToDo - work out the right thing here
|
||||
# eg - do we recurse?
|
||||
# - do we support packages?
|
||||
entries = directory.directoryEntries
|
||||
while entries.HasMoreElements():
|
||||
entry = entries.GetNext(components.interfaces.nsIFile)
|
||||
if os.path.splitext(entry.path)[1]==".py":
|
||||
try:
|
||||
self.autoRegisterComponent(when, entry)
|
||||
except:
|
||||
print "** Registration of '%s' failed!" % (entry.path,)
|
||||
traceback.print_exc()
|
||||
|
||||
def autoRegisterComponent (self, when, componentFile):
|
||||
# bool return
|
||||
|
||||
reg_loc = components.manager.registryLocationForSpec(componentFile)
|
||||
# Use the registry to see if we actually need to do anything
|
||||
if not self._hasChanged(reg_loc, componentFile):
|
||||
return 1
|
||||
|
||||
# Sheesh - it appears we should also use the observer service
|
||||
# to let the system know of our auto-register progress.
|
||||
|
||||
# auto-register via the module.
|
||||
m = self._getCOMModuleForLocation(componentFile)
|
||||
m.registerSelf(components.manager, componentFile, reg_loc, self._reg_component_type_)
|
||||
self._setRegistryInfo(reg_loc, componentFile)
|
||||
return 1
|
||||
|
||||
def autoUnregisterComponent (self, when, componentFile):
|
||||
# bool return
|
||||
# auto-unregister via the module.
|
||||
m = self._getCOMModuleForLocation(componentFile)
|
||||
reg_loc = components.manager.registryLocationForSpec(componentFile)
|
||||
try:
|
||||
m.unregisterSelf(components.manager, componentFile, reg_loc)
|
||||
finally:
|
||||
self._removeRegistryInfo( reg_loc, componentFile)
|
||||
return 1
|
||||
|
||||
def registerDeferredComponents (self, when):
|
||||
# bool return
|
||||
if xpcom.verbose:
|
||||
print "Python component loader - registerDeferred() called"
|
||||
return 0 # no more to register
|
||||
def unloadAll (self, when):
|
||||
if xpcom.verbose:
|
||||
print "Python component loader being asked to unload all components!"
|
||||
self.registry = None
|
||||
self.comp_mgr = None
|
||||
self.com_modules = {}
|
||||
# Internal Helpers
|
||||
def _setRegistryInfo(self, registry_location, nsIFile):
|
||||
if self.registry is None:
|
||||
return # No registry work allowed.
|
||||
e_location = self.registry.escapeKey(registry_location, 1)
|
||||
if e_location is None: # No escaped key needed.
|
||||
e_location = registry_location
|
||||
key = self.registry.addSubtreeRaw(self.xpcom_registry_key, e_location)
|
||||
self.registry.setLongLong(key, lastModValueName, nsIFile.lastModificationDate)
|
||||
self.registry.setLongLong(key, fileSizeValueName, nsIFile.fileSize)
|
||||
def _hasChanged(self, registry_location, nsIFile):
|
||||
if self.registry is None:
|
||||
# Can't cache in registry - assume it has changed.
|
||||
return 1
|
||||
e_location = self.registry.escapeKey(registry_location, 1)
|
||||
if e_location is None: # No escaped key needed.
|
||||
e_location = registry_location
|
||||
try:
|
||||
key = self.registry.getSubtreeRaw(self.xpcom_registry_key, e_location)
|
||||
if nsIFile.lastModificationDate != self.registry.getLongLong(key, lastModValueName):
|
||||
return 1
|
||||
if nsIFile.fileSize != self.registry.getLongLong(key, fileSizeValueName):
|
||||
return 1
|
||||
return 0
|
||||
except xpcom.Exception, details:
|
||||
return 1
|
||||
|
||||
def _removeRegistryInfo(self, registry_location, nsIFile):
|
||||
if self.registry is None:
|
||||
return # No registry work allowed.
|
||||
e_location = self.registry.escapeKey(registry_location, 1)
|
||||
if e_location is None: # No escaped key needed.
|
||||
e_location = registry_location
|
||||
try:
|
||||
key = self.registry.removeSubtreeRaw(self.xpcom_registry_key, e_location)
|
||||
except xpcom.Exception, details:
|
||||
pass
|
||||
|
||||
def MakePythonComponentLoaderModule(serviceManager, nsIFile):
|
||||
import module
|
||||
return module.Module( [PythonComponentLoader] )
|
||||
75
mozilla/extensions/python/xpcom/server/module.py
Normal file
75
mozilla/extensions/python/xpcom/server/module.py
Normal file
@@ -0,0 +1,75 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
from xpcom import components
|
||||
from xpcom import ServerException, Exception
|
||||
from xpcom import nsError
|
||||
|
||||
import factory
|
||||
|
||||
import types
|
||||
import os
|
||||
|
||||
class Module:
|
||||
_com_interfaces_ = components.interfaces.nsIModule
|
||||
def __init__(self, comps):
|
||||
# Build a map of classes we can provide factories for.
|
||||
c = self.components = {}
|
||||
for klass in comps:
|
||||
c[components.ID(klass._reg_clsid_)] = klass
|
||||
|
||||
def getClassObject(self, compMgr, clsid, iid):
|
||||
# Single retval result.
|
||||
try:
|
||||
klass = self.components[clsid]
|
||||
except KeyError:
|
||||
raise ServerException(nsError.NS_ERROR_FACTORY_NOT_REGISTERED)
|
||||
|
||||
# We can ignore the IID - the auto-wrapp process will automatically QI us.
|
||||
return factory.Factory(klass)
|
||||
|
||||
def registerSelf(self, compMgr, location, registryLocation, componentType):
|
||||
# void function.
|
||||
for klass in self.components.values():
|
||||
print "Registering: %s" % (klass.__name__,)
|
||||
reg_contractid = klass._reg_contractid_
|
||||
reg_desc = getattr(klass, "_reg_desc_", reg_contractid)
|
||||
compMgr.registerComponentWithType(klass._reg_clsid_,
|
||||
reg_desc,
|
||||
reg_contractid,
|
||||
location,
|
||||
registryLocation,
|
||||
1,
|
||||
1,
|
||||
componentType)
|
||||
|
||||
# See if this class nominates custom register_self
|
||||
extra_func = getattr(klass, "_reg_registrar_", (None,None))[0]
|
||||
if extra_func is not None:
|
||||
extra_func(compMgr, location, registryLocation, componentType)
|
||||
print "Registered %d Python components in %s" % (len(self.components),os.path.basename(location.path))
|
||||
|
||||
def unregisterSelf(self, compMgr, location, registryLocation):
|
||||
# void function.
|
||||
for klass in self.components.values():
|
||||
ok = 1
|
||||
try:
|
||||
compMgr.unregisterComponentSpec(klass._reg_clsid_, location)
|
||||
except Exception:
|
||||
ok = 0
|
||||
# Give the class a bash even if we failed!
|
||||
extra_func = getattr(klass, "_reg_registrar_", (None,None))[1]
|
||||
if extra_func is not None:
|
||||
try:
|
||||
extra_func(compMgr, location, registryLocation)
|
||||
except Exception:
|
||||
ok = 0
|
||||
if ok:
|
||||
print "Successfully unregistered", klass.__name__
|
||||
else:
|
||||
print "Unregistration of", klass.__name__, "failed. (probably just not already registered)"
|
||||
|
||||
def canUnload(self, compMgr):
|
||||
# single bool result
|
||||
return 0 # we can never unload!
|
||||
|
||||
211
mozilla/extensions/python/xpcom/server/policy.py
Normal file
211
mozilla/extensions/python/xpcom/server/policy.py
Normal file
@@ -0,0 +1,211 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
from xpcom import xpcom_consts, _xpcom, client, nsError, ServerException, COMException
|
||||
import xpcom
|
||||
import traceback
|
||||
import xpcom.server
|
||||
import operator
|
||||
|
||||
_supports_primitives_map_ = {} # Filled on first use.
|
||||
|
||||
def _GetNominatedInterfaces(obj):
|
||||
ret = getattr(obj, "_com_interfaces_", None)
|
||||
if ret is None: return None
|
||||
# See if the user only gave one.
|
||||
try:
|
||||
ret[0]
|
||||
except TypeError:
|
||||
ret = [ret]
|
||||
real_ret = []
|
||||
# For each interface, walk to the root of the interface tree.
|
||||
iim = _xpcom.XPTI_GetInterfaceInfoManager()
|
||||
for interface in ret:
|
||||
try:
|
||||
interface_info = iim.GetInfoForIID(interface)
|
||||
except COMException:
|
||||
# Allow an interface name.
|
||||
interface_info = iim.GetInfoForName(interface)
|
||||
real_ret.append(interface_info.GetIID())
|
||||
parent = interface_info.GetParent()
|
||||
while parent is not None:
|
||||
real_ret.append(parent.GetIID())
|
||||
parent = parent.GetParent()
|
||||
return real_ret
|
||||
|
||||
class DefaultPolicy:
|
||||
def __init__(self, instance, iid):
|
||||
self._obj_ = instance
|
||||
self._nominated_interfaces_ = ni = _GetNominatedInterfaces(instance)
|
||||
self._iid_ = iid
|
||||
if ni is None:
|
||||
raise ValueError, "The object '%r' can not be used as a COM object" % (instance,)
|
||||
if iid not in ni:
|
||||
# The object may delegate QI.
|
||||
try:
|
||||
delegate_qi = instance._query_interface_
|
||||
except AttributeError:
|
||||
delegate_qi = None
|
||||
# Perform the actual QI and throw away the result - the _real_
|
||||
# QI performed by the framework will set things right!
|
||||
if delegate_qi is None or not delegate_qi(iid):
|
||||
raise ServerException(nsError.NS_ERROR_NO_INTERFACE)
|
||||
# Stuff for the magic interface conversion.
|
||||
self._interface_info_ = None
|
||||
self._interface_iid_map_ = {} # Cache - Indexed by (method_index, param_index)
|
||||
|
||||
def _QueryInterface_(self, com_object, iid):
|
||||
# Framework allows us to return a single boolean integer,
|
||||
# or a COM object.
|
||||
if iid in self._nominated_interfaces_:
|
||||
# We return the underlying object re-wrapped
|
||||
# in a new gateway - which is desirable, as one gateway should only support
|
||||
# one interface (this wont affect the users of this policy - we can have as many
|
||||
# gateways as we like pointing to the same Python objects - the users never
|
||||
# see what object the call came in from.
|
||||
# NOTE: We could have simply returned the instance and let the framework
|
||||
# do the auto-wrap for us - but this way we prevent a round-trip back into Python
|
||||
# code just for the autowrap.
|
||||
return xpcom.server.WrapObject(self._obj_, iid)
|
||||
|
||||
# See if the instance has a QI
|
||||
# use lower-case "_query_interface_" as win32com does, and it doesnt really matter.
|
||||
delegate = getattr(self._obj_, "_query_interface_", None)
|
||||
if delegate is not None:
|
||||
# The COM object itself doesnt get passed to the child
|
||||
# (again, as win32com doesnt). It is rarely needed
|
||||
# (in win32com, we dont even pass it to the policy, although we have identified
|
||||
# one place where we should - for marshalling - so I figured I may as well pass it
|
||||
# to the policy layer here, but no all the way down to the object.
|
||||
return delegate(iid)
|
||||
# Finally see if we are being queried for one of the "nsISupports primitives"
|
||||
if not _supports_primitives_map_:
|
||||
iim = _xpcom.XPTI_GetInterfaceInfoManager()
|
||||
for (iid_name, attr, cvt) in _supports_primitives_data_:
|
||||
special_iid = iim.GetInfoForName(iid_name).GetIID()
|
||||
_supports_primitives_map_[special_iid] = (attr, cvt)
|
||||
attr, cvt = _supports_primitives_map_.get(iid, (None,None))
|
||||
if attr is not None and hasattr(self._obj_, attr):
|
||||
return xpcom.server.WrapObject(SupportsPrimitive(iid, self._obj_, attr, cvt), iid)
|
||||
# Out of clever things to try!
|
||||
return None # We dont support this IID.
|
||||
|
||||
def _MakeInterfaceParam_(self, interface, iid, method_index, mi, param_index):
|
||||
# Wrap a "raw" interface object in a nice object. The result of this
|
||||
# function will be passed to one of the gateway methods.
|
||||
if iid is None:
|
||||
# look up the interface info - this will be true for all xpcom called interfaces.
|
||||
if self._interface_info_ is None:
|
||||
import xpcom.xpt
|
||||
self._interface_info_ = xpcom.xpt.Interface( self._iid_ )
|
||||
iid = self._interface_iid_map_.get( (method_index, param_index))
|
||||
if iid is None:
|
||||
iid = self._interface_info_.GetIIDForParam(method_index, param_index)
|
||||
self._interface_iid_map_[(method_index, param_index)] = iid
|
||||
# iid = _xpcom.IID_nsISupports
|
||||
return client.Interface(interface, iid)
|
||||
|
||||
def _CallMethod_(self, com_object, index, info, params):
|
||||
# print "_CallMethod_", index, info, params
|
||||
flags, name, param_descs, ret = info
|
||||
assert ret[1][0] == xpcom_consts.TD_UINT32, "Expected an nsresult (%s)" % (ret,)
|
||||
if xpcom_consts.XPT_MD_IS_GETTER(flags):
|
||||
# Look for a function of that name
|
||||
func = getattr(self._obj_, "get_" + name, None)
|
||||
if func is None:
|
||||
assert len(param_descs)==1 and len(params)==0, "Can only handle a single [out] arg for a default getter"
|
||||
ret = getattr(self._obj_, name) # Let attribute error go here!
|
||||
else:
|
||||
ret = func(*params)
|
||||
return 0, ret
|
||||
elif xpcom_consts.XPT_MD_IS_SETTER(flags):
|
||||
# Look for a function of that name
|
||||
func = getattr(self._obj_, "set_" + name, None)
|
||||
if func is None:
|
||||
assert len(param_descs)==1 and len(params)==1, "Can only handle a single [in] arg for a default setter"
|
||||
setattr(self._obj_, name, params[0]) # Let attribute error go here!
|
||||
else:
|
||||
func(*params)
|
||||
return 0
|
||||
else:
|
||||
# A regular method.
|
||||
func = getattr(self._obj_, name)
|
||||
return 0, func(*params)
|
||||
|
||||
def _doHandleException(self, func_name, exc_info):
|
||||
exc_val = exc_info[1]
|
||||
is_server_exception = isinstance(exc_val, ServerException)
|
||||
if is_server_exception:
|
||||
if xpcom.verbose:
|
||||
print "** Information: '%s' raised COM Exception %s" % (func_name, exc_val)
|
||||
traceback.print_exception(exc_info[0], exc_val, exc_info[2])
|
||||
print "** Returning nsresult from existing exception", exc_val
|
||||
return exc_val.errno
|
||||
# Unhandled exception - always print a warning.
|
||||
print "** Unhandled exception calling '%s'" % (func_name,)
|
||||
traceback.print_exception(exc_info[0], exc_val, exc_info[2])
|
||||
print "** Returning nsresult of NS_ERROR_FAILURE"
|
||||
return nsError.NS_ERROR_FAILURE
|
||||
|
||||
|
||||
# Called whenever an unhandled Python exception is detected as a result
|
||||
# of _CallMethod_ - this exception may have been raised during the _CallMethod_
|
||||
# invocation, or after its return, but when unpacking the results
|
||||
# eg, type errors, such as a Python integer being used as a string "out" param.
|
||||
def _CallMethodException_(self, com_object, index, info, params, exc_info):
|
||||
# Later we may want to have some smart "am I debugging" flags?
|
||||
# Or maybe just delegate to the actual object - it's probably got the best
|
||||
# idea what to do with them!
|
||||
flags, name, param_descs, ret = info
|
||||
exc_typ, exc_val, exc_tb = exc_info
|
||||
# use the xpt module to get a better repr for the method.
|
||||
# But if we fail, ignore it!
|
||||
try:
|
||||
import xpcom.xpt
|
||||
m = xpcom.xpt.Method(info, index, None)
|
||||
func_repr = m.Describe().lstrip()
|
||||
except:
|
||||
func_repr = "%s(%r)" % (name, param_descs)
|
||||
return self._doHandleException(func_repr, exc_info)
|
||||
|
||||
# Called whenever a gateway fails due to anything other than _CallMethod_.
|
||||
# Really only used for the component loader etc objects, so most
|
||||
# users should never see exceptions triggered here.
|
||||
def _GatewayException_(self, name, exc_info):
|
||||
return self._doHandleException(name, exc_info)
|
||||
|
||||
_supports_primitives_data_ = [
|
||||
("nsISupportsString", "__str__", str),
|
||||
("nsISupportsWString", "__str__", str),
|
||||
("nsISupportsPRUint64", "__long__", long),
|
||||
("nsISupportsPRInt64", "__long__", long),
|
||||
("nsISupportsPRUint32", "__int__", int),
|
||||
("nsISupportsPRInt32", "__int__", int),
|
||||
("nsISupportsPRUint16", "__int__", int),
|
||||
("nsISupportsPRInt16", "__int__", int),
|
||||
("nsISupportsPRUint8", "__int__", int),
|
||||
("nsISupportsPRBool", "__nonzero__", operator.truth),
|
||||
("nsISupportsDouble", "__float__", float),
|
||||
("nsISupportsFloat", "__float__", float),
|
||||
]
|
||||
|
||||
# Support for the nsISupports primitives:
|
||||
class SupportsPrimitive:
|
||||
_com_interfaces_ = ["nsISupports"]
|
||||
def __init__(self, iid, base_ob, attr_name, converter):
|
||||
self.iid = iid
|
||||
self.base_ob = base_ob
|
||||
self.attr_name = attr_name
|
||||
self.converter = converter
|
||||
def _query_interface_(self, iid):
|
||||
if iid == self.iid:
|
||||
return 1
|
||||
return None
|
||||
def get_data(self):
|
||||
method = getattr(self.base_ob, self.attr_name)
|
||||
val = method()
|
||||
return self.converter(val)
|
||||
def set_data(self, val):
|
||||
raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED)
|
||||
def toString(self):
|
||||
return str(self.get_data())
|
||||
219
mozilla/extensions/python/xpcom/src/ErrorUtils.cpp
Normal file
219
mozilla/extensions/python/xpcom/src/ErrorUtils.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsFileStream.h>
|
||||
|
||||
static char *PyTraceback_AsString(PyObject *exc_tb);
|
||||
|
||||
// The internal helper that actually moves the
|
||||
// formatted string to the target!
|
||||
|
||||
void LogMessage(const char *prefix, const char *pszMessageText)
|
||||
{
|
||||
nsOutputConsoleStream console;
|
||||
console << prefix << pszMessageText;
|
||||
}
|
||||
|
||||
// A helper for the various logging routines.
|
||||
static void VLogF(const char *prefix, const char *fmt, va_list argptr)
|
||||
{
|
||||
char buff[512];
|
||||
|
||||
vsprintf(buff, fmt, argptr);
|
||||
|
||||
LogMessage(prefix, buff);
|
||||
}
|
||||
|
||||
void PyXPCOM_LogError(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Error: ", fmt, marker);
|
||||
// If we have a Python exception, also log that:
|
||||
PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
|
||||
PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
|
||||
if (exc_typ) {
|
||||
PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
|
||||
char *string1 = nsnull;
|
||||
nsOutputStringStream streamout(string1);
|
||||
|
||||
if (exc_tb) {
|
||||
const char *szTraceback = PyTraceback_AsString(exc_tb);
|
||||
if (szTraceback == NULL)
|
||||
streamout << "Can't get the traceback info!";
|
||||
else {
|
||||
streamout << "Traceback (most recent call last):\n";
|
||||
streamout << szTraceback;
|
||||
PyMem_Free((ANY *)szTraceback);
|
||||
}
|
||||
}
|
||||
PyObject *temp = PyObject_Str(exc_typ);
|
||||
if (temp) {
|
||||
streamout << PyString_AsString(temp);
|
||||
Py_DECREF(temp);
|
||||
} else
|
||||
streamout << "Can't convert exception to a string!";
|
||||
streamout << ": ";
|
||||
if (exc_val != NULL) {
|
||||
temp = PyObject_Str(exc_val);
|
||||
if (temp) {
|
||||
streamout << PyString_AsString(temp);
|
||||
Py_DECREF(temp);
|
||||
} else
|
||||
streamout << "Can't convert exception value to a string!";
|
||||
}
|
||||
streamout << "\n";
|
||||
LogMessage("PyXPCOM Exception:", string1);
|
||||
}
|
||||
PyErr_Restore(exc_typ, exc_val, exc_tb);
|
||||
}
|
||||
|
||||
void PyXPCOM_LogWarning(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Warning: ", fmt, marker);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void PyXPCOM_LogDebug(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Debug: ", fmt, marker);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
PyObject *PyXPCOM_BuildPyException(nsresult r)
|
||||
{
|
||||
// Need the message etc.
|
||||
PyObject *evalue = Py_BuildValue("i", r);
|
||||
PyErr_SetObject(PyXPCOM_Error, evalue);
|
||||
Py_XDECREF(evalue);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nsresult PyXPCOM_SetCOMErrorFromPyException()
|
||||
{
|
||||
if (!PyErr_Occurred())
|
||||
// No error occurred
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* Obtains a string from a Python traceback.
|
||||
This is the exact same string as "traceback.print_exc" would return.
|
||||
|
||||
Pass in a Python traceback object (probably obtained from PyErr_Fetch())
|
||||
Result is a string which must be free'd using PyMem_Free()
|
||||
*/
|
||||
#define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;}
|
||||
|
||||
char *PyTraceback_AsString(PyObject *exc_tb)
|
||||
{
|
||||
char *errMsg = NULL; /* a static that hold a local error message */
|
||||
char *result = NULL; /* a valid, allocated result. */
|
||||
PyObject *modStringIO = NULL;
|
||||
PyObject *modTB = NULL;
|
||||
PyObject *obFuncStringIO = NULL;
|
||||
PyObject *obStringIO = NULL;
|
||||
PyObject *obFuncTB = NULL;
|
||||
PyObject *argsTB = NULL;
|
||||
PyObject *obResult = NULL;
|
||||
|
||||
/* Import the modules we need - cStringIO and traceback */
|
||||
modStringIO = PyImport_ImportModule("cStringIO");
|
||||
if (modStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant import cStringIO\n");
|
||||
|
||||
modTB = PyImport_ImportModule("traceback");
|
||||
if (modTB==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant import traceback\n");
|
||||
/* Construct a cStringIO object */
|
||||
obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
|
||||
if (obFuncStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant find cStringIO.StringIO\n");
|
||||
obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
|
||||
if (obStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cStringIO.StringIO() failed\n");
|
||||
/* Get the traceback.print_exception function, and call it. */
|
||||
obFuncTB = PyObject_GetAttrString(modTB, "print_tb");
|
||||
if (obFuncTB==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant find traceback.print_tb\n");
|
||||
|
||||
argsTB = Py_BuildValue("OOO",
|
||||
exc_tb ? exc_tb : Py_None,
|
||||
Py_None,
|
||||
obStringIO);
|
||||
if (argsTB==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant make print_tb arguments\n");
|
||||
|
||||
obResult = PyObject_CallObject(obFuncTB, argsTB);
|
||||
if (obResult==NULL)
|
||||
TRACEBACK_FETCH_ERROR("traceback.print_tb() failed\n");
|
||||
/* Now call the getvalue() method in the StringIO instance */
|
||||
Py_DECREF(obFuncStringIO);
|
||||
obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue");
|
||||
if (obFuncStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant find getvalue function\n");
|
||||
Py_DECREF(obResult);
|
||||
obResult = PyObject_CallObject(obFuncStringIO, NULL);
|
||||
if (obResult==NULL)
|
||||
TRACEBACK_FETCH_ERROR("getvalue() failed.\n");
|
||||
|
||||
/* And it should be a string all ready to go - duplicate it. */
|
||||
if (!PyString_Check(obResult))
|
||||
TRACEBACK_FETCH_ERROR("getvalue() did not return a string\n");
|
||||
|
||||
{ // a temp scope so I can use temp locals.
|
||||
char *tempResult = PyString_AsString(obResult);
|
||||
result = (char *)PyMem_Malloc(strlen(tempResult)+1);
|
||||
if (result==NULL)
|
||||
TRACEBACK_FETCH_ERROR("memory error duplicating the traceback string");
|
||||
|
||||
strcpy(result, tempResult);
|
||||
} // end of temp scope.
|
||||
done:
|
||||
/* All finished - first see if we encountered an error */
|
||||
if (result==NULL && errMsg != NULL) {
|
||||
result = (char *)PyMem_Malloc(strlen(errMsg)+1);
|
||||
if (result != NULL)
|
||||
/* if it does, not much we can do! */
|
||||
strcpy(result, errMsg);
|
||||
}
|
||||
Py_XDECREF(modStringIO);
|
||||
Py_XDECREF(modTB);
|
||||
Py_XDECREF(obFuncStringIO);
|
||||
Py_XDECREF(obStringIO);
|
||||
Py_XDECREF(obFuncTB);
|
||||
Py_XDECREF(argsTB);
|
||||
Py_XDECREF(obResult);
|
||||
return result;
|
||||
}
|
||||
|
||||
// See comments in PyXPCOM.h for why we need this!
|
||||
void PyXPCOM_MakePendingCalls()
|
||||
{
|
||||
while (1) {
|
||||
int rc = Py_MakePendingCalls();
|
||||
if (rc == 0)
|
||||
break;
|
||||
// An exception - just report it as normal.
|
||||
// Note that a traceback is very unlikely!
|
||||
PyXPCOM_LogError("Unhandled exception detected before entering Python.\n");
|
||||
PyErr_Clear();
|
||||
// And loop around again until we are told everything is done!
|
||||
}
|
||||
}
|
||||
757
mozilla/extensions/python/xpcom/src/PyGBase.cpp
Normal file
757
mozilla/extensions/python/xpcom/src/PyGBase.cpp
Normal file
@@ -0,0 +1,757 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// PyGBase.cpp - implementation of the PyG_Base class
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIModule.h>
|
||||
#include <nsIComponentLoader.h>
|
||||
#include <nsIInputStream.h>
|
||||
|
||||
static PRInt32 cGateways = 0;
|
||||
PRInt32 _PyXPCOM_GetGatewayCount(void)
|
||||
{
|
||||
return cGateways;
|
||||
}
|
||||
|
||||
extern PyG_Base *MakePyG_nsIModule(PyObject *);
|
||||
extern PyG_Base *MakePyG_nsIComponentLoader(PyObject *instance);
|
||||
extern PyG_Base *MakePyG_nsIInputStream(PyObject *instance);
|
||||
|
||||
static char *PyXPCOM_szDefaultGatewayAttributeName = "_com_instance_default_gateway_";
|
||||
nsresult GetDefaultGateway(PyObject *instance, REFNSIID iid, void **ret);
|
||||
void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
|
||||
PRBool CheckDefaultGateway(PyObject *real_inst, REFNSIID iid, nsISupports **ret_gateway);
|
||||
|
||||
/*static*/ nsresult
|
||||
PyG_Base::CreateNew(PyObject *pPyInstance, const nsIID &iid, void **ppResult)
|
||||
{
|
||||
NS_PRECONDITION(ppResult && *ppResult==NULL, "NULL or uninitialized pointer");
|
||||
if (ppResult==nsnull)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PyG_Base *ret;
|
||||
// Hack for few extra gateways we support.
|
||||
if (iid.Equals(NS_GET_IID(nsIModule)))
|
||||
ret = MakePyG_nsIModule(pPyInstance);
|
||||
else if (iid.Equals(NS_GET_IID(nsIComponentLoader)))
|
||||
ret = MakePyG_nsIComponentLoader(pPyInstance);
|
||||
else if (iid.Equals(NS_GET_IID(nsIInputStream)))
|
||||
ret = MakePyG_nsIInputStream(pPyInstance);
|
||||
else
|
||||
ret = new PyXPCOM_XPTStub(pPyInstance, iid);
|
||||
if (ret==nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
ret->AddRef(); // The first reference for the caller.
|
||||
*ppResult = ret->ThisAsIID(iid);
|
||||
NS_ABORT_IF_FALSE(*ppResult != NULL, "ThisAsIID() gave NULL, but we know it supports it!");
|
||||
return *ppResult ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PyG_Base::PyG_Base(PyObject *instance, const nsIID &iid)
|
||||
{
|
||||
// Note that "instance" is the _policy_ instance!!
|
||||
NS_INIT_REFCNT();
|
||||
PR_AtomicIncrement(&cGateways);
|
||||
m_pBaseObject = NULL;
|
||||
// m_pWeakRef is an nsCOMPtr and needs no init.
|
||||
m_iid = iid;
|
||||
m_pPyObject = instance;
|
||||
NS_PRECONDITION(instance, "NULL PyObject for PyXPCOM_XPTStub!");
|
||||
#ifdef DEBUG_LIFETIMES
|
||||
{
|
||||
char *iid_repr;
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
|
||||
if (iim!=nsnull)
|
||||
iim->GetNameForIID(&iid, &iid_repr);
|
||||
PyObject *real_instance = PyObject_GetAttrString(instance, "_obj_");
|
||||
PyObject *real_repr = PyObject_Repr(real_instance);
|
||||
|
||||
PYXPCOM_LOG_DEBUG("PyG_Base created at %p\n instance_repr=%s\n IID=%s\n", this, PyString_AsString(real_repr), iid_repr);
|
||||
nsAllocator::Free(iid_repr);
|
||||
Py_XDECREF(real_instance);
|
||||
Py_XDECREF(real_repr);
|
||||
}
|
||||
#endif // DEBUG_LIFETIMES
|
||||
Py_XINCREF(instance); // instance should never be NULL - but whats an X between friends!
|
||||
|
||||
PyXPCOM_DLLAddRef();
|
||||
|
||||
#ifdef DEBUG_FULL
|
||||
LogF("PyGatewayBase: created %s", m_pPyObject ? m_pPyObject->ob_type->tp_name : "<NULL>");
|
||||
#endif
|
||||
}
|
||||
|
||||
PyG_Base::~PyG_Base()
|
||||
{
|
||||
PR_AtomicDecrement(&cGateways);
|
||||
#ifdef DEBUG_LIFETIMES
|
||||
PYXPCOM_LOG_DEBUG("PyG_Base: deleted %p", this);
|
||||
#endif
|
||||
if ( m_pPyObject ) {
|
||||
CEnterLeavePython celp;
|
||||
Py_DECREF(m_pPyObject);
|
||||
}
|
||||
if (m_pBaseObject)
|
||||
m_pBaseObject->Release();
|
||||
if (m_pWeakRef) {
|
||||
// Need to ensure some other thread isnt doing a QueryReferent on
|
||||
// our weak reference at the same time
|
||||
CEnterLeaveXPCOMFramework _celf;
|
||||
PyXPCOM_GatewayWeakReference *p = (PyXPCOM_GatewayWeakReference *)(nsISupports *)m_pWeakRef;
|
||||
p->m_pBase = nsnull;
|
||||
m_pWeakRef = nsnull;
|
||||
}
|
||||
PyXPCOM_DLLRelease();
|
||||
}
|
||||
|
||||
// Get the correct interface pointer for this object given the IID.
|
||||
void *PyG_Base::ThisAsIID( const nsIID &iid )
|
||||
{
|
||||
if (this==NULL) return NULL;
|
||||
if (iid.Equals(NS_GET_IID(nsISupports)))
|
||||
return (nsISupports *)(nsIInternalPython *)this;
|
||||
if (iid.Equals(NS_GET_IID(nsISupportsWeakReference)))
|
||||
return (nsISupportsWeakReference *)this;
|
||||
if (iid.Equals(NS_GET_IID(nsIInternalPython)))
|
||||
return (nsISupports *)(nsIInternalPython *)this;
|
||||
return NULL;
|
||||
};
|
||||
|
||||
// Call back into Python, passing a Python instance, and get back
|
||||
// an interface object that wraps the instance.
|
||||
/*static*/ PRBool
|
||||
PyG_Base::AutoWrapPythonInstance(PyObject *ob, const nsIID &iid, nsISupports **ppret)
|
||||
{
|
||||
NS_PRECONDITION(ppret!=NULL, "null pointer when wrapping a Python instance!");
|
||||
NS_PRECONDITION(ob && PyInstance_Check(ob), "AutoWrapPythonInstance is expecting an non-NULL instance!");
|
||||
PRBool ok = PR_FALSE;
|
||||
// XXX - todo - this static object leaks! (but Python on Windows leaks 2000+ objects as it is ;-)
|
||||
static PyObject *func = NULL; // fetch this once and remember!
|
||||
PyObject *obIID = NULL;
|
||||
PyObject *wrap_ret = NULL;
|
||||
PyObject *args = NULL;
|
||||
if (func==NULL) { // not thread-safe, but nothing bad can happen, except an extra reference leak
|
||||
PyObject *mod = PyImport_ImportModule("xpcom.server");
|
||||
if (mod)
|
||||
func = PyObject_GetAttrString(mod, "WrapObject");
|
||||
Py_XDECREF(mod);
|
||||
if (func==NULL) goto done;
|
||||
}
|
||||
// See if the instance has previously been wrapped.
|
||||
if (CheckDefaultGateway(ob, iid, ppret)) {
|
||||
ok = PR_TRUE; // life is good!
|
||||
} else {
|
||||
PyErr_Clear();
|
||||
|
||||
obIID = Py_nsIID::PyObjectFromIID(iid);
|
||||
if (obIID==NULL) goto done;
|
||||
args = Py_BuildValue("OO", ob, obIID);
|
||||
if (args==NULL) goto done;
|
||||
wrap_ret = PyEval_CallObject(func, args);
|
||||
if (wrap_ret==NULL) goto done;
|
||||
ok = Py_nsISupports::InterfaceFromPyObject(wrap_ret, iid, ppret, PR_FALSE, PR_FALSE);
|
||||
#ifdef DEBUG
|
||||
if (ok)
|
||||
// Check we _now_ have a default gateway
|
||||
{
|
||||
nsISupports *temp = NULL;
|
||||
NS_ABORT_IF_FALSE(CheckDefaultGateway(ob, iid, &temp), "Auto-wrapped object didnt get a default gateway!");
|
||||
if (temp) temp->Release();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
done:
|
||||
// Py_XDECREF(func); -- func is static for performance reasons.
|
||||
Py_XDECREF(obIID);
|
||||
Py_XDECREF(wrap_ret);
|
||||
Py_XDECREF(args);
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Call back into Python, passing a raw nsIInterface object, getting back
|
||||
// the object to actually use as the gateway parameter for this interface.
|
||||
// For example, it is expected that the policy will wrap the interface
|
||||
// object in one of the xpcom.client.Interface objects, allowing
|
||||
// natural usage of the interface from Python clients.
|
||||
// Note that piid will usually be NULL - this is because the runtime
|
||||
// reflection interfaces dont provide this information to me.
|
||||
// In this case, the Python code may choose to lookup the complete
|
||||
// interface info to obtain the IID.
|
||||
// It is expected (but should not be assumed) that the method info
|
||||
// or the IID will be NULL.
|
||||
// Worst case, the code should provide a wrapper for the nsiSupports interface,
|
||||
// so at least the user can simply QI the object.
|
||||
PyObject *
|
||||
PyG_Base::MakeInterfaceParam(nsISupports *pis,
|
||||
const nsIID *piid,
|
||||
int methodIndex /* = -1 */,
|
||||
const XPTParamDescriptor *d /* = NULL */,
|
||||
int paramIndex /* = -1 */)
|
||||
{
|
||||
if (pis==NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
// This condition is true today, but not necessarily so.
|
||||
// But if it ever triggers, the poor Python code has no real hope
|
||||
// of returning something useful, so we should at least do our
|
||||
// best to provide the useful data.
|
||||
NS_WARN_IF_FALSE( ((piid != NULL) ^ (d != NULL)) == 1, "No information on the interface available - Python's gunna have a hard time doing much with it!");
|
||||
PyObject *obIID = NULL;
|
||||
PyObject *obISupports = NULL;
|
||||
PyObject *obParamDesc = NULL;
|
||||
PyObject *result = NULL;
|
||||
|
||||
// get the basic interface first, as if we fail, we can try and use this.
|
||||
nsIID iid_check = piid ? *piid : NS_GET_IID(nsISupports);
|
||||
obISupports = Py_nsISupports::PyObjectFromInterface(pis, iid_check, PR_TRUE, PR_FALSE);
|
||||
if (!obISupports)
|
||||
goto done;
|
||||
if (piid==NULL) {
|
||||
obIID = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
} else
|
||||
obIID = Py_nsIID::PyObjectFromIID(*piid);
|
||||
if (obIID==NULL)
|
||||
goto done;
|
||||
obParamDesc = PyObject_FromXPTParamDescriptor(d);
|
||||
if (obParamDesc==NULL)
|
||||
goto done;
|
||||
|
||||
result = PyObject_CallMethod(m_pPyObject,
|
||||
"_MakeInterfaceParam_",
|
||||
"OOiOi",
|
||||
obISupports,
|
||||
obIID,
|
||||
methodIndex,
|
||||
obParamDesc,
|
||||
paramIndex);
|
||||
done:
|
||||
if (PyErr_Occurred()) {
|
||||
NS_WARN_IF_FALSE(result==NULL, "Have an error, but also a result!");
|
||||
PyXPCOM_LogError("Wrapping an interface object for the gateway failed\n");
|
||||
}
|
||||
Py_XDECREF(obIID);
|
||||
Py_XDECREF(obParamDesc);
|
||||
if (result==NULL) // we had an error.
|
||||
// return our obISupports. If NULL, we are really hosed and nothing we can do.
|
||||
return obISupports;
|
||||
// Dont need to return this - we have a better result.
|
||||
Py_XDECREF(obISupports);
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_Base::QueryInterface(REFNSIID iid, void** ppv)
|
||||
{
|
||||
#ifdef PYXPCOM_DEBUG_FULL
|
||||
{
|
||||
char *sziid = iid.ToString();
|
||||
LogF("PyGatewayBase::QueryInterface: %s", sziid);
|
||||
Allocator::Free(sziid);
|
||||
}
|
||||
#endif
|
||||
NS_PRECONDITION(ppv, "NULL pointer");
|
||||
if (ppv==nsnull)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*ppv = nsnull;
|
||||
// If one of our native interfaces (but NOT nsISupports if we have a base)
|
||||
// return this.
|
||||
// It is important is that nsISupports come from the base object
|
||||
// to ensure that we live by XPCOM identity rules (other interfaces need
|
||||
// not abide by this rule - only nsISupports.)
|
||||
if ( (m_pBaseObject==NULL || !iid.Equals(NS_GET_IID(nsISupports)))
|
||||
&& (*ppv=ThisAsIID(iid)) != NULL ) {
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
// If we have a "base object", then we need to delegate _every_ remaining
|
||||
// QI to it.
|
||||
if (m_pBaseObject != NULL && (m_pBaseObject->QueryInterface(iid, ppv)==NS_OK))
|
||||
return NS_OK;
|
||||
|
||||
// Call the Python policy to see if it (says it) supports the interface
|
||||
PRBool supports = PR_FALSE;
|
||||
{ // temp scope for Python lock
|
||||
CEnterLeavePython celp;
|
||||
|
||||
PyObject * ob = Py_nsIID::PyObjectFromIID(iid);
|
||||
PyObject * this_interface_ob = Py_nsISupports::PyObjectFromInterface((nsIInternalPython *)this, NS_GET_IID(nsISupports), PR_TRUE, PR_FALSE);
|
||||
if ( !ob || !this_interface_ob) {
|
||||
Py_XDECREF(ob);
|
||||
Py_XDECREF(this_interface_ob);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
PyObject *result = PyObject_CallMethod(m_pPyObject, "_QueryInterface_",
|
||||
"OO",
|
||||
this_interface_ob, ob);
|
||||
Py_DECREF(ob);
|
||||
Py_DECREF(this_interface_ob);
|
||||
|
||||
if ( result ) {
|
||||
if (Py_nsISupports::InterfaceFromPyObject(result, iid, (nsISupports **)ppv, PR_TRUE)) {
|
||||
// If OK, but NULL, _QI_ returned None, which simply means
|
||||
// "no such interface"
|
||||
supports = (*ppv!=NULL);
|
||||
// result has been QI'd and AddRef'd all ready for return.
|
||||
} else {
|
||||
// Dump this message and any Python exception before
|
||||
// reporting the fact that QI failed - this error
|
||||
// may provide clues!
|
||||
PyXPCOM_LogError("The _QueryInterface_ method returned an object of type '%s', but an interface was expected\n", result->ob_type->tp_name);
|
||||
// supports remains false
|
||||
}
|
||||
Py_DECREF(result);
|
||||
} else {
|
||||
NS_ABORT_IF_FALSE(PyErr_Occurred(), "Got NULL result, but no Python error flagged!");
|
||||
NS_WARN_IF_FALSE(!supports, "Have failure with success flag set!");
|
||||
PyXPCOM_LogError("The _QueryInterface_ processing failed.\n");
|
||||
// supports remains false.
|
||||
// We have reported the error, and are returning to COM,
|
||||
// so we should clear it.
|
||||
PyErr_Clear();
|
||||
}
|
||||
} // end of temp scope for Python lock - lock released here!
|
||||
if ( !supports )
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
|
||||
// Now setup the base object pointer back to me.
|
||||
// We do a QI on our internal one to ensure we can safely cast
|
||||
// the result to a PyG_Base (both from the POV that is may not
|
||||
// be a Python object, and that the vtables offsets may screw
|
||||
// us even if it is!)
|
||||
nsISupports *pLook = (nsISupports *)(*ppv);
|
||||
nsIInternalPython *pTemp;
|
||||
if (pLook->QueryInterface(NS_GET_IID(nsIInternalPython), (void **)&pTemp)==NS_OK) {
|
||||
// One of our objects, so set the base object if it doesnt already have one
|
||||
PyG_Base *pG = (PyG_Base *)pTemp;
|
||||
// Eeek - just these few next lines need to be thread-safe :-(
|
||||
CEnterLeaveXPCOMFramework _celf;
|
||||
if (pG->m_pBaseObject==NULL && pG != (PyG_Base *)this) {
|
||||
pG->m_pBaseObject = this;
|
||||
pG->m_pBaseObject->AddRef();
|
||||
#ifdef DEBUG_LIFETIMES
|
||||
PYXPCOM_LOG_DEBUG("PyG_Base setting BaseObject of %p to %p\n", pG, this);
|
||||
#endif
|
||||
}
|
||||
pTemp->Release();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsrefcnt
|
||||
PyG_Base::AddRef(void)
|
||||
{
|
||||
nsrefcnt cnt = (nsrefcnt) PR_AtomicIncrement((PRInt32*)&mRefCnt);
|
||||
NS_LOG_ADDREF(this, cnt, "PyG_Base", sizeof(*this));
|
||||
return cnt;
|
||||
}
|
||||
|
||||
nsrefcnt
|
||||
PyG_Base::Release(void)
|
||||
{
|
||||
nsrefcnt cnt = (nsrefcnt) PR_AtomicDecrement((PRInt32*)&mRefCnt);
|
||||
NS_LOG_RELEASE(this, cnt, "PyG_Base");
|
||||
if ( cnt == 0 )
|
||||
delete this;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_Base::GetWeakReference(nsIWeakReference **ret)
|
||||
{
|
||||
NS_PRECONDITION(ret, "null pointer");
|
||||
if (ret==nsnull) return NS_ERROR_INVALID_POINTER;
|
||||
if (!m_pWeakRef) {
|
||||
// First query for a weak reference - create it.
|
||||
m_pWeakRef = new PyXPCOM_GatewayWeakReference(this);
|
||||
NS_ABORT_IF_FALSE(m_pWeakRef, "Shouldn't be able to fail creating a weak reference!");
|
||||
if (!m_pWeakRef)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
*ret = m_pWeakRef;
|
||||
(*ret)->AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult PyG_Base::HandleNativeGatewayError(const char *szMethodName)
|
||||
{
|
||||
nsresult rc = NS_OK;
|
||||
if (PyErr_Occurred()) {
|
||||
// The error handling - fairly involved, but worth it as
|
||||
// good error reporting is critical for users to know WTF
|
||||
// is going on - especially with TypeErrors etc in their
|
||||
// return values (ie, after the Python code has successfully
|
||||
// existed, but we encountered errors unpacking their
|
||||
// result values for the COM caller - there is literally no
|
||||
// way to catch these exceptions from Python code, as their
|
||||
// is no Python function on the call-stack)
|
||||
|
||||
// First line of attack in an error is to call-back on the policy.
|
||||
// If the callback of the error handler succeeds and returns an
|
||||
// integer (for the nsresult), we take no further action.
|
||||
|
||||
// If this callback fails, we log _2_ exceptions - the error handler
|
||||
// error, and the original error.
|
||||
|
||||
PRBool bProcessMainError = PR_TRUE; // set to false if our exception handler does its thing!
|
||||
PyObject *exc_typ, *exc_val, *exc_tb;
|
||||
PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
|
||||
|
||||
PyObject *err_result = PyObject_CallMethod(m_pPyObject,
|
||||
"_GatewayException_",
|
||||
"z(OOO)",
|
||||
szMethodName,
|
||||
exc_typ ? exc_typ : Py_None, // should never be NULL, but defensive programming...
|
||||
exc_val ? exc_val : Py_None, // may well be NULL.
|
||||
exc_tb ? exc_tb : Py_None); // may well be NULL.
|
||||
if (err_result == NULL) {
|
||||
PyXPCOM_LogError("The exception handler _CallMethodException_ failed!\n");
|
||||
} else if (err_result == Py_None) {
|
||||
// The exception handler has chosen not to do anything with
|
||||
// this error, so we still need to print it!
|
||||
;
|
||||
} else if (PyInt_Check(err_result)) {
|
||||
// The exception handler has given us the nresult.
|
||||
rc = PyInt_AsLong(err_result);
|
||||
bProcessMainError = PR_FALSE;
|
||||
} else {
|
||||
// The exception handler succeeded, but returned other than
|
||||
// int or None.
|
||||
PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", err_result->ob_type->tp_name);
|
||||
}
|
||||
Py_XDECREF(err_result);
|
||||
PyErr_Restore(exc_typ, exc_val, exc_tb);
|
||||
if (bProcessMainError) {
|
||||
PyXPCOM_LogError("The function '%s' failed\n", szMethodName);
|
||||
rc = PyXPCOM_SetCOMErrorFromPyException();
|
||||
}
|
||||
PyErr_Clear();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static nsresult do_dispatch(
|
||||
PyObject *pPyObject,
|
||||
PyObject **ppResult,
|
||||
const char *szMethodName,
|
||||
const char *szFormat,
|
||||
va_list va
|
||||
)
|
||||
{
|
||||
NS_PRECONDITION(ppResult, "Must provide a result buffer");
|
||||
*ppResult = nsnull;
|
||||
// Build the Invoke arguments...
|
||||
PyObject *args = NULL;
|
||||
PyObject *method = NULL;
|
||||
PyObject *real_ob = NULL;
|
||||
nsresult ret = NS_ERROR_FAILURE;
|
||||
if ( szFormat )
|
||||
args = Py_VaBuildValue((char *)szFormat, va);
|
||||
else
|
||||
args = PyTuple_New(0);
|
||||
if ( !args )
|
||||
goto done;
|
||||
|
||||
// make sure a tuple.
|
||||
if ( !PyTuple_Check(args) ) {
|
||||
PyObject *a = PyTuple_New(1);
|
||||
if ( a == NULL )
|
||||
{
|
||||
Py_DECREF(args);
|
||||
goto done;
|
||||
}
|
||||
PyTuple_SET_ITEM(a, 0, args);
|
||||
args = a;
|
||||
}
|
||||
// Bit to a hack here to maintain the use of a policy.
|
||||
// We actually get the policies underlying object
|
||||
// to make the call on.
|
||||
real_ob = PyObject_GetAttrString(pPyObject, "_obj_");
|
||||
if (real_ob == NULL) {
|
||||
PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute.");
|
||||
goto done;
|
||||
}
|
||||
method = PyObject_GetAttrString(real_ob, (char *)szMethodName);
|
||||
if ( !method ) {
|
||||
PyErr_Clear();
|
||||
ret = NS_COMFALSE;
|
||||
goto done;
|
||||
}
|
||||
// Make the call
|
||||
*ppResult = PyEval_CallObject(method, args);
|
||||
ret = *ppResult ? NS_OK : NS_ERROR_FAILURE;
|
||||
done:
|
||||
Py_XDECREF(method);
|
||||
Py_XDECREF(real_ob);
|
||||
Py_XDECREF(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
nsresult PyG_Base::InvokeNativeViaPolicyInternal(
|
||||
const char *szMethodName,
|
||||
PyObject **ppResult,
|
||||
const char *szFormat,
|
||||
va_list va
|
||||
)
|
||||
{
|
||||
if ( m_pPyObject == NULL || szMethodName == NULL )
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PyObject *temp = nsnull;
|
||||
if (ppResult == nsnull)
|
||||
ppResult = &temp;
|
||||
nsresult nr = do_dispatch(m_pPyObject, ppResult, szMethodName, szFormat, va);
|
||||
|
||||
// If temp is NULL, they provided a buffer, and we dont touch it.
|
||||
// If not NULL, *ppResult = temp, and _we_ do own it.
|
||||
Py_XDECREF(temp);
|
||||
return nr;
|
||||
}
|
||||
|
||||
nsresult PyG_Base::InvokeNativeViaPolicy(
|
||||
const char *szMethodName,
|
||||
PyObject **ppResult /* = NULL */,
|
||||
const char *szFormat /* = NULL */,
|
||||
...
|
||||
)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, szFormat);
|
||||
nsresult nr = InvokeNativeViaPolicyInternal(szMethodName, ppResult, szFormat, va);
|
||||
va_end(va);
|
||||
|
||||
if (nr==NS_COMFALSE) {
|
||||
// Only problem was missing method.
|
||||
PyErr_Format(PyExc_AttributeError, "The object does not have a '%s' function.", szMethodName);
|
||||
}
|
||||
return nr == NS_OK ? NS_OK : HandleNativeGatewayError(szMethodName);
|
||||
}
|
||||
|
||||
nsresult PyG_Base::InvokeNativeGetViaPolicy(
|
||||
const char *szPropertyName,
|
||||
PyObject **ppResult /* = NULL */
|
||||
)
|
||||
{
|
||||
PyObject *ob_ret = NULL;
|
||||
nsresult ret = NS_OK;
|
||||
PyObject *real_ob = NULL;
|
||||
if ( m_pPyObject == NULL || szPropertyName == NULL )
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
// First see if we have a method of that name.
|
||||
char buf[256];
|
||||
strcpy(buf, "get_");
|
||||
strncat(buf, szPropertyName, sizeof(buf)*sizeof(buf[0])-strlen(buf)-1);
|
||||
buf[sizeof(buf)/sizeof(buf[0])-1] = '\0';
|
||||
ret = InvokeNativeViaPolicyInternal(buf, ppResult, nsnull, nsnull);
|
||||
if (ret == NS_COMFALSE) {
|
||||
// No method of that name - just try a property.
|
||||
// Bit to a hack here to maintain the use of a policy.
|
||||
// We actually get the policies underlying object
|
||||
// to make the call on.
|
||||
real_ob = PyObject_GetAttrString(m_pPyObject, "_obj_");
|
||||
if (real_ob == NULL) {
|
||||
PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute.");
|
||||
ret = HandleNativeGatewayError(szPropertyName);
|
||||
goto done;
|
||||
}
|
||||
ob_ret = PyObject_GetAttrString(real_ob, (char *)szPropertyName);
|
||||
if (ob_ret==NULL) {
|
||||
PyErr_Format(PyExc_AttributeError,
|
||||
"The object does not have a 'get_%s' function, or a '%s attribute.",
|
||||
szPropertyName, szPropertyName);
|
||||
} else {
|
||||
ret = NS_OK;
|
||||
if (ppResult)
|
||||
*ppResult = ob_ret;
|
||||
else
|
||||
Py_XDECREF(ob_ret);
|
||||
}
|
||||
}
|
||||
if (ret != NS_OK)
|
||||
ret = HandleNativeGatewayError(szPropertyName);
|
||||
|
||||
done:
|
||||
Py_XDECREF(real_ob);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nsresult PyG_Base::InvokeNativeSetViaPolicy(
|
||||
const char *szPropertyName,
|
||||
...
|
||||
)
|
||||
{
|
||||
if ( m_pPyObject == NULL || szPropertyName == NULL )
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
PyObject *ob_ret = NULL;
|
||||
nsresult ret = NS_OK;
|
||||
PyObject *real_ob = NULL;
|
||||
char buf[256];
|
||||
strcpy(buf, "set_");
|
||||
strncat(buf, szPropertyName, sizeof(buf)*sizeof(buf[0])-strlen(buf)-1);
|
||||
buf[sizeof(buf)/sizeof(buf[0])-1] = '\0';
|
||||
va_list va;
|
||||
va_start(va, szPropertyName);
|
||||
ret = InvokeNativeViaPolicyInternal(buf, NULL, "O", va);
|
||||
va_end(va);
|
||||
if (ret == NS_COMFALSE) {
|
||||
// No method of that name - just try a property.
|
||||
// Bit to a hack here to maintain the use of a policy.
|
||||
// We actually get the policies underlying object
|
||||
// to make the call on.
|
||||
real_ob = PyObject_GetAttrString(m_pPyObject, "_obj_");
|
||||
if (real_ob == NULL) {
|
||||
PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute.");
|
||||
ret = HandleNativeGatewayError(szPropertyName);
|
||||
goto done;
|
||||
}
|
||||
va_list va2;
|
||||
va_start(va2, szPropertyName);
|
||||
PyObject *arg = va_arg( va2, PyObject *);
|
||||
va_end(va2);
|
||||
if (PyObject_SetAttrString(real_ob, (char *)szPropertyName, arg) == 0)
|
||||
ret = NS_OK;
|
||||
else {
|
||||
PyErr_Format(PyExc_AttributeError,
|
||||
"The object does not have a 'set_%s' function, or a '%s attribute.",
|
||||
szPropertyName, szPropertyName);
|
||||
}
|
||||
}
|
||||
if (ret != NS_OK)
|
||||
ret = HandleNativeGatewayError(szPropertyName);
|
||||
done:
|
||||
Py_XDECREF(real_ob);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
|
||||
Some special support to help with object identity.
|
||||
|
||||
In the simplest case, assume a Python COM object is
|
||||
supporting a function "nsIWhatever GetWhatever()",
|
||||
so implements it as:
|
||||
return this
|
||||
it is almost certain they intend returning
|
||||
the same COM OBJECT to the caller! Thus, if a user of this COM
|
||||
object does:
|
||||
|
||||
p1 = foo.GetWhatever();
|
||||
p2 = foo.GetWhatever();
|
||||
|
||||
We almost certainly expect p1==p2==foo.
|
||||
|
||||
We previously _did_ have special support for the "this"
|
||||
example above, but this implements a generic scheme that
|
||||
works for _all_ objects.
|
||||
|
||||
Whenever we are asked to "AutoWrap" a Python object, the
|
||||
first thing we do is see if it has been auto-wrapped before.
|
||||
|
||||
If not, we create a new wrapper, then make a COM weak reference
|
||||
to that wrapper, and store it directly back into the instance
|
||||
we are auto-wrapping! The use of a weak-reference prevents
|
||||
cycles.
|
||||
|
||||
The existance of this attribute in an instance indicates if it
|
||||
has been previously auto-wrapped.
|
||||
|
||||
If it _has_ previously been auto-wrapped, we de-reference the
|
||||
weak reference, and use that gateway.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
nsresult GetDefaultGateway(PyObject *instance, REFNSIID iid, void **ret)
|
||||
{
|
||||
// NOTE: Instance is the real instance, _not_ the policy.
|
||||
PyObject *ob_existing_weak = PyObject_GetAttrString(instance, PyXPCOM_szDefaultGatewayAttributeName);
|
||||
if (ob_existing_weak != NULL) {
|
||||
PRBool ok = PR_TRUE;
|
||||
nsCOMPtr<nsIWeakReference> pWeakRef;
|
||||
ok = NS_SUCCEEDED(Py_nsISupports::InterfaceFromPyObject(ob_existing_weak,
|
||||
NS_GET_IID(nsIWeakReference),
|
||||
getter_AddRefs(pWeakRef),
|
||||
PR_FALSE));
|
||||
Py_DECREF(ob_existing_weak);
|
||||
if (ok)
|
||||
return pWeakRef->QueryReferent( iid, ret);
|
||||
} else
|
||||
PyErr_Clear();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PRBool CheckDefaultGateway(PyObject *real_inst, REFNSIID iid, nsISupports **ret_gateway)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(real_inst, "Did not have an _obj_ attribute");
|
||||
if (real_inst==NULL) {
|
||||
PyErr_Clear();
|
||||
return PR_FALSE;
|
||||
}
|
||||
PyObject *ob_existing_weak = PyObject_GetAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName);
|
||||
if (ob_existing_weak != NULL) {
|
||||
// We have an existing default, but as it is a weak reference, it
|
||||
// may no longer be valid. Check it.
|
||||
PRBool ok = PR_TRUE;
|
||||
nsCOMPtr<nsIWeakReference> pWeakRef;
|
||||
ok = NS_SUCCEEDED(Py_nsISupports::InterfaceFromPyObject(ob_existing_weak,
|
||||
NS_GET_IID(nsIWeakReference),
|
||||
getter_AddRefs(pWeakRef),
|
||||
PR_FALSE));
|
||||
Py_DECREF(ob_existing_weak);
|
||||
if (ok) {
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
ok = NS_SUCCEEDED(pWeakRef->QueryReferent( iid, (void **)(ret_gateway)));
|
||||
Py_END_ALLOW_THREADS;
|
||||
}
|
||||
if (!ok) {
|
||||
// We have the attribute, but not valid - wipe it
|
||||
// before restoring it.
|
||||
if (0 != PyObject_DelAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName))
|
||||
PyErr_Clear();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
PyErr_Clear();
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void AddDefaultGateway(PyObject *instance, nsISupports *gateway)
|
||||
{
|
||||
// NOTE: Instance is the _policy_!
|
||||
PyObject *real_inst = PyObject_GetAttrString(instance, "_obj_");
|
||||
NS_ABORT_IF_FALSE(real_inst, "Could not get the '_obj_' element");
|
||||
if (!real_inst) return;
|
||||
if (!PyObject_HasAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName)) {
|
||||
nsCOMPtr<nsISupportsWeakReference> swr( do_QueryInterface((nsISupportsWeakReference *)(gateway)) );
|
||||
NS_ABORT_IF_FALSE(swr, "Our gateway failed with a weak reference query");
|
||||
// Create the new default gateway - get a weak reference for our gateway.
|
||||
if (swr) {
|
||||
nsIWeakReference *pWeakReference = NULL;
|
||||
swr->GetWeakReference( &pWeakReference );
|
||||
if (pWeakReference) {
|
||||
PyObject *ob_new_weak = Py_nsISupports::PyObjectFromInterface(pWeakReference,
|
||||
NS_GET_IID(nsIWeakReference),
|
||||
PR_FALSE, /* bAddRef */
|
||||
PR_FALSE ); /* bMakeNicePyObject */
|
||||
// pWeakReference reference consumed.
|
||||
if (ob_new_weak) {
|
||||
PyObject_SetAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName, ob_new_weak);
|
||||
Py_DECREF(ob_new_weak);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Py_DECREF(real_inst);
|
||||
}
|
||||
143
mozilla/extensions/python/xpcom/src/PyGInputStream.cpp
Normal file
143
mozilla/extensions/python/xpcom/src/PyGInputStream.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// PyGInputStream.cpp
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written October 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIInputStream.h>
|
||||
|
||||
class PyG_nsIInputStream : public PyG_Base, public nsIInputStream
|
||||
{
|
||||
public:
|
||||
PyG_nsIInputStream(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIInputStream)) {;}
|
||||
PYGATEWAY_BASE_SUPPORT(nsIInputStream, PyG_Base);
|
||||
|
||||
NS_IMETHOD Close(void);
|
||||
NS_IMETHOD Available(PRUint32 *_retval);
|
||||
NS_IMETHOD Read(char * buf, PRUint32 count, PRUint32 *_retval);
|
||||
NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval);
|
||||
NS_IMETHOD GetNonBlocking(PRBool *aNonBlocking);
|
||||
NS_IMETHOD GetObserver(nsIInputStreamObserver * *aObserver);
|
||||
NS_IMETHOD SetObserver(nsIInputStreamObserver * aObserver);
|
||||
};
|
||||
|
||||
|
||||
PyG_Base *MakePyG_nsIInputStream(PyObject *instance)
|
||||
{
|
||||
return new PyG_nsIInputStream(instance);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::Close()
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "close";
|
||||
return InvokeNativeViaPolicy(methodName, NULL);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::Available(PRUint32 *_retval)
|
||||
{
|
||||
NS_PRECONDITION(_retval, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *ret;
|
||||
const char *methodName = "available";
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
*_retval = PyInt_AsLong(ret);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
Py_XDECREF(ret);
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::Read(char * buf, PRUint32 count, PRUint32 *_retval)
|
||||
{
|
||||
NS_PRECONDITION(_retval, "null pointer");
|
||||
NS_PRECONDITION(buf, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *ret;
|
||||
const char *methodName = "read";
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "i", count);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
PRUint32 py_size;
|
||||
const void *py_buf;
|
||||
if (PyObject_AsReadBuffer(ret, &py_buf, (int *)&py_size)!=0) {
|
||||
PyErr_Format(PyExc_TypeError, "nsIInputStream::read() method must return a buffer object - not a '%s' object", ret->ob_type->tp_name);
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
} else {
|
||||
if (py_size > count) {
|
||||
PyXPCOM_LogWarning("nsIInputStream::read() was asked for %d bytes, but the string returned is %d bytes - truncating!\n", count, py_size);
|
||||
py_size = count;
|
||||
}
|
||||
memcpy(buf, py_buf, py_size);
|
||||
*_retval = py_size;
|
||||
}
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval)
|
||||
{
|
||||
NS_WARNING("ReadSegments() not implemented!!!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::GetNonBlocking(PRBool *aNonBlocking)
|
||||
{
|
||||
NS_PRECONDITION(aNonBlocking, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *ret;
|
||||
const char *propName = "nonBlocking";
|
||||
nsresult nr = InvokeNativeGetViaPolicy(propName, &ret);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
*aNonBlocking = PyInt_AsLong(ret);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(propName);
|
||||
Py_XDECREF(ret);
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::GetObserver(nsIInputStreamObserver * *aObserver)
|
||||
{
|
||||
NS_PRECONDITION(aObserver, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *ret;
|
||||
const char *propName = "observer";
|
||||
nsresult nr = InvokeNativeGetViaPolicy(propName, &ret);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
Py_nsISupports::InterfaceFromPyObject(ret, NS_GET_IID(nsIInputStreamObserver), (nsISupports **)aObserver, PR_FALSE);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(propName);
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIInputStream::SetObserver(nsIInputStreamObserver * aObserver)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *propName = "observer";
|
||||
PyObject *obObserver = MakeInterfaceParam(aObserver, &NS_GET_IID(nsIInputStreamObserver));
|
||||
if (obObserver==NULL)
|
||||
return HandleNativeGatewayError(propName);
|
||||
nsresult nr = InvokeNativeSetViaPolicy(propName, obObserver);
|
||||
Py_DECREF(obObserver);
|
||||
return nr;
|
||||
}
|
||||
331
mozilla/extensions/python/xpcom/src/PyGModule.cpp
Normal file
331
mozilla/extensions/python/xpcom/src/PyGModule.cpp
Normal file
@@ -0,0 +1,331 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
// Unfortunately, we can not use an XPConnect object for
|
||||
// the nsiModule and nsiComponentLoader interfaces.
|
||||
// As XPCOM shuts down, it shuts down the interface manager before
|
||||
// it releases all the modules. This is a bit of a problem for
|
||||
// us, as it means we can't get runtime info on the interface at shutdown time.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIModule.h>
|
||||
#include <nsIComponentLoader.h>
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Can only assume dynamic loading on Windows.
|
||||
#define LOADER_LINKS_WITH_PYTHON
|
||||
|
||||
#endif // XP_WIN
|
||||
|
||||
extern void PyXPCOM_InterpreterState_Ensure();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// This is the main entry point called by the Python component
|
||||
// loader.
|
||||
extern "C" NS_EXPORT nsresult PyXPCOM_NSGetModule(nsIComponentManager *servMgr,
|
||||
nsIFile* location,
|
||||
nsIModule** result)
|
||||
{
|
||||
NS_PRECONDITION(result!=NULL, "null result pointer in PyXPCOM_NSGetModule!");
|
||||
NS_PRECONDITION(location!=NULL, "null nsIFile pointer in PyXPCOM_NSGetModule!");
|
||||
NS_PRECONDITION(servMgr!=NULL, "null servMgr pointer in PyXPCOM_NSGetModule!");
|
||||
#ifndef LOADER_LINKS_WITH_PYTHON
|
||||
if (!Py_IsInitialized()) {
|
||||
Py_Initialize();
|
||||
if (!Py_IsInitialized()) {
|
||||
PyXPCOM_LogError("Python initialization failed!\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PyEval_InitThreads();
|
||||
PyXPCOM_InterpreterState_Ensure();
|
||||
PyEval_SaveThread();
|
||||
}
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *func = NULL;
|
||||
PyObject *obServMgr = NULL;
|
||||
PyObject *obLocation = NULL;
|
||||
PyObject *wrap_ret = NULL;
|
||||
PyObject *args = NULL;
|
||||
PyObject *mod = PyImport_ImportModule("xpcom.server");
|
||||
if (!mod) goto done;
|
||||
func = PyObject_GetAttrString(mod, "NS_GetModule");
|
||||
if (func==NULL) goto done;
|
||||
obServMgr = Py_nsISupports::PyObjectFromInterface(servMgr, NS_GET_IID(nsIComponentManager), PR_TRUE);
|
||||
if (obServMgr==NULL) goto done;
|
||||
obLocation = Py_nsISupports::PyObjectFromInterface(location, NS_GET_IID(nsIFile), PR_TRUE);
|
||||
if (obLocation==NULL) goto done;
|
||||
args = Py_BuildValue("OO", obServMgr, obLocation);
|
||||
if (args==NULL) goto done;
|
||||
wrap_ret = PyEval_CallObject(func, args);
|
||||
if (wrap_ret==NULL) goto done;
|
||||
Py_nsISupports::InterfaceFromPyObject(wrap_ret, NS_GET_IID(nsIModule), (nsISupports **)result, PR_FALSE, PR_FALSE);
|
||||
done:
|
||||
nsresult nr = NS_OK;
|
||||
if (PyErr_Occurred()) {
|
||||
PyXPCOM_LogError("Obtaining the module object from Python failed.\n");
|
||||
nr = PyXPCOM_SetCOMErrorFromPyException();
|
||||
}
|
||||
Py_XDECREF(func);
|
||||
Py_XDECREF(obServMgr);
|
||||
Py_XDECREF(obLocation);
|
||||
Py_XDECREF(wrap_ret);
|
||||
Py_XDECREF(mod);
|
||||
Py_XDECREF(args);
|
||||
return nr;
|
||||
}
|
||||
|
||||
class PyG_nsIModule : public PyG_Base, public nsIModule
|
||||
{
|
||||
public:
|
||||
PyG_nsIModule(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIModule)) {;}
|
||||
PYGATEWAY_BASE_SUPPORT(nsIModule, PyG_Base);
|
||||
|
||||
NS_IMETHOD GetClassObject(nsIComponentManager *aCompMgr, const nsCID & aClass, const nsIID & aIID, void * *result);
|
||||
NS_IMETHOD RegisterSelf(nsIComponentManager *aCompMgr, nsIFile *location, const char *registryLocation, const char *componentType);
|
||||
NS_IMETHOD UnregisterSelf(nsIComponentManager *aCompMgr, nsIFile *location, const char *registryLocation);
|
||||
NS_IMETHOD CanUnload(nsIComponentManager *aCompMgr, PRBool *_retval);
|
||||
};
|
||||
|
||||
PyG_Base *MakePyG_nsIModule(PyObject *instance)
|
||||
{
|
||||
return new PyG_nsIModule(instance);
|
||||
}
|
||||
|
||||
|
||||
// Create a factory object for creating instances of aClass.
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIModule::GetClassObject(nsIComponentManager *aCompMgr,
|
||||
const nsCID& aClass,
|
||||
const nsIID& aIID,
|
||||
void** r_classObj)
|
||||
{
|
||||
NS_PRECONDITION(r_classObj, "null pointer");
|
||||
*r_classObj = nsnull;
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *cm = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManager));
|
||||
PyObject *iid = Py_nsIID::PyObjectFromIID(aIID);
|
||||
PyObject *clsid = Py_nsIID::PyObjectFromIID(aClass);
|
||||
const char *methodName = "getClassObject";
|
||||
PyObject *ret = NULL;
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "OOO", cm, clsid, iid);
|
||||
Py_XDECREF(cm);
|
||||
Py_XDECREF(iid);
|
||||
Py_XDECREF(clsid);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
nr = Py_nsISupports::InterfaceFromPyObject(ret, aIID, (nsISupports **)r_classObj, PR_FALSE);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
}
|
||||
if (NS_FAILED(nr)) {
|
||||
NS_ABORT_IF_FALSE(*r_classObj==NULL, "returning error result with an interface - probable leak!");
|
||||
}
|
||||
Py_XDECREF(ret);
|
||||
return nr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIModule::RegisterSelf(nsIComponentManager *aCompMgr,
|
||||
nsIFile* aPath,
|
||||
const char* registryLocation,
|
||||
const char* componentType)
|
||||
{
|
||||
NS_PRECONDITION(aCompMgr, "null pointer");
|
||||
NS_PRECONDITION(aPath, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *cm = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManager));
|
||||
PyObject *path = MakeInterfaceParam(aPath, &NS_GET_IID(nsIFile));
|
||||
const char *methodName = "registerSelf";
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOzz", cm, path, registryLocation, componentType);
|
||||
Py_XDECREF(cm);
|
||||
Py_XDECREF(path);
|
||||
return nr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIModule::UnregisterSelf(nsIComponentManager* aCompMgr,
|
||||
nsIFile* aPath,
|
||||
const char* registryLocation)
|
||||
{
|
||||
NS_PRECONDITION(aCompMgr, "null pointer");
|
||||
NS_PRECONDITION(aPath, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *cm = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManager));
|
||||
PyObject *path = MakeInterfaceParam(aPath, &NS_GET_IID(nsIFile));
|
||||
const char *methodName = "unregisterSelf";
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOz", cm, path, registryLocation);
|
||||
Py_XDECREF(cm);
|
||||
Py_XDECREF(path);
|
||||
return nr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyG_nsIModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload)
|
||||
{
|
||||
NS_PRECONDITION(aCompMgr, "null pointer");
|
||||
NS_PRECONDITION(okToUnload, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *cm = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManager));
|
||||
const char *methodName = "canUnload";
|
||||
PyObject *ret = NULL;
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "O", cm);
|
||||
Py_XDECREF(cm);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
*okToUnload = PyInt_AsLong(ret);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
}
|
||||
Py_XDECREF(ret);
|
||||
return nr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class PyG_nsIComponentLoader : public PyG_Base, public nsIComponentLoader
|
||||
{
|
||||
public:
|
||||
PyG_nsIComponentLoader(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIComponentLoader)) {;}
|
||||
PYGATEWAY_BASE_SUPPORT(nsIComponentLoader, PyG_Base);
|
||||
|
||||
NS_DECL_NSICOMPONENTLOADER
|
||||
};
|
||||
|
||||
PyG_Base *MakePyG_nsIComponentLoader(PyObject *instance)
|
||||
{
|
||||
return new PyG_nsIComponentLoader(instance);
|
||||
}
|
||||
|
||||
/* nsIFactory getFactory (in nsIIDRef aCID, in string aLocation, in string aType); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::GetFactory(const nsIID & aCID, const char *aLocation, const char *aType, nsIFactory **_retval)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "getFactory";
|
||||
PyObject *iid = Py_nsIID::PyObjectFromIID(aCID);
|
||||
PyObject *ret = NULL;
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "Ozz",
|
||||
iid,
|
||||
aLocation,
|
||||
aType);
|
||||
Py_XDECREF(iid);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
Py_nsISupports::InterfaceFromPyObject(ret, NS_GET_IID(nsIFactory), (nsISupports **)_retval, PR_FALSE);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
}
|
||||
Py_XDECREF(ret);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* void init (in nsIComponentManager aCompMgr, in nsISupports aRegistry); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aRegistry)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "init";
|
||||
PyObject *c = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManager));
|
||||
PyObject *r = MakeInterfaceParam(aRegistry, &NS_GET_IID(nsISupports));
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OO", c, r);
|
||||
Py_XDECREF(c);
|
||||
Py_XDECREF(r);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* void onRegister (in nsIIDRef aCID, in string aType, in string aClassName, in string aContractID, in string aLocation, in boolean aReplace, in boolean aPersist); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::OnRegister(const nsIID & aCID, const char *aType, const char *aClassName, const char *aContractID, const char *aLocation, PRBool aReplace, PRBool aPersist)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "onRegister";
|
||||
PyObject *iid = Py_nsIID::PyObjectFromIID(aCID);
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "Ossssii",
|
||||
iid,
|
||||
aType,
|
||||
aClassName,
|
||||
aContractID,
|
||||
aLocation,
|
||||
aReplace,
|
||||
aPersist);
|
||||
Py_XDECREF(iid);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* void autoRegisterComponents (in long aWhen, in nsIFile aDirectory); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::AutoRegisterComponents(PRInt32 aWhen, nsIFile *aDirectory)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "autoRegisterComponents";
|
||||
PyObject *c = MakeInterfaceParam(aDirectory, &NS_GET_IID(nsIFile));
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "iO", aWhen, c);
|
||||
Py_XDECREF(c);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* boolean autoRegisterComponent (in long aWhen, in nsIFile aComponent); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::AutoRegisterComponent(PRInt32 aWhen, nsIFile *aComponent, PRBool *_retval)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "autoRegisterComponent";
|
||||
PyObject *ret = NULL;
|
||||
PyObject *c = MakeInterfaceParam(aComponent, &NS_GET_IID(nsIFile));
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "iO", aWhen, c);
|
||||
Py_XDECREF(c);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
*_retval = PyInt_AsLong(ret);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
}
|
||||
Py_XDECREF(ret);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* boolean autoUnregisterComponent (in long aWhen, in nsIFile aComponent); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::AutoUnregisterComponent(PRInt32 aWhen, nsIFile *aComponent, PRBool *_retval)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "autoUnregisterComponent";
|
||||
PyObject *ret = NULL;
|
||||
PyObject *c = MakeInterfaceParam(aComponent, &NS_GET_IID(nsIFile));
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "iO", aWhen, c);
|
||||
Py_XDECREF(c);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
*_retval = PyInt_AsLong(ret);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
}
|
||||
Py_XDECREF(ret);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* boolean registerDeferredComponents (in long aWhen); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::RegisterDeferredComponents(PRInt32 aWhen, PRBool *_retval)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "registerDeferredComponents";
|
||||
PyObject *ret = NULL;
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "i", aWhen);
|
||||
if (NS_SUCCEEDED(nr)) {
|
||||
*_retval = PyInt_AsLong(ret);
|
||||
if (PyErr_Occurred())
|
||||
nr = HandleNativeGatewayError(methodName);
|
||||
}
|
||||
Py_XDECREF(ret);
|
||||
return nr;
|
||||
}
|
||||
|
||||
/* void unloadAll (in long aWhen); */
|
||||
NS_IMETHODIMP PyG_nsIComponentLoader::UnloadAll(PRInt32 aWhen)
|
||||
{
|
||||
CEnterLeavePython _celp;
|
||||
const char *methodName = "unloadAll";
|
||||
return InvokeNativeViaPolicy(methodName, NULL, "i", aWhen);
|
||||
}
|
||||
|
||||
|
||||
144
mozilla/extensions/python/xpcom/src/PyGStub.cpp
Normal file
144
mozilla/extensions/python/xpcom/src/PyGStub.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// PyXPTStub - the stub for implementing interfaces.
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIInterfaceInfoManager.h>
|
||||
|
||||
void *PyXPCOM_XPTStub::ThisAsIID(const nsIID &iid)
|
||||
{
|
||||
if (iid.Equals(NS_GET_IID(nsISupports)))
|
||||
return (nsISupports *)(nsXPTCStubBase *)this;
|
||||
else if (iid.Equals(m_iid))
|
||||
return (nsISupports *)(nsXPTCStubBase *)this;
|
||||
else
|
||||
return PyG_Base::ThisAsIID(iid);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyXPCOM_XPTStub::GetInterfaceInfo(nsIInterfaceInfo** info)
|
||||
{
|
||||
NS_PRECONDITION(info, "NULL pointer");
|
||||
if (info==nsnull)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
// Simply get the XPCOM runtime to provide this
|
||||
// (but there must be some reason why they dont get it themselves!?
|
||||
// Maybe because they dont know the IID?
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
|
||||
NS_ABORT_IF_FALSE(iim != nsnull, "Cant get interface from IIM!");
|
||||
if (iim==nsnull)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return iim->GetInfoForIID( &m_iid, info);
|
||||
}
|
||||
|
||||
// call this method and return result
|
||||
NS_IMETHODIMP
|
||||
PyXPCOM_XPTStub::CallMethod(PRUint16 methodIndex,
|
||||
const nsXPTMethodInfo* info,
|
||||
nsXPTCMiniVariant* params)
|
||||
{
|
||||
nsresult rc = NS_ERROR_FAILURE;
|
||||
NS_PRECONDITION(info, "NULL methodinfo pointer");
|
||||
NS_PRECONDITION(params, "NULL variant pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *obParams = NULL;
|
||||
PyObject *result = NULL;
|
||||
PyObject *obThisObject = NULL;
|
||||
PyObject *obMI = PyObject_FromXPTMethodDescriptor(info);
|
||||
PyXPCOM_GatewayVariantHelper arg_helper(this, methodIndex, info, params);
|
||||
if (obMI==NULL)
|
||||
goto done;
|
||||
// base object is passed raw.
|
||||
obThisObject = Py_nsISupports::PyObjectFromInterface((nsIInternalPython*)this, NS_GET_IID(nsISupports), PR_TRUE, PR_FALSE);
|
||||
obParams = arg_helper.MakePyArgs();
|
||||
if (obParams==NULL)
|
||||
goto done;
|
||||
result = PyObject_CallMethod(m_pPyObject,
|
||||
"_CallMethod_",
|
||||
"OiOO",
|
||||
obThisObject,
|
||||
(int)methodIndex,
|
||||
obMI,
|
||||
obParams);
|
||||
if (result!=NULL) {
|
||||
rc = arg_helper.ProcessPythonResult(result);
|
||||
// Use an xor to check failure && pyerr, or !failure && !pyerr.
|
||||
NS_ABORT_IF_FALSE( ((NS_FAILED(rc)!=0)^(PyErr_Occurred()!=0)) == 0, "We must have failure with a Python error, or success without a Python error.");
|
||||
}
|
||||
done:
|
||||
if (PyErr_Occurred()) {
|
||||
// The error handling - fairly involved, but worth it as
|
||||
// good error reporting is critical for users to know WTF
|
||||
// is going on - especially with TypeErrors etc in their
|
||||
// return values (ie, after the Python code has successfully
|
||||
// existed, but we encountered errors unpacking their
|
||||
// result values for the COM caller - there is literally no
|
||||
// way to catch these exceptions from Python code, as their
|
||||
// is no Python function on the call-stack)
|
||||
|
||||
// First line of attack in an error is to call-back on the policy.
|
||||
// If the callback of the error handler succeeds and returns an
|
||||
// integer (for the nsresult), we take no further action.
|
||||
|
||||
// If this callback fails, we log _2_ exceptions - the error handler
|
||||
// error, and the original error.
|
||||
|
||||
PRBool bProcessMainError = PR_TRUE; // set to false if our exception handler does its thing!
|
||||
PyObject *exc_typ, *exc_val, *exc_tb;
|
||||
PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
|
||||
PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
|
||||
|
||||
PyObject *err_result = PyObject_CallMethod(m_pPyObject,
|
||||
"_CallMethodException_",
|
||||
"OiOO(OOO)",
|
||||
obThisObject,
|
||||
(int)methodIndex,
|
||||
obMI,
|
||||
obParams,
|
||||
exc_typ ? exc_typ : Py_None, // should never be NULL, but defensive programming...
|
||||
exc_val ? exc_val : Py_None, // may well be NULL.
|
||||
exc_tb ? exc_tb : Py_None); // may well be NULL.
|
||||
if (err_result == NULL) {
|
||||
PyXPCOM_LogError("The exception handler _CallMethodException_ failed!\n");
|
||||
} else if (err_result == Py_None) {
|
||||
// The exception handler has chosen not to do anything with
|
||||
// this error, so we still need to print it!
|
||||
;
|
||||
} else if (PyInt_Check(err_result)) {
|
||||
// The exception handler has given us the nresult.
|
||||
rc = PyInt_AsLong(err_result);
|
||||
bProcessMainError = PR_FALSE;
|
||||
} else {
|
||||
// The exception handler succeeded, but returned other than
|
||||
// int or None.
|
||||
PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", err_result->ob_type->tp_name);
|
||||
}
|
||||
Py_XDECREF(err_result);
|
||||
PyErr_Restore(exc_typ, exc_val, exc_tb);
|
||||
if (bProcessMainError) {
|
||||
PyXPCOM_LogError("The function '%s' failed\n", info->GetName());
|
||||
rc = PyXPCOM_SetCOMErrorFromPyException();
|
||||
}
|
||||
// else everything is already setup,
|
||||
// just clear the Python error state.
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
Py_XDECREF(obMI);
|
||||
Py_XDECREF(obParams);
|
||||
Py_XDECREF(obThisObject);
|
||||
Py_XDECREF(result);
|
||||
return rc;
|
||||
}
|
||||
51
mozilla/extensions/python/xpcom/src/PyGWeakReference.cpp
Normal file
51
mozilla/extensions/python/xpcom/src/PyGWeakReference.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// PyGWeakReference - implements weak references for gateways.
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written November 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
|
||||
PyXPCOM_GatewayWeakReference::PyXPCOM_GatewayWeakReference( PyG_Base *base )
|
||||
{
|
||||
m_pBase = base;
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
PyXPCOM_GatewayWeakReference::~PyXPCOM_GatewayWeakReference()
|
||||
{
|
||||
// Simply zap my reference to the gateway!
|
||||
// No need to zap my gateway's reference to me, as
|
||||
// it already holds a reference, so if we are destructing,
|
||||
// then it can't possibly hold one.
|
||||
m_pBase = NULL;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(PyXPCOM_GatewayWeakReference);
|
||||
NS_IMPL_THREADSAFE_RELEASE(PyXPCOM_GatewayWeakReference);
|
||||
NS_IMPL_THREADSAFE_QUERY_INTERFACE(PyXPCOM_GatewayWeakReference, NS_GET_IID(nsIWeakReference));
|
||||
|
||||
NS_IMETHODIMP
|
||||
PyXPCOM_GatewayWeakReference::QueryReferent(REFNSIID iid, void * *ret)
|
||||
{
|
||||
{
|
||||
// Temp scope for lock. We can't hold the lock during
|
||||
// a QI, as this may itself need the lock.
|
||||
// Make sure our object isn't dieing right now on another thread.
|
||||
CEnterLeaveXPCOMFramework _celf;
|
||||
if (m_pBase == NULL)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
m_pBase->AddRef(); // Can't die while we have a ref.
|
||||
} // end of lock scope - lock unlocked.
|
||||
nsresult nr = m_pBase->QueryInterface(iid, ret);
|
||||
m_pBase->Release();
|
||||
return nr;
|
||||
}
|
||||
165
mozilla/extensions/python/xpcom/src/PyIComponentManager.cpp
Normal file
165
mozilla/extensions/python/xpcom/src/PyIComponentManager.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIComponentManager.h>
|
||||
|
||||
static nsIComponentManager *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsIComponentManager);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsIComponentManager *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
static PyObject *PyCreateInstanceByContractID(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *pid, *notyet = NULL;
|
||||
PyObject *obIID = NULL;
|
||||
if (!PyArg_ParseTuple(args, "s|zO", &pid, ¬yet, &obIID))
|
||||
return NULL;
|
||||
if (notyet != NULL) {
|
||||
PyErr_SetString(PyExc_ValueError, "2nd arg must be none");
|
||||
return NULL;
|
||||
}
|
||||
nsIComponentManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (obIID==NULL)
|
||||
iid = NS_GET_IID(nsISupports);
|
||||
else
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
nsISupports *pis;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->CreateInstanceByContractID(pid, NULL, iid, (void **)&pis);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyContractIDToClassID(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *pid;
|
||||
if (!PyArg_ParseTuple(args, "s", &pid))
|
||||
return NULL;
|
||||
nsIComponentManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->ContractIDToClassID(pid, &iid);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
return Py_nsIID::PyObjectFromIID(iid);
|
||||
}
|
||||
|
||||
static PyObject *PyCLSIDToContractID(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID;
|
||||
if (!PyArg_ParseTuple(args, "O", &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
char *ret_pid = nsnull;
|
||||
char *ret_class = nsnull;
|
||||
nsIComponentManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->CLSIDToContractID(iid, &ret_class, &ret_pid);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
PyObject *ob_pid = PyString_FromString(ret_pid);
|
||||
PyObject *ob_class = PyString_FromString(ret_class);
|
||||
PyObject *ret = Py_BuildValue("OO", ob_pid, ob_class);
|
||||
nsAllocator::Free(ret_pid);
|
||||
nsAllocator::Free(ret_class);
|
||||
Py_XDECREF(ob_pid);
|
||||
Py_XDECREF(ob_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *PyEnumerateCLSIDs(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
|
||||
nsIComponentManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIEnumerator *pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->EnumerateCLSIDs(&pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyEnumerateContractIDs(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
|
||||
nsIComponentManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIEnumerator *pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->EnumerateContractIDs(&pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE);
|
||||
}
|
||||
|
||||
struct PyMethodDef
|
||||
PyMethods_IComponentManager[] =
|
||||
{
|
||||
{ "CreateInstanceByContractID", PyCreateInstanceByContractID, 1},
|
||||
{ "createInstanceByContractID", PyCreateInstanceByContractID, 1},
|
||||
{ "EnumerateCLSIDs", PyEnumerateCLSIDs, 1},
|
||||
{ "enumerateCLSIDs", PyEnumerateCLSIDs, 1},
|
||||
{ "EnumerateContractIDs", PyEnumerateContractIDs, 1},
|
||||
{ "enumerateContractIDs", PyEnumerateContractIDs, 1},
|
||||
{ "ContractIDToClassID", PyContractIDToClassID, 1},
|
||||
{ "contractIDToClassID", PyContractIDToClassID, 1},
|
||||
{ "CLSIDToContractID", PyCLSIDToContractID, 1},
|
||||
{NULL}
|
||||
};
|
||||
198
mozilla/extensions/python/xpcom/src/PyIEnumerator.cpp
Normal file
198
mozilla/extensions/python/xpcom/src/PyIEnumerator.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIEnumerator.h>
|
||||
|
||||
static nsIEnumerator *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsIEnumerator);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsIEnumerator *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
static PyObject *PyFirst(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":First"))
|
||||
return NULL;
|
||||
|
||||
nsIEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->First();
|
||||
Py_END_ALLOW_THREADS;
|
||||
return PyInt_FromLong(r);
|
||||
}
|
||||
|
||||
static PyObject *PyNext(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":Next"))
|
||||
return NULL;
|
||||
|
||||
nsIEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->Next();
|
||||
Py_END_ALLOW_THREADS;
|
||||
return PyInt_FromLong(r);
|
||||
}
|
||||
|
||||
static PyObject *PyCurrentItem(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID = NULL;
|
||||
if (!PyArg_ParseTuple(args, "|O:CurrentItem", &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIID iid(NS_GET_IID(nsISupports));
|
||||
if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
nsIEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsISupports *pRet = nsnull;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->CurrentItem(&pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
if (obIID) {
|
||||
nsISupports *temp;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pRet->QueryInterface(iid, (void **)&temp);
|
||||
pRet->Release();
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) ) {
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
}
|
||||
pRet = temp;
|
||||
}
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, iid, PR_FALSE);
|
||||
}
|
||||
|
||||
// A method added for Python performance if you really need
|
||||
// it. Allows you to fetch a block of objects in one
|
||||
// hit, allowing the loop to remain implemented in C.
|
||||
static PyObject *PyFetchBlock(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID = NULL;
|
||||
int n_wanted;
|
||||
int n_fetched = 0;
|
||||
if (!PyArg_ParseTuple(args, "i|O:FetchBlock", &n_wanted, &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIID iid(NS_GET_IID(nsISupports));
|
||||
if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
nsIEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
// We want to fetch with the thread-lock released,
|
||||
// but this means we can not append to the PyList
|
||||
nsISupports **fetched = new nsISupports*[n_wanted];
|
||||
if (fetched==nsnull) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
memset(fetched, 0, sizeof(nsISupports *) * n_wanted);
|
||||
nsresult r = NS_OK;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
for (;n_fetched<n_wanted;) {
|
||||
nsISupports *pNew;
|
||||
r = pI->CurrentItem(&pNew);
|
||||
if (NS_FAILED(r)) {
|
||||
r = 0; // Normal enum end
|
||||
break;
|
||||
}
|
||||
if (obIID) {
|
||||
nsISupports *temp;
|
||||
r = pNew->QueryInterface(iid, (void **)&temp);
|
||||
pNew->Release();
|
||||
if ( NS_FAILED(r) ) {
|
||||
break;
|
||||
}
|
||||
pNew = temp;
|
||||
}
|
||||
fetched[n_fetched] = pNew;
|
||||
n_fetched++; // must increment before breaking out.
|
||||
if (NS_FAILED(pI->Next()))
|
||||
break; // not an error condition.
|
||||
}
|
||||
Py_END_ALLOW_THREADS;
|
||||
PyObject *ret;
|
||||
if (NS_SUCCEEDED(r)) {
|
||||
ret = PyList_New(n_fetched);
|
||||
if (ret)
|
||||
for (int i=0;i<n_fetched;i++) {
|
||||
PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid, PR_FALSE);
|
||||
PyList_SET_ITEM(ret, i, new_ob);
|
||||
}
|
||||
} else
|
||||
ret = PyXPCOM_BuildPyException(r);
|
||||
|
||||
if ( ret == NULL ) {
|
||||
// Free the objects we consumed.
|
||||
for (int i=0;i<n_fetched;i++)
|
||||
fetched[i]->Release();
|
||||
|
||||
}
|
||||
delete [] fetched;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *PyIsDone(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":IsDone"))
|
||||
return NULL;
|
||||
|
||||
nsIEnumerator *pI = GetI(self);
|
||||
nsresult r;
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->IsDone();
|
||||
Py_END_ALLOW_THREADS;
|
||||
if (NS_FAILED(r))
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
PyObject *ret = r==NS_OK ? Py_True : Py_False;
|
||||
Py_INCREF(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct PyMethodDef
|
||||
PyMethods_IEnumerator[] =
|
||||
{
|
||||
{ "First", PyFirst, 1},
|
||||
{ "first", PyFirst, 1},
|
||||
{ "Next", PyNext, 1},
|
||||
{ "next", PyNext, 1},
|
||||
{ "CurrentItem", PyCurrentItem, 1},
|
||||
{ "currentItem", PyCurrentItem, 1},
|
||||
{ "IsDone", PyIsDone, 1},
|
||||
{ "isDone", PyIsDone, 1},
|
||||
{ "FetchBlock", PyFetchBlock, 1},
|
||||
{ "fetchBlock", PyFetchBlock, 1},
|
||||
{NULL}
|
||||
};
|
||||
202
mozilla/extensions/python/xpcom/src/PyIID.cpp
Normal file
202
mozilla/extensions/python/xpcom/src/PyIID.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// Py_nsIID.cpp -- IID type for Python/XPCOM
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
//
|
||||
// @doc
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIInterfaceInfoManager.h>
|
||||
|
||||
nsIID Py_nsIID_NULL = {0,0,0,{0,0,0,0,0,0,0,0}};
|
||||
|
||||
// @pymethod <o Py_nsIID>|xpcom|IID|Creates a new IID object
|
||||
PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID;
|
||||
PyObject *obBuf;
|
||||
if ( PyArg_ParseTuple(args, "O", &obBuf)) {
|
||||
if (PyBuffer_Check(obBuf)) {
|
||||
PyBufferProcs *pb = NULL;
|
||||
pb = obBuf->ob_type->tp_as_buffer;
|
||||
void *buf = NULL;
|
||||
int size = (*pb->bf_getreadbuffer)(obBuf, 0, &buf);
|
||||
if (size != sizeof(nsIID) || buf==NULL) {
|
||||
PyErr_Format(PyExc_ValueError, "A buffer object to be converted to an IID must be exactly %d bytes long", sizeof(nsIID));
|
||||
return NULL;
|
||||
}
|
||||
nsIID iid;
|
||||
unsigned char *ptr = (unsigned char *)buf;
|
||||
iid.m0 = XPT_SWAB32(*((PRUint32 *)ptr));
|
||||
ptr = ((unsigned char *)buf) + offsetof(nsIID, m1);
|
||||
iid.m1 = XPT_SWAB16(*((PRUint16 *)ptr));
|
||||
ptr = ((unsigned char *)buf) + offsetof(nsIID, m2);
|
||||
iid.m2 = XPT_SWAB16(*((PRUint16 *)ptr));
|
||||
ptr = ((unsigned char *)buf) + offsetof(nsIID, m3);
|
||||
for (int i=0;i<8;i++) {
|
||||
iid.m3[i] = *((PRUint8 *)ptr);
|
||||
ptr += sizeof(PRUint8);
|
||||
}
|
||||
return new Py_nsIID(iid);
|
||||
}
|
||||
}
|
||||
PyErr_Clear();
|
||||
// @pyparm string/Unicode|iidString||A string representation of an IID, or a ContractID.
|
||||
if ( !PyArg_ParseTuple(args, "O", &obIID) )
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
return new Py_nsIID(iid);
|
||||
}
|
||||
|
||||
/*static*/ PRBool
|
||||
Py_nsIID::IIDFromPyObject(PyObject *ob, nsIID *pRet) {
|
||||
PRBool ok = PR_TRUE;
|
||||
nsIID iid;
|
||||
if (ob==NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "The object is invalid!");
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (PyString_Check(ob)) {
|
||||
ok = iid.Parse(PyString_AsString(ob));
|
||||
if (!ok) {
|
||||
PyXPCOM_BuildPyException(NS_ERROR_ILLEGAL_VALUE);
|
||||
return PR_FALSE;
|
||||
}
|
||||
} else if (ob->ob_type == &type) {
|
||||
iid = ((Py_nsIID *)ob)->m_iid;
|
||||
} else if (PyInstance_Check(ob)) {
|
||||
// Get the _iidobj_ attribute
|
||||
PyObject *use_ob = PyObject_GetAttrString(ob, "_iidobj_");
|
||||
if (use_ob==NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "Only instances with _iidobj_ attributes can be used as IID objects");
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (use_ob->ob_type != &type) {
|
||||
Py_DECREF(use_ob);
|
||||
PyErr_SetString(PyExc_TypeError, "instance _iidobj_ attributes must be raw IID object");
|
||||
return PR_FALSE;
|
||||
}
|
||||
iid = ((Py_nsIID *)use_ob)->m_iid;
|
||||
Py_DECREF(use_ob);
|
||||
} else {
|
||||
PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an IID", ob->ob_type->tp_name);
|
||||
ok = PR_FALSE;
|
||||
}
|
||||
if (ok) *pRet = iid;
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
// @object Py_nsIID|A Python object, representing an IID/CLSID.
|
||||
// <nl>All pythoncom functions that return a CLSID/IID will return one of these
|
||||
// objects. However, in almost all cases, functions that expect a CLSID/IID
|
||||
// as a param will accept either a string object, or a native Py_nsIID object.
|
||||
PyTypeObject Py_nsIID::type =
|
||||
{
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"IID",
|
||||
sizeof(Py_nsIID),
|
||||
0,
|
||||
PyTypeMethod_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
PyTypeMethod_getattr, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
PyTypeMethod_compare, /* tp_compare */
|
||||
PyTypeMethod_repr, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
PyTypeMethod_hash, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
PyTypeMethod_str, /* tp_str */
|
||||
};
|
||||
|
||||
Py_nsIID::Py_nsIID(const nsIID &riid)
|
||||
{
|
||||
ob_type = &type;
|
||||
_Py_NewReference(this);
|
||||
m_iid = riid;
|
||||
}
|
||||
|
||||
/*static*/PyObject *
|
||||
Py_nsIID::PyTypeMethod_getattr(PyObject *self, char *name)
|
||||
{
|
||||
Py_nsIID *me = (Py_nsIID *)self;
|
||||
if (strcmp(name, "name")==0) {
|
||||
char *iid_repr = nsnull;
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
|
||||
if (iim!=nsnull)
|
||||
iim->GetNameForIID(&me->m_iid, &iid_repr);
|
||||
if (iid_repr==nsnull)
|
||||
iid_repr = me->m_iid.ToString();
|
||||
PyObject *ret;
|
||||
if (iid_repr != nsnull) {
|
||||
ret = PyString_FromString(iid_repr);
|
||||
nsAllocator::Free(iid_repr);
|
||||
} else
|
||||
ret = PyString_FromString("<cant get IID info!>");
|
||||
return ret;
|
||||
}
|
||||
return PyErr_Format(PyExc_AttributeError, "IID objects have no attribute '%s'", name);
|
||||
}
|
||||
|
||||
/* static */ int
|
||||
Py_nsIID::PyTypeMethod_compare(PyObject *self, PyObject *other)
|
||||
{
|
||||
Py_nsIID *s_iid = (Py_nsIID *)self;
|
||||
Py_nsIID *o_iid = (Py_nsIID *)other;
|
||||
return memcmp(&s_iid->m_iid, &o_iid->m_iid, sizeof(s_iid->m_iid));
|
||||
}
|
||||
|
||||
/* static */ PyObject *
|
||||
Py_nsIID::PyTypeMethod_repr(PyObject *self)
|
||||
{
|
||||
Py_nsIID *s_iid = (Py_nsIID *)self;
|
||||
char buf[256];
|
||||
char *sziid = s_iid->m_iid.ToString();
|
||||
sprintf(buf, "_xpcom.IID('%s')", sziid);
|
||||
nsAllocator::Free(sziid);
|
||||
return PyString_FromString(buf);
|
||||
}
|
||||
|
||||
/* static */ PyObject *
|
||||
Py_nsIID::PyTypeMethod_str(PyObject *self)
|
||||
{
|
||||
Py_nsIID *s_iid = (Py_nsIID *)self;
|
||||
char *sziid = s_iid->m_iid.ToString();
|
||||
PyObject *ret = PyString_FromString(sziid);
|
||||
nsAllocator::Free(sziid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* static */long
|
||||
Py_nsIID::PyTypeMethod_hash(PyObject *self)
|
||||
{
|
||||
const nsIID &iid = ((Py_nsIID *)self)->m_iid;
|
||||
|
||||
long ret = iid.m0 + iid.m1 + iid.m2;
|
||||
for (int i=0;i<7;i++)
|
||||
ret += iid.m3[i];
|
||||
if ( ret == -1 )
|
||||
return -2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
Py_nsIID::PyTypeMethod_dealloc(PyObject *ob)
|
||||
{
|
||||
delete (Py_nsIID *)ob;
|
||||
}
|
||||
127
mozilla/extensions/python/xpcom/src/PyIInputStream.cpp
Normal file
127
mozilla/extensions/python/xpcom/src/PyIInputStream.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written September 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include "nsIInputStream.h"
|
||||
|
||||
// Prevents us needing to use an nsIScriptableInputStream
|
||||
// (and even that can't read binary data!!!)
|
||||
|
||||
static nsIInputStream *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsIInputStream);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsIInputStream *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
static PyObject *DoPyRead_Buffer(nsIInputStream *pI, PyObject *obBuffer, PRUint32 n)
|
||||
{
|
||||
PRUint32 nread;
|
||||
void *buf;
|
||||
PRUint32 buf_len;
|
||||
if (PyObject_AsWriteBuffer(obBuffer, &buf, (int *)&buf_len) != 0) {
|
||||
PyErr_Clear();
|
||||
PyErr_SetString(PyExc_TypeError, "The buffer object does not have a write buffer!");
|
||||
return NULL;
|
||||
}
|
||||
if (n==(PRUint32)-1) {
|
||||
n = buf_len;
|
||||
} else {
|
||||
if (n > buf_len) {
|
||||
NS_WARNING("Warning: PyIInputStream::read() was passed an integer size greater than the size of the passed buffer! Buffer size used.\n");
|
||||
n = buf_len;
|
||||
}
|
||||
}
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->Read((char *)buf, n, &nread);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyInt_FromLong(nread);
|
||||
}
|
||||
|
||||
static PyObject *DoPyRead_Size(nsIInputStream *pI, PRUint32 n)
|
||||
{
|
||||
if (n==-1) {
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->Available(&n);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if (NS_FAILED(r))
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
}
|
||||
char *buf = (char *)nsAllocator::Alloc(n);
|
||||
if (buf==NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
nsresult r;
|
||||
PRUint32 nread;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->Read(buf, n, &nread);
|
||||
Py_END_ALLOW_THREADS;
|
||||
PyObject *rc = NULL;
|
||||
if ( NS_SUCCEEDED(r) ) {
|
||||
rc = PyBuffer_New(nread);
|
||||
if (rc != NULL) {
|
||||
void *ob_buf;
|
||||
PRUint32 buf_len;
|
||||
if (PyObject_AsWriteBuffer(rc, &ob_buf, (int *)&buf_len) != 0) {
|
||||
// should never fail - we just created it!
|
||||
return NULL;
|
||||
}
|
||||
if (buf_len != nread) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "New buffer isnt the size we create it!");
|
||||
return NULL;
|
||||
}
|
||||
memcpy(ob_buf, buf, nread);
|
||||
}
|
||||
} else
|
||||
PyXPCOM_BuildPyException(r);
|
||||
nsAllocator::Free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static PyObject *PyRead(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obBuffer = NULL;
|
||||
PRUint32 n = (PRUint32)-1;
|
||||
|
||||
nsIInputStream *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
if (PyArg_ParseTuple(args, "|i", (int *)&n))
|
||||
// This worked - no args, or just an int.
|
||||
return DoPyRead_Size(pI, n);
|
||||
// try our other supported arg format.
|
||||
PyErr_Clear();
|
||||
if (!PyArg_ParseTuple(args, "O|i", &obBuffer, (int *)&n)) {
|
||||
PyErr_Clear();
|
||||
PyErr_SetString(PyExc_TypeError, "'read()' must be called as (buffer_ob, int_size=-1) or (int_size=-1)");
|
||||
return NULL;
|
||||
}
|
||||
return DoPyRead_Buffer(pI, obBuffer, n);
|
||||
}
|
||||
|
||||
|
||||
struct PyMethodDef
|
||||
PyMethods_IInputStream[] =
|
||||
{
|
||||
{ "read", PyRead, 1},
|
||||
// The rest are handled as normal
|
||||
{NULL}
|
||||
};
|
||||
391
mozilla/extensions/python/xpcom/src/PyIInterfaceInfo.cpp
Normal file
391
mozilla/extensions/python/xpcom/src/PyIInterfaceInfo.cpp
Normal file
@@ -0,0 +1,391 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
|
||||
|
||||
static nsIInterfaceInfo *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsIInterfaceInfo);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsIInterfaceInfo *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
static PyObject *PyGetName(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":GetName"))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
char *name;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetName(&name);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
PyObject *ret = PyString_FromString(name);
|
||||
nsAllocator::Free(name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *PyGetIID(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":GetIID"))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIID *iid_ret;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetIID(&iid_ret);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
PyObject *ret = Py_nsIID::PyObjectFromIID(*iid_ret);
|
||||
nsAllocator::Free(iid_ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *PyIsScriptable(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":IsScriptable"))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
PRBool b_ret;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->IsScriptable(&b_ret);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyInt_FromLong(b_ret);
|
||||
}
|
||||
|
||||
static PyObject *PyGetParent(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":GetParent"))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetParent(&pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyGetMethodCount(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":GetMethodCount"))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
PRUint16 ret;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetMethodCount(&ret);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyInt_FromLong(ret);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *PyGetConstantCount(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":GetConstantCount"))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
PRUint16 ret;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetConstantCount(&ret);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyInt_FromLong(ret);
|
||||
}
|
||||
|
||||
static PyObject *PyGetMethodInfo(PyObject *self, PyObject *args)
|
||||
{
|
||||
PRUint16 index;
|
||||
if (!PyArg_ParseTuple(args, "h:GetMethodInfo", &index))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
PRUint16 nmethods;
|
||||
pI->GetMethodCount(&nmethods);
|
||||
if (index>=nmethods) {
|
||||
PyErr_SetString(PyExc_ValueError, "The method index is out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const nsXPTMethodInfo *pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetMethodInfo(index, &pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyObject_FromXPTMethodDescriptor(pRet);
|
||||
}
|
||||
|
||||
static PyObject *PyGetMethodInfoForName(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *name;
|
||||
if (!PyArg_ParseTuple(args, "s:GetMethodInfoForName", &name))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
const nsXPTMethodInfo *pRet;
|
||||
PRUint16 index;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetMethodInfoForName(name, &index, &pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
PyObject *ret_i = PyObject_FromXPTMethodDescriptor(pRet);
|
||||
if (ret_i==NULL)
|
||||
return NULL;
|
||||
PyObject *real_ret = Py_BuildValue("iO", (int)index, ret_i);
|
||||
Py_DECREF(ret_i);
|
||||
return real_ret;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *PyGetConstant(PyObject *self, PyObject *args)
|
||||
{
|
||||
PRUint16 index;
|
||||
if (!PyArg_ParseTuple(args, "h:GetConstant", &index))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
const nsXPTConstant *pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetConstant(index, &pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyObject_FromXPTConstant(pRet);
|
||||
}
|
||||
|
||||
static PRBool __GetMethodInfoHelper(nsIInterfaceInfo *pii, int mi, int pi, const nsXPTMethodInfo **ppmi)
|
||||
{
|
||||
PRUint16 nmethods=0;
|
||||
pii->GetMethodCount(&nmethods);
|
||||
if (mi<0 || mi>=nmethods) {
|
||||
PyErr_SetString(PyExc_ValueError, "The method index is out of range");
|
||||
return PR_FALSE;
|
||||
}
|
||||
const nsXPTMethodInfo *pmi;
|
||||
nsresult r = pii->GetMethodInfo(mi, &pmi);
|
||||
if ( NS_FAILED(r) ) {
|
||||
PyXPCOM_BuildPyException(r);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
int nparams=0;
|
||||
nparams = pmi->GetParamCount();
|
||||
if (pi<0 || pi>=nparams) {
|
||||
PyErr_SetString(PyExc_ValueError, "The param index is out of range");
|
||||
return PR_FALSE;
|
||||
}
|
||||
*ppmi = pmi;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PyObject *PyGetInfoForParam(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIInterfaceInfo *pii = GetI(self);
|
||||
if (pii==NULL)
|
||||
return NULL;
|
||||
PRUint16 mi, pi;
|
||||
if (!PyArg_ParseTuple(args, "hh:GetInfoForParam", &mi, &pi))
|
||||
return NULL;
|
||||
const nsXPTMethodInfo *pmi;
|
||||
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
|
||||
return NULL;
|
||||
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
|
||||
nsIInterfaceInfo *pnewii = nsnull;
|
||||
nsresult n = pii->GetInfoForParam(mi, ¶m_info, &pnewii);
|
||||
if (NS_FAILED(n))
|
||||
return PyXPCOM_BuildPyException(n);
|
||||
return Py_nsISupports::PyObjectFromInterface(pnewii, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyGetIIDForParam(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIInterfaceInfo *pii = GetI(self);
|
||||
if (pii==NULL)
|
||||
return NULL;
|
||||
PRUint16 mi, pi;
|
||||
if (!PyArg_ParseTuple(args, "hh:GetIIDForParam", &mi, &pi))
|
||||
return NULL;
|
||||
const nsXPTMethodInfo *pmi;
|
||||
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
|
||||
return NULL;
|
||||
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
|
||||
nsIID *piid;
|
||||
nsresult n = pii->GetIIDForParam(mi, ¶m_info, &piid);
|
||||
if (NS_FAILED(n) || piid==nsnull)
|
||||
return PyXPCOM_BuildPyException(n);
|
||||
return Py_nsIID::PyObjectFromIID(*piid);
|
||||
}
|
||||
|
||||
static PyObject *PyGetTypeForParam(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIInterfaceInfo *pii = GetI(self);
|
||||
if (pii==NULL)
|
||||
return NULL;
|
||||
PRUint16 mi, pi, dim;
|
||||
if (!PyArg_ParseTuple(args, "hhh:GetTypeForParam", &mi, &pi, &dim))
|
||||
return NULL;
|
||||
const nsXPTMethodInfo *pmi;
|
||||
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
|
||||
return NULL;
|
||||
nsXPTType datumType;
|
||||
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
|
||||
nsresult n = pii->GetTypeForParam(mi, ¶m_info, dim, &datumType);
|
||||
if (NS_FAILED(n))
|
||||
return PyXPCOM_BuildPyException(n);
|
||||
return PyObject_FromXPTTypeDescriptor((const XPTTypeDescriptor *)&datumType);
|
||||
}
|
||||
|
||||
static PyObject *PyGetSizeIsArgNumberForParam(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIInterfaceInfo *pii = GetI(self);
|
||||
if (pii==NULL)
|
||||
return NULL;
|
||||
PRUint16 mi, pi, dim;
|
||||
if (!PyArg_ParseTuple(args, "hhh:GetSizeIsArgNumberForParam", &mi, &pi, &dim))
|
||||
return NULL;
|
||||
const nsXPTMethodInfo *pmi;
|
||||
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
|
||||
return NULL;
|
||||
PRUint8 ret;
|
||||
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
|
||||
nsresult n = pii->GetSizeIsArgNumberForParam(mi, ¶m_info, dim, &ret);
|
||||
if (NS_FAILED(n))
|
||||
return PyXPCOM_BuildPyException(n);
|
||||
return PyInt_FromLong(ret);
|
||||
}
|
||||
|
||||
static PyObject *PyGetLengthIsArgNumberForParam(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIInterfaceInfo *pii = GetI(self);
|
||||
if (pii==NULL)
|
||||
return NULL;
|
||||
PRUint16 mi, pi, dim;
|
||||
if (!PyArg_ParseTuple(args, "hhh:GetLengthIsArgNumberForParam", &mi, &pi, &dim))
|
||||
return NULL;
|
||||
const nsXPTMethodInfo *pmi;
|
||||
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
|
||||
return NULL;
|
||||
PRUint8 ret;
|
||||
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
|
||||
nsresult n = pii->GetLengthIsArgNumberForParam(mi, ¶m_info, dim, &ret);
|
||||
if (NS_FAILED(n))
|
||||
return PyXPCOM_BuildPyException(n);
|
||||
return PyInt_FromLong(ret);
|
||||
}
|
||||
|
||||
static PyObject *PyGetInterfaceIsArgNumberForParam(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIInterfaceInfo *pii = GetI(self);
|
||||
if (pii==NULL)
|
||||
return NULL;
|
||||
PRUint16 mi, pi;
|
||||
if (!PyArg_ParseTuple(args, "hhh:GetInterfaceIsArgNumberForParam", &mi, &pi))
|
||||
return NULL;
|
||||
const nsXPTMethodInfo *pmi;
|
||||
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
|
||||
return NULL;
|
||||
PRUint8 ret;
|
||||
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
|
||||
nsresult n = pii->GetInterfaceIsArgNumberForParam(mi, ¶m_info, &ret);
|
||||
if (NS_FAILED(n))
|
||||
return PyXPCOM_BuildPyException(n);
|
||||
return PyInt_FromLong(ret);
|
||||
}
|
||||
|
||||
struct PyMethodDef
|
||||
PyMethods_IInterfaceInfo[] =
|
||||
{
|
||||
{ "GetName", PyGetName, 1},
|
||||
{ "GetIID", PyGetIID, 1},
|
||||
{ "IsScriptable", PyIsScriptable, 1},
|
||||
{ "GetParent", PyGetParent, 1},
|
||||
{ "GetMethodCount", PyGetMethodCount, 1},
|
||||
{ "GetConstantCount", PyGetConstantCount, 1},
|
||||
{ "GetMethodInfo", PyGetMethodInfo, 1},
|
||||
{ "GetMethodInfoForName", PyGetMethodInfoForName, 1},
|
||||
{ "GetConstant", PyGetConstant, 1},
|
||||
{ "GetInfoForParam", PyGetInfoForParam, 1},
|
||||
{ "GetIIDForParam", PyGetIIDForParam, 1},
|
||||
{ "GetTypeForParam", PyGetTypeForParam, 1},
|
||||
{ "GetSizeIsArgNumberForParam", PyGetSizeIsArgNumberForParam, 1},
|
||||
{ "GetLengthIsArgNumberForParam", PyGetLengthIsArgNumberForParam, 1},
|
||||
{ "GetInterfaceIsArgNumberForParam", PyGetInterfaceIsArgNumberForParam, 1},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
/*
|
||||
NS_IMETHOD GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info) = 0;
|
||||
NS_IMETHOD GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info) = 0;
|
||||
NS_IMETHOD GetConstant(PRUint16 index, const nsXPTConstant * *constant) = 0;
|
||||
NS_IMETHOD GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) = 0;
|
||||
NS_IMETHOD GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) = 0;
|
||||
NS_IMETHOD GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval) = 0;
|
||||
NS_IMETHOD GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) = 0;
|
||||
NS_IMETHOD GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) = 0;
|
||||
NS_IMETHOD GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval) = 0;
|
||||
|
||||
*/
|
||||
167
mozilla/extensions/python/xpcom/src/PyIInterfaceInfoManager.cpp
Normal file
167
mozilla/extensions/python/xpcom/src/PyIInterfaceInfoManager.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIInterfaceInfoManager.h>
|
||||
|
||||
static nsIInterfaceInfoManager *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsIInterfaceInfoManager);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsIInterfaceInfoManager *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
static PyObject *PyGetInfoForIID(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID = NULL;
|
||||
if (!PyArg_ParseTuple(args, "O", &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfoManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pi;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetInfoForIID(&iid, &pi);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
nsIID new_iid = NS_GET_IID(nsIInterfaceInfo);
|
||||
// Can not auto-wrap the interface info manager as it is critical to
|
||||
// building the support we need for autowrap.
|
||||
return Py_nsISupports::PyObjectFromInterface(pi, new_iid, PR_FALSE, PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyGetInfoForName(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *name;
|
||||
if (!PyArg_ParseTuple(args, "s", &name))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfoManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pi;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetInfoForName(name, &pi);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
// Can not auto-wrap the interface info manager as it is critical to
|
||||
// building the support we need for autowrap.
|
||||
return Py_nsISupports::PyObjectFromInterface(pi, NS_GET_IID(nsIInterfaceInfo), PR_FALSE, PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyGetNameForIID(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID = NULL;
|
||||
if (!PyArg_ParseTuple(args, "O", &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfoManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
char *ret_name = NULL;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetNameForIID(&iid, &ret_name);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
PyObject *ret = PyString_FromString(ret_name);
|
||||
nsAllocator::Free(ret_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *PyGetIIDForName(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *name;
|
||||
if (!PyArg_ParseTuple(args, "s", &name))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfoManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIID *iid_ret;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetIIDForName(name, &iid_ret);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
PyObject *ret = Py_nsIID::PyObjectFromIID(*iid_ret);
|
||||
nsAllocator::Free(iid_ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *PyEnumerateInterfaces(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfoManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIEnumerator *pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->EnumerateInterfaces(&pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// void autoRegisterInterfaces();
|
||||
|
||||
PyMethodDef
|
||||
PyMethods_IInterfaceInfoManager[] =
|
||||
{
|
||||
{ "GetInfoForIID", PyGetInfoForIID, 1},
|
||||
{ "getInfoForIID", PyGetInfoForIID, 1},
|
||||
{ "GetInfoForName", PyGetInfoForName, 1},
|
||||
{ "getInfoForName", PyGetInfoForName, 1},
|
||||
{ "GetIIDForName", PyGetIIDForName, 1},
|
||||
{ "getIIDForName", PyGetIIDForName, 1},
|
||||
{ "GetNameForIID", PyGetNameForIID, 1},
|
||||
{ "getNameForIID", PyGetNameForIID, 1},
|
||||
{ "EnumerateInterfaces", PyEnumerateInterfaces, 1},
|
||||
{ "enumerateInterfaces", PyEnumerateInterfaces, 1},
|
||||
{NULL}
|
||||
};
|
||||
101
mozilla/extensions/python/xpcom/src/PyIServiceManager.cpp
Normal file
101
mozilla/extensions/python/xpcom/src/PyIServiceManager.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIServiceManager.h>
|
||||
|
||||
|
||||
static nsIServiceManager *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsIServiceManager);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsIServiceManager *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
static PyObject *PyRegisterService(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIServiceManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
PyObject *obCID, *obInterface;
|
||||
if (!PyArg_ParseTuple(args, "OO", &obCID, &obInterface))
|
||||
return NULL;
|
||||
|
||||
nsCOMPtr<nsISupports> pis;
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(obInterface, NS_GET_IID(nsISupports), getter_AddRefs(pis), PR_FALSE))
|
||||
return NULL;
|
||||
nsresult r;
|
||||
if (PyString_Check(obCID) || PyUnicode_Check(obCID)) {
|
||||
const char *val = PyString_AsString(obCID);
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->RegisterService(val, pis);
|
||||
Py_END_ALLOW_THREADS;
|
||||
} else {
|
||||
nsCID cid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obCID, &cid))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->RegisterService(cid, pis);
|
||||
Py_END_ALLOW_THREADS;
|
||||
}
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *PyGetService(PyObject *self, PyObject *args)
|
||||
{
|
||||
nsIServiceManager *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
PyObject *obIID, *obCID;
|
||||
if (!PyArg_ParseTuple(args, "OO", &obCID, &obIID))
|
||||
return NULL;
|
||||
nsIID cid, iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
nsISupports *pis;
|
||||
nsresult r;
|
||||
if (PyString_Check(obCID) || PyUnicode_Check(obCID)) {
|
||||
char *val = PyString_AsString(obCID);
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetService(val, iid, &pis);
|
||||
Py_END_ALLOW_THREADS;
|
||||
} else {
|
||||
if (!Py_nsIID::IIDFromPyObject(obCID, &cid))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetService(cid, iid, &pis);
|
||||
Py_END_ALLOW_THREADS;
|
||||
}
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE);
|
||||
}
|
||||
|
||||
struct PyMethodDef
|
||||
PyMethods_IServiceManager[] =
|
||||
{
|
||||
{ "GetService", PyGetService, 1},
|
||||
{ "getService", PyGetService, 1},
|
||||
{ "RegisterService", PyRegisterService, 1},
|
||||
{ "registerService", PyRegisterService, 1},
|
||||
{NULL}
|
||||
};
|
||||
165
mozilla/extensions/python/xpcom/src/PyISimpleEnumerator.cpp
Normal file
165
mozilla/extensions/python/xpcom/src/PyISimpleEnumerator.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsISimpleEnumerator.h>
|
||||
|
||||
static nsISimpleEnumerator *GetI(PyObject *self) {
|
||||
nsIID iid = NS_GET_IID(nsISimpleEnumerator);
|
||||
|
||||
if (!Py_nsISupports::Check(self, iid)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
|
||||
return NULL;
|
||||
}
|
||||
return (nsISimpleEnumerator *)Py_nsISupports::GetI(self);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *PyHasMoreElements(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":HasMoreElements"))
|
||||
return NULL;
|
||||
|
||||
nsISimpleEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsresult r;
|
||||
PRBool more;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->HasMoreElements(&more);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return PyInt_FromLong(more);
|
||||
}
|
||||
|
||||
static PyObject *PyGetNext(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID = NULL;
|
||||
if (!PyArg_ParseTuple(args, "|O:GetNext", &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIID iid(NS_GET_IID(nsISupports));
|
||||
if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
nsISimpleEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsISupports *pRet = nsnull;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetNext(&pRet);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
if (obIID) {
|
||||
nsISupports *temp;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pRet->QueryInterface(iid, (void **)&temp);
|
||||
pRet->Release();
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) ) {
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
}
|
||||
pRet = temp;
|
||||
}
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, iid, PR_FALSE);
|
||||
}
|
||||
|
||||
// A method added for Python performance if you really need
|
||||
// it. Allows you to fetch a block of objects in one
|
||||
// hit, allowing the loop to remain implemented in C.
|
||||
static PyObject *PyFetchBlock(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID = NULL;
|
||||
int n_wanted;
|
||||
int n_fetched = 0;
|
||||
if (!PyArg_ParseTuple(args, "i|O:FetchBlock", &n_wanted, &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIID iid(NS_GET_IID(nsISupports));
|
||||
if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
nsISimpleEnumerator *pI = GetI(self);
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
// We want to fetch with the thread-lock released,
|
||||
// but this means we can not append to the PyList
|
||||
nsISupports **fetched = new nsISupports*[n_wanted];
|
||||
if (fetched==nsnull) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
memset(fetched, 0, sizeof(nsISupports *) * n_wanted);
|
||||
nsresult r;
|
||||
PRBool more;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
for (;n_fetched<n_wanted;) {
|
||||
r = pI->HasMoreElements(&more);
|
||||
if (NS_FAILED(r))
|
||||
break; // this _is_ an error!
|
||||
if (!more)
|
||||
break; // Normal enum end.
|
||||
nsISupports *pNew;
|
||||
r = pI->GetNext(&pNew);
|
||||
if (NS_FAILED(r)) // IS an error
|
||||
break;
|
||||
if (obIID) {
|
||||
nsISupports *temp;
|
||||
r = pNew->QueryInterface(iid, (void **)&temp);
|
||||
pNew->Release();
|
||||
if ( NS_FAILED(r) ) {
|
||||
break;
|
||||
}
|
||||
pNew = temp;
|
||||
}
|
||||
fetched[n_fetched] = pNew;
|
||||
n_fetched++;
|
||||
}
|
||||
Py_END_ALLOW_THREADS;
|
||||
PyObject *ret;
|
||||
if (NS_SUCCEEDED(r)) {
|
||||
ret = PyList_New(n_fetched);
|
||||
if (ret)
|
||||
for (int i=0;i<n_fetched;i++) {
|
||||
PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid, PR_FALSE);
|
||||
PyList_SET_ITEM(ret, i, new_ob);
|
||||
}
|
||||
} else
|
||||
ret = PyXPCOM_BuildPyException(r);
|
||||
|
||||
if ( ret == NULL ) {
|
||||
// Free the objects we consumed.
|
||||
for (int i=0;i<n_fetched;i++)
|
||||
fetched[i]->Release();
|
||||
|
||||
}
|
||||
delete [] fetched;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct PyMethodDef
|
||||
PyMethods_ISimpleEnumerator[] =
|
||||
{
|
||||
{ "HasMoreElements", PyHasMoreElements, 1},
|
||||
{ "hasMoreElements", PyHasMoreElements, 1},
|
||||
{ "GetNext", PyGetNext, 1},
|
||||
{ "getNext", PyGetNext, 1},
|
||||
{ "FetchBlock", PyFetchBlock, 1},
|
||||
{ "fetchBlock", PyFetchBlock, 1},
|
||||
{NULL}
|
||||
};
|
||||
343
mozilla/extensions/python/xpcom/src/PyISupports.cpp
Normal file
343
mozilla/extensions/python/xpcom/src/PyISupports.cpp
Normal file
@@ -0,0 +1,343 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
|
||||
static PRInt32 cInterfaces=0;
|
||||
static PyObject *g_obFuncMakeInterfaceCount = NULL; // XXX - never released!!!
|
||||
|
||||
PRInt32
|
||||
_PyXPCOM_GetInterfaceCount(void)
|
||||
{
|
||||
return cInterfaces;
|
||||
}
|
||||
|
||||
Py_nsISupports::Py_nsISupports(nsISupports *punk, const nsIID &iid, PyTypeObject *this_type)
|
||||
{
|
||||
ob_type = this_type;
|
||||
m_obj = punk;
|
||||
m_iid = iid;
|
||||
// refcnt of object managed by caller.
|
||||
PR_AtomicIncrement(&cInterfaces);
|
||||
PyXPCOM_DLLAddRef();
|
||||
_Py_NewReference(this);
|
||||
}
|
||||
|
||||
Py_nsISupports::~Py_nsISupports()
|
||||
{
|
||||
SafeRelease(this);
|
||||
PR_AtomicDecrement(&cInterfaces);
|
||||
PyXPCOM_DLLRelease();
|
||||
}
|
||||
|
||||
/*static*/ nsISupports *
|
||||
Py_nsISupports::GetI(PyObject *self, nsIID *ret_iid)
|
||||
{
|
||||
if (self==NULL) {
|
||||
PyErr_SetString(PyExc_ValueError, "The Python object is invalid");
|
||||
return NULL;
|
||||
}
|
||||
Py_nsISupports *pis = (Py_nsISupports *)self;
|
||||
if (pis->m_obj==NULL) {
|
||||
// This should never be able to happen.
|
||||
PyErr_SetString(PyExc_ValueError, "Internal Error - The XPCOM object has been released.");
|
||||
return NULL;
|
||||
}
|
||||
if (ret_iid)
|
||||
*ret_iid = pis->m_iid;
|
||||
return pis->m_obj;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
Py_nsISupports::SafeRelease(Py_nsISupports *ob)
|
||||
{
|
||||
if (!ob)
|
||||
return;
|
||||
if (ob->m_obj)
|
||||
{
|
||||
long rcnt;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
rcnt = ob->m_obj->Release();
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
#ifdef _DEBUG_LIFETIMES
|
||||
LogF(buf, " SafeRelease(%ld) -> %s at 0x%0lx, nsISupports at 0x%0lx - Release() returned %ld",GetCurrentThreadId(), ob->ob_type->tp_name,ob, ob->m_obj,rcnt);
|
||||
#endif
|
||||
ob->m_obj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ Py_nsISupports *
|
||||
Py_nsISupports::Constructor(nsISupports *pInitObj, const nsIID &iid)
|
||||
{
|
||||
return new Py_nsISupports(pInitObj,
|
||||
iid,
|
||||
type);
|
||||
}
|
||||
|
||||
/*static*/PRBool
|
||||
Py_nsISupports::InterfaceFromPyObject(PyObject *ob,
|
||||
const nsIID &iid,
|
||||
nsISupports **ppv,
|
||||
PRBool bNoneOK,
|
||||
PRBool bTryAutoWrap /* = PR_TRUE */)
|
||||
{
|
||||
if ( ob == NULL )
|
||||
{
|
||||
// don't overwrite an error message
|
||||
if ( !PyErr_Occurred() )
|
||||
PyErr_SetString(PyExc_TypeError, "The Python object is invalid");
|
||||
return PR_FALSE;
|
||||
}
|
||||
if ( ob == Py_None )
|
||||
{
|
||||
if ( bNoneOK )
|
||||
{
|
||||
*ppv = NULL;
|
||||
return PR_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "None is not a invalid interface object in this context");
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (PyInstance_Check(ob)) {
|
||||
// Get the _comobj_ attribute
|
||||
PyObject *use_ob = PyObject_GetAttrString(ob, "_comobj_");
|
||||
if (use_ob==NULL) {
|
||||
PyErr_Clear();
|
||||
if (bTryAutoWrap)
|
||||
// Try and auto-wrap it - errors will leave Py exception set,
|
||||
return PyXPCOM_XPTStub::AutoWrapPythonInstance(ob, iid, ppv);
|
||||
PyErr_SetString(PyExc_TypeError, "The Python instance can not be converted to an XP COM object");
|
||||
return PR_FALSE;
|
||||
} else
|
||||
ob = use_ob;
|
||||
|
||||
} else {
|
||||
Py_XINCREF(ob);
|
||||
}
|
||||
|
||||
nsISupports *pis;
|
||||
PRBool rc = PR_FALSE;
|
||||
if ( !Check(ob) )
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be used as COM objects", ob->ob_type->tp_name);
|
||||
goto done;
|
||||
}
|
||||
nsIID already_iid;
|
||||
pis = GetI(ob, &already_iid);
|
||||
if ( !pis )
|
||||
goto done; /* exception was set by GetI() */
|
||||
/* note: we don't (yet) explicitly hold a reference to pis */
|
||||
if (iid.Equals(Py_nsIID_NULL)) {
|
||||
// a bit of a hack - we are asking for the arbitary interface
|
||||
// wrapped by this object, not some other specific interface -
|
||||
// so no QI, just an AddRef();
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
pis->AddRef();
|
||||
Py_END_ALLOW_THREADS
|
||||
*ppv = pis;
|
||||
} else {
|
||||
// specific interface requested - if it is not already the
|
||||
// specific interface, QI for it and discard pis.
|
||||
if (iid.Equals(already_iid)) {
|
||||
*ppv = pis;
|
||||
pis->AddRef();
|
||||
} else {
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
r = pis->QueryInterface(iid, (void **)ppv);
|
||||
Py_END_ALLOW_THREADS
|
||||
if ( NS_FAILED(r) )
|
||||
{
|
||||
PyXPCOM_BuildPyException(r);
|
||||
goto done;
|
||||
}
|
||||
/* note: the QI added a ref for the return value */
|
||||
}
|
||||
}
|
||||
|
||||
rc = PR_TRUE;
|
||||
done:
|
||||
Py_XDECREF(ob);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Interface conversions
|
||||
/*static*/void
|
||||
Py_nsISupports::RegisterInterface( const nsIID &iid, PyTypeObject *t)
|
||||
{
|
||||
if (mapIIDToType==NULL)
|
||||
mapIIDToType = PyDict_New();
|
||||
|
||||
if (mapIIDToType) {
|
||||
PyObject *key = Py_nsIID::PyObjectFromIID(iid);
|
||||
if (key)
|
||||
PyDict_SetItem(mapIIDToType, key, (PyObject *)t);
|
||||
Py_XDECREF(key);
|
||||
}
|
||||
}
|
||||
|
||||
/*static */PyObject *
|
||||
Py_nsISupports::PyObjectFromInterface(nsISupports *pis,
|
||||
const nsIID &riid,
|
||||
PRBool bAddRef,
|
||||
PRBool bMakeNicePyObject /* = PR_TRUE */)
|
||||
{
|
||||
// Quick exit.
|
||||
if (pis==NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
PyTypeObject *createType = NULL;
|
||||
// If the IID is for nsISupports, dont bother with
|
||||
// a map lookup as we know the type!
|
||||
if (!riid.Equals(NS_GET_IID(nsISupports))) {
|
||||
|
||||
// Look up the map
|
||||
PyObject *obiid = Py_nsIID::PyObjectFromIID(riid);
|
||||
if (!obiid) return NULL;
|
||||
|
||||
if (mapIIDToType != NULL)
|
||||
createType = (PyTypeObject *)PyDict_GetItem(mapIIDToType, obiid);
|
||||
Py_DECREF(obiid);
|
||||
}
|
||||
if (createType==NULL)
|
||||
createType = Py_nsISupports::type;
|
||||
// Check it is indeed one of our types.
|
||||
if (!PyXPCOM_TypeObject::IsType(createType)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "The type map is invalid");
|
||||
return NULL;
|
||||
}
|
||||
// we can now safely cast the thing to a PyComTypeObject and use it
|
||||
PyXPCOM_TypeObject *myCreateType = (PyXPCOM_TypeObject *)createType;
|
||||
if (myCreateType->ctor==NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "The type does not declare a PyCom constructor");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_nsISupports *ret = (*myCreateType->ctor)(pis, riid);
|
||||
#ifdef _DEBUG_LIFETIMES
|
||||
PyXPCOM_LogF("XPCOM Object created at 0x%0xld, nsISupports at 0x%0xld",
|
||||
ret, ret->m_obj);
|
||||
#endif
|
||||
if (ret && bAddRef && pis) pis->AddRef();
|
||||
if (ret && bMakeNicePyObject)
|
||||
return MakeInterfaceResult(ret, riid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Call back into Python, passing a raw nsIInterface object, getting back
|
||||
// the object to actually pass to Python.
|
||||
PyObject *
|
||||
Py_nsISupports::MakeInterfaceResult(PyObject *pyis,
|
||||
const nsIID &iid)
|
||||
{
|
||||
NS_PRECONDITION(pyis, "NULL pyobject!");
|
||||
PyObject *obIID = NULL;
|
||||
PyObject *args = NULL;
|
||||
PyObject *func = NULL;
|
||||
PyObject *mod = NULL;
|
||||
PyObject *ret = NULL;
|
||||
|
||||
obIID = Py_nsIID::PyObjectFromIID(iid);
|
||||
if (obIID==NULL)
|
||||
goto done;
|
||||
|
||||
if (g_obFuncMakeInterfaceCount==NULL) {
|
||||
PyObject *mod = PyImport_ImportModule("xpcom.client");
|
||||
if (mod)
|
||||
g_obFuncMakeInterfaceCount = PyObject_GetAttrString(mod, "MakeInterfaceResult");
|
||||
Py_XDECREF(mod);
|
||||
}
|
||||
if (g_obFuncMakeInterfaceCount==NULL) goto done;
|
||||
|
||||
args = Py_BuildValue("OO", pyis, obIID);
|
||||
if (args==NULL) goto done;
|
||||
ret = PyEval_CallObject(g_obFuncMakeInterfaceCount, args);
|
||||
done:
|
||||
if (PyErr_Occurred()) {
|
||||
NS_ABORT_IF_FALSE(ret==NULL, "Have an error, but also a return val!");
|
||||
PyXPCOM_LogError("Creating an interface object to be used as a parameter failed\n");
|
||||
PyErr_Clear();
|
||||
}
|
||||
Py_XDECREF(mod);
|
||||
Py_XDECREF(args);
|
||||
Py_XDECREF(obIID);
|
||||
if (ret==NULL) // eek - error - return the original with no refcount mod.
|
||||
ret = pyis;
|
||||
else
|
||||
// no error - decref the old object
|
||||
Py_DECREF(pyis);
|
||||
// return our obISupports. If NULL, we are really hosed and nothing we can do.
|
||||
return ret;
|
||||
}
|
||||
|
||||
// @pymethod <o Py_nsISupports>|Py_nsISupports|QueryInterface|Queries an object for a specific interface.
|
||||
PyObject *
|
||||
Py_nsISupports::QueryInterface(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obiid;
|
||||
int bWrap = 1;
|
||||
// @pyparm IID|iid||The IID requested.
|
||||
// @rdesc The result is always a <o Py_nsISupports> object.
|
||||
// Any error (including E_NOINTERFACE) will generate a <o com_error> exception.
|
||||
if (!PyArg_ParseTuple(args, "O|i:QueryInterface", &obiid, &bWrap))
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obiid, &iid))
|
||||
return NULL;
|
||||
|
||||
nsISupports *pMyIS = GetI(self);
|
||||
if (pMyIS==NULL) return NULL;
|
||||
|
||||
nsISupports *pis;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pMyIS->QueryInterface(iid, (void **)&pis);
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
/* Note that this failure may include E_NOINTERFACE */
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
return PyObjectFromInterface(pis, iid, PR_FALSE, (PRBool)bWrap);
|
||||
}
|
||||
|
||||
|
||||
// @object Py_nsISupports|The base object for all PythonCOM objects. Wraps a COM nsISupports interface.
|
||||
/*static*/ struct PyMethodDef
|
||||
Py_nsISupports::methods[] =
|
||||
{
|
||||
{ "queryInterface", Py_nsISupports::QueryInterface, 1, "Queries the object for an interface."},
|
||||
{ "QueryInterface", Py_nsISupports::QueryInterface, 1, "An alias for queryInterface."},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
/*static*/void Py_nsISupports::InitType(void)
|
||||
{
|
||||
type = new PyXPCOM_TypeObject(
|
||||
"nsISupports",
|
||||
NULL,
|
||||
sizeof(Py_nsISupports),
|
||||
methods,
|
||||
Constructor);
|
||||
}
|
||||
|
||||
PyXPCOM_TypeObject *Py_nsISupports::type = NULL;
|
||||
PyObject *Py_nsISupports::mapIIDToType = NULL;
|
||||
557
mozilla/extensions/python/xpcom/src/PyXPCOM.h
Normal file
557
mozilla/extensions/python/xpcom/src/PyXPCOM.h
Normal file
@@ -0,0 +1,557 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// PyXPCOM.h - the main header file for the Python XPCOM support.
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#ifndef __PYXPCOM_H__
|
||||
#define __PYXPCOM_H__
|
||||
|
||||
#ifdef XP_WIN
|
||||
# ifdef BUILD_PYXPCOM
|
||||
/* We are building the main dll */
|
||||
# define PYXPCOM_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
/* This module uses the dll */
|
||||
# define PYXPCOM_EXPORT __declspec(dllimport)
|
||||
# endif // BUILD_PYXPCOM
|
||||
|
||||
// We need these libs!
|
||||
# pragma comment(lib, "xpcom.lib")
|
||||
# pragma comment(lib, "nspr4.lib")
|
||||
|
||||
#else // XP_WIN
|
||||
# define PYXPCOM_EXPORT
|
||||
#endif // XP_WIN
|
||||
|
||||
|
||||
// An IID we treat as NULL when passing as a reference.
|
||||
extern nsIID Py_nsIID_NULL;
|
||||
|
||||
/*************************************************************************
|
||||
**************************************************************************
|
||||
|
||||
Error and exception related function.
|
||||
|
||||
**************************************************************************
|
||||
*************************************************************************/
|
||||
|
||||
// The exception object (loaded from the xpcom .py code)
|
||||
extern PYXPCOM_EXPORT PyObject *PyXPCOM_Error;
|
||||
|
||||
// Client related functions - generally called by interfaces before
|
||||
// they return NULL back to Python to indicate the error.
|
||||
// All these functions return NULL so interfaces can generally
|
||||
// just "return PyXPCOM_BuildPyException(hr, punk, IID_IWhatever)"
|
||||
PYXPCOM_EXPORT PyObject *PyXPCOM_BuildPyException(nsresult res);
|
||||
|
||||
// Used in gateways to handle the current Python exception
|
||||
// NOTE: this function assumes it is operating within the Python context
|
||||
PYXPCOM_EXPORT nsresult PyXPCOM_SetCOMErrorFromPyException();
|
||||
|
||||
// A couple of logging/error functions. These probably end up
|
||||
// being written to the console service.
|
||||
|
||||
// Log a warning for the user - something at runtime
|
||||
// they may care about, but nothing that prevents us actually
|
||||
// working.
|
||||
// As it's designed for user error/warning, it exists in non-debug builds.
|
||||
PYXPCOM_EXPORT void PyXPCOM_LogWarning(const char *fmt, ...);
|
||||
|
||||
// Log an error for the user - something that _has_ prevented
|
||||
// us working. This is probably accompanied by a traceback.
|
||||
// As it's designed for user error/warning, it exists in non-debug builds.
|
||||
PYXPCOM_EXPORT void PyXPCOM_LogError(const char *fmt, ...);
|
||||
|
||||
#ifdef DEBUG
|
||||
// Mainly designed for developers of the XPCOM package.
|
||||
// Only enabled in debug builds.
|
||||
PYXPCOM_EXPORT void PyXPCOM_LogDebug(const char *fmt, ...);
|
||||
#define PYXPCOM_LOG_DEBUG PyXPCOM_LogDebug
|
||||
#else
|
||||
#define PYXPCOM_LOG_DEBUG()
|
||||
#endif // DEBUG
|
||||
|
||||
/*************************************************************************
|
||||
**************************************************************************
|
||||
|
||||
Support for CALLING (ie, using) interfaces.
|
||||
|
||||
**************************************************************************
|
||||
*************************************************************************/
|
||||
|
||||
class Py_nsISupports;
|
||||
|
||||
typedef Py_nsISupports* (* PyXPCOM_I_CTOR)(nsISupports *, const nsIID &);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// class PyXPCOM_TypeObject
|
||||
// Base class for (most of) the type objects.
|
||||
|
||||
class PYXPCOM_EXPORT PyXPCOM_TypeObject : public PyTypeObject {
|
||||
public:
|
||||
PyXPCOM_TypeObject(
|
||||
const char *name,
|
||||
PyXPCOM_TypeObject *pBaseType,
|
||||
int typeSize,
|
||||
struct PyMethodDef* methodList,
|
||||
PyXPCOM_I_CTOR ctor);
|
||||
~PyXPCOM_TypeObject();
|
||||
|
||||
PyMethodChain chain;
|
||||
PyXPCOM_TypeObject *baseType;
|
||||
PyXPCOM_I_CTOR ctor;
|
||||
|
||||
static PRBool IsType(PyTypeObject *t);
|
||||
// Static methods for the Python type.
|
||||
static void Py_dealloc(PyObject *ob);
|
||||
static PyObject *Py_repr(PyObject *ob);
|
||||
static PyObject *Py_str(PyObject *ob);
|
||||
static PyObject *Py_getattr(PyObject *self, char *name);
|
||||
static int Py_setattr(PyObject *op, char *name, PyObject *v);
|
||||
static int Py_cmp(PyObject *ob1, PyObject *ob2);
|
||||
static long Py_hash(PyObject *self);
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// class Py_nsISupports
|
||||
// This class serves 2 purposes:
|
||||
// * It is a base class for other interfaces we support "natively"
|
||||
// * It is instantiated for _all_ other interfaces.
|
||||
//
|
||||
// This is different than win32com, where a PyIUnknown only
|
||||
// ever holds an IUnknown - but here, we could be holding
|
||||
// _any_ interface.
|
||||
class PYXPCOM_EXPORT Py_nsISupports : public PyObject
|
||||
{
|
||||
public:
|
||||
static PRBool Check( PyObject *ob, const nsIID &checkIID = Py_nsIID_NULL) {
|
||||
Py_nsISupports *self = static_cast<Py_nsISupports *>(ob);
|
||||
if (ob==NULL || !PyXPCOM_TypeObject::IsType(ob->ob_type ))
|
||||
return PR_FALSE;
|
||||
if (!checkIID.Equals(Py_nsIID_NULL))
|
||||
return self->m_iid.Equals(checkIID) != 0;
|
||||
return PR_TRUE;
|
||||
}
|
||||
// Get the nsISupports interface from the PyObject WITH NO REF COUNT ADDED
|
||||
static nsISupports *GetI(PyObject *self, nsIID *ret_iid = NULL);
|
||||
nsISupports *m_obj;
|
||||
nsIID m_iid;
|
||||
|
||||
// Given an nsISupports and an Interface ID, create and return an object
|
||||
// Does not QI the object - the caller must ensure the nsISupports object
|
||||
// is really a pointer to an object identified by the IID.
|
||||
// PRBool bAddRef indicates if a COM reference count should be added to the interface.
|
||||
// This depends purely on the context in which it is called. If the interface is obtained
|
||||
// from a function that creates a new ref (eg, ???) then you should use
|
||||
// FALSE. If you receive the pointer as (eg) a param to a gateway function, then
|
||||
// you normally need to pass TRUE, as this is truly a new reference.
|
||||
// *** ALWAYS take the time to get this right. ***
|
||||
// PRBool bMakeNicePyObject indicates if we should call back into
|
||||
// Python to wrap the object. This allows Python code to
|
||||
// see the correct xpcom.client.Interface object even when calling
|
||||
// xpcom function directly.
|
||||
static PyObject *PyObjectFromInterface(nsISupports *ps,
|
||||
const nsIID &iid,
|
||||
PRBool bAddRef,
|
||||
PRBool bMakeNicePyObject = PR_TRUE);
|
||||
|
||||
// Given a Python object that is a registered COM type, return a given
|
||||
// interface pointer on its underlying object, with a NEW REFERENCE ADDED.
|
||||
// bTryAutoWrap indicates if a Python instance object should attempt to
|
||||
// be automatically wrapped in an XPCOM object. This is really only
|
||||
// provided to stop accidental recursion should the object returned by
|
||||
// the wrap process itself be in instance (where it should already be
|
||||
// a COM object.
|
||||
static PRBool InterfaceFromPyObject(
|
||||
PyObject *ob,
|
||||
const nsIID &iid,
|
||||
nsISupports **ppret,
|
||||
PRBool bNoneOK,
|
||||
PRBool bTryAutoWrap = PR_TRUE);
|
||||
|
||||
static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid);
|
||||
// The Python methods
|
||||
static PyObject *QueryInterface(PyObject *self, PyObject *args);
|
||||
|
||||
// Internal (sort-of) objects.
|
||||
static PyXPCOM_TypeObject *type;
|
||||
static PyMethodDef methods[];
|
||||
static PyObject *mapIIDToType;
|
||||
static void SafeRelease(Py_nsISupports *ob);
|
||||
static void RegisterInterface( const nsIID &iid, PyTypeObject *t);
|
||||
static void InitType();
|
||||
|
||||
~Py_nsISupports();
|
||||
protected:
|
||||
// ctor is protected - must create objects via
|
||||
// PyObjectFromInterface()
|
||||
Py_nsISupports(nsISupports *p,
|
||||
const nsIID &iid,
|
||||
PyTypeObject *type);
|
||||
|
||||
static PyObject *MakeInterfaceResult(PyObject *pyis, const nsIID &iid);
|
||||
|
||||
};
|
||||
|
||||
// Python/XPCOM IID support
|
||||
class PYXPCOM_EXPORT Py_nsIID : public PyObject
|
||||
{
|
||||
public:
|
||||
Py_nsIID(const nsIID &riid);
|
||||
nsIID m_iid;
|
||||
|
||||
PRBool
|
||||
IsEqual(const nsIID &riid) {
|
||||
return m_iid.Equals(riid);
|
||||
}
|
||||
|
||||
PRBool
|
||||
IsEqual(PyObject *ob) {
|
||||
return ob &&
|
||||
ob->ob_type== &type &&
|
||||
m_iid.Equals(((Py_nsIID *)ob)->m_iid);
|
||||
}
|
||||
|
||||
PRBool
|
||||
IsEqual(Py_nsIID &iid) {
|
||||
return m_iid.Equals(iid.m_iid);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyObjectFromIID(const nsIID &iid) {
|
||||
return new Py_nsIID(iid);
|
||||
}
|
||||
|
||||
static PRBool IIDFromPyObject(PyObject *ob, nsIID *pRet);
|
||||
/* Python support */
|
||||
static PyObject *PyTypeMethod_getattr(PyObject *self, char *name);
|
||||
static int PyTypeMethod_compare(PyObject *self, PyObject *ob);
|
||||
static PyObject *PyTypeMethod_repr(PyObject *self);
|
||||
static long PyTypeMethod_hash(PyObject *self);
|
||||
static PyObject *PyTypeMethod_str(PyObject *self);
|
||||
static void PyTypeMethod_dealloc(PyObject *self);
|
||||
static PyTypeObject type;
|
||||
static PyMethodDef methods[];
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// Helper classes for managing arrays of variants.
|
||||
class PythonTypeDescriptor; // Forward declare.
|
||||
|
||||
class PYXPCOM_EXPORT PyXPCOM_InterfaceVariantHelper {
|
||||
public:
|
||||
PyXPCOM_InterfaceVariantHelper();
|
||||
~PyXPCOM_InterfaceVariantHelper();
|
||||
PRBool Init(PyObject *obParams);
|
||||
PRBool FillArray();
|
||||
|
||||
PyObject *MakePythonResult();
|
||||
|
||||
nsXPTCVariant *m_var_array;
|
||||
int m_num_array;
|
||||
protected:
|
||||
PyObject *MakeSinglePythonResult(int index);
|
||||
PRBool FillInVariant(const PythonTypeDescriptor &, int, int);
|
||||
PRBool PrepareOutVariant(const PythonTypeDescriptor &td, int value_index);
|
||||
PRBool SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size);
|
||||
PRUint32 GetSizeIs( int var_index, PRBool is_arg1);
|
||||
|
||||
PyObject *m_pyparams; // sequence of actual params passed (ie, not including hidden)
|
||||
PyObject *m_typedescs; // desc of _all_ params, including hidden.
|
||||
PythonTypeDescriptor *m_python_type_desc_array;
|
||||
void **m_buffer_array;
|
||||
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
**************************************************************************
|
||||
|
||||
Support for IMPLEMENTING interfaces.
|
||||
|
||||
**************************************************************************
|
||||
*************************************************************************/
|
||||
#define NS_IINTERNALPYTHON_IID_STR "AC7459FC-E8AB-4f2e-9C4F-ADDC53393A20"
|
||||
#define NS_IINTERNALPYTHON_IID \
|
||||
{ 0xac7459fc, 0xe8ab, 0x4f2e, { 0x9c, 0x4f, 0xad, 0xdc, 0x53, 0x39, 0x3a, 0x20 } }
|
||||
|
||||
class PyXPCOM_GatewayWeakReference;
|
||||
|
||||
// This interface is needed primarily to give us a known vtable base.
|
||||
// If we QI a Python object for this interface, we can safely cast the result
|
||||
// to a PyG_Base. Any other interface, we do now know which vtable we will get.
|
||||
// Later, we may get some internal functions
|
||||
// (eg, win32com allows us to get the underlying Python object, but
|
||||
// we should try and avoid that if possible.
|
||||
class nsIInternalPython : public nsISupports {
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IINTERNALPYTHON_IID)
|
||||
};
|
||||
|
||||
// This is roughly equivilent to PyGatewayBase in win32com
|
||||
//
|
||||
class PYXPCOM_EXPORT PyG_Base : public nsIInternalPython, public nsISupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISUPPORTSWEAKREFERENCE
|
||||
|
||||
// A static "constructor" - the real ctor is protected.
|
||||
static nsresult CreateNew(PyObject *pPyInstance,
|
||||
const nsIID &iid,
|
||||
void **ppResult);
|
||||
|
||||
// A utility to auto-wrap an arbitary Python instance
|
||||
// in a COM gateway.
|
||||
static PRBool AutoWrapPythonInstance(PyObject *ob,
|
||||
const nsIID &iid,
|
||||
nsISupports **ppret);
|
||||
|
||||
|
||||
// A helper that creates objects to be passed for nsISupports
|
||||
// objects. See extensive comments in PyG_Base.cpp.
|
||||
PyObject *MakeInterfaceParam(nsISupports *pis,
|
||||
const nsIID *piid,
|
||||
int methodIndex = -1,
|
||||
const XPTParamDescriptor *d = NULL,
|
||||
int paramIndex = -1);
|
||||
|
||||
// A helper that ensures all casting and vtable offsetting etc
|
||||
// done against this object happens in the one spot!
|
||||
virtual void *ThisAsIID( const nsIID &iid ) = 0;
|
||||
|
||||
// Helpers for "native" interfaces.
|
||||
// Not used by the generic stub interface.
|
||||
nsresult HandleNativeGatewayError(const char *szMethodName);
|
||||
// These data members used by the converter helper functions - hence public
|
||||
nsIID m_iid;
|
||||
PyObject * m_pPyObject;
|
||||
// We keep a reference count on this object, and the object
|
||||
// itself uses normal refcount rules - thus, it will only
|
||||
// die when we die, and all external references are removed.
|
||||
// This means that once we have created it (and while we
|
||||
// are alive) it will never die.
|
||||
nsCOMPtr<nsIWeakReference> m_pWeakRef;
|
||||
protected:
|
||||
PyG_Base(PyObject *instance, const nsIID &iid);
|
||||
virtual ~PyG_Base();
|
||||
PyG_Base *m_pBaseObject; // A chain to implement identity rules.
|
||||
nsresult InvokeNativeViaPolicy( const char *szMethodName,
|
||||
PyObject **ppResult = NULL,
|
||||
const char *szFormat = NULL,
|
||||
...
|
||||
);
|
||||
nsresult InvokeNativeViaPolicyInternal( const char *szMethodName,
|
||||
PyObject **ppResult,
|
||||
const char *szFormat,
|
||||
va_list va);
|
||||
nsresult InvokeNativeGetViaPolicy(const char *szPropertyName,
|
||||
PyObject **ppResult = NULL
|
||||
);
|
||||
nsresult InvokeNativeSetViaPolicy(const char *szPropertyName,
|
||||
...);
|
||||
};
|
||||
|
||||
class PYXPCOM_EXPORT PyXPCOM_XPTStub : public PyG_Base, public nsXPTCStubBase
|
||||
{
|
||||
friend class PyG_Base;
|
||||
public:
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) \
|
||||
{return PyG_Base::QueryInterface(aIID, aInstancePtr);} \
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void) {return PyG_Base::AddRef();} \
|
||||
NS_IMETHOD_(nsrefcnt) Release(void) {return PyG_Base::Release();} \
|
||||
|
||||
NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info);
|
||||
// call this method and return result
|
||||
NS_IMETHOD CallMethod(PRUint16 methodIndex,
|
||||
const nsXPTMethodInfo* info,
|
||||
nsXPTCMiniVariant* params);
|
||||
|
||||
virtual void *ThisAsIID(const nsIID &iid);
|
||||
protected:
|
||||
PyXPCOM_XPTStub(PyObject *instance, const nsIID &iid) : PyG_Base(instance, iid) {;}
|
||||
private:
|
||||
};
|
||||
|
||||
// For the Gateways me manually implement.
|
||||
#define PYGATEWAY_BASE_SUPPORT(INTERFACE, GATEWAY_BASE) \
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) \
|
||||
{return PyG_Base::QueryInterface(aIID, aInstancePtr);} \
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void) {return PyG_Base::AddRef();} \
|
||||
NS_IMETHOD_(nsrefcnt) Release(void) {return PyG_Base::Release();} \
|
||||
virtual void *ThisAsIID(const nsIID &iid) { \
|
||||
if (iid.Equals(NS_GET_IID(INTERFACE))) return (INTERFACE *)this; \
|
||||
return GATEWAY_BASE::ThisAsIID(iid); \
|
||||
} \
|
||||
|
||||
|
||||
// Weak Reference class. This is a true COM object, representing
|
||||
// a weak reference to a Python object. For each Python XPCOM object,
|
||||
// there is exactly zero or one corresponding weak reference instance.
|
||||
// When both are alive, each holds a pointer to the other. When the main
|
||||
// object dies due to XPCOM reference counting, it zaps the pointer
|
||||
// in its corresponding weak reference object. Thus, the weak-reference
|
||||
// can live beyond the object (possibly with a NULL pointer back to the
|
||||
// "real" object, but as implemented, the weak reference will never be
|
||||
// destroyed before the object
|
||||
class PYXPCOM_EXPORT PyXPCOM_GatewayWeakReference : public nsIWeakReference {
|
||||
public:
|
||||
PyXPCOM_GatewayWeakReference(PyG_Base *base);
|
||||
~PyXPCOM_GatewayWeakReference();
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEAKREFERENCE;
|
||||
PyG_Base *m_pBase; // NO REF COUNT!!!
|
||||
};
|
||||
|
||||
|
||||
// Helpers classes for our gateways.
|
||||
class PYXPCOM_EXPORT PyXPCOM_GatewayVariantHelper
|
||||
{
|
||||
public:
|
||||
PyXPCOM_GatewayVariantHelper( PyG_Base *gateway,
|
||||
int methodIndex,
|
||||
const nsXPTMethodInfo *info,
|
||||
nsXPTCMiniVariant* params );
|
||||
~PyXPCOM_GatewayVariantHelper();
|
||||
PyObject *MakePyArgs();
|
||||
nsresult ProcessPythonResult(PyObject *ob);
|
||||
PyG_Base *m_gateway;
|
||||
private:
|
||||
nsresult BackFillVariant( PyObject *ob, int index);
|
||||
PyObject *MakeSingleParam(int index, PythonTypeDescriptor &td);
|
||||
PRBool GetIIDForINTERFACE_ID(int index, const nsIID **ppret);
|
||||
nsresult GetArrayType(PRUint8 index, PRUint8 *ret);
|
||||
PRUint32 GetSizeIs( int var_index, PRBool is_arg1);
|
||||
PRBool SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size);
|
||||
PRBool CanSetSizeIs( int var_index, PRBool is_arg1 );
|
||||
|
||||
|
||||
nsXPTCMiniVariant* m_params;
|
||||
const nsXPTMethodInfo *m_info;
|
||||
int m_method_index;
|
||||
PythonTypeDescriptor *m_python_type_desc_array;
|
||||
int m_num_type_descs;
|
||||
|
||||
};
|
||||
|
||||
// Misc converters.
|
||||
PyObject *PyObject_FromXPTTypeDescriptor( const XPTTypeDescriptor *d);
|
||||
PyObject *PyObject_FromXPTParamDescriptor( const XPTParamDescriptor *d);
|
||||
PyObject *PyObject_FromXPTMethodDescriptor( const XPTMethodDescriptor *d);
|
||||
PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *d);
|
||||
|
||||
|
||||
// DLL reference counting functions.
|
||||
// Although we maintain the count, we never actually
|
||||
// finalize Python when it hits zero!
|
||||
void PyXPCOM_DLLAddRef();
|
||||
void PyXPCOM_DLLRelease();
|
||||
|
||||
/*************************************************************************
|
||||
**************************************************************************
|
||||
|
||||
LOCKING AND THREADING
|
||||
|
||||
**************************************************************************
|
||||
*************************************************************************/
|
||||
|
||||
//
|
||||
// We have 2 discrete locks in use (when no free-threaded is used, anyway).
|
||||
// The first type of lock is the global Python lock. This is the standard lock
|
||||
// in use by Python, and must be used as documented by Python. Specifically, no
|
||||
// 2 threads may _ever_ call _any_ Python code (including INCREF/DECREF) without
|
||||
// first having this thread lock.
|
||||
//
|
||||
// The second type of lock is a "global framework lock", and used whenever 2 threads
|
||||
// of C code need access to global data. This is different than the Python
|
||||
// lock - this lock is used when no Python code can ever be called by the
|
||||
// threads, but the C code still needs thread-safety.
|
||||
|
||||
// We also supply helper classes which make the usage of these locks a one-liner.
|
||||
|
||||
// The "framework" lock, implemented as a PRLock
|
||||
PYXPCOM_EXPORT void PyXPCOM_AcquireGlobalLock(void);
|
||||
PYXPCOM_EXPORT void PyXPCOM_ReleaseGlobalLock(void);
|
||||
|
||||
// Helper class for the DLL global lock.
|
||||
//
|
||||
// This class magically waits for PyXPCOM framework global lock, and releases it
|
||||
// when finished.
|
||||
// NEVER new one of these objects - only use on the stack!
|
||||
class CEnterLeaveXPCOMFramework {
|
||||
public:
|
||||
CEnterLeaveXPCOMFramework() {PyXPCOM_AcquireGlobalLock();}
|
||||
~CEnterLeaveXPCOMFramework() {PyXPCOM_ReleaseGlobalLock();}
|
||||
};
|
||||
|
||||
// Python thread-lock stuff. Free-threading patches use different semantics, but
|
||||
// these are abstracted away here...
|
||||
//#include <threadstate.h>
|
||||
|
||||
// Helper class for Enter/Leave Python
|
||||
//
|
||||
// This class magically waits for the Python global lock, and releases it
|
||||
// when finished.
|
||||
|
||||
// Nested invocations will deadlock, so be careful.
|
||||
|
||||
// NEVER new one of these objects - only use on the stack!
|
||||
|
||||
extern PYXPCOM_EXPORT PyInterpreterState *PyXPCOM_InterpreterState;
|
||||
extern PYXPCOM_EXPORT PRBool PyXPCOM_ThreadState_Ensure();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_ThreadState_Free();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_ThreadState_Clear();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Acquire();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Release();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_MakePendingCalls();
|
||||
|
||||
extern PYXPCOM_EXPORT PRBool PyXPCOM_Globals_Ensure();
|
||||
|
||||
class CEnterLeavePython {
|
||||
public:
|
||||
CEnterLeavePython() {
|
||||
created = PyXPCOM_ThreadState_Ensure();
|
||||
PyXPCOM_InterpreterLock_Acquire();
|
||||
if (created) {
|
||||
// If pending python calls are waiting as we enter Python,
|
||||
// it will generally mean an asynch signal handler, etc.
|
||||
// We can either call it here, or wait for Python to call it
|
||||
// as part of its "even 'n' opcodes" check. If we wait for
|
||||
// Python to check it and the pending call raises an exception,
|
||||
// then it is _our_ code that will fail - this is unfair,
|
||||
// as the signal was raised before we were entered - indeed,
|
||||
// we may be directly responding to the signal!
|
||||
// Thus, we flush all the pending calls here, and report any
|
||||
// exceptions via our normal exception reporting mechanism.
|
||||
// We can then execute our code in the knowledge that only
|
||||
// signals raised _while_ we are executing will cause exceptions.
|
||||
PyXPCOM_MakePendingCalls();
|
||||
}
|
||||
}
|
||||
~CEnterLeavePython() {
|
||||
// The interpreter state must be cleared
|
||||
// _before_ we release the lock, as some of
|
||||
// the sys. attributes cleared (eg, the current exception)
|
||||
// may need the lock to invoke their destructors -
|
||||
// specifically, when exc_value is a class instance, and
|
||||
// the exception holds the last reference!
|
||||
if ( created )
|
||||
PyXPCOM_ThreadState_Clear();
|
||||
PyXPCOM_InterpreterLock_Release();
|
||||
if ( created )
|
||||
PyXPCOM_ThreadState_Free();
|
||||
}
|
||||
private:
|
||||
PRBool created;
|
||||
};
|
||||
|
||||
#endif // __PYXPCOM_H__
|
||||
49
mozilla/extensions/python/xpcom/src/PyXPCOM_std.h
Normal file
49
mozilla/extensions/python/xpcom/src/PyXPCOM_std.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// standard include - sets up all the defines used by
|
||||
// the mozilla make process - too lazy to work out how to integrate
|
||||
// with their make, so this will do!
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
// Main Mozilla cross-platform declarations.
|
||||
#include "xp_core.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
# ifndef DEBUG
|
||||
# define DEBUG
|
||||
# endif
|
||||
|
||||
# define DEVELOPER_DEBUG
|
||||
# define NS_DEBUG
|
||||
# define DEBUG_markh
|
||||
#endif // DEBUG
|
||||
|
||||
#include <nsIAllocator.h>
|
||||
#include <nsIWeakReference.h>
|
||||
#include <nsXPIDLString.h>
|
||||
#include <nsCRT.h>
|
||||
#include <xptcall.h>
|
||||
#include <xpt_xdr.h>
|
||||
|
||||
// This header is considered internal - hence
|
||||
// we can use it to trigger "exports"
|
||||
#define BUILD_PYXPCOM
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
// Mozilla also defines this - we undefine it to
|
||||
// prevent a compiler warning.
|
||||
# undef HAVE_LONG_LONG
|
||||
#endif // HAVE_LONG_LONG
|
||||
|
||||
#include "Python.h"
|
||||
#include "PyXPCOM.h"
|
||||
136
mozilla/extensions/python/xpcom/src/Pyxpt_info.cpp
Normal file
136
mozilla/extensions/python/xpcom/src/Pyxpt_info.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// Pyxpt_info.cpp - wrappers for the xpt_info objects.
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
#include "PyXPCOM_std.h"
|
||||
|
||||
PyObject *PyObject_FromXPTTypeDescriptor( const XPTTypeDescriptor *d)
|
||||
{
|
||||
if (d==nsnull) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
return Py_BuildValue("bbbh",
|
||||
d->prefix.flags,
|
||||
d->argnum,
|
||||
d->argnum2,
|
||||
d->type.iface // this is actually a union!
|
||||
);
|
||||
}
|
||||
|
||||
PyObject *PyObject_FromXPTParamDescriptor( const XPTParamDescriptor *d)
|
||||
{
|
||||
if (d==nsnull) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
PyObject *ob = PyObject_FromXPTTypeDescriptor(&d->type);
|
||||
PyObject *ret = Py_BuildValue("bO", d->flags, ob);
|
||||
Py_DECREF(ob);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject *PyObject_FromXPTMethodDescriptor( const XPTMethodDescriptor *d)
|
||||
{
|
||||
if (d==nsnull) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
PyObject *ob_params = PyTuple_New(d->num_args);
|
||||
if (ob_params==NULL)
|
||||
return NULL;
|
||||
for (int i=0;i<d->num_args;i++)
|
||||
PyTuple_SET_ITEM(ob_params, i, PyObject_FromXPTParamDescriptor(d->params+i));
|
||||
PyObject *ob_ret = PyObject_FromXPTParamDescriptor(d->result);
|
||||
PyObject *ret = Py_BuildValue("bsOO", d->flags, d->name, ob_params, ob_ret);
|
||||
Py_XDECREF(ob_ret);
|
||||
Py_XDECREF(ob_params);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *c)
|
||||
{
|
||||
if (c==nsnull) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
PyObject *ob_type = PyObject_FromXPTTypeDescriptor(&c->type);
|
||||
if (ob_type==NULL)
|
||||
return NULL;
|
||||
PyObject *v = NULL;
|
||||
switch (c->type.prefix.flags) {
|
||||
case TD_INT8:
|
||||
v = PyInt_FromLong( c->value.i8 );
|
||||
break;
|
||||
case TD_INT16:
|
||||
v = PyInt_FromLong( c->value.i16 );
|
||||
break;
|
||||
case TD_INT32:
|
||||
v = PyInt_FromLong( c->value.i32 );
|
||||
break;
|
||||
case TD_INT64:
|
||||
v = PyLong_FromLongLong(c->value.i64);
|
||||
break;
|
||||
case TD_UINT8:
|
||||
v = PyInt_FromLong( c->value.ui8 );
|
||||
break;
|
||||
case TD_UINT16:
|
||||
v = PyInt_FromLong( c->value.ui16 );
|
||||
break;
|
||||
case TD_UINT32:
|
||||
v = PyInt_FromLong( c->value.ui8 );
|
||||
break;
|
||||
case TD_UINT64:
|
||||
v = PyLong_FromUnsignedLongLong(c->value.ui64);
|
||||
break;
|
||||
case TD_FLOAT:
|
||||
v = PyFloat_FromDouble(c->value.flt);
|
||||
break;
|
||||
case TD_DOUBLE:
|
||||
v = PyFloat_FromDouble(c->value.dbl);
|
||||
break;
|
||||
case TD_BOOL:
|
||||
v = c->value.bul ? Py_True : Py_False;
|
||||
Py_INCREF(v);
|
||||
break;
|
||||
case TD_CHAR:
|
||||
v = PyString_FromStringAndSize(&c->value.ch, 1);
|
||||
break;
|
||||
case TD_WCHAR:
|
||||
v = PyUnicode_FromUnicode(&c->value.wch, 1);
|
||||
break;
|
||||
// TD_VOID = 13,
|
||||
case TD_PNSIID:
|
||||
v = Py_nsIID::PyObjectFromIID(*c->value.iid);
|
||||
break;
|
||||
// TD_PBSTR = 15,
|
||||
case TD_PSTRING:
|
||||
v = PyString_FromString(c->value.str);
|
||||
break;
|
||||
case TD_PWSTRING:
|
||||
v = PyUnicode_FromUnicode(c->value.wstr, nsCRT::strlen(c->value.wstr));
|
||||
break;
|
||||
// TD_INTERFACE_TYPE = 18,
|
||||
// TD_INTERFACE_IS_TYPE = 19,
|
||||
// TD_ARRAY = 20,
|
||||
// TD_PSTRING_SIZE_IS = 21,
|
||||
// TD_PWSTRING_SIZE_IS = 22
|
||||
default:
|
||||
v = PyString_FromString("Unknown type code!!");
|
||||
break;
|
||||
|
||||
}
|
||||
PyObject *ret = Py_BuildValue("sbO", c->name, ob_type, v);
|
||||
Py_DECREF(ob_type);
|
||||
Py_DECREF(v);
|
||||
return ret;
|
||||
}
|
||||
194
mozilla/extensions/python/xpcom/src/TypeObject.cpp
Normal file
194
mozilla/extensions/python/xpcom/src/TypeObject.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIInterfaceInfoManager.h>
|
||||
#include <nsISupportsPrimitives.h>
|
||||
|
||||
|
||||
static PyTypeObject PyInterfaceType_Type = {
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0, /* Number of items for varobject */
|
||||
"interface-type", /* Name of this type */
|
||||
sizeof(PyTypeObject), /* Basic object size */
|
||||
0, /* Item size for varobject */
|
||||
0, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
PyType_Type.tp_getattr, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
PyType_Type.tp_repr, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_xxx1*/
|
||||
0, /*tp_xxx2*/
|
||||
0, /*tp_xxx3*/
|
||||
0, /*tp_xxx4*/
|
||||
"Define the behavior of a PythonCOM Interface type.",
|
||||
};
|
||||
|
||||
/*static*/ PRBool
|
||||
PyXPCOM_TypeObject::IsType(PyTypeObject *t)
|
||||
{
|
||||
return t->ob_type == &PyInterfaceType_Type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The type methods
|
||||
//
|
||||
/*static*/PyObject *
|
||||
PyXPCOM_TypeObject::Py_getattr(PyObject *self, char *name)
|
||||
{
|
||||
if (strcmp(name, "IID")==0)
|
||||
return Py_nsIID::PyObjectFromIID( ((Py_nsISupports *)self)->m_iid );
|
||||
|
||||
PyXPCOM_TypeObject *this_type = (PyXPCOM_TypeObject *)self->ob_type;
|
||||
return Py_FindMethodInChain(&this_type->chain, self, name);
|
||||
}
|
||||
|
||||
/*static*/int
|
||||
PyXPCOM_TypeObject::Py_setattr(PyObject *op, char *name, PyObject *v)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "%s has read-only attributes", op->ob_type->tp_name );
|
||||
PyErr_SetString(PyExc_TypeError, buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// @pymethod int|Py_nsISupports|__cmp__|Implements XPCOM rules for object identity.
|
||||
/*static*/int
|
||||
PyXPCOM_TypeObject::Py_cmp(PyObject *self, PyObject *other)
|
||||
{
|
||||
// @comm NOTE: Copied from COM - have not confirmed these rules are true for XPCOM
|
||||
// @comm As per the XPCOM rules for object identity, both objects are queried for nsISupports, and these values compared.
|
||||
// The only meaningful test is for equality - the result of other comparisons is undefined
|
||||
// (ie, determined by the object's relative addresses in memory.
|
||||
nsISupports *pUnkOther;
|
||||
nsISupports *pUnkThis;
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(self, NS_GET_IID(nsISupports), &pUnkThis, PR_FALSE))
|
||||
return -1;
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(other, NS_GET_IID(nsISupports), &pUnkOther, PR_FALSE)) {
|
||||
pUnkThis->Release();
|
||||
return -1;
|
||||
}
|
||||
int rc = pUnkThis==pUnkOther ? 0 :
|
||||
(pUnkThis < pUnkOther ? -1 : 1);
|
||||
pUnkThis->Release();
|
||||
pUnkOther->Release();
|
||||
return rc;
|
||||
}
|
||||
|
||||
// @pymethod int|Py_nsISupports|__hash__|Implement a hash-code for the XPCOM object using XPCOM identity rules.
|
||||
/*static*/long PyXPCOM_TypeObject::Py_hash(PyObject *self)
|
||||
{
|
||||
// We always return the value of the nsISupports *.
|
||||
nsISupports *pUnkThis;
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(self, NS_GET_IID(nsISupports), &pUnkThis, PR_FALSE))
|
||||
return -1;
|
||||
long ret = _Py_HashPointer(pUnkThis);
|
||||
pUnkThis->Release();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// @method string|Py_nsISupports|__repr__|Called to create a representation of a Py_nsISupports object
|
||||
/*static */PyObject *
|
||||
PyXPCOM_TypeObject::Py_repr(PyObject *self)
|
||||
{
|
||||
// @comm The repr of this object displays both the object's address, and its attached nsISupports's address
|
||||
Py_nsISupports *pis = (Py_nsISupports *)self;
|
||||
// Try and get the IID name.
|
||||
char *iid_repr;
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
|
||||
if (iim!=nsnull)
|
||||
iim->GetNameForIID(&pis->m_iid, &iid_repr);
|
||||
if (iid_repr==nsnull)
|
||||
// no IIM available, or it doesnt know the name.
|
||||
iid_repr = pis->m_iid.ToString();
|
||||
// XXX - need some sort of buffer overflow.
|
||||
char buf[512];
|
||||
sprintf(buf, "<XPCOM object (%s) at 0x%p/0x%p>", iid_repr, self, pis->m_obj);
|
||||
nsAllocator::Free(iid_repr);
|
||||
return PyString_FromString(buf);
|
||||
}
|
||||
|
||||
/*static */PyObject *
|
||||
PyXPCOM_TypeObject::Py_str(PyObject *self)
|
||||
{
|
||||
Py_nsISupports *pis = (Py_nsISupports *)self;
|
||||
nsresult rv;
|
||||
char *val = NULL;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
{ // scope to kill pointer while thread-lock released.
|
||||
nsCOMPtr<nsISupportsString> ss( do_QueryInterface(pis->m_obj, &rv ));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = ss->ToString(&val);
|
||||
} // end-scope
|
||||
Py_END_ALLOW_THREADS;
|
||||
PyObject *ret;
|
||||
if (NS_FAILED(rv))
|
||||
ret = Py_repr(self);
|
||||
else
|
||||
ret = PyString_FromString(val);
|
||||
if (val) nsAllocator::Free(val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* static */void
|
||||
PyXPCOM_TypeObject::Py_dealloc(PyObject *self)
|
||||
{
|
||||
delete (Py_nsISupports *)self;
|
||||
}
|
||||
|
||||
PyXPCOM_TypeObject::PyXPCOM_TypeObject( const char *name, PyXPCOM_TypeObject *pBase, int typeSize, struct PyMethodDef* methodList, PyXPCOM_I_CTOR thector)
|
||||
{
|
||||
static const PyTypeObject type_template = {
|
||||
PyObject_HEAD_INIT(&PyInterfaceType_Type)
|
||||
0, /*ob_size*/
|
||||
"XPCOMTypeTemplate", /*tp_name*/
|
||||
sizeof(Py_nsISupports), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
Py_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
Py_getattr, /* tp_getattr */
|
||||
Py_setattr, /* tp_setattr */
|
||||
Py_cmp, /* tp_compare */
|
||||
Py_repr, /* tp_repr */
|
||||
0, /* tp_as_number*/
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
Py_hash, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
Py_str, /* tp_str */
|
||||
};
|
||||
|
||||
*((PyTypeObject *)this) = type_template;
|
||||
|
||||
chain.methods = methodList;
|
||||
chain.link = pBase ? &pBase->chain : NULL;
|
||||
|
||||
baseType = pBase;
|
||||
ctor = thector;
|
||||
|
||||
// cast away const, as Python doesnt use it.
|
||||
tp_name = (char *)name;
|
||||
tp_basicsize = typeSize;
|
||||
}
|
||||
|
||||
PyXPCOM_TypeObject::~PyXPCOM_TypeObject()
|
||||
{
|
||||
}
|
||||
2092
mozilla/extensions/python/xpcom/src/VariantUtils.cpp
Normal file
2092
mozilla/extensions/python/xpcom/src/VariantUtils.cpp
Normal file
File diff suppressed because it is too large
Load Diff
217
mozilla/extensions/python/xpcom/src/dllmain.cpp
Normal file
217
mozilla/extensions/python/xpcom/src/dllmain.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <prthread.h>
|
||||
|
||||
#ifdef XP_WIN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
static PRInt32 g_cLockCount = 0;
|
||||
static PRBool bDidInitPython = PR_FALSE;
|
||||
static PyThreadState *ptsGlobal = nsnull;
|
||||
PyInterpreterState *PyXPCOM_InterpreterState;
|
||||
static PRLock *g_lockMain = nsnull;
|
||||
|
||||
PRUintn tlsIndex = 0;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Thread-state helpers/global functions.
|
||||
//
|
||||
|
||||
// This function must be called at some time when the interpreter lock and state is valid.
|
||||
// Called by init{module} functions and also COM factory entry point.
|
||||
void PyXPCOM_InterpreterState_Ensure()
|
||||
{
|
||||
if (PyXPCOM_InterpreterState==NULL) {
|
||||
PyThreadState *threadStateSave = PyThreadState_Swap(NULL);
|
||||
if (threadStateSave==NULL)
|
||||
Py_FatalError("Can not setup interpreter state, as current state is invalid");
|
||||
|
||||
PyXPCOM_InterpreterState = threadStateSave->interp;
|
||||
PyThreadState_Swap(threadStateSave);
|
||||
}
|
||||
}
|
||||
|
||||
void PyXPCOM_InterpreterState_Free()
|
||||
{
|
||||
PyXPCOM_ThreadState_Free();
|
||||
PyXPCOM_InterpreterState = NULL; // Eek - should I be freeing something?
|
||||
}
|
||||
|
||||
// This structure is stored in the TLS slot. At this stage only a Python thread state
|
||||
// is kept, but this may change in the future...
|
||||
struct ThreadData{
|
||||
PyThreadState *ts;
|
||||
};
|
||||
|
||||
// Ensure that we have a Python thread state available to use.
|
||||
// If this is called for the first time on a thread, it will allocate
|
||||
// the thread state. This does NOT change the state of the Python lock.
|
||||
// Returns TRUE if a new thread state was created, or FALSE if a
|
||||
// thread state already existed.
|
||||
PRBool PyXPCOM_ThreadState_Ensure()
|
||||
{
|
||||
ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
|
||||
if (pData==NULL) { /* First request on this thread */
|
||||
/* Check we have an interpreter state */
|
||||
if (PyXPCOM_InterpreterState==NULL) {
|
||||
Py_FatalError("Can not setup thread state, as have no interpreter state");
|
||||
}
|
||||
pData = (ThreadData *)nsAllocator::Alloc(sizeof(ThreadData));
|
||||
if (!pData)
|
||||
Py_FatalError("Out of memory allocating thread state.");
|
||||
memset(pData, 0, sizeof(*pData));
|
||||
if (NS_FAILED( PR_SetThreadPrivate( tlsIndex, pData ) ) ) {
|
||||
NS_ABORT_IF_FALSE(0, "Could not create thread data for this thread!");
|
||||
Py_FatalError("Could not thread private thread data!");
|
||||
}
|
||||
pData->ts = PyThreadState_New(PyXPCOM_InterpreterState);
|
||||
return PR_TRUE; // Did create a thread state state
|
||||
}
|
||||
return PR_FALSE; // Thread state was previously created
|
||||
}
|
||||
|
||||
// Asuming we have a valid thread state, acquire the Python lock.
|
||||
void PyXPCOM_InterpreterLock_Acquire()
|
||||
{
|
||||
ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
|
||||
NS_ABORT_IF_FALSE(pData, "Have no thread data for this thread!");
|
||||
PyThreadState *thisThreadState = pData->ts;
|
||||
PyEval_AcquireThread(thisThreadState);
|
||||
}
|
||||
|
||||
// Asuming we have a valid thread state, release the Python lock.
|
||||
void PyXPCOM_InterpreterLock_Release()
|
||||
{
|
||||
ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
|
||||
NS_ABORT_IF_FALSE(pData, "Have no thread data for this thread!");
|
||||
PyThreadState *thisThreadState = pData->ts;
|
||||
PyEval_ReleaseThread(thisThreadState);
|
||||
}
|
||||
|
||||
// Free the thread state for the current thread
|
||||
// (Presumably previously create with a call to
|
||||
// PyXPCOM_ThreadState_Ensure)
|
||||
void PyXPCOM_ThreadState_Free()
|
||||
{
|
||||
ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
|
||||
if (!pData) return;
|
||||
PyThreadState *thisThreadState = pData->ts;
|
||||
PyThreadState_Delete(thisThreadState);
|
||||
PR_SetThreadPrivate(tlsIndex, NULL);
|
||||
nsAllocator::Free(pData);
|
||||
}
|
||||
|
||||
void PyXPCOM_ThreadState_Clear()
|
||||
{
|
||||
ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
|
||||
PyThreadState *thisThreadState = pData->ts;
|
||||
PyThreadState_Clear(thisThreadState);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Lock/exclusion global functions.
|
||||
//
|
||||
|
||||
void PyXPCOM_AcquireGlobalLock(void)
|
||||
{
|
||||
NS_PRECONDITION(g_lockMain != nsnull, "Cant acquire a NULL lock!");
|
||||
PR_Lock(g_lockMain);
|
||||
}
|
||||
void PyXPCOM_ReleaseGlobalLock(void)
|
||||
{
|
||||
NS_PRECONDITION(g_lockMain != nsnull, "Cant release a NULL lock!");
|
||||
PR_Unlock(g_lockMain);
|
||||
}
|
||||
|
||||
void PyXPCOM_DLLAddRef(void)
|
||||
{
|
||||
// Must be thread-safe, although cant have the Python lock!
|
||||
CEnterLeaveXPCOMFramework _celf;
|
||||
PRInt32 cnt = PR_AtomicIncrement(&g_cLockCount);
|
||||
if (cnt==1) { // First call
|
||||
if (!Py_IsInitialized()) {
|
||||
Py_Initialize();
|
||||
// Make sure our Windows framework is all setup.
|
||||
PyXPCOM_Globals_Ensure();
|
||||
// Make sure we have _something_ as sys.argv.
|
||||
if (PySys_GetObject("argv")==NULL) {
|
||||
PyObject *path = PyList_New(0);
|
||||
PyObject *str = PyString_FromString("");
|
||||
PyList_Append(path, str);
|
||||
PySys_SetObject("argv", path);
|
||||
Py_XDECREF(path);
|
||||
Py_XDECREF(str);
|
||||
}
|
||||
|
||||
// Must force Python to start using thread locks, as
|
||||
// we are free-threaded (maybe, I think, sometimes :-)
|
||||
PyEval_InitThreads();
|
||||
// Release Python lock, as first thing we do is re-get it.
|
||||
ptsGlobal = PyEval_SaveThread();
|
||||
// NOTE: We never finalize Python!!
|
||||
}
|
||||
}
|
||||
}
|
||||
void PyXPCOM_DLLRelease(void)
|
||||
{
|
||||
PR_AtomicDecrement(&g_cLockCount);
|
||||
}
|
||||
|
||||
extern "C" PRBool _init(void)
|
||||
{
|
||||
PRStatus status;
|
||||
g_lockMain = PR_NewLock();
|
||||
status = PR_NewThreadPrivateIndex( &tlsIndex, NULL );
|
||||
NS_WARN_IF_FALSE(status==0, "Could not allocate TLS storage");
|
||||
if (NS_FAILED(status)) {
|
||||
PR_DestroyLock(g_lockMain);
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
extern "C" void _fini(void)
|
||||
{
|
||||
PR_DestroyLock(g_lockMain);
|
||||
// I can't locate a way to kill this -
|
||||
// should I pass a dtor to PR_NewThreadPrivateIndex??
|
||||
// TlsFree(tlsIndex);
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
||||
extern "C" __declspec(dllexport)
|
||||
BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved)
|
||||
{
|
||||
switch (dwReason) {
|
||||
case DLL_PROCESS_ATTACH: {
|
||||
if (!_init())
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
case DLL_PROCESS_DETACH:
|
||||
{
|
||||
_fini();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TRUE; // ok
|
||||
}
|
||||
#endif // XP_WIN
|
||||
392
mozilla/extensions/python/xpcom/src/loader/pyloader.cpp
Normal file
392
mozilla/extensions/python/xpcom/src/loader/pyloader.cpp
Normal file
@@ -0,0 +1,392 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// pyloader
|
||||
//
|
||||
// Not part of the main Python _xpcom package, but a seperate, thin DLL.
|
||||
//
|
||||
// The main loader and registrar for Python. A thin DLL that is designed to live in
|
||||
// the xpcom "components" directory. Simply locates and loads the standard
|
||||
// _xpcom support module and transfers control to that.
|
||||
|
||||
#include "xp_core.h"
|
||||
#include "nsIComponentLoader.h"
|
||||
#include "nsIRegistry.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIModule.h"
|
||||
|
||||
#include <nsFileStream.h> // For console logging.
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
#undef HAVE_LONG_LONG
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Can only assume dynamic loading on Windows.
|
||||
#define LOADER_LINKS_WITH_PYTHON
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LOADER_LINKS_WITH_PYTHON
|
||||
#include "Python.h"
|
||||
|
||||
static PyThreadState *ptsGlobal = nsnull;
|
||||
static char *PyTraceback_AsString(PyObject *exc_tb);
|
||||
|
||||
#else // LOADER_LINKS_WITH_PYTHON
|
||||
|
||||
static PRBool find_xpcom_module(char *buf, size_t bufsize);
|
||||
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
|
||||
|
||||
#ifdef XP_WIN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_UNIX
|
||||
#include <dlfcn.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef nsresult (*pfnPyXPCOM_NSGetModule)(nsIComponentManager *servMgr,
|
||||
nsIFile* location,
|
||||
nsIModule** result);
|
||||
|
||||
|
||||
pfnPyXPCOM_NSGetModule pfnEntryPoint = nsnull;
|
||||
|
||||
|
||||
static void LogError(const char *fmt, ...);
|
||||
|
||||
extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
|
||||
nsIFile* location,
|
||||
nsIModule** result)
|
||||
{
|
||||
// What to do for other platforms here?
|
||||
// I tried using their nsDll class, but it wont allow
|
||||
// a LoadLibrary() - it insists on a full path it can load.
|
||||
// So if Im going to the trouble of locating the DLL on Windows,
|
||||
// I may as well just do the whole thing myself.
|
||||
#ifdef LOADER_LINKS_WITH_PYTHON
|
||||
PRBool bDidInitPython = !Py_IsInitialized(); // well, I will next line, anyway :-)
|
||||
if (bDidInitPython) {
|
||||
// If Python was already initialized, we almost certainly
|
||||
// do not have the thread-lock, so can not attempt to import anything
|
||||
// We simply must assume/hope that Python already has our module loaded.
|
||||
Py_Initialize();
|
||||
if (!Py_IsInitialized()) {
|
||||
LogError("Python initialization failed!\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PyObject *mod = PyImport_ImportModule("xpcom._xpcom");
|
||||
if (mod==NULL) {
|
||||
LogError("Could not import the Python XPCOM extension\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
if (pfnEntryPoint == nsnull) {
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
||||
#ifdef DEBUG
|
||||
const char *mod_name = "_xpcom_d.pyd";
|
||||
#else
|
||||
const char *mod_name = "_xpcom.pyd";
|
||||
#endif
|
||||
HMODULE hmod = GetModuleHandle(mod_name);
|
||||
if (hmod==NULL) {
|
||||
LogError("Could not get a handle to the Python XPCOM extension\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
pfnEntryPoint = (pfnPyXPCOM_NSGetModule)GetProcAddress(hmod, "PyXPCOM_NSGetModule");
|
||||
#endif // XP_WIN
|
||||
|
||||
#ifdef XP_UNIX
|
||||
static char module_path[1024];
|
||||
if (!find_xpcom_module(module_path, sizeof(module_path)))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
void *handle = dlopen(module_path, RTLD_GLOBAL | RTLD_LAZY);
|
||||
if (handle==NULL) {
|
||||
LogError("Could not open the Python XPCOM extension at '%s' - '%s'\n", module_path, dlerror());
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
pfnEntryPoint = (pfnPyXPCOM_NSGetModule)dlsym(handle, "PyXPCOM_NSGetModule");
|
||||
#endif // XP_UNIX
|
||||
}
|
||||
if (pfnEntryPoint==NULL) {
|
||||
LogError("Could not load main Python entry point\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef LOADER_LINKS_WITH_PYTHON
|
||||
// We abandon the thread-lock, as the first thing Python does
|
||||
// is re-establish the lock (the Python thread-state story SUCKS!!!
|
||||
|
||||
if (bDidInitPython)
|
||||
ptsGlobal = PyEval_SaveThread();
|
||||
// Note this is never restored, and Python is never finalized!
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
return (*pfnEntryPoint)(servMgr, location, result);
|
||||
}
|
||||
|
||||
// The internal helper that actually moves the
|
||||
// formatted string to the target!
|
||||
|
||||
void LogMessage(const char *prefix, const char *pszMessageText)
|
||||
{
|
||||
nsOutputConsoleStream console;
|
||||
console << prefix << pszMessageText;
|
||||
}
|
||||
|
||||
// A helper for the various logging routines.
|
||||
static void VLogF(const char *prefix, const char *fmt, va_list argptr)
|
||||
{
|
||||
char buff[512];
|
||||
|
||||
vsprintf(buff, fmt, argptr);
|
||||
|
||||
LogMessage(prefix, buff);
|
||||
}
|
||||
|
||||
static void LogError(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Loader Error: ", fmt, marker);
|
||||
#ifdef LOADER_LINKS_WITH_PYTHON
|
||||
// If we have a Python exception, also log that:
|
||||
PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
|
||||
PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
|
||||
if (exc_typ) {
|
||||
char *string1 = nsnull;
|
||||
nsOutputStringStream streamout(string1);
|
||||
|
||||
if (exc_tb) {
|
||||
const char *szTraceback = PyTraceback_AsString(exc_tb);
|
||||
if (szTraceback == NULL)
|
||||
streamout << "Can't get the traceback info!";
|
||||
else {
|
||||
streamout << "Traceback (most recent call last):\n";
|
||||
streamout << szTraceback;
|
||||
PyMem_Free((ANY *)szTraceback);
|
||||
}
|
||||
}
|
||||
PyObject *temp = PyObject_Str(exc_typ);
|
||||
if (temp) {
|
||||
streamout << PyString_AsString(temp);
|
||||
Py_DECREF(temp);
|
||||
} else
|
||||
streamout << "Can convert exception to a string!";
|
||||
streamout << ": ";
|
||||
if (exc_val != NULL) {
|
||||
temp = PyObject_Str(exc_val);
|
||||
if (temp) {
|
||||
streamout << PyString_AsString(temp);
|
||||
Py_DECREF(temp);
|
||||
} else
|
||||
streamout << "Can convert exception value to a string!";
|
||||
}
|
||||
streamout << "\n";
|
||||
LogMessage("PyXPCOM Exception:", string1);
|
||||
}
|
||||
PyErr_Restore(exc_typ, exc_val, exc_tb);
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
}
|
||||
|
||||
static void LogWarning(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Loader Warning: ", fmt, marker);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void LogDebug(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Loader Debug: ", fmt, marker);
|
||||
}
|
||||
#else
|
||||
#define LogDebug()
|
||||
#endif
|
||||
|
||||
#ifdef LOADER_LINKS_WITH_PYTHON
|
||||
|
||||
/* Obtains a string from a Python traceback.
|
||||
This is the exact same string as "traceback.print_exc" would return.
|
||||
|
||||
Pass in a Python traceback object (probably obtained from PyErr_Fetch())
|
||||
Result is a string which must be free'd using PyMem_Free()
|
||||
*/
|
||||
#define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;}
|
||||
|
||||
char *PyTraceback_AsString(PyObject *exc_tb)
|
||||
{
|
||||
char *errMsg = NULL; /* a static that hold a local error message */
|
||||
char *result = NULL; /* a valid, allocated result. */
|
||||
PyObject *modStringIO = NULL;
|
||||
PyObject *modTB = NULL;
|
||||
PyObject *obFuncStringIO = NULL;
|
||||
PyObject *obStringIO = NULL;
|
||||
PyObject *obFuncTB = NULL;
|
||||
PyObject *argsTB = NULL;
|
||||
PyObject *obResult = NULL;
|
||||
|
||||
/* Import the modules we need - cStringIO and traceback */
|
||||
modStringIO = PyImport_ImportModule("cStringIO");
|
||||
if (modStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant import cStringIO\n");
|
||||
|
||||
modTB = PyImport_ImportModule("traceback");
|
||||
if (modTB==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant import traceback\n");
|
||||
/* Construct a cStringIO object */
|
||||
obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
|
||||
if (obFuncStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant find cStringIO.StringIO\n");
|
||||
obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
|
||||
if (obStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cStringIO.StringIO() failed\n");
|
||||
/* Get the traceback.print_exception function, and call it. */
|
||||
obFuncTB = PyObject_GetAttrString(modTB, "print_tb");
|
||||
if (obFuncTB==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant find traceback.print_tb\n");
|
||||
|
||||
argsTB = Py_BuildValue("OOO",
|
||||
exc_tb ? exc_tb : Py_None,
|
||||
Py_None,
|
||||
obStringIO);
|
||||
if (argsTB==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant make print_tb arguments\n");
|
||||
|
||||
obResult = PyObject_CallObject(obFuncTB, argsTB);
|
||||
if (obResult==NULL)
|
||||
TRACEBACK_FETCH_ERROR("traceback.print_tb() failed\n");
|
||||
/* Now call the getvalue() method in the StringIO instance */
|
||||
Py_DECREF(obFuncStringIO);
|
||||
obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue");
|
||||
if (obFuncStringIO==NULL)
|
||||
TRACEBACK_FETCH_ERROR("cant find getvalue function\n");
|
||||
Py_DECREF(obResult);
|
||||
obResult = PyObject_CallObject(obFuncStringIO, NULL);
|
||||
if (obResult==NULL)
|
||||
TRACEBACK_FETCH_ERROR("getvalue() failed.\n");
|
||||
|
||||
/* And it should be a string all ready to go - duplicate it. */
|
||||
if (!PyString_Check(obResult))
|
||||
TRACEBACK_FETCH_ERROR("getvalue() did not return a string\n");
|
||||
|
||||
{ // a temp scope so I can use temp locals.
|
||||
char *tempResult = PyString_AsString(obResult);
|
||||
result = (char *)PyMem_Malloc(strlen(tempResult)+1);
|
||||
if (result==NULL)
|
||||
TRACEBACK_FETCH_ERROR("memory error duplicating the traceback string");
|
||||
|
||||
strcpy(result, tempResult);
|
||||
} // end of temp scope.
|
||||
done:
|
||||
/* All finished - first see if we encountered an error */
|
||||
if (result==NULL && errMsg != NULL) {
|
||||
result = (char *)PyMem_Malloc(strlen(errMsg)+1);
|
||||
if (result != NULL)
|
||||
/* if it does, not much we can do! */
|
||||
strcpy(result, errMsg);
|
||||
}
|
||||
Py_XDECREF(modStringIO);
|
||||
Py_XDECREF(modTB);
|
||||
Py_XDECREF(obFuncStringIO);
|
||||
Py_XDECREF(obStringIO);
|
||||
Py_XDECREF(obFuncTB);
|
||||
Py_XDECREF(argsTB);
|
||||
Py_XDECREF(obResult);
|
||||
return result;
|
||||
}
|
||||
|
||||
#else // LOADER_LINKS_WITH_PYTHON
|
||||
|
||||
#ifdef XP_UNIX
|
||||
|
||||
// From Python getpath.c
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
static int
|
||||
isfile(char *filename) /* Is file, not directory */
|
||||
{
|
||||
struct stat buf;
|
||||
if (stat(filename, &buf) != 0)
|
||||
return 0;
|
||||
if (!S_ISREG(buf.st_mode))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
isxfile(char *filename) /* Is executable file */
|
||||
{
|
||||
struct stat buf;
|
||||
if (stat(filename, &buf) != 0)
|
||||
return 0;
|
||||
if (!S_ISREG(buf.st_mode))
|
||||
return 0;
|
||||
if ((buf.st_mode & 0111) == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
isdir(char *filename) /* Is directory */
|
||||
{
|
||||
struct stat buf;
|
||||
if (stat(filename, &buf) != 0)
|
||||
return 0;
|
||||
if (!S_ISDIR(buf.st_mode))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
PRBool find_xpcom_module(char *buf, size_t bufsize)
|
||||
{
|
||||
char *pypath = getenv("PYTHONPATH");
|
||||
char *searchPath = pypath ? strdup(pypath) : NULL;
|
||||
char *tok = searchPath ? strtok(searchPath, ":") : NULL;
|
||||
while (tok != NULL) {
|
||||
int thissize = bufsize;
|
||||
int baselen = strlen(tok);
|
||||
strncpy(buf, tok, thissize);
|
||||
thissize-=baselen;
|
||||
if (thissize > 1 && buf[baselen-1] != '/') {
|
||||
buf[baselen++]='/';
|
||||
}
|
||||
strncpy(buf+baselen, "xpcom/_xpcommodule.so", thissize);
|
||||
// LogDebug("Python _xpcom module at '%s'?\n", buf);
|
||||
if (isfile(buf)) {
|
||||
// LogDebug("Found python _xpcom module at '%s'\n", buf);
|
||||
return PR_TRUE;
|
||||
}
|
||||
tok = strtok(NULL, ":");
|
||||
}
|
||||
LogError("Failed to find a Python _xpcom module\n");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#endif // XP_UNIX
|
||||
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
|
||||
66
mozilla/extensions/python/xpcom/src/readme.html
Normal file
66
mozilla/extensions/python/xpcom/src/readme.html
Normal file
@@ -0,0 +1,66 @@
|
||||
<!-- Copyright (c) 2000-2001 ActiveState Tool Corporation. -->
|
||||
<!-- See the file LICENSE.txt for licensing information. -->
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Building the Python XPCOM package</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Building the Python XPCOM package.</h1>
|
||||
|
||||
<p>This file describes how to build the Python XPCOM C++ sources.</p>
|
||||
<p>There are the following steps</p>
|
||||
<ul>
|
||||
<li><a href="#ConfiguringTheEnvironment">Configure environment variables</a></li>
|
||||
<li><a href="#BuildingTheSources">Building the sources</a></li>
|
||||
</ul>
|
||||
<p>Testing etc is described in the <a href="../readme.html">main readme</a>.</p>
|
||||
<h2><a name="ConfiguringTheEnvironment">Configuring environment variables</a></h2>
|
||||
<h3> MOZ_SRC </h3>
|
||||
<p><b>Windows: </b>Run the standard MOZENV.BAT used to build Mozilla. This
|
||||
sets MOZ_SRC</p>
|
||||
<p><b>Unix:</b> Set MOZ_SRC to point to the base source directory - assumes
|
||||
"mozilla" sub-directory with mozilla directory tree under that. eg: assuming
|
||||
<i>/home/user/src/mozilla/dist/...</i>"</p>
|
||||
<pre>export MOZ_SRC=/home/user/src</pre>
|
||||
<h3>PYTHON_SRC</h3>
|
||||
<p><b>Windows:</b> Set <i> PYTHON_SRC</i> to point to the base Python source directory.
|
||||
eg: assuming <i>c:\src\python\PCBuild\...</i><pre>set PYTHON_SRC=c:\src\python</pre>
|
||||
<p>Unix: Set PYTHON_SRC to point to the base of an "installed" Python
|
||||
tree. eg:<pre>export PYTHON_SRC=/usr/local/ActivePython-1.6</pre>
|
||||
<h2><a name="BuildingTheSources">Building the sources</a></h2>
|
||||
<p>You must ensure some environment variables are setup. The section on <a href="#ConfiguringTheEnvironment">configuring
|
||||
environment variables explains how.</a></p>
|
||||
<p>There are 2 build processes to run All C++ sources are in the <i>xpcom\src</i>
|
||||
directory.:</p>
|
||||
<h3>Windows</h3>
|
||||
<ul>
|
||||
<li> Execute "compile.py" in this directory. This will take <i>Setup.in</i>, create an MSDev project, and build
|
||||
<i>..\_xpcom.pyd</i> and <i>..\_xpcom_d.pyd</i>"</li>
|
||||
<li> Change to the <i>loader</i> directory.</li>
|
||||
<li> Run <i>nmake -f makefile.win</i>. This will create <i>pyloader.dll</i>, and
|
||||
automatically copy it to the Mozilla build directory.</li>
|
||||
<a href="#ConfiguringTheEnvironment">
|
||||
</ul>
|
||||
<p>Finally, </a><a href="../readme.html#RunningTheTests">run the tests</a>,
|
||||
where we also test everything imports correctly.</p>
|
||||
<h3>Linux</h3>
|
||||
<p><b> NOTE:</b> Do not attempt to use "Setup.in" to create a Makefile </p>
|
||||
<ul>
|
||||
<li>Run "make" in this directory. This will create <i>../_xpcommodule.so</i></li>
|
||||
<li> Run "make" in the loader directory. This will create <i>libpyloader.so</i>,
|
||||
and copy it to the Mozilla directory.</li>
|
||||
<a href="#ConfiguringTheEnvironment">
|
||||
</ul>
|
||||
<p>Finally, </a><a href="../readme.html#RunningTheTests">running the tests</a>,
|
||||
where we also test everything imports correctly.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
532
mozilla/extensions/python/xpcom/src/xpcom.cpp
Normal file
532
mozilla/extensions/python/xpcom/src/xpcom.cpp
Normal file
@@ -0,0 +1,532 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
//
|
||||
// This code is part of the XPCOM extensions for Python.
|
||||
//
|
||||
// Written May 2000 by Mark Hammond.
|
||||
//
|
||||
// Based heavily on the Python COM support, which is
|
||||
// (c) Mark Hammond and Greg Stein.
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <nsIInterfaceInfoManager.h>
|
||||
#include <nsIFileSpec.h>
|
||||
#include <nsSpecialSystemDirectory.h>
|
||||
#include <nsIThread.h>
|
||||
#include <nsISupportsPrimitives.h>
|
||||
#include <nsIModule.h>
|
||||
#include <nsIInputStream.h>
|
||||
|
||||
#ifdef XP_WIN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
#include <nsIEventQueue.h>
|
||||
#include <nsIProxyObjectManager.h>
|
||||
|
||||
PYXPCOM_EXPORT PyObject *PyXPCOM_Error = NULL;
|
||||
extern void PyXPCOM_InterpreterState_Ensure();
|
||||
extern PRInt32 _PyXPCOM_GetGatewayCount(void);
|
||||
extern PRInt32 _PyXPCOM_GetInterfaceCount(void);
|
||||
|
||||
extern void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
|
||||
|
||||
// Hrm - So we can't have templates, eh??
|
||||
// preprocessor to the rescue, I guess.
|
||||
#define PyXPCOM_INTERFACE_DEFINE(ClassName, InterfaceName, Methods ) \
|
||||
\
|
||||
extern struct PyMethodDef Methods[]; \
|
||||
\
|
||||
class ClassName : public Py_nsISupports \
|
||||
{ \
|
||||
public: \
|
||||
static PyXPCOM_TypeObject *type; \
|
||||
static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid) { \
|
||||
return new ClassName(pInitObj, iid); \
|
||||
} \
|
||||
static void InitType(PyObject *iidNameDict) { \
|
||||
type = new PyXPCOM_TypeObject( \
|
||||
#InterfaceName, \
|
||||
Py_nsISupports::type, \
|
||||
sizeof(ClassName), \
|
||||
Methods, \
|
||||
Constructor); \
|
||||
const nsIID &iid = NS_GET_IID(InterfaceName); \
|
||||
RegisterInterface(iid, type); \
|
||||
PyObject *iid_ob = Py_nsIID::PyObjectFromIID(iid); \
|
||||
PyDict_SetItemString(iidNameDict, "IID_"#InterfaceName, iid_ob); \
|
||||
Py_DECREF(iid_ob); \
|
||||
} \
|
||||
protected: \
|
||||
ClassName(nsISupports *p, const nsIID &iid) : \
|
||||
Py_nsISupports(p, iid, type) { \
|
||||
/* The IID _must_ be the IID of the interface we are wrapping! */ \
|
||||
NS_ABORT_IF_FALSE(iid.Equals(NS_GET_IID(InterfaceName)), "Bad IID"); \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
PyXPCOM_TypeObject *ClassName::type = NULL; \
|
||||
\
|
||||
// End of PyXPCOM_INTERFACE_DEFINE macro
|
||||
|
||||
// And the classes
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIComponentManager, nsIComponentManager, PyMethods_IComponentManager)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfoManager, nsIInterfaceInfoManager, PyMethods_IInterfaceInfoManager)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIEnumerator, nsIEnumerator, PyMethods_IEnumerator)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsISimpleEnumerator, nsISimpleEnumerator, PyMethods_ISimpleEnumerator)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfo, nsIInterfaceInfo, PyMethods_IInterfaceInfo)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIServiceManager, nsIServiceManager, PyMethods_IServiceManager)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIInputStream, nsIInputStream, PyMethods_IInputStream)
|
||||
|
||||
// "boot-strap" methods - interfaces we need to get the base
|
||||
// interface support!
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_NS_LocateSpecialSystemDirectory(PyObject *self, PyObject *args)
|
||||
{
|
||||
int typ;
|
||||
if (!PyArg_ParseTuple(args, "i", &typ))
|
||||
return NULL;
|
||||
nsIFileSpec *spec = NULL;
|
||||
nsSpecialSystemDirectory systemDir((nsSpecialSystemDirectory::SystemDirectories)typ);
|
||||
return PyString_FromString(systemDir.GetNativePathCString());
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_NS_NewFileSpec(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *szspec = NULL;
|
||||
if (!PyArg_ParseTuple(args, "|s", &szspec))
|
||||
return NULL;
|
||||
nsIFileSpec *spec = NULL;
|
||||
nsresult nr;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
nr = NS_NewFileSpec(&spec);
|
||||
if (NS_SUCCEEDED(nr) && spec && szspec)
|
||||
nr = spec->SetNativePath(szspec);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if (NS_FAILED(nr) || spec==nsnull)
|
||||
return PyXPCOM_BuildPyException(nr);
|
||||
return Py_nsISupports::PyObjectFromInterface(spec, NS_GET_IID(nsIFileSpec), PR_TRUE);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_NS_GetGlobalComponentManager(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
nsIComponentManager* cm;
|
||||
nsresult rv;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
rv = NS_GetGlobalComponentManager(&cm);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(rv) )
|
||||
return PyXPCOM_BuildPyException(rv);
|
||||
// NOTE - NS_GetGlobalComponentManager DOES NOT ADD A REFCOUNT
|
||||
// (naughty, naughty) - we we explicitly ask our converter to
|
||||
// add one, even tho this is not the common pattern.
|
||||
|
||||
// Return a type based on the IID
|
||||
// Can not auto-wrap the interface info manager as it is critical to
|
||||
// building the support we need for autowrap.
|
||||
return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsIComponentManager), PR_TRUE, PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_GetGlobalServiceManager(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
nsIServiceManager* sm;
|
||||
nsresult rv;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
rv = nsServiceManager::GetGlobalServiceManager(&sm);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(rv) )
|
||||
return PyXPCOM_BuildPyException(rv);
|
||||
// NOTE - GetGlobalServiceManager DOES NOT ADD A REFCOUNT
|
||||
// (naughty, naughty) - we we explicitly ask our converter to
|
||||
// add one, even tho this is not the common pattern.
|
||||
|
||||
// Return a type based on the IID
|
||||
// Can not auto-wrap the interface info manager as it is critical to
|
||||
// building the support we need for autowrap.
|
||||
return Py_nsISupports::PyObjectFromInterface(sm, NS_GET_IID(nsIServiceManager), PR_TRUE, PR_FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_XPTI_GetInterfaceInfoManager(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
nsIInterfaceInfoManager* im;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
im = XPTI_GetInterfaceInfoManager();
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( im == nsnull )
|
||||
return PyXPCOM_BuildPyException(NS_ERROR_FAILURE);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
// Can not auto-wrap the interface info manager as it is critical to
|
||||
// building the support we need for autowrap.
|
||||
return Py_nsISupports::PyObjectFromInterface(im, NS_GET_IID(nsIInterfaceInfoManager), PR_FALSE, PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_XPTC_InvokeByIndex(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIS, *obParams;
|
||||
nsCOMPtr<nsISupports> pis;
|
||||
int index;
|
||||
|
||||
// We no longer rely on PyErr_Occurred() for our error state,
|
||||
// but keeping this assertion can't hurt - it should still always be true!
|
||||
NS_WARN_IF_FALSE(!PyErr_Occurred(), "Should be no pending Python error!");
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OiO", &obIS, &index, &obParams))
|
||||
return NULL;
|
||||
|
||||
// Ack! We must ask for the "native" interface supported by
|
||||
// the object, not specifically nsISupports, else we may not
|
||||
// back the same pointer (eg, Python, following identity rules,
|
||||
// will return the "original" gateway when QI'd for nsISupports)
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(
|
||||
obIS,
|
||||
Py_nsIID_NULL,
|
||||
getter_AddRefs(pis),
|
||||
PR_FALSE))
|
||||
return NULL;
|
||||
|
||||
PyXPCOM_InterfaceVariantHelper arg_helper;
|
||||
if (!arg_helper.Init(obParams))
|
||||
return NULL;
|
||||
|
||||
if (!arg_helper.FillArray())
|
||||
return NULL;
|
||||
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = XPTC_InvokeByIndex(pis, index, arg_helper.m_num_array, arg_helper.m_var_array);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
return arg_helper.MakePythonResult();
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_WrapObject(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *ob, *obIID;
|
||||
if (!PyArg_ParseTuple(args, "OO", &ob, &obIID))
|
||||
return NULL;
|
||||
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
nsISupports *ret = NULL;
|
||||
nsresult r = PyXPCOM_XPTStub::CreateNew(ob, iid, (void **)&ret);
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
// _ALL_ wrapped objects are associated with a weak-ref
|
||||
// to their "main" instance.
|
||||
AddDefaultGateway(ob, ret); // inject a weak reference to myself into the instance.
|
||||
|
||||
// Now wrap it in an interface.
|
||||
return Py_nsISupports::PyObjectFromInterface(ret, iid, PR_FALSE);
|
||||
}
|
||||
|
||||
// @pymethod int|pythoncom|_GetInterfaceCount|Retrieves the number of interface objects currently in existance
|
||||
static PyObject *
|
||||
PyXPCOMMethod_GetInterfaceCount(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":_GetInterfaceCount"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(_PyXPCOM_GetInterfaceCount());
|
||||
// @comm If is occasionally a good idea to call this function before your Python program
|
||||
// terminates. If this function returns non-zero, then you still have PythonCOM objects
|
||||
// alive in your program (possibly in global variables).
|
||||
}
|
||||
|
||||
// @pymethod int|pythoncom|_GetGatewayCount|Retrieves the number of gateway objects currently in existance
|
||||
static PyObject *
|
||||
PyXPCOMMethod_GetGatewayCount(PyObject *self, PyObject *args)
|
||||
{
|
||||
// @comm This is the number of Python object that implement COM servers which
|
||||
// are still alive (ie, serving a client). The only way to reduce this count
|
||||
// is to have the process which uses these PythonCOM servers release its references.
|
||||
if (!PyArg_ParseTuple(args, ":_GetGatewayCount"))
|
||||
return NULL;
|
||||
return PyInt_FromLong(_PyXPCOM_GetGatewayCount());
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_NS_ShutdownXPCOM(PyObject *self, PyObject *args)
|
||||
{
|
||||
// @comm This is the number of Python object that implement COM servers which
|
||||
// are still alive (ie, serving a client). The only way to reduce this count
|
||||
// is to have the process which uses these PythonCOM servers release its references.
|
||||
if (!PyArg_ParseTuple(args, ":NS_ShutdownXPCOM"))
|
||||
return NULL;
|
||||
nsresult nr;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
nr = NS_ShutdownXPCOM(nsnull);
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
// Dont raise an exception - as we are probably shutting down
|
||||
// and dont really case - just return the status
|
||||
return PyInt_FromLong(nr);
|
||||
}
|
||||
|
||||
static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
|
||||
|
||||
// A hack to work around their magic constants!
|
||||
static PyObject *
|
||||
PyXPCOMMethod_GetProxyForObject(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obQueue, *obIID, *obOb;
|
||||
int flags;
|
||||
if (!PyArg_ParseTuple(args, "OOOi", &obQueue, &obIID, &obOb, &flags))
|
||||
return NULL;
|
||||
nsIID iid;
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
nsCOMPtr<nsISupports> pob;
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(obOb, iid, getter_AddRefs(pob), PR_FALSE))
|
||||
return NULL;
|
||||
nsIEventQueue *pQueue = NULL;
|
||||
nsIEventQueue *pQueueRelease = NULL;
|
||||
|
||||
if (PyInt_Check(obQueue)) {
|
||||
pQueue = (nsIEventQueue *)PyInt_AsLong(obQueue);
|
||||
} else {
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(obQueue, NS_GET_IID(nsIEventQueue), (nsISupports **)&pQueue, PR_TRUE))
|
||||
return NULL;
|
||||
pQueueRelease = pQueue;
|
||||
}
|
||||
|
||||
nsresult rv_proxy;
|
||||
nsISupports *presult = nsnull;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
NS_WITH_SERVICE(nsIProxyObjectManager,
|
||||
proxyMgr,
|
||||
kProxyObjectManagerCID,
|
||||
&rv_proxy);
|
||||
|
||||
if ( NS_SUCCEEDED(rv_proxy) ) {
|
||||
rv_proxy = proxyMgr->GetProxyForObject(pQueue,
|
||||
iid,
|
||||
pob,
|
||||
flags,
|
||||
(void **)&presult);
|
||||
}
|
||||
if (pQueueRelease)
|
||||
pQueueRelease->Release();
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
PyObject *result;
|
||||
if (NS_SUCCEEDED(rv_proxy) ) {
|
||||
result = Py_nsISupports::PyObjectFromInterface(presult, iid, PR_FALSE);
|
||||
} else {
|
||||
result = PyXPCOM_BuildPyException(rv_proxy);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PyObject *AllocateBuffer(PyObject *self, PyObject *args)
|
||||
{
|
||||
int bufSize;
|
||||
if (!PyArg_ParseTuple(args, "i", &bufSize))
|
||||
return NULL;
|
||||
return PyBuffer_New(bufSize);
|
||||
}
|
||||
|
||||
PyObject *LogWarning(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *msg;
|
||||
if (!PyArg_ParseTuple(args, "s", &msg))
|
||||
return NULL;
|
||||
PyXPCOM_LogWarning("%s", msg);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *LogError(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *msg;
|
||||
if (!PyArg_ParseTuple(args, "s", &msg))
|
||||
return NULL;
|
||||
PyXPCOM_LogError("%s", msg);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
extern PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args);
|
||||
|
||||
static struct PyMethodDef xpcom_methods[]=
|
||||
{
|
||||
{"NS_LocateSpecialSystemDirectory", PyXPCOMMethod_NS_LocateSpecialSystemDirectory, 1},
|
||||
{"NS_GetGlobalComponentManager", PyXPCOMMethod_NS_GetGlobalComponentManager, 1},
|
||||
{"NS_NewFileSpec", PyXPCOMMethod_NS_NewFileSpec, 1},
|
||||
{"XPTI_GetInterfaceInfoManager", PyXPCOMMethod_XPTI_GetInterfaceInfoManager, 1},
|
||||
{"XPTC_InvokeByIndex", PyXPCOMMethod_XPTC_InvokeByIndex, 1},
|
||||
{"GetGlobalServiceManager", PyXPCOMMethod_GetGlobalServiceManager, 1},
|
||||
{"IID", PyXPCOMMethod_IID, 1}, // IID is wrong - deprecated - not just IID, but CID, etc.
|
||||
{"ID", PyXPCOMMethod_IID, 1}, // This is the official name.
|
||||
{"NS_ShutdownXPCOM", PyXPCOMMethod_NS_ShutdownXPCOM, 1},
|
||||
{"WrapObject", PyXPCOMMethod_WrapObject, 1},
|
||||
{"_GetInterfaceCount", PyXPCOMMethod_GetInterfaceCount, 1},
|
||||
{"_GetGatewayCount", PyXPCOMMethod_GetGatewayCount, 1},
|
||||
{"getProxyForObject", PyXPCOMMethod_GetProxyForObject, 1},
|
||||
{"GetProxyForObject", PyXPCOMMethod_GetProxyForObject, 1},
|
||||
{"AllocateBuffer", AllocateBuffer, 1},
|
||||
{"LogWarning", LogWarning, 1},
|
||||
{"LogError", LogError, 1},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Other helpers/global functions.
|
||||
//
|
||||
PRBool PyXPCOM_Globals_Ensure()
|
||||
{
|
||||
PRBool rc = PR_TRUE;
|
||||
|
||||
PyXPCOM_InterpreterState_Ensure();
|
||||
|
||||
// The exception object - we load it from .py code!
|
||||
if (PyXPCOM_Error == NULL) {
|
||||
rc = PR_FALSE;
|
||||
PyObject *mod = NULL;
|
||||
|
||||
mod = PyImport_ImportModule("xpcom");
|
||||
if (mod!=NULL) {
|
||||
PyXPCOM_Error = PyObject_GetAttrString(mod, "Exception");
|
||||
Py_DECREF(mod);
|
||||
}
|
||||
rc = (PyXPCOM_Error != NULL);
|
||||
}
|
||||
if (!rc)
|
||||
return rc;
|
||||
|
||||
static PRBool bHaveInitXPCOM = PR_FALSE;
|
||||
if (!bHaveInitXPCOM) {
|
||||
nsCOMPtr<nsIThread> thread_check;
|
||||
// xpcom appears to assert if already initialized
|
||||
// Is there an official way to determine this?
|
||||
if (NS_FAILED(nsIThread::GetMainThread(getter_AddRefs(thread_check)))) {
|
||||
// not already initialized.
|
||||
|
||||
// We need to locate the Mozilla bin directory.
|
||||
#ifdef XP_WIN
|
||||
// On Windows this by using "xpcom.dll"
|
||||
|
||||
char landmark[MAX_PATH+1];
|
||||
HMODULE hmod = GetModuleHandle("xpcom.dll");
|
||||
if (hmod==NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "We dont appear to be linked against xpcom.dll!?!?");
|
||||
return PR_FALSE;
|
||||
}
|
||||
GetModuleFileName(hmod, landmark, sizeof(landmark)/sizeof(landmark[0]));
|
||||
char *end = landmark + (strlen(landmark)-1);
|
||||
while (end > landmark && *end != '\\')
|
||||
end--;
|
||||
if (end > landmark) *end = '\0';
|
||||
|
||||
nsCOMPtr<nsILocalFile> ns_bin_dir;
|
||||
NS_NewLocalFile(landmark, PR_FALSE, getter_AddRefs(ns_bin_dir));
|
||||
nsresult rv = NS_InitXPCOM(nsnull, ns_bin_dir);
|
||||
#else
|
||||
// Elsewhere, Mozilla can find it itself (we hope!)
|
||||
nsresult rv = NS_InitXPCOM(nsnull, nsnull);
|
||||
#endif // XP_WIN
|
||||
if (NS_FAILED(rv)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "The XPCOM subsystem could not be initialized");
|
||||
return PR_FALSE;
|
||||
}
|
||||
// Also set the "special directory"
|
||||
#ifdef XP_WIN
|
||||
nsFileSpec spec(landmark);
|
||||
nsSpecialSystemDirectory::Set(nsSpecialSystemDirectory::OS_CurrentProcessDirectory, &spec);
|
||||
#endif // XP_WIN
|
||||
}
|
||||
// Even if xpcom was already init, we want to flag it as init!
|
||||
bHaveInitXPCOM = PR_TRUE;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#define REGISTER_IID(t) { \
|
||||
PyObject *iid_ob = Py_nsIID::PyObjectFromIID(NS_GET_IID(t)); \
|
||||
PyDict_SetItemString(dict, "IID_"#t, iid_ob); \
|
||||
Py_DECREF(iid_ob); \
|
||||
}
|
||||
|
||||
#define REGISTER_INT(val) { \
|
||||
PyObject *ob = PyInt_FromLong(val); \
|
||||
PyDict_SetItemString(dict, #val, ob); \
|
||||
Py_DECREF(ob); \
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// The module init code.
|
||||
//
|
||||
extern "C"
|
||||
#ifdef MS_WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void
|
||||
init_xpcom() {
|
||||
PyObject *oModule;
|
||||
|
||||
// ensure the framework has valid state to work with.
|
||||
if (!PyXPCOM_Globals_Ensure())
|
||||
return;
|
||||
|
||||
// Must force Python to start using thread locks
|
||||
PyEval_InitThreads();
|
||||
|
||||
// Create the module and add the functions
|
||||
oModule = Py_InitModule("_xpcom", xpcom_methods);
|
||||
|
||||
PyObject *dict = PyModule_GetDict(oModule);
|
||||
PyObject *pycom_Error = PyXPCOM_Error;
|
||||
if (pycom_Error == NULL || PyDict_SetItemString(dict, "error", pycom_Error) != 0)
|
||||
{
|
||||
PyErr_SetString(PyExc_MemoryError, "can't define error");
|
||||
return;
|
||||
}
|
||||
PyDict_SetItemString(dict, "IIDType", (PyObject *)&Py_nsIID::type);
|
||||
|
||||
REGISTER_IID(nsISupports);
|
||||
REGISTER_IID(nsISupportsString);
|
||||
REGISTER_IID(nsIModule);
|
||||
REGISTER_IID(nsIFactory);
|
||||
REGISTER_IID(nsIWeakReference);
|
||||
REGISTER_IID(nsISupportsWeakReference);
|
||||
// Register our custom interfaces.
|
||||
|
||||
Py_nsISupports::InitType();
|
||||
Py_nsIComponentManager::InitType(dict);
|
||||
Py_nsIInterfaceInfoManager::InitType(dict);
|
||||
Py_nsIEnumerator::InitType(dict);
|
||||
Py_nsISimpleEnumerator::InitType(dict);
|
||||
Py_nsIInterfaceInfo::InitType(dict);
|
||||
Py_nsIServiceManager::InitType(dict);
|
||||
Py_nsIInputStream::InitType(dict);
|
||||
|
||||
// We have special support for proxies - may as well add their constants!
|
||||
REGISTER_INT(PROXY_SYNC);
|
||||
REGISTER_INT(PROXY_ASYNC);
|
||||
REGISTER_INT(PROXY_ALWAYS);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
test_com_exceptions
|
||||
** Unhandled exception calling 'int8 do_short(in int16, inout int16, out int16, out retval int16);'
|
||||
** Returning nsresult of NS_ERROR_FAILURE
|
||||
** Unhandled exception calling 'int8 do_unsigned_short(in uint16, inout uint16, out uint16, out retval uint16);'
|
||||
** Returning nsresult of NS_ERROR_FAILURE
|
||||
** Unhandled exception calling 'int8 do_unsigned_long_long(in uint64, inout uint64, out uint64, out retval uint64);'
|
||||
** Returning nsresult of NS_ERROR_FAILURE
|
||||
The xpcom exception tests passed
|
||||
7
mozilla/extensions/python/xpcom/test/output/test_comfile
Normal file
7
mozilla/extensions/python/xpcom/test/output/test_comfile
Normal file
@@ -0,0 +1,7 @@
|
||||
test_comfile
|
||||
Open as string test worked.
|
||||
Open as URL test worked.
|
||||
File test using buffers worked.
|
||||
Local file read test worked.
|
||||
Read the correct data.
|
||||
Chunks read the correct data.
|
||||
@@ -0,0 +1,4 @@
|
||||
test_components
|
||||
The interfaces object appeared to work!
|
||||
The classes object appeared to work!
|
||||
The ID function appeared to work!
|
||||
@@ -0,0 +1,2 @@
|
||||
test_isupports_primitives
|
||||
The nsISupports primitive interface tests appeared to work
|
||||
9
mozilla/extensions/python/xpcom/test/output/test_misc
Normal file
9
mozilla/extensions/python/xpcom/test/output/test_misc
Normal file
@@ -0,0 +1,9 @@
|
||||
test_misc
|
||||
Running all tests - use '-h' to see command-line options...
|
||||
The netscape sample worked!
|
||||
Enumerated all the ContractIDs
|
||||
xpcom object hashing tests seemed to work
|
||||
Dumping every interface I can find - please wait
|
||||
(verbosity is turned off, so Im not actually going to print them)
|
||||
Finished dumping all the interfaces.
|
||||
The IID tests seemed to work
|
||||
1
mozilla/extensions/python/xpcom/test/output/test_streams
Normal file
1
mozilla/extensions/python/xpcom/test/output/test_streams
Normal file
@@ -0,0 +1 @@
|
||||
test_streams
|
||||
@@ -0,0 +1,4 @@
|
||||
test_test_component
|
||||
Testing the Python.TestComponent component
|
||||
The Python test component worked!
|
||||
Javascript could successfully use the Python test component.
|
||||
@@ -0,0 +1,2 @@
|
||||
test_weakreferences
|
||||
Weak-reference tests appear to have worked!
|
||||
18
mozilla/extensions/python/xpcom/test/regrtest.py
Normal file
18
mozilla/extensions/python/xpcom/test/regrtest.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# regrtest.py
|
||||
#
|
||||
# The Regression Tests for the xpcom package.
|
||||
import os
|
||||
import sys
|
||||
|
||||
import test.regrtest # The standard Python test suite.
|
||||
|
||||
path = os.path.abspath(os.path.split(sys.argv[0])[0])
|
||||
tests = []
|
||||
for arg in sys.argv[1:]:
|
||||
if arg[0] not in "-/":
|
||||
tests.append(arg)
|
||||
tests = tests or test.regrtest.findtests(path, [])
|
||||
test.regrtest.main(tests, path)
|
||||
70
mozilla/extensions/python/xpcom/test/test_com_exceptions.py
Normal file
70
mozilla/extensions/python/xpcom/test/test_com_exceptions.py
Normal file
@@ -0,0 +1,70 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# Test pyxpcom exception.
|
||||
|
||||
from xpcom import components, nsError, ServerException, COMException
|
||||
from xpcom.server import WrapObject
|
||||
|
||||
class PythonFailingComponent:
|
||||
# Re-use the test interface for this test.
|
||||
_com_interfaces_ = components.interfaces.nsIPythonTestInterfaceExtra
|
||||
|
||||
def do_boolean(self, p1, p2):
|
||||
# This should cause the caller to see a "silent" NS_ERROR_FAILURE exception.
|
||||
raise ServerException()
|
||||
|
||||
def do_octet(self, p1, p2):
|
||||
# This should cause the caller to see a "silent" NS_ERROR_NOT_IMPLEMENTED exception.
|
||||
raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED)
|
||||
|
||||
def do_short(self, p1, p2):
|
||||
# This should cause the caller to see a "debug" NS_ERROR_FAILURE exception.
|
||||
raise COMException(nsError.NS_ERROR_NOT_IMPLEMENTED)
|
||||
|
||||
def do_unsigned_short(self, p1, p2):
|
||||
# This should cause the caller to see a "debug" NS_ERROR_FAILURE exception.
|
||||
raise "Foo"
|
||||
|
||||
def do_long(self, p1, p2):
|
||||
# This should cause the caller to see a "silent" NS_ERROR_FAILURE exception.
|
||||
raise ServerException
|
||||
|
||||
def do_unsigned_long(self, p1, p2):
|
||||
# This should cause the caller to see a "silent" NS_ERROR_NOT_IMPLEMENTED exception.
|
||||
raise ServerException, nsError.NS_ERROR_NOT_IMPLEMENTED
|
||||
|
||||
def do_long_long(self, p1, p2):
|
||||
# This should cause the caller to see a "silent" NS_ERROR_NOT_IMPLEMENTED exception.
|
||||
raise ServerException, (nsError.NS_ERROR_NOT_IMPLEMENTED, "testing")
|
||||
|
||||
def do_unsigned_long_long(self, p1, p2):
|
||||
# Report of a crash in this case - test it!
|
||||
raise ServerException, "A bad exception param"
|
||||
|
||||
def _testit(expected_errno, func, *args):
|
||||
try:
|
||||
apply(func, args)
|
||||
except COMException, what:
|
||||
if what.errno != expected_errno:
|
||||
raise
|
||||
|
||||
def test():
|
||||
# For the benefit of the test suite, we print some reassuring messages.
|
||||
import sys
|
||||
sys.__stderr__.write("***** NOTE: Three tracebacks below this is normal\n")
|
||||
ob = WrapObject( PythonFailingComponent(), components.interfaces.nsIPythonTestInterfaceExtra)
|
||||
_testit(nsError.NS_ERROR_FAILURE, ob.do_boolean, 0, 0)
|
||||
_testit(nsError.NS_ERROR_NOT_IMPLEMENTED, ob.do_octet, 0, 0)
|
||||
_testit(nsError.NS_ERROR_FAILURE, ob.do_short, 0, 0)
|
||||
_testit(nsError.NS_ERROR_FAILURE, ob.do_unsigned_short, 0, 0)
|
||||
_testit(nsError.NS_ERROR_FAILURE, ob.do_long, 0, 0)
|
||||
_testit(nsError.NS_ERROR_NOT_IMPLEMENTED, ob.do_unsigned_long, 0, 0)
|
||||
_testit(nsError.NS_ERROR_NOT_IMPLEMENTED, ob.do_long_long, 0, 0)
|
||||
_testit(nsError.NS_ERROR_FAILURE, ob.do_unsigned_long_long, 0, 0)
|
||||
print "The xpcom exception tests passed"
|
||||
# For the benefit of the test suite, some more reassuring messages.
|
||||
sys.__stderr__.write("***** NOTE: Three tracebacks printed above this is normal\n")
|
||||
sys.__stderr__.write("***** It is testing the Python XPCOM Exception semantics\n")
|
||||
|
||||
test()
|
||||
7
mozilla/extensions/python/xpcom/test/test_comfile.py
Normal file
7
mozilla/extensions/python/xpcom/test/test_comfile.py
Normal file
@@ -0,0 +1,7 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
"""Test the xpcom.file module."""
|
||||
# Called "test_comfile" as Python has a standard test called test_file :-(
|
||||
import xpcom.file
|
||||
xpcom.file._TestAll()
|
||||
@@ -0,0 +1,149 @@
|
||||
<!-- Copyright (c) 2000-2001 ActiveState Tool Corporation. -->
|
||||
<!-- See the file LICENSE.txt for licensing information. -->
|
||||
|
||||
<center><b><font size=+2>Python Component Sample</font></b>
|
||||
|
||||
<p>
|
||||
<br>
|
||||
Last modified
|
||||
<script>
|
||||
document.write(document.lastModified);
|
||||
</script>
|
||||
</center>
|
||||
|
||||
<p>XPConnect allows JavaScript
|
||||
to transparantly access and manipulate XPCOM objects;
|
||||
|
||||
<p>Big Deal, I hear you say! But it also works for Python!!!
|
||||
|
||||
<p>
|
||||
This sample demonstrates accessing a XPCOM object through XPConnect.
|
||||
The JavaScript executed when this page loads creates an instance
|
||||
of the Python object by
|
||||
using the <tt>Components</tt> object, then accesses it through
|
||||
the <a href="py_test_component.idl">nsISample</a> interface by calling <tt>QueryInterface</tt>:
|
||||
<br>
|
||||
<pre>
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var sample = Components.classes["component://mozilla/sample/sample-world"].createInstance();
|
||||
sample = sample.QueryInterface(Components.interfaces.nsISample);
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The buttons on the form are connected to JavaScript event handlers which
|
||||
call the methods defined in Python
|
||||
|
||||
|
||||
<p><b><a name="Compiling">Compiling the idl</b>
|
||||
|
||||
<p>The XPIDL compiler (xpidl on Unix, xpidl.exe on Windows, and a CodeWarrior plugin on Mac)
|
||||
is compiled at build time (except on Mac) thus
|
||||
you will have to build mozilla in order to test this out. If you
|
||||
have already built mozilla then the compiler will be located at <tt>mozilla\dist\WIN32_D.OBJ\bin\xpidl.exe</tt>.
|
||||
|
||||
<p>Once you have the XPIDL compiler enter the following command at your
|
||||
prompt:
|
||||
<br><tt>D:\whereever\xpcom\test\test_component>d:\mozilla\dist\WIN32_D.OBJ\bin\xpidl -I
|
||||
d:\mozilla\dist\idl -m typelib py_test_component.idl</tt>. You must then copy the generated .xpt file
|
||||
to the mozilla component directory.
|
||||
|
||||
<p>The <tt>-I d:\mozilla\dist\idl</tt> points the compiler to the folder
|
||||
containing the other idl files, needed because nsISample.idl inherits from
|
||||
nsISupports.idl. The <tt>-m typelib</tt> instruction tells the compiler
|
||||
to build the .XPT typelib file.</tt>.
|
||||
|
||||
<p>
|
||||
For more information on compilation see the <a href="http://www.mozilla.org/scriptable/xpidl/">xpidl
|
||||
compiler page</a>.
|
||||
|
||||
<p><b>Running the sample</b>
|
||||
<p><b>NOTE: This doesnt work for me - I get an access denied error using XPConnect!</b>
|
||||
<p>Using Mozilla, load this file. Pay attention
|
||||
to the console when clicking "write".
|
||||
|
||||
<!-- XXX keep in sync with stuff in pre tag below -->
|
||||
<script>
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var sample = Components.classes["Python.TestComponent"].createInstance();
|
||||
sample = sample.QueryInterface(Components.interfaces.nsIPythonTestInterface);
|
||||
dump("sample = " + sample + "\n");
|
||||
|
||||
function get()
|
||||
{
|
||||
var field = document.getElementById('Value');
|
||||
field.value = sample.str_value;
|
||||
}
|
||||
|
||||
function set()
|
||||
{
|
||||
var field = document.getElementById('Value');
|
||||
sample.str_value = field.value;
|
||||
}
|
||||
|
||||
function poke()
|
||||
{
|
||||
var field = document.getElementById('Value');
|
||||
sample.poke(field.value);
|
||||
}
|
||||
|
||||
function write()
|
||||
{
|
||||
sample.writeValue("here is what I'm writing: ");
|
||||
}
|
||||
</script>
|
||||
|
||||
<p>
|
||||
<form name="form">
|
||||
<input type="button" value="Get" onclick="get();">
|
||||
<input type="button" value="Set" onclick="set();">
|
||||
<input type="button" value="Poke" onclick="poke();">
|
||||
<input type="text" id="Value">
|
||||
<input type="button" value="Write" onclick="write();">
|
||||
<form>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
JavaScript and form source:
|
||||
|
||||
<!-- XXX keep in sync with actual script -->
|
||||
<pre>
|
||||
<script>
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var sample = Components.classes["component://Python.TestComponent"].createInstance();
|
||||
sample = sample.QueryInterface(Components.interfaces.nsIPythonTestInterface);
|
||||
dump("sample = " + sample + "\n");
|
||||
|
||||
function get()
|
||||
{
|
||||
var field = document.getElementById('Value');
|
||||
field.value = sample.str_value;
|
||||
}
|
||||
|
||||
function set()
|
||||
{
|
||||
var field = document.getElementById('Value');
|
||||
sample.str_value = field.value;
|
||||
}
|
||||
|
||||
function poke()
|
||||
{
|
||||
var field = document.getElementById('Value');
|
||||
sample.poke(field.value);
|
||||
}
|
||||
|
||||
function write()
|
||||
{
|
||||
sample.writeValue("here is what I'm writing: ");
|
||||
}
|
||||
</script>
|
||||
|
||||
<form name="form">
|
||||
<input type="button" value="Get" onclick="get();">
|
||||
<input type="button" value="Set" onclick="set();">
|
||||
<input type="button" value="Poke" onclick="poke();">
|
||||
<input type="text" id="Value">
|
||||
<input type="button" value="Write" onclick="write();">
|
||||
<form>
|
||||
|
||||
</pre>
|
||||
@@ -0,0 +1,183 @@
|
||||
/* Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. */
|
||||
|
||||
// NOTE: This is a TEST interface, not a DEMO interface :-)
|
||||
// We try to get as many data-types etc exposed, meaning this
|
||||
// doesnt really make a good demo of a "simple component"
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(1ECAED4F-E4D5-4ee7-ABF0-7D72AE1441D7)]
|
||||
interface nsIPythonTestInterface : nsISupports
|
||||
{
|
||||
// Some constants for us to test - one for every type supported by xpidl
|
||||
const short One = 1;
|
||||
const long Two = 2;
|
||||
const long MinusOne = -1;
|
||||
const long BigLong = 0x7FFFFFFF;
|
||||
const long BigULong = 0xFFFFFFFF;
|
||||
|
||||
// Declare every type supported as an attribute.
|
||||
attribute boolean boolean_value; // PRBool
|
||||
attribute octet octet_value; // PRUint8
|
||||
attribute short short_value; // PRInt16
|
||||
attribute unsigned short ushort_value; // PRUint16
|
||||
attribute long long_value; // PRInt32
|
||||
attribute unsigned long ulong_value; // PRUint32
|
||||
attribute long long long_long_value; // PRInt64
|
||||
attribute unsigned long long ulong_long_value; // PRUint64
|
||||
attribute float float_value; // float
|
||||
attribute double double_value; // double
|
||||
attribute char char_value; // char
|
||||
attribute wchar wchar_value; // PRUnichar
|
||||
attribute string string_value; // char *
|
||||
attribute wstring wstring_value; // PRUnichar*
|
||||
attribute nsIIDRef iid_value; // an IID
|
||||
attribute nsIPythonTestInterface interface_value; // A specific interface
|
||||
attribute nsISupports isupports_value; // A generic interface
|
||||
|
||||
// Declare every type supported as a method with an "in", "in/out" and "out" params
|
||||
boolean do_boolean(in boolean p1, inout boolean p2, out boolean p3);
|
||||
octet do_octet(in octet p1, inout octet p2, out octet p3);
|
||||
short do_short(in short p1, inout short p2, out short p3);
|
||||
unsigned short do_unsigned_short(in unsigned short p1, inout unsigned short p2, out unsigned short p3);
|
||||
long do_long(in long p1, inout long p2, out long p3);
|
||||
unsigned long do_unsigned_long(in unsigned long p1, inout unsigned long p2, out unsigned long p3);
|
||||
long long do_long_long(in long long p1, inout long long p2, out long long p3);
|
||||
unsigned long long do_unsigned_long_long(in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3);
|
||||
float do_float(in float p1, inout float p2, out float p3);
|
||||
double do_double(in double p1, inout double p2, out double p3);
|
||||
char do_char(in char p1, inout char p2, out char p3);
|
||||
wchar do_wchar(in wchar p1, inout wchar p2, out wchar p3);
|
||||
string do_string(in string p1, inout string p2, out string p3);
|
||||
wstring do_wstring(in wstring p1, inout wstring p2, out wstring p3);
|
||||
nsIIDRef do_nsIIDRef(in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3);
|
||||
nsIPythonTestInterface do_nsIPythonTestInterface(in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3);
|
||||
nsISupports do_nsISupports(in nsISupports p1, inout nsISupports p2, out nsISupports p3);
|
||||
void do_nsISupportsIs(in nsIIDRef iid, [iid_is(iid),retval] out nsQIResult result);
|
||||
// Do I really need these??
|
||||
// void do_nsISupportsIs2(inout nsIIDRef iid, [iid_is(iid)] inout nsQIResult result);
|
||||
// void do_nsISupportsIs3(out nsIIDRef iid, [iid_is(iid)] inout nsQIResult result);
|
||||
// void do_nsISupportsIs4(out nsIIDRef iid, [iid_is(iid)] out nsQIResult result);
|
||||
};
|
||||
|
||||
// Another interface - we use another interface purely for testing purposes -
|
||||
// We ensure that the entire interface hierarcy is available correctly.
|
||||
[scriptable, uuid(B38D1538-FE92-42c3-831F-285242EDEEA4)]
|
||||
interface nsIPythonTestInterfaceExtra : nsIPythonTestInterface
|
||||
{
|
||||
// These were copied from the XPCOM test 'xpctest.idl'
|
||||
// (and a few extras added)
|
||||
void MultiplyEachItemInIntegerArray(
|
||||
in PRInt32 val,
|
||||
in PRUint32 count,
|
||||
[array, size_is(count)] inout PRInt32 valueArray);
|
||||
void MultiplyEachItemInIntegerArrayAndAppend(
|
||||
in PRInt32 val,
|
||||
inout PRUint32 count,
|
||||
[array, size_is(count)] inout PRInt32 valueArray);
|
||||
|
||||
// Note that this method shares a single "size_is" between 2 params!
|
||||
void CompareStringArrays([array, size_is(count)] in string arr1,
|
||||
[array, size_is(count)] in string arr2,
|
||||
in unsigned long count,
|
||||
[retval] out short result);
|
||||
|
||||
void DoubleStringArray(inout PRUint32 count,
|
||||
[array, size_is(count)] inout string valueArray);
|
||||
void ReverseStringArray(in PRUint32 count,
|
||||
[array, size_is(count)] inout string valueArray);
|
||||
|
||||
// One count, one inout array.
|
||||
void DoubleString(inout PRUint32 count,
|
||||
[size_is(count)] inout string str);
|
||||
// One in count and in array, plus out count and out array
|
||||
void DoubleString2(in PRUint32 in_count, [size_is(in_count)] in string in_str,
|
||||
out PRUint32 out_count, [size_is(out_count)] out string out_str);
|
||||
// As per DoubleString2, but out string also marked retval
|
||||
void DoubleString3(in PRUint32 in_count, [size_is(in_count)] in string in_str,
|
||||
out PRUint32 out_count, [size_is(out_count), retval] out string out_str);
|
||||
// One in array, one out array, one share inout count.
|
||||
void DoubleString4([size_is(count)] in string in_str, inout PRUint32 count, [size_is(count)] out string out_str);
|
||||
// UpString defines the count as only "in" - meaning the result must be the same size
|
||||
void UpString(in PRUint32 count,
|
||||
[size_is(count)] inout string str);
|
||||
// UpString2 defines count as only "in", and a string as only "out"
|
||||
void UpString2(in PRUint32 count,
|
||||
[size_is(count)] in string in_str,
|
||||
[size_is(count)]out string out_str);
|
||||
// Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!)
|
||||
void GetFixedString(in PRUint32 count, [size_is(count)]out string out_str);
|
||||
|
||||
void DoubleWideString(inout PRUint32 count,
|
||||
[size_is(count)] inout wstring str);
|
||||
void DoubleWideString2(in PRUint32 in_count, [size_is(in_count)] in wstring in_str,
|
||||
out PRUint32 out_count, [size_is(out_count)] out wstring out_str);
|
||||
void DoubleWideString3(in PRUint32 in_count, [size_is(in_count)] in wstring in_str,
|
||||
out PRUint32 out_count, [size_is(out_count), retval] out wstring out_str);
|
||||
void DoubleWideString4([size_is(count)] in wstring in_str, inout PRUint32 count, [size_is(count)] out wstring out_str);
|
||||
// UpWideString defines the count as only "in" - meaning the result must be the same size
|
||||
void UpWideString(in PRUint32 count,
|
||||
[size_is(count)] inout wstring str);
|
||||
// UpWideString2 defines count as only "in", and a string as only "out"
|
||||
void UpWideString2(in PRUint32 count,
|
||||
[size_is(count)] in wstring in_str,
|
||||
[size_is(count)]out wstring out_str);
|
||||
// Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!)
|
||||
void GetFixedWideString(in PRUint32 count, [size_is(count)]out string out_str);
|
||||
|
||||
void GetStrings(out PRUint32 count,
|
||||
[retval, array, size_is(count)] out string str);
|
||||
|
||||
void UpOctetArray(inout PRUint32 count,
|
||||
[array, size_is(count)] inout PRUint8 data);
|
||||
|
||||
void UpOctetArray2(inout PRUint32 count,
|
||||
[array, size_is(count)] inout PRUint8 data);
|
||||
|
||||
// Arrays of interfaces
|
||||
void CheckInterfaceArray(in PRUint32 count,
|
||||
[array, size_is(count)] in nsISupports data,
|
||||
[retval] out PRBool all_non_null);
|
||||
void GetInterfaceArray(out PRUint32 count,
|
||||
[array, size_is(count)] out nsISupports data);
|
||||
void ExtendInterfaceArray(inout PRUint32 count,
|
||||
[array, size_is(count)] inout nsISupports data);
|
||||
|
||||
// Arrays of IIDs
|
||||
void CheckIIDArray(in PRUint32 count,
|
||||
[array, size_is(count)] in nsIIDRef data,
|
||||
[retval] out PRBool all_mine);
|
||||
void GetIIDArray(out PRUint32 count,
|
||||
[array, size_is(count)] out nsIIDRef data);
|
||||
void ExtendIIDArray(inout PRUint32 count,
|
||||
[array, size_is(count)] inout nsIIDRef data);
|
||||
|
||||
// More specific tests.
|
||||
// Test our count param can be shared as an "in" param.
|
||||
void SumArrays(in PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]in PRInt32 array2, [retval]out PRInt32 result);
|
||||
// Test our count param can be shared as an "out" param.
|
||||
void GetArrays(out PRUint32 count, [array, size_is(count)]out PRInt32 array1, [array, size_is(count)]out PRInt32 array2);
|
||||
// Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!)
|
||||
void GetFixedArray(in PRUint32 count, [array, size_is(count)]out PRInt32 array1);
|
||||
// Test our "in" count param can be shared as one "in", plus one "out" param.
|
||||
void CopyArray(in PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]out PRInt32 array2);
|
||||
// Test our "in-out" count param can be shared as one "in", plus one "out" param.
|
||||
void CopyAndDoubleArray(inout PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]out PRInt32 array2);
|
||||
// Test our "in-out" count param can be shared as one "in", plus one "in-out" param.
|
||||
void AppendArray(inout PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]inout PRInt32 array2);
|
||||
};
|
||||
|
||||
// DOM String support is a "recent" (01/2001) addition to XPCOM. These test
|
||||
// have their own interface for no real good reason ;-)
|
||||
[scriptable, uuid(657ae651-a973-4818-8c06-f4b948b3d758)]
|
||||
interface nsIPythonTestInterfaceDOMStrings : nsIPythonTestInterfaceExtra
|
||||
{
|
||||
DOMString GetDOMStringResult();
|
||||
void GetDOMStringOut([retval] out DOMString s);
|
||||
PRUint32 GetDOMStringLength(in DOMString s);
|
||||
PRUint32 GetDOMStringRefLength(in DOMStringRef s);
|
||||
PRUint32 GetDOMStringPtrLength(in DOMStringPtr s);
|
||||
void ConcatDOMStrings(in DOMString s1, in DOMString s2, out DOMString ret);
|
||||
attribute DOMString domstring_value;
|
||||
readonly attribute DOMString domstring_value_ro;
|
||||
};
|
||||
@@ -0,0 +1,344 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# NOTE: This is a TEST interface, not a DEMO interface :-)
|
||||
# We try to get as many data-types etc exposed, meaning this
|
||||
# doesnt really make a good demo of a "simple component"
|
||||
|
||||
|
||||
from xpcom import components, verbose
|
||||
|
||||
class PythonTestComponent:
|
||||
# Note we only list the "child" interface, not our intermediate interfaces
|
||||
# (which we must, by definition, also support)
|
||||
_com_interfaces_ = components.interfaces.nsIPythonTestInterfaceDOMStrings
|
||||
_reg_clsid_ = "{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}"
|
||||
_reg_contractid_ = "Python.TestComponent"
|
||||
def __init__(self):
|
||||
self.boolean_value = 1
|
||||
self.octet_value = 2
|
||||
self.short_value = 3
|
||||
self.ushort_value = 4
|
||||
self.long_value = 5
|
||||
self.ulong_value = 6
|
||||
self.long_long_value = 7
|
||||
self.ulong_long_value = 8
|
||||
self.float_value = 9.0
|
||||
self.double_value = 10.0
|
||||
self.char_value = "a"
|
||||
self.wchar_value = "b"
|
||||
self.string_value = "cee"
|
||||
self.wstring_value = "dee"
|
||||
self.iid_value = self._reg_clsid_
|
||||
self.interface_value = None
|
||||
self.isupports_value = None
|
||||
self.domstring_value = "dom"
|
||||
|
||||
def __del__(self):
|
||||
if verbose:
|
||||
print "Python.TestComponent: __del__ method called - object is destructing"
|
||||
|
||||
def do_boolean(self, p1, p2):
|
||||
# boolean do_boolean(in boolean p1, inout boolean p2, out boolean p3);
|
||||
ret = p1 ^ p2
|
||||
return ret, not ret, ret
|
||||
|
||||
def do_octet(self, p1, p2):
|
||||
# octet do_octet(in octet p1, inout octet p2, out octet p3);
|
||||
return p1+p2, p1-p2, p1*p2
|
||||
|
||||
def do_short(self, p1, p2):
|
||||
# short do_short(in short p1, inout short p2, out short p3);
|
||||
return p1+p2, p1-p2, p1*p2
|
||||
|
||||
def do_unsigned_short(self, p1, p2):
|
||||
# unsigned short do_unsigned_short(in unsigned short p1, inout unsigned short p2, out unsigned short p3);
|
||||
return p1+p2, p1-p2, p1*p2
|
||||
def do_long(self, p1, p2):
|
||||
# long do_long(in long p1, inout long p2, out long p3);
|
||||
return p1+p2, p1-p2, p1*p2
|
||||
|
||||
def do_unsigned_long(self, p1, p2):
|
||||
# unsigned long do_unsigned_long(in unsigned long p1, inout unsigned long p2, out unsigned long p3);
|
||||
return p1+p2, p1-p2, p1*p2
|
||||
def do_long_long(self, p1, p2):
|
||||
# long long do_long_long(in long long p1, inout long long p2, out long long p3);
|
||||
return p1+p2, p1-p2, p1*p2
|
||||
def do_unsigned_long_long(self, p1, p2):
|
||||
# unsigned long long do_unsigned_long_long(in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3);
|
||||
return p1+p2, p1-p2, p1*p2
|
||||
def do_float(self, p1, p2):
|
||||
# float do_float(in float p1, inout float p2, out float p3);
|
||||
return p1+p2, p1-p2, p1*p2
|
||||
def do_double(self, p1, p2):
|
||||
# double do_double(in double p1, inout double p2, out double p3);
|
||||
return p1+p2, p1-p2, p1*p2
|
||||
def do_char(self, p1, p2):
|
||||
# char do_char(in char p1, inout char p2, out char p3);
|
||||
return chr(ord(p1)+ord(p2)), p2, p1
|
||||
def do_wchar(self, p1, p2):
|
||||
# wchar do_wchar(in wchar p1, inout wchar p2, out wchar p3);
|
||||
return chr(ord(p1)+ord(p2)), p2, p1
|
||||
def do_string(self, p1, p2):
|
||||
# string do_string(in string p1, inout string p2, out string p3);
|
||||
ret = ""
|
||||
if p1 is not None: ret = ret + p1
|
||||
if p2 is not None: ret = ret + p2
|
||||
return ret, p1, p2
|
||||
def do_wstring(self, p1, p2):
|
||||
# wstring do_wstring(in wstring p1, inout wstring p2, out wstring p3);
|
||||
ret = u""
|
||||
if p1 is not None: ret = ret + p1
|
||||
if p2 is not None: ret = ret + p2
|
||||
return ret, p1, p2
|
||||
def do_nsIIDRef(self, p1, p2):
|
||||
# nsIIDRef do_nsIIDRef(in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3);
|
||||
return p1, self._reg_clsid_, p2
|
||||
def do_nsIPythonTestInterface(self, p1, p2):
|
||||
# nsIPythonTestInterface do_nsIPythonTestInterface(in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3);
|
||||
return p2, p1, self
|
||||
def do_nsISupports(self, p1, p2):
|
||||
# nsISupports do_nsISupports(in nsISupports p1, inout nsISupports p2, out nsISupports p3);
|
||||
return self, p1, p2
|
||||
def do_nsISupportsIs(self, iid):
|
||||
# void do_nsISupportsIs(in nsIIDRef iid, [iid_is(iid),retval] out nsQIResult result)
|
||||
# Note the framework does the QI etc on us, so there is no real point me doing it.
|
||||
# (However, user code _should_ do the QI - otherwise any errors are deemed "internal" (as they
|
||||
# are raised by the C++ framework), and therefore logged to the console, etc.
|
||||
# A user QI allows the user to fail gracefully, whatever gracefully means for them!
|
||||
return self
|
||||
# Do I really need these??
|
||||
## def do_nsISupportsIs2(self, iid, interface):
|
||||
## # void do_nsISupportsIs2(inout nsIIDRef iid, [iid_is(iid),retval] inout nsQIResult result);
|
||||
## return iid, interface
|
||||
## def do_nsISupportsIs3(self, interface):
|
||||
## # void do_nsISupportsIs3(out nsIIDRef iid, [iid_is(iid)] inout nsQIResult result);
|
||||
## return self._com_interfaces_, interface
|
||||
## def do_nsISupportsIs4(self):
|
||||
## # void do_nsISupportsIs4(out nsIIDRef iid, [iid_is(iid)] out nsQIResult result);
|
||||
## return self._com_interfaces_, self
|
||||
|
||||
# Methods from the nsIPythonTestInterfaceExtra interface
|
||||
#
|
||||
def MultiplyEachItemInIntegerArray(self, val, valueArray):
|
||||
# void MultiplyEachItemInIntegerArray(
|
||||
# in PRInt32 val,
|
||||
# in PRUint32 count,
|
||||
# [array, size_is(count)] inout PRInt32 valueArray);
|
||||
# NOTE - the "sizeis" params are never passed to or returned from Python!
|
||||
results = []
|
||||
for item in valueArray:
|
||||
results.append(item * val)
|
||||
return results
|
||||
def MultiplyEachItemInIntegerArrayAndAppend(self, val, valueArray):
|
||||
#void MultiplyEachItemInIntegerArrayAndAppend(
|
||||
# in PRInt32 val,
|
||||
# inout PRUint32 count,
|
||||
# [array, size_is(count)] inout PRInt32 valueArray);
|
||||
results = valueArray[:]
|
||||
for item in valueArray:
|
||||
results.append(item * val)
|
||||
return results
|
||||
def DoubleStringArray(self, valueArray):
|
||||
# void DoubleStringArray(inout PRUint32 count,
|
||||
# [array, size_is(count)] inout string valueArray);
|
||||
results = []
|
||||
for item in valueArray:
|
||||
results.append(item * 2)
|
||||
return results
|
||||
|
||||
def ReverseStringArray(self, valueArray):
|
||||
# void ReverseStringArray(in PRUint32 count,
|
||||
# [array, size_is(count)] inout string valueArray);
|
||||
valueArray.reverse()
|
||||
return valueArray
|
||||
|
||||
# Note that this method shares a single "size_is" between 2 params!
|
||||
def CompareStringArrays(self, ar1, ar2):
|
||||
# void CompareStringArrays([array, size_is(count)] in string arr1,
|
||||
# [array, size_is(count)] in string arr2,
|
||||
# in unsigned long count,
|
||||
# [retval] out short result);
|
||||
return cmp(ar1, ar2)
|
||||
|
||||
def DoubleString(self, val):
|
||||
# void DoubleString(inout PRUint32 count,
|
||||
# [size_is(count)] inout string str);
|
||||
return val * 2
|
||||
def DoubleString2(self, val):
|
||||
# void DoubleString2(in PRUint32 in_count, [size_is(in_count)] in string in_str,
|
||||
# out PRUint32 out_count, [size_is(out_count)] out string out_str);
|
||||
return val * 2
|
||||
def DoubleString3(self, val):
|
||||
# void DoubleString3(in PRUint32 in_count, [size_is(in_count)] in string in_str,
|
||||
# out PRUint32 out_count, [size_is(out_count), retval] string out_str);
|
||||
return val * 2
|
||||
def DoubleString4(self, val):
|
||||
# void DoubleString4([size_is(count)] in string in_str, inout PRUint32 count, [size_is(count)] out string out_str);
|
||||
return val * 2
|
||||
def UpString(self, val):
|
||||
# // UpString defines the count as only "in" - meaning the result must be the same size
|
||||
# void UpString(in PRUint32 count,
|
||||
# [size_is(count)] inout string str);
|
||||
return val.upper()
|
||||
UpString2 = UpString
|
||||
# // UpString2 defines count as only "in", and a string as only "out"
|
||||
# void UpString2(in PRUint32 count,
|
||||
# [size_is(count)] inout string in_str,
|
||||
# [size_is(count)]out string out_str);
|
||||
|
||||
def GetFixedString(self, count):
|
||||
# void GetFixedString(in PRUint32 count, [size_is(count)out string out_str);
|
||||
return "A" * count
|
||||
|
||||
# DoubleWideString functions are identical to DoubleString, except use wide chars!
|
||||
def DoubleWideString(self, val):
|
||||
return val * 2
|
||||
def DoubleWideString2(self, val):
|
||||
return val * 2
|
||||
def DoubleWideString3(self, val):
|
||||
return val * 2
|
||||
def DoubleWideString4(self, val):
|
||||
return val * 2
|
||||
def UpWideString(self, val):
|
||||
return val.upper()
|
||||
UpWideString2 = UpWideString
|
||||
|
||||
# Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!)
|
||||
def GetFixedWideString(self, count):
|
||||
# void GetFixedWideString(in PRUint32 count, [size_is(count)out string out_str);
|
||||
return u"A" * count
|
||||
|
||||
def GetStrings(self):
|
||||
# void GetStrings(out PRUint32 count,
|
||||
# [retval, array, size_is(count)] out string str);
|
||||
return "Hello from the Python test component".split()
|
||||
# Some tests for our special "PRUint8" support.
|
||||
def UpOctetArray( self, data ):
|
||||
# void UpOctetArray(inout PRUint32 count,
|
||||
# [array, size_is(count)] inout PRUint8 data);
|
||||
return data.upper()
|
||||
|
||||
def UpOctetArray2( self, data ):
|
||||
# void UpOctetArray2(inout PRUint32 count,
|
||||
# [array, size_is(count)] inout PRUint8 data);
|
||||
data = data.upper()
|
||||
# This time we return a list of integers.
|
||||
return map( ord, data )
|
||||
|
||||
# Arrays of interfaces
|
||||
def CheckInterfaceArray(self, interfaces):
|
||||
# void CheckInterfaceArray(in PRUint32 count,
|
||||
# [array, size_is(count)] in nsISupports data,
|
||||
# [retval] out PRBool all_non_null);
|
||||
ret = 1
|
||||
for i in interfaces:
|
||||
if i is None:
|
||||
ret = 0
|
||||
break
|
||||
return ret
|
||||
def GetInterfaceArray(self):
|
||||
# void GetInterfaceArray(out PRUint32 count,
|
||||
# [array, size_is(count)] out nsISupports data);
|
||||
return self, self, self, None
|
||||
def ExtendInterfaceArray(self, data):
|
||||
# void ExtendInterfaceArray(inout PRUint32 count,
|
||||
# [array, size_is(count)] inout nsISupports data);
|
||||
return data * 2
|
||||
|
||||
# Arrays of IIDs
|
||||
def CheckIIDArray(self, data):
|
||||
# void CheckIIDArray(in PRUint32 count,
|
||||
# [array, size_is(count)] in nsIIDRef data,
|
||||
# [retval] out PRBool all_mine);
|
||||
ret = 1
|
||||
for i in data:
|
||||
if i!= self._com_interfaces_ and i != self._reg_clsid_:
|
||||
ret = 0
|
||||
break
|
||||
return ret
|
||||
def GetIIDArray(self):
|
||||
# void GetIIDArray(out PRUint32 count,
|
||||
# [array, size_is(count)] out nsIIDRef data);
|
||||
return self._com_interfaces_, self._reg_clsid_
|
||||
def ExtendIIDArray(self, data):
|
||||
# void ExtendIIDArray(inout PRUint32 count,
|
||||
# [array, size_is(count)] inout nsIIDRef data);
|
||||
return data * 2
|
||||
|
||||
# Test our count param can be shared as an "in" param.
|
||||
def SumArrays(self, array1, array2):
|
||||
# void SumArrays(in PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]in array2, [retval]result);
|
||||
if len(array1)!=len(array2):
|
||||
print "SumArrays - not expecting different lengths!"
|
||||
result = 0
|
||||
for i in array1:
|
||||
result = result + i
|
||||
for i in array2:
|
||||
result = result+i
|
||||
return result
|
||||
|
||||
# Test our count param can be shared as an "out" param.
|
||||
def GetArrays(self):
|
||||
# void GetArrays(out PRUint32 count, [array, size_is(count)]out array1, [array, size_is(count)]out array2);
|
||||
return (1,2,3), (4,5,6)
|
||||
# Test we can get an "out" array with an "in" size
|
||||
def GetFixedArray(self, size):
|
||||
# void GetFixedArray(in PRUint32 count, [array, size_is(count)]out PRInt32 array1]);
|
||||
return 0 * size
|
||||
|
||||
# Test our "in" count param can be shared as one "in", plus one "out" param.
|
||||
def CopyArray(self, array1):
|
||||
# void CopyArray(in PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]out array2);
|
||||
return array1
|
||||
# Test our "in-out" count param can be shared as one "in", plus one "out" param.
|
||||
def CopyAndDoubleArray(self, array):
|
||||
# void CopyAndDoubleArray(inout PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]out array2);
|
||||
return array + array
|
||||
# Test our "in-out" count param can be shared as one "in", plus one "in-out" param.
|
||||
def AppendArray(self, array1, array2):
|
||||
# void AppendArray(inout PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]inout array2);
|
||||
rc = array1
|
||||
if array2 is not None:
|
||||
rc.extend(array2)
|
||||
return rc
|
||||
|
||||
# Some tests for the "new" (Feb-2001) DOMString type.
|
||||
def GetDOMStringResult( self ):
|
||||
# Result: DOMString &
|
||||
return "A DOM String"
|
||||
def GetDOMStringOut( self ):
|
||||
# Result: DOMString &
|
||||
return "Another DOM String"
|
||||
def GetDOMStringLength( self, param0 ):
|
||||
# Result: uint32
|
||||
# In: param0: DOMString &
|
||||
return len(param0)
|
||||
|
||||
def GetDOMStringRefLength( self, param0 ):
|
||||
# Result: uint32
|
||||
# In: param0: DOMString &
|
||||
return len(param0)
|
||||
|
||||
def GetDOMStringPtrLength( self, param0 ):
|
||||
# Result: uint32
|
||||
# In: param0: DOMString *
|
||||
return len(param0)
|
||||
|
||||
def ConcatDOMStrings( self, param0, param1 ):
|
||||
# Result: void - None
|
||||
# In: param0: DOMString &
|
||||
# In: param1: DOMString &
|
||||
# Out: DOMString &
|
||||
return param0 + param1
|
||||
def get_domstring_value( self ):
|
||||
# Result: DOMString &
|
||||
return self.domstring_value
|
||||
def set_domstring_value( self, param0 ):
|
||||
# Result: void - None
|
||||
# In: param0: DOMString &
|
||||
self.domstring_value = param0
|
||||
|
||||
def get_domstring_value_ro( self ):
|
||||
# Result: DOMString &
|
||||
return self.domstring_value
|
||||
78
mozilla/extensions/python/xpcom/test/test_components.py
Normal file
78
mozilla/extensions/python/xpcom/test/test_components.py
Normal file
@@ -0,0 +1,78 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
"""Tests the "xpcom.components" object.
|
||||
"""
|
||||
|
||||
import xpcom.components
|
||||
|
||||
if not __debug__:
|
||||
raise RuntimeError, "This test uses assert, so must be run in debug mode"
|
||||
|
||||
def test_interfaces():
|
||||
"Test the xpcom.components.interfaces object"
|
||||
|
||||
iid = xpcom.components.interfaces.nsISupports
|
||||
assert iid == xpcom._xpcom.IID_nsISupports, "Got the wrong IID!"
|
||||
iid = xpcom.components.interfaces['nsISupports']
|
||||
assert iid == xpcom._xpcom.IID_nsISupports, "Got the wrong IID!"
|
||||
|
||||
# Test dictionary semantics
|
||||
num_fetched = num_nsisupports = 0
|
||||
for name, iid in xpcom.components.interfaces.items():
|
||||
num_fetched = num_fetched + 1
|
||||
if name == "nsISupports":
|
||||
num_nsisupports = num_nsisupports + 1
|
||||
assert iid == xpcom._xpcom.IID_nsISupports, "Got the wrong IID!"
|
||||
assert xpcom.components.interfaces[name] == iid
|
||||
# Check all the lengths match.
|
||||
assert len(xpcom.components.interfaces.keys()) == len(xpcom.components.interfaces.values()) == \
|
||||
len(xpcom.components.interfaces.items()) == len(xpcom.components.interfaces) == \
|
||||
num_fetched, "The collection lengths were wrong"
|
||||
if num_nsisupports != 1:
|
||||
print "Didnt find exactly 1 nsiSupports!"
|
||||
print "The interfaces object appeared to work!"
|
||||
|
||||
def test_classes():
|
||||
# Need a well-known contractID here?
|
||||
prog_id = "@mozilla.org/filelocator;1"
|
||||
clsid = xpcom.components.ID("{78043e01-e603-11d2-915f-f08a208628fc}")
|
||||
|
||||
# Check we can create the instance (dont check we can do anything with it tho!)
|
||||
klass = xpcom.components.classes[prog_id]
|
||||
instance = klass.createInstance()
|
||||
|
||||
# Test dictionary semantics
|
||||
num_fetched = num_mine = 0
|
||||
for name, klass in xpcom.components.classes.items():
|
||||
num_fetched = num_fetched + 1
|
||||
if name == prog_id:
|
||||
if klass.clsid != clsid:
|
||||
print "Eeek - didn't get the correct IID - got", klass.clsid
|
||||
num_mine = num_mine + 1
|
||||
|
||||
# xpcom appears to add charset info to the contractid!?
|
||||
# assert xpcom.components.classes[name].contractid == prog_id, "Expected '%s', got '%s'" % (prog_id, xpcom.components.classes[name].contractid)
|
||||
# Check all the lengths match.
|
||||
if len(xpcom.components.classes.keys()) == len(xpcom.components.classes.values()) == \
|
||||
len(xpcom.components.classes.items()) == len(xpcom.components.classes) == \
|
||||
num_fetched:
|
||||
pass
|
||||
else:
|
||||
raise RuntimeError, "The collection lengths were wrong"
|
||||
if num_fetched <= 0:
|
||||
raise RuntimeError, "Didnt get any classes!!!"
|
||||
if num_mine != 1:
|
||||
raise RuntimeError, "Didnt find exactly 1 of my contractid! (%d)" % (num_mine,)
|
||||
print "The classes object appeared to work!"
|
||||
|
||||
def test_id():
|
||||
id = xpcom.components.ID(str(xpcom._xpcom.IID_nsISupports))
|
||||
assert id == xpcom._xpcom.IID_nsISupports
|
||||
print "The ID function appeared to work!"
|
||||
|
||||
|
||||
# regrtest doesnt like if __name__=='__main__' blocks - it fails when running as a test!
|
||||
test_interfaces()
|
||||
test_classes()
|
||||
test_id()
|
||||
@@ -0,0 +1,116 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# Test our support for the interfaces defined in nsISupportsPrimitives.idl
|
||||
#
|
||||
# The framework supports nsISupportsString and nsISupportsWString, but
|
||||
# only if our class doesnt provide explicit support.
|
||||
|
||||
from xpcom import components
|
||||
|
||||
class NoSupportsString:
|
||||
_com_interfaces_ = [components.interfaces.nsISupports]
|
||||
pass
|
||||
|
||||
class ImplicitSupportsString:
|
||||
_com_interfaces_ = [components.interfaces.nsISupports]
|
||||
def __str__(self):
|
||||
return "<MyImplicitStrObject>"
|
||||
|
||||
class ExplicitSupportsString:
|
||||
_com_interfaces_ = [components.interfaces.nsISupports, components.interfaces.nsISupportsString]
|
||||
# __str__ will be ignored by XPCOM, as we have _explicit_ support.
|
||||
def __str__(self):
|
||||
return "<MyImplicitStrObject>"
|
||||
# This is the one that will be used.
|
||||
def toString(self):
|
||||
return "<MyExplicitStrObject>"
|
||||
|
||||
class ImplicitSupportsInt:
|
||||
_com_interfaces_ = [components.interfaces.nsISupports]
|
||||
def __int__(self):
|
||||
return 99
|
||||
|
||||
class ExplicitSupportsInt:
|
||||
_com_interfaces_ = [components.interfaces.nsISupportsPRInt32]
|
||||
def get_data(self):
|
||||
return 99
|
||||
|
||||
class ImplicitSupportsLong:
|
||||
_com_interfaces_ = [components.interfaces.nsISupports]
|
||||
def __long__(self):
|
||||
return 99L
|
||||
|
||||
class ExplicitSupportsLong:
|
||||
_com_interfaces_ = [components.interfaces.nsISupportsPRInt64]
|
||||
def get_data(self):
|
||||
return 99
|
||||
|
||||
class ExplicitSupportsFloat:
|
||||
_com_interfaces_ = [components.interfaces.nsISupportsDouble]
|
||||
def get_data(self):
|
||||
return 99.99
|
||||
|
||||
class ImplicitSupportsFloat:
|
||||
_com_interfaces_ = [components.interfaces.nsISupports]
|
||||
def __float__(self):
|
||||
return 99.99
|
||||
|
||||
def test():
|
||||
import xpcom.server, xpcom.client
|
||||
ob = xpcom.server.WrapObject( NoSupportsString(), components.interfaces.nsISupports)
|
||||
if not str(ob).startswith("<XPCOM interface"):
|
||||
raise RuntimeError, "Wrong str() value: %s" % (ob,)
|
||||
|
||||
ob = xpcom.server.WrapObject( ImplicitSupportsString(), components.interfaces.nsISupports)
|
||||
if str(ob) != "<MyImplicitStrObject>":
|
||||
raise RuntimeError, "Wrong str() value: %s" % (ob,)
|
||||
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsString(), components.interfaces.nsISupports)
|
||||
if str(ob) != "<MyExplicitStrObject>":
|
||||
raise RuntimeError, "Wrong str() value: %s" % (ob,)
|
||||
|
||||
# Try our conversions.
|
||||
try:
|
||||
int(ob)
|
||||
raise RuntimeError, "Expected to get a ValueError converting this COM object to an int"
|
||||
except ValueError:
|
||||
pass
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsInt(), components.interfaces.nsISupports)
|
||||
if int(ob) != 99:
|
||||
raise RuntimeError, "Bad value: %s" % (int(ob),)
|
||||
if float(ob) != 99.0:
|
||||
raise RuntimeError, "Bad value: %s" % (float(ob),)
|
||||
|
||||
ob = xpcom.server.WrapObject( ImplicitSupportsInt(), components.interfaces.nsISupports)
|
||||
if int(ob) != 99:
|
||||
raise RuntimeError, "Bad value: %s" % (int(ob),)
|
||||
if float(ob) != 99.0:
|
||||
raise RuntimeError, "Bad value: %s" % (float(ob),)
|
||||
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsLong(), components.interfaces.nsISupports)
|
||||
if long(ob) != 99 or not repr(long(ob)).endswith("L"):
|
||||
raise RuntimeError, "Bad value: %s" % (repr(long(ob)),)
|
||||
if float(ob) != 99.0:
|
||||
raise RuntimeError, "Bad value: %s" % (float(ob),)
|
||||
|
||||
ob = xpcom.server.WrapObject( ImplicitSupportsLong(), components.interfaces.nsISupports)
|
||||
if long(ob) != 99 or not repr(long(ob)).endswith("L"):
|
||||
raise RuntimeError, "Bad value: %s" % (repr(long(ob)),)
|
||||
if float(ob) != 99.0:
|
||||
raise RuntimeError, "Bad value: %s" % (float(ob),)
|
||||
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsFloat(), components.interfaces.nsISupports)
|
||||
if float(ob) != 99.99:
|
||||
raise RuntimeError, "Bad value: %s" % (float(ob),)
|
||||
if int(ob) != 99:
|
||||
raise RuntimeError, "Bad value: %s" % (int(ob),)
|
||||
|
||||
ob = xpcom.server.WrapObject( ImplicitSupportsFloat(), components.interfaces.nsISupports)
|
||||
if float(ob) != 99.99:
|
||||
raise RuntimeError, "Bad value: %s" % (float(ob),)
|
||||
if int(ob) != 99:
|
||||
raise RuntimeError, "Bad value: %s" % (int(ob),)
|
||||
|
||||
print "The nsISupports primitive interface tests appeared to work"
|
||||
test()
|
||||
171
mozilla/extensions/python/xpcom/test/test_misc.py
Normal file
171
mozilla/extensions/python/xpcom/test/test_misc.py
Normal file
@@ -0,0 +1,171 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
import xpcom
|
||||
import xpcom.client
|
||||
import xpcom._xpcom
|
||||
import xpcom.components
|
||||
import string
|
||||
|
||||
import traceback, getopt, sys
|
||||
|
||||
verbose_level = 0
|
||||
|
||||
def DumpEveryInterfaceUnderTheSun():
|
||||
"Dump every interface under the sun!"
|
||||
import xpcom, xpcom.xpt, xpcom._xpcom
|
||||
iim = xpcom._xpcom.XPTI_GetInterfaceInfoManager()
|
||||
|
||||
print "Dumping every interface I can find - please wait"
|
||||
if verbose_level == 0:
|
||||
print "(verbosity is turned off, so Im not actually going to print them)"
|
||||
enum = iim.EnumerateInterfaces()
|
||||
rc = enum.First()
|
||||
num = 0
|
||||
while rc==0:
|
||||
item = enum.CurrentItem(xpcom._xpcom.IID_nsIInterfaceInfo)
|
||||
try:
|
||||
iid = item.GetIID()
|
||||
except xpcom.Exception:
|
||||
if verbose_level:
|
||||
print "Can't dump", item
|
||||
continue # Dont bother dumping this.
|
||||
interface = xpcom.xpt.Interface(iid)
|
||||
num = num + 1
|
||||
text = interface.Describe()
|
||||
if verbose_level:
|
||||
print text
|
||||
|
||||
rc = enum.Next()
|
||||
if num < 200:
|
||||
print "Only found", num, "interfaces - this seems unusually low!"
|
||||
print "Finished dumping all the interfaces."
|
||||
|
||||
def EnumContractIDs():
|
||||
"""Enumerate all the ContractIDs registered"""
|
||||
cm = xpcom._xpcom.NS_GetGlobalComponentManager()
|
||||
enum = cm.EnumerateContractIDs()
|
||||
rc = enum.First()
|
||||
n = 0
|
||||
while rc == 0:
|
||||
n = n + 1
|
||||
if verbose_level:
|
||||
print "ContractID:", enum.CurrentItem()
|
||||
rc = enum.Next()
|
||||
if n < 200:
|
||||
print "Only found", n, "ContractIDs - this seems unusually low!"
|
||||
print "Enumerated all the ContractIDs"
|
||||
|
||||
def TestSampleComponent():
|
||||
"""Test the standard Netscape 'sample' sample"""
|
||||
# contractid = "mozilla.jssample.1" # the JS version
|
||||
contractid = "@mozilla.org/sample;1" # The C++ version.
|
||||
c = xpcom.components.classes[contractid].createInstance() \
|
||||
.queryInterface(xpcom.components.interfaces.nsISample)
|
||||
assert c.value == "initial value"
|
||||
c.value = "new value"
|
||||
assert c.value == "new value"
|
||||
c.poke("poked value")
|
||||
assert c.value == "poked value"
|
||||
c.writeValue("Python just poked:")
|
||||
print "The netscape sample worked!"
|
||||
|
||||
def TestHash():
|
||||
"Test that hashing COM objects works"
|
||||
d = {}
|
||||
contractid = "@mozilla.org/sample;1" # The C++ version.
|
||||
c = xpcom.components.classes[contractid].createInstance() \
|
||||
.queryInterface(xpcom.components.interfaces.nsISample)
|
||||
d[c] = None
|
||||
if not d.has_key(c):
|
||||
raise RuntimeError, "Can't get the exact same object back!"
|
||||
if not d.has_key(c.queryInterface(xpcom.components.interfaces.nsISupports)):
|
||||
raise RuntimeError, "Can't get back as nsISupports"
|
||||
# And the same in reverse - stick an nsISupports in, and make sure an explicit interface comes back.
|
||||
d = {}
|
||||
contractid = "@mozilla.org/sample;1" # The C++ version.
|
||||
c = xpcom.components.classes[contractid].createInstance() \
|
||||
.queryInterface(xpcom.components.interfaces.nsISupports)
|
||||
d[c] = None
|
||||
if not d.has_key(c):
|
||||
raise RuntimeError, "Can't get the exact same object back!"
|
||||
if not d.has_key(c.queryInterface(xpcom.components.interfaces.nsISample)):
|
||||
raise RuntimeError, "Can't get back as nsISupports"
|
||||
print "xpcom object hashing tests seemed to work"
|
||||
|
||||
def TestIIDs():
|
||||
"Do some basic IID semantic tests."
|
||||
iid_str = "{7ee4bdc6-cb53-42c1-a9e4-616b8e012aba}"
|
||||
IID = xpcom._xpcom.IID
|
||||
assert IID(iid_str)==IID(iid_str), "IIDs with identical strings dont compare!"
|
||||
assert hash(IID(iid_str))==hash(IID(iid_str)), "IIDs with identical strings dont have identical hashes!"
|
||||
assert IID(iid_str)==IID(iid_str.upper()), "IIDs with case-different strings dont compare!"
|
||||
assert hash(IID(iid_str))==hash(IID(iid_str.upper())), "IIDs with case-different strings dont have identical hashes!"
|
||||
# If the above work, this shoud too, but WTF
|
||||
dict = {}
|
||||
dict[IID(iid_str)] = None
|
||||
assert dict.has_key(IID(iid_str))
|
||||
assert dict.has_key(IID(iid_str.upper()))
|
||||
print "The IID tests seemed to work"
|
||||
|
||||
|
||||
def usage(tests):
|
||||
import os
|
||||
print "Usage: %s [-v] [Test ...]" % os.path.basename(sys.argv[0])
|
||||
print " -v : Verbose - print more information"
|
||||
print "where Test is one of:"
|
||||
for t in tests:
|
||||
print t.__name__,":", t.__doc__
|
||||
print
|
||||
print "If not tests are specified, all tests are run"
|
||||
sys.exit(1)
|
||||
|
||||
def main():
|
||||
tests = []
|
||||
args = []
|
||||
for ob in globals().values():
|
||||
if type(ob)==type(main) and ob.__doc__:
|
||||
tests.append(ob)
|
||||
if __name__ == '__main__': # Only process args when not running under the test suite!
|
||||
opts, args = getopt.getopt(sys.argv[1:], "hv")
|
||||
for opt, val in opts:
|
||||
if opt=="-h":
|
||||
usage(tests)
|
||||
if opt=="-v":
|
||||
global verbose_level
|
||||
verbose_level = verbose_level + 1
|
||||
|
||||
if len(args)==0:
|
||||
print "Running all tests - use '-h' to see command-line options..."
|
||||
dotests = tests
|
||||
else:
|
||||
dotests = []
|
||||
for arg in args:
|
||||
for t in tests:
|
||||
if t.__name__==arg:
|
||||
dotests.append(t)
|
||||
break
|
||||
else:
|
||||
print "Test '%s' unknown - skipping" % arg
|
||||
if not len(dotests):
|
||||
print "Nothing to do!"
|
||||
usage(tests)
|
||||
for test in dotests:
|
||||
try:
|
||||
test()
|
||||
except:
|
||||
print "Test %s failed" % test.__name__
|
||||
traceback.print_exc()
|
||||
|
||||
# regrtest doesnt like if __name__=='__main__' blocks - it fails when running as a test!
|
||||
|
||||
|
||||
main()
|
||||
if __name__=='__main__':
|
||||
# We can only afford to shutdown if we are truly running as the main script.
|
||||
# (xpcom can't handle shutdown/init pairs)
|
||||
xpcom._xpcom.NS_ShutdownXPCOM()
|
||||
ni = xpcom._xpcom._GetInterfaceCount()
|
||||
ng = xpcom._xpcom._GetGatewayCount()
|
||||
if ni or ng:
|
||||
print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
|
||||
86
mozilla/extensions/python/xpcom/test/test_streams.py
Normal file
86
mozilla/extensions/python/xpcom/test/test_streams.py
Normal file
@@ -0,0 +1,86 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
import xpcom
|
||||
from xpcom import _xpcom, components, COMException, ServerException, nsError
|
||||
from StringIO import StringIO
|
||||
|
||||
test_data = "abcdefeghijklmnopqrstuvwxyz"
|
||||
|
||||
class koTestSimpleStreamBase:
|
||||
_com_interfaces_ = [components.interfaces.nsIInputStream]
|
||||
# We avoid registering this object - see comments in get_test_inout_? below.
|
||||
|
||||
def __init__(self):
|
||||
self.data=StringIO(test_data)
|
||||
|
||||
def close( self ):
|
||||
pass
|
||||
|
||||
def available( self ):
|
||||
return self.data.len-self.data.pos
|
||||
|
||||
def readStr( self, amount):
|
||||
return self.data.read(amount)
|
||||
|
||||
read=readStr
|
||||
|
||||
def get_observer( self ):
|
||||
raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED)
|
||||
|
||||
def set_observer( self, param0 ):
|
||||
raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED)
|
||||
|
||||
# This class has "nonBlocking" as an attribute.
|
||||
class koTestSimpleStream1(koTestSimpleStreamBase):
|
||||
nonBlocking=0
|
||||
|
||||
# This class has "nonBlocking" as getter/setters.
|
||||
class koTestSimpleStream2(koTestSimpleStreamBase):
|
||||
def __init__(self):
|
||||
koTestSimpleStreamBase.__init__(self)
|
||||
self.isNonBlocking = 0
|
||||
def get_nonBlocking(self):
|
||||
return self.isNonBlocking
|
||||
|
||||
def get_test_input_1():
|
||||
# We use a couple of internal hacks here that mean we can avoid having the object
|
||||
# registered. This code means that we are still working over the xpcom boundaries, tho
|
||||
# (and the point of this test is not the registration, etc).
|
||||
import xpcom.server, xpcom.client
|
||||
ob = xpcom.server.WrapObject( koTestSimpleStream1(), _xpcom.IID_nsISupports)
|
||||
ob = xpcom.client.Component(ob, components.interfaces.nsIInputStream)
|
||||
return ob
|
||||
|
||||
def get_test_input_2():
|
||||
# We use a couple of internal hacks here that mean we can avoid having the object
|
||||
# registered. This code means that we are still working over the xpcom boundaries, tho
|
||||
# (and the point of this test is not the registration, etc).
|
||||
import xpcom.server, xpcom.client
|
||||
ob = xpcom.server.WrapObject( koTestSimpleStream2(), _xpcom.IID_nsISupports)
|
||||
ob = xpcom.client.Component(ob, components.interfaces.nsIInputStream)
|
||||
return ob
|
||||
|
||||
def test_input(myStream):
|
||||
if myStream.read(5) != test_data[:5]:
|
||||
raise "Read the wrong data!"
|
||||
if myStream.read(0) != '':
|
||||
raise "Read the wrong emtpy data!"
|
||||
if myStream.read(5) != test_data[5:10]:
|
||||
raise "Read the wrong data after an empty read!"
|
||||
if myStream.read(-1) != test_data[10:]:
|
||||
raise "Couldnt read the rest of the data"
|
||||
if myStream.nonBlocking:
|
||||
raise "Expected default to be blocking"
|
||||
try:
|
||||
myStream.observer = None
|
||||
raise "Shouldnt get here!"
|
||||
except COMException, details:
|
||||
if details.errno != nsError.NS_ERROR_NOT_IMPLEMENTED:
|
||||
raise "Unexpected COM exception: %s (%r)" % (details, details)
|
||||
|
||||
if __name__=='__main__':
|
||||
test_input( get_test_input_1() )
|
||||
test_input( get_test_input_2() )
|
||||
print "The stream tests worked!"
|
||||
|
||||
80
mozilla/extensions/python/xpcom/test/test_test_component.js
Normal file
80
mozilla/extensions/python/xpcom/test/test_test_component.js
Normal file
@@ -0,0 +1,80 @@
|
||||
/* Javascript code calling the Python test interface. */
|
||||
|
||||
function MakeTestInterface()
|
||||
{
|
||||
var clazz = Components.classes["Python.TestComponent"];
|
||||
var iface = Components.interfaces.nsIPythonTestInterfaceDOMStrings;
|
||||
return new clazz(iface);
|
||||
}
|
||||
|
||||
var c = new MakeTestInterface();
|
||||
|
||||
if (c.boolean_value != 1)
|
||||
throw("boolean_value has wrong initial value");
|
||||
c.boolean_value = false;
|
||||
if (c.boolean_value != false)
|
||||
throw("boolean_value has wrong new value");
|
||||
|
||||
// Python's own test does thorough testing of all numeric types
|
||||
// Wont bother from here!
|
||||
|
||||
if (c.char_value != 'a')
|
||||
throw("char_value has wrong initial value");
|
||||
c.char_value = 'b';
|
||||
if (c.char_value != 'b')
|
||||
throw("char_value has wrong new value");
|
||||
|
||||
if (c.wchar_value != 'b')
|
||||
throw("wchar_value has wrong initial value");
|
||||
c.wchar_value = 'c';
|
||||
if (c.wchar_value != 'c')
|
||||
throw("wchar_value has wrong new value");
|
||||
|
||||
if (c.string_value != 'cee')
|
||||
throw("string_value has wrong initial value");
|
||||
c.string_value = 'dee';
|
||||
if (c.string_value != 'dee')
|
||||
throw("string_value has wrong new value");
|
||||
|
||||
if (c.wstring_value != 'dee')
|
||||
throw("wstring_value has wrong initial value");
|
||||
c.wstring_value = 'eee';
|
||||
if (c.wstring_value != 'eee')
|
||||
throw("wstring_value has wrong new value");
|
||||
|
||||
if (c.domstring_value != 'dom')
|
||||
throw("domstring_value has wrong initial value");
|
||||
c.domstring_value = 'New value';
|
||||
if (c.domstring_value != 'New value')
|
||||
throw("domstring_value has wrong new value");
|
||||
|
||||
var v = new Object();
|
||||
v.value = "Hello"
|
||||
var l = new Object();
|
||||
l.value = v.value.length;
|
||||
c.DoubleString(l, v);
|
||||
if ( v.value != "HelloHello")
|
||||
throw("Could not double the string!");
|
||||
|
||||
var v = new Object();
|
||||
v.value = "Hello"
|
||||
var l = new Object();
|
||||
l.value = v.value.length;
|
||||
c.DoubleWideString(l, v);
|
||||
if ( v.value != "HelloHello")
|
||||
throw("Could not double the wide string!");
|
||||
|
||||
// Some basic array tests
|
||||
var v = new Array()
|
||||
v[0] = 1;
|
||||
v[2] = 2;
|
||||
v[3] = 3;
|
||||
var v2 = new Array()
|
||||
v2[0] = 4;
|
||||
v2[2] = 5;
|
||||
v2[3] = 6;
|
||||
if (c.SumArrays(v.length, v, v2) != 21)
|
||||
throw("Could not sum an array of integers!");
|
||||
|
||||
|
||||
print("javascript successfully tested the Python test component.");
|
||||
435
mozilla/extensions/python/xpcom/test/test_test_component.py
Normal file
435
mozilla/extensions/python/xpcom/test/test_test_component.py
Normal file
@@ -0,0 +1,435 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
import sys, os
|
||||
import xpcom.components
|
||||
import xpcom._xpcom
|
||||
import xpcom.nsError
|
||||
|
||||
num_errors = 0
|
||||
|
||||
component_iid = xpcom.components.ID("{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}")
|
||||
new_iid = xpcom.components.ID("{2AF747D3-ECBC-457b-9AF9-5C5D80EDC360}")
|
||||
|
||||
contractid = "Python.TestComponent"
|
||||
|
||||
really_big_string = "This is really repetitive!" * 10000
|
||||
really_big_wstring = u"This is really repetitive!" * 10000
|
||||
|
||||
def print_error(error):
|
||||
print error
|
||||
global num_errors
|
||||
num_errors = num_errors + 1
|
||||
|
||||
def _test_value(what, got, expecting):
|
||||
ok = got == expecting
|
||||
if type(got)==type(expecting)==type(0.0):
|
||||
ok = abs(got-expecting) < 0.001
|
||||
if not ok:
|
||||
print_error("*** Error %s - got '%r', but expecting '%r'" % (what, got, expecting))
|
||||
|
||||
def test_attribute(ob, attr_name, expected_init, new_value, new_value_really = None):
|
||||
if xpcom.verbose:
|
||||
print "Testing attribute %s" % (attr_name,)
|
||||
if new_value_really is None:
|
||||
new_value_really = new_value # Handy for eg bools - set a BOOL to 2, you still get back 1!
|
||||
|
||||
_test_value( "getting initial attribute value (%s)" % (attr_name,), getattr(ob, attr_name), expected_init)
|
||||
setattr(ob, attr_name, new_value)
|
||||
_test_value( "getting new attribute value (%s)" % (attr_name,), getattr(ob, attr_name), new_value_really)
|
||||
# And set it back to the expected init.
|
||||
setattr(ob, attr_name, expected_init)
|
||||
_test_value( "getting back initial attribute value after change (%s)" % (attr_name,), getattr(ob, attr_name), expected_init)
|
||||
|
||||
def test_attribute_failure(ob, attr_name, new_value, expected_exception):
|
||||
try:
|
||||
setattr(ob, attr_name, new_value)
|
||||
print_error("*** Setting attribute '%s' to '%r' didnt yield an exception!" % (attr_name, new_value) )
|
||||
except:
|
||||
exc_typ = sys.exc_info()[0]
|
||||
ok = issubclass(exc_typ, expected_exception)
|
||||
if not ok:
|
||||
print_error("*** Wrong exception setting '%s' to '%r'- got '%s: %s', expected '%s'" % (attr_name, new_value, exc_typ, exc_val, expected_exception))
|
||||
|
||||
|
||||
def test_method(method, args, expected_results):
|
||||
if xpcom.verbose:
|
||||
print "Testing %s%s" % (method.__name__, `args`)
|
||||
ret = method(*args)
|
||||
if ret != expected_results:
|
||||
print_error("calling method %s - expected %s, but got %s" % (method.__name__, expected_results, ret))
|
||||
|
||||
def test_int_method(meth):
|
||||
test_method(meth, (0,0), (0,0,0))
|
||||
test_method(meth, (1,1), (2,0,1))
|
||||
test_method(meth, (5,2), (7,3,10))
|
||||
# test_method(meth, (2,5), (7,-3,10))
|
||||
|
||||
def test_constant(ob, cname, val):
|
||||
v = getattr(ob, cname)
|
||||
if v != val:
|
||||
print_error("Bad value for constant '%s' - got '%r'" % (cname, v))
|
||||
try:
|
||||
setattr(ob, cname, 0)
|
||||
print_error("The object allowed us to set the constant '%s'" % (cname,))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def test_base_interface(c):
|
||||
test_attribute(c, "boolean_value", 1, 0)
|
||||
test_attribute(c, "boolean_value", 1, -1, 1) # Set a bool to anything, you should always get back 0 or 1
|
||||
test_attribute(c, "boolean_value", 1, 4, 1) # Set a bool to anything, you should always get back 0 or 1
|
||||
test_attribute(c, "boolean_value", 1, "1", 1) # This works by virtual of PyNumber_Int - not sure I agree, but...
|
||||
test_attribute_failure(c, "boolean_value", "boo", ValueError)
|
||||
test_attribute_failure(c, "boolean_value", test_base_interface, TypeError)
|
||||
|
||||
test_attribute(c, "octet_value", 2, 5)
|
||||
test_attribute(c, "octet_value", 2, 0)
|
||||
test_attribute(c, "octet_value", 2, 128) # octet is unsigned 8 bit
|
||||
test_attribute(c, "octet_value", 2, 255) # octet is unsigned 8 bit
|
||||
test_attribute(c, "octet_value", 2, -1, 255) # octet is unsigned 8 bit
|
||||
test_attribute_failure(c, "octet_value", "boo", ValueError)
|
||||
|
||||
test_attribute(c, "short_value", 3, 10)
|
||||
test_attribute(c, "short_value", 3, -1) # 16 bit signed
|
||||
test_attribute(c, "short_value", 3, 0xFFFF, -1) # 16 bit signed
|
||||
test_attribute(c, "short_value", 3, 0L)
|
||||
test_attribute(c, "short_value", 3, 1L)
|
||||
test_attribute(c, "short_value", 3, -1L)
|
||||
test_attribute(c, "short_value", 3, 0xFFFFL, -1)
|
||||
test_attribute_failure(c, "short_value", "boo", ValueError)
|
||||
|
||||
test_attribute(c, "ushort_value", 4, 5)
|
||||
test_attribute(c, "ushort_value", 4, 0)
|
||||
test_attribute(c, "ushort_value", 4, -1, 0xFFFF) # 16 bit signed
|
||||
test_attribute(c, "ushort_value", 4, 0xFFFF) # 16 bit signed
|
||||
test_attribute(c, "ushort_value", 4, 0L)
|
||||
test_attribute(c, "ushort_value", 4, 1L)
|
||||
test_attribute(c, "ushort_value", 4, -1L, 0xFFFF)
|
||||
test_attribute_failure(c, "ushort_value", "boo", ValueError)
|
||||
|
||||
test_attribute(c, "long_value", 5, 7)
|
||||
test_attribute(c, "long_value", 5, 0)
|
||||
test_attribute(c, "long_value", 5, 0xFFFFFFFF, -1) # 32 bit signed.
|
||||
test_attribute(c, "long_value", 5, -1) # 32 bit signed.
|
||||
test_attribute(c, "long_value", 5, 0L)
|
||||
test_attribute(c, "long_value", 5, 1L)
|
||||
test_attribute(c, "long_value", 5, -1L)
|
||||
test_attribute_failure(c, "long_value", 0xFFFFL * 0xFFFF, OverflowError) # long int too long to convert
|
||||
test_attribute_failure(c, "long_value", "boo", ValueError)
|
||||
|
||||
test_attribute(c, "ulong_value", 6, 7)
|
||||
test_attribute(c, "ulong_value", 6, 0)
|
||||
test_attribute(c, "ulong_value", 6, 0xFFFFFFFF) # 32 bit signed.
|
||||
test_attribute_failure(c, "ulong_value", "boo", ValueError)
|
||||
|
||||
test_attribute(c, "long_long_value", 7, 8)
|
||||
test_attribute(c, "long_long_value", 7, 0)
|
||||
test_attribute(c, "long_long_value", 7, -1)
|
||||
test_attribute(c, "long_long_value", 7, 0xFFFF)
|
||||
test_attribute(c, "long_long_value", 7, 0xFFFFL * 2)
|
||||
test_attribute_failure(c, "long_long_value", 0xFFFFL * 0xFFFF * 0xFFFF * 0xFFFF, OverflowError) # long int too long to convert
|
||||
test_attribute_failure(c, "long_long_value", "boo", ValueError)
|
||||
|
||||
test_attribute(c, "ulong_long_value", 8, 9)
|
||||
test_attribute(c, "ulong_long_value", 8, 0)
|
||||
test_attribute_failure(c, "ulong_long_value", "boo", ValueError)
|
||||
test_attribute_failure(c, "ulong_long_value", -1, OverflowError) # can't convert negative value to unsigned long)
|
||||
|
||||
test_attribute(c, "float_value", 9.0, 10.2)
|
||||
test_attribute(c, "float_value", 9.0, 0)
|
||||
test_attribute(c, "float_value", 9.0, -1)
|
||||
test_attribute(c, "float_value", 9.0, 1L)
|
||||
test_attribute_failure(c, "float_value", "boo", ValueError)
|
||||
|
||||
test_attribute(c, "double_value", 10.0, 9.0)
|
||||
test_attribute(c, "double_value", 10.0, 0)
|
||||
test_attribute(c, "double_value", 10.0, -1)
|
||||
test_attribute(c, "double_value", 10.0, 1L)
|
||||
test_attribute_failure(c, "double_value", "boo", ValueError)
|
||||
|
||||
test_attribute(c, "char_value", "a", "b")
|
||||
test_attribute(c, "char_value", "a", "\0")
|
||||
test_attribute_failure(c, "char_value", "xy", ValueError)
|
||||
test_attribute(c, "char_value", "a", u"c")
|
||||
test_attribute(c, "char_value", "a", u"\0")
|
||||
test_attribute_failure(c, "char_value", u"xy", ValueError)
|
||||
|
||||
test_attribute(c, "wchar_value", "b", "a")
|
||||
test_attribute(c, "wchar_value", "b", "\0")
|
||||
test_attribute_failure(c, "wchar_value", "hi", ValueError)
|
||||
test_attribute(c, "wchar_value", "b", u"a")
|
||||
test_attribute(c, "wchar_value", "b", u"\0")
|
||||
test_attribute_failure(c, "wchar_value", u"hi", ValueError)
|
||||
|
||||
test_attribute(c, "string_value", "cee", "dee")
|
||||
test_attribute(c, "string_value", "cee", "a null >\0<", "a null >") # strings are NULL terminated!!
|
||||
test_attribute(c, "string_value", "cee", "")
|
||||
test_attribute(c, "string_value", "cee", u"dee")
|
||||
test_attribute(c, "string_value", "cee", u"a null >\0<", "a null >") # strings are NULL terminated!!
|
||||
test_attribute(c, "string_value", "cee", u"")
|
||||
|
||||
test_attribute(c, "wstring_value", "dee", "cee")
|
||||
test_attribute(c, "wstring_value", "dee", "a null >\0<", "a null >") # strings are NULL terminated!!
|
||||
test_attribute(c, "wstring_value", "dee", "")
|
||||
test_attribute(c, "wstring_value", "dee", really_big_string)
|
||||
test_attribute(c, "wstring_value", "dee", u"cee")
|
||||
test_attribute(c, "wstring_value", "dee", u"a null >\0<", "a null >") # strings are NULL terminated!!
|
||||
test_attribute(c, "wstring_value", "dee", u"")
|
||||
test_attribute(c, "wstring_value", "dee", really_big_wstring)
|
||||
|
||||
test_attribute(c, "iid_value", component_iid, new_iid)
|
||||
test_attribute(c, "iid_value", component_iid, str(new_iid), new_iid)
|
||||
test_attribute(c, "iid_value", component_iid, xpcom._xpcom.IID(new_iid))
|
||||
|
||||
test_attribute_failure(c, "no_attribute", "boo", AttributeError)
|
||||
|
||||
test_attribute(c, "interface_value", None, c)
|
||||
test_attribute_failure(c, "interface_value", 2, TypeError)
|
||||
|
||||
test_attribute(c, "isupports_value", None, c)
|
||||
|
||||
# The methods
|
||||
test_method(c.do_boolean, (0,1), (1,0,1))
|
||||
test_method(c.do_boolean, (1,0), (1,0,1))
|
||||
test_method(c.do_boolean, (1,1), (0,1,0))
|
||||
|
||||
test_int_method(c.do_octet)
|
||||
test_int_method(c.do_short)
|
||||
|
||||
test_int_method(c.do_unsigned_short)
|
||||
test_int_method(c.do_long)
|
||||
test_int_method(c.do_unsigned_long)
|
||||
test_int_method(c.do_long_long)
|
||||
test_int_method(c.do_unsigned_long)
|
||||
test_int_method(c.do_float)
|
||||
test_int_method(c.do_double)
|
||||
|
||||
test_method(c.do_char, ("A", " "), (chr(ord("A")+ord(" ")), " ","A") )
|
||||
test_method(c.do_char, ("A", "\0"), ("A", "\0","A") )
|
||||
test_method(c.do_wchar, ("A", " "), (chr(ord("A")+ord(" ")), " ","A") )
|
||||
test_method(c.do_wchar, ("A", "\0"), ("A", "\0","A") )
|
||||
|
||||
test_method(c.do_string, ("Hello from ", "Python"), ("Hello from Python", "Hello from ", "Python") )
|
||||
test_method(c.do_string, (u"Hello from ", u"Python"), ("Hello from Python", "Hello from ", "Python") )
|
||||
test_method(c.do_string, (None, u"Python"), ("Python", None, "Python") )
|
||||
test_method(c.do_string, (None, really_big_string), (really_big_string, None, really_big_string) )
|
||||
test_method(c.do_string, (None, really_big_wstring), (really_big_string, None, really_big_string) )
|
||||
test_method(c.do_wstring, ("Hello from ", "Python"), ("Hello from Python", "Hello from ", "Python") )
|
||||
test_method(c.do_wstring, (u"Hello from ", u"Python"), ("Hello from Python", "Hello from ", "Python") )
|
||||
test_method(c.do_string, (None, really_big_wstring), (really_big_wstring, None, really_big_wstring) )
|
||||
test_method(c.do_string, (None, really_big_string), (really_big_wstring, None, really_big_wstring) )
|
||||
test_method(c.do_nsIIDRef, (component_iid, new_iid), (component_iid, component_iid, new_iid))
|
||||
test_method(c.do_nsIIDRef, (new_iid, component_iid), (new_iid, component_iid, component_iid))
|
||||
test_method(c.do_nsIPythonTestInterface, (None, None), (None, None, c))
|
||||
test_method(c.do_nsIPythonTestInterface, (c, c), (c, c, c))
|
||||
test_method(c.do_nsISupports, (None, None), (c, None, None))
|
||||
test_method(c.do_nsISupports, (c,c), (c, c, c))
|
||||
test_method(c.do_nsISupportsIs, (xpcom._xpcom.IID_nsISupports,), c)
|
||||
test_method(c.do_nsISupportsIs, (xpcom.components.interfaces.nsIPythonTestInterface,), c)
|
||||
## test_method(c.do_nsISupportsIs2, (xpcom.components.interfaces.nsIPythonTestInterface,c), (xpcom.components.interfaces.nsIPythonTestInterface,c))
|
||||
## test_method(c.do_nsISupportsIs3, (c,), (xpcom.components.interfaces.nsIPythonTestInterface,c))
|
||||
## test_method(c.do_nsISupportsIs4, (), (xpcom.components.interfaces.nsIPythonTestInterface,c))
|
||||
# Test the constants.
|
||||
test_constant(c, "One", 1)
|
||||
test_constant(c, "Two", 2)
|
||||
test_constant(c, "MinusOne", -1)
|
||||
test_constant(c, "BigLong", 0x7FFFFFFF)
|
||||
test_constant(c, "BigULong", 0xFFFFFFFF)
|
||||
# Test the components.Interfaces semantics
|
||||
i = xpcom.components.interfaces.nsIPythonTestInterface
|
||||
test_constant(i, "One", 1)
|
||||
test_constant(i, "Two", 2)
|
||||
test_constant(i, "MinusOne", -1)
|
||||
test_constant(i, "BigLong", 0x7FFFFFFF)
|
||||
test_constant(i, "BigULong", 0xFFFFFFFF)
|
||||
|
||||
def test_derived_interface(c):
|
||||
val = "Hello\0there"
|
||||
expected = val * 2
|
||||
|
||||
test_method(c.DoubleString, (val,), expected)
|
||||
test_method(c.DoubleString2, (val,), expected)
|
||||
test_method(c.DoubleString3, (val,), expected)
|
||||
test_method(c.DoubleString4, (val,), expected)
|
||||
test_method(c.UpString, (val,), val.upper())
|
||||
test_method(c.UpString2, (val,), val.upper())
|
||||
test_method(c.GetFixedString, (20,), "A"*20)
|
||||
val = u"Hello\0there"
|
||||
expected = val * 2
|
||||
test_method(c.DoubleWideString, (val,), expected)
|
||||
test_method(c.DoubleWideString2, (val,), expected)
|
||||
test_method(c.DoubleWideString3, (val,), expected)
|
||||
test_method(c.DoubleWideString4, (val,), expected)
|
||||
test_method(c.UpWideString, (val,), val.upper())
|
||||
test_method(c.UpWideString2, (val,), val.upper())
|
||||
test_method(c.GetFixedWideString, (20,), u"A"*20)
|
||||
items = [1,2,3,4,5]
|
||||
test_method(c.MultiplyEachItemInIntegerArray, (3, items,), map(lambda i:i*3, items))
|
||||
|
||||
test_method(c.MultiplyEachItemInIntegerArrayAndAppend, (3, items), items + map(lambda i:i*3, items))
|
||||
items = "Hello from Python".split()
|
||||
expected = map( lambda x: x*2, items)
|
||||
test_method(c.DoubleStringArray, (items,), expected)
|
||||
|
||||
test_method(c.CompareStringArrays, (items, items), cmp(items, items))
|
||||
# Can we pass lists and tuples correctly?
|
||||
test_method(c.CompareStringArrays, (items, tuple(items)), cmp(items, items))
|
||||
items2 = ["Not", "the", "same"]
|
||||
test_method(c.CompareStringArrays, (items, items2), cmp(items, items2))
|
||||
|
||||
expected = items[:]
|
||||
expected.reverse()
|
||||
test_method(c.ReverseStringArray, (items,), expected)
|
||||
|
||||
expected = "Hello from the Python test component".split()
|
||||
test_method(c.GetStrings, (), expected)
|
||||
|
||||
val = "Hello\0there"
|
||||
test_method(c.UpOctetArray, (val,), val.upper())
|
||||
test_method(c.UpOctetArray2, (val,), val.upper())
|
||||
|
||||
test_method(c.CheckInterfaceArray, ((c, c),), 1)
|
||||
test_method(c.CheckInterfaceArray, ((c, None),), 0)
|
||||
test_method(c.CheckInterfaceArray, ((),), 1)
|
||||
|
||||
test_method(c.GetInterfaceArray, (), [c,c,c, None])
|
||||
test_method(c.ExtendInterfaceArray, ((c,c,c, None),), [c,c,c,None,c,c,c,None] )
|
||||
|
||||
expected = [xpcom.components.interfaces.nsIPythonTestInterfaceDOMStrings, xpcom.components.classes[contractid].clsid]
|
||||
test_method(c.GetIIDArray, (), expected)
|
||||
|
||||
val = [xpcom.components.interfaces.nsIPythonTestInterfaceExtra, xpcom.components.classes[contractid].clsid]
|
||||
expected = val * 2
|
||||
test_method(c.ExtendIIDArray, (val,), expected)
|
||||
|
||||
test_method(c.GetArrays, (), ( [1,2,3], [4,5,6] ) )
|
||||
test_method(c.CopyArray, ([1,2,3],), [1,2,3] )
|
||||
test_method(c.CopyAndDoubleArray, ([1,2,3],), [1,2,3,1,2,3] )
|
||||
test_method(c.AppendArray, ([1,2,3],), [1,2,3])
|
||||
test_method(c.AppendArray, ([1,2,3],[4,5,6]), [1,2,3,4,5,6])
|
||||
|
||||
c = c.queryInterface(xpcom.components.interfaces.nsIPythonTestInterfaceDOMStrings)
|
||||
test_method(c.GetDOMStringResult, (), "A DOM String")
|
||||
test_method(c.GetDOMStringOut, (), "Another DOM String")
|
||||
val = "Hello there"
|
||||
test_method(c.GetDOMStringLength, (val,), len(val))
|
||||
test_method(c.GetDOMStringRefLength, (val,), len(val))
|
||||
test_method(c.GetDOMStringPtrLength, (val,), len(val))
|
||||
test_method(c.ConcatDOMStrings, (val,val), val+val)
|
||||
test_attribute(c, "domstring_value", "dom", "new dom")
|
||||
if c.domstring_value_ro != "dom":
|
||||
print "Read-only DOMString not currect - got", c.domstring_ro
|
||||
try:
|
||||
c.dom_string_ro = "new dom"
|
||||
print "Managed to set a readonly attribute - eek!"
|
||||
except AttributeError:
|
||||
pass
|
||||
except:
|
||||
print "Unexpected exception when setting readonly attribute: %s: %s" % (sys.exc_info()[0], sys.exc_info()[1])
|
||||
if c.domstring_value_ro != "dom":
|
||||
print "Read-only DOMString not correct after failed set attempt - got", c.domstring_ro
|
||||
|
||||
def do_test_failures():
|
||||
c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterfaceExtra)
|
||||
try:
|
||||
ret = c.do_nsISupportsIs( xpcom._xpcom.IID_nsIInterfaceInfoManager )
|
||||
print "*** got", ret, "***"
|
||||
raise RuntimeError, "We worked when using an IID we dont support!?!"
|
||||
except xpcom.Exception, details:
|
||||
if details.errno != xpcom.nsError.NS_ERROR_NO_INTERFACE:
|
||||
raise RuntimeError, "Wrong COM exception type: %r" % (details,)
|
||||
|
||||
def test_failures():
|
||||
# This extra stack-frame ensures Python cleans up sys.last_traceback etc
|
||||
do_test_failures()
|
||||
|
||||
def test_all():
|
||||
c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterface)
|
||||
test_base_interface(c)
|
||||
# Now create an instance using the derived IID, and test that.
|
||||
c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterfaceExtra)
|
||||
test_base_interface(c)
|
||||
test_derived_interface(c)
|
||||
test_failures()
|
||||
|
||||
try:
|
||||
from sys import gettotalrefcount
|
||||
except ImportError:
|
||||
# Not a Debug build - assume no references (can't be leaks then :-)
|
||||
def gettotalrefcount():
|
||||
return 0
|
||||
|
||||
def test_from_js():
|
||||
# Ensure we can find the js test script - same dir as this!
|
||||
# Assume the path of sys.argv[0] is where we can find the js test code.
|
||||
# (Running under the regression test is a little painful)
|
||||
script_dir = os.path.split(sys.argv[0])[0]
|
||||
fname = os.path.join( script_dir, "test_test_component.js")
|
||||
if not os.path.isfile(fname):
|
||||
raise RuntimeError, "Can not find '%s'" % (fname,)
|
||||
# Note we _dont_ pump the test output out, as debug "xpcshell" spews
|
||||
# extra debug info that will cause our output comparison to fail.
|
||||
try:
|
||||
data = os.popen('xpcshell "' + fname + '"').readlines()
|
||||
good = 0
|
||||
for line in data:
|
||||
if line.strip() == "javascript successfully tested the Python test component.":
|
||||
good = 1
|
||||
if good:
|
||||
print "Javascript could successfully use the Python test component."
|
||||
else:
|
||||
print "** The javascript test appeared to fail! Test output follows **"
|
||||
print "".join(data)
|
||||
print "** End of javascript test output **"
|
||||
|
||||
except os.error, why:
|
||||
print "Error executing the javascript test program:", why
|
||||
|
||||
|
||||
def doit(num_loops = -1):
|
||||
if "-v" in sys.argv: # Hack the verbose flag for the server
|
||||
xpcom.verbose = 1
|
||||
# Do the test lots of times - can help shake-out ref-count bugs.
|
||||
print "Testing the Python.TestComponent component"
|
||||
if num_loops == -1: num_loops = 10
|
||||
for i in xrange(num_loops):
|
||||
test_all()
|
||||
|
||||
if i==0:
|
||||
# First loop is likely to "leak" as we cache things.
|
||||
# Leaking after that is a problem.
|
||||
num_refs = gettotalrefcount()
|
||||
|
||||
if num_errors:
|
||||
break
|
||||
|
||||
lost = gettotalrefcount() - num_refs
|
||||
# Sometimes we get spurious counts off by 1 or 2.
|
||||
# This can't indicate a real leak, as we have looped
|
||||
# more than twice!
|
||||
if abs(lost)>2:
|
||||
print "*** Lost %d references" % (lost,)
|
||||
|
||||
if num_errors:
|
||||
print "There were", num_errors, "errors testing the Python component :-("
|
||||
else:
|
||||
print "The Python test component worked!"
|
||||
|
||||
# regrtest doesnt like if __name__=='__main__' blocks - it fails when running as a test!
|
||||
num_iters = -1
|
||||
if __name__=='__main__' and len(sys.argv) > 1:
|
||||
num_iters = int(sys.argv[1])
|
||||
|
||||
doit(num_iters)
|
||||
test_from_js()
|
||||
|
||||
if __name__=='__main__':
|
||||
# But we can only do this if _not_ testing - otherwise we
|
||||
# screw up any tests that want to run later.
|
||||
xpcom._xpcom.NS_ShutdownXPCOM()
|
||||
ni = xpcom._xpcom._GetInterfaceCount()
|
||||
ng = xpcom._xpcom._GetGatewayCount()
|
||||
if ni or ng:
|
||||
print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
|
||||
|
||||
52
mozilla/extensions/python/xpcom/test/test_weakreferences.py
Normal file
52
mozilla/extensions/python/xpcom/test/test_weakreferences.py
Normal file
@@ -0,0 +1,52 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# test_weakreferences.py - Test our weak reference implementation.
|
||||
from xpcom import components, _xpcom
|
||||
import xpcom.server, xpcom.client
|
||||
|
||||
num_alive = 0
|
||||
|
||||
class koTestSimple:
|
||||
_com_interfaces_ = [components.interfaces.nsIInputStream]
|
||||
def __init__(self):
|
||||
global num_alive
|
||||
num_alive += 1
|
||||
def __del__(self):
|
||||
global num_alive
|
||||
num_alive -= 1
|
||||
def close( self ):
|
||||
pass
|
||||
|
||||
def test():
|
||||
ob = xpcom.server.WrapObject( koTestSimple(), components.interfaces.nsIInputStream)
|
||||
|
||||
if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
|
||||
|
||||
# Check we can create a weak reference to our object.
|
||||
wr = xpcom.client.WeakReference(ob)
|
||||
if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
|
||||
|
||||
# Check we can call methods via the weak reference.
|
||||
if wr() is None: raise RuntimeError, "Our weak-reference is returning None before it should!"
|
||||
wr().close()
|
||||
|
||||
ob = None # This should kill the object.
|
||||
if num_alive != 0: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
|
||||
if wr() is not None: raise RuntimeError, "Our weak-reference is not returning None when it should!"
|
||||
|
||||
# Now a test that we can get a _new_ interface from the weak reference - ie,
|
||||
# an IID the real object has never previously been queried for
|
||||
# (this behaviour previously caused a bug - never again ;-)
|
||||
ob = xpcom.server.WrapObject( koTestSimple(), components.interfaces.nsISupports)
|
||||
if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
|
||||
wr = xpcom.client.WeakReference(ob, components.interfaces.nsIInputStream)
|
||||
if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
|
||||
wr() # This would die once upon a time ;-)
|
||||
ob = None # This should kill the object.
|
||||
if num_alive != 0: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
|
||||
if wr() is not None: raise RuntimeError, "Our weak-reference is not returning None when it should!"
|
||||
|
||||
|
||||
test()
|
||||
print "Weak-reference tests appear to have worked!"
|
||||
33
mozilla/extensions/python/xpcom/tools/regxpcom.py
Normal file
33
mozilla/extensions/python/xpcom/tools/regxpcom.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# regxpcom.py - basically the standard regxpcom.cpp ported to Python.
|
||||
|
||||
from xpcom import components, _xpcom
|
||||
import sys
|
||||
import os
|
||||
|
||||
def ProcessArgs(args):
|
||||
unregister = 0
|
||||
for arg in args:
|
||||
if arg == "-u":
|
||||
unregister = 1
|
||||
else:
|
||||
spec = components.classes['@mozilla.org/file/local;1'].createInstance()
|
||||
spec = spec.QueryInterface(components.interfaces.nsILocalFile)
|
||||
spec.initWithPath(os.path.abspath(arg))
|
||||
if unregister:
|
||||
components.manager.autoUnregisterComponent( components.manager.NS_Startup, spec)
|
||||
print "Successfully unregistered", spec.path
|
||||
else:
|
||||
components.manager.autoRegisterComponent( components.manager.NS_Startup, spec)
|
||||
print "Successfully registered", spec.path
|
||||
unregister = 0
|
||||
|
||||
import xpcom
|
||||
if len(sys.argv) < 2:
|
||||
components.manager.autoRegister( components.manager.NS_Startup, None)
|
||||
else:
|
||||
ProcessArgs(sys.argv[1:])
|
||||
|
||||
_xpcom.NS_ShutdownXPCOM()
|
||||
79
mozilla/extensions/python/xpcom/tools/tracer_demo.py
Normal file
79
mozilla/extensions/python/xpcom/tools/tracer_demo.py
Normal file
@@ -0,0 +1,79 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# This is a demo is how to use the xpcom.server "tracer" facility.
|
||||
#
|
||||
# This demo installs a tracer that uses the Python profiler. It then
|
||||
# creates the Python test component, and references some methods
|
||||
# and properties. It then dumps the profile statistics.
|
||||
|
||||
# This same technique could also be used for debugging, for example.
|
||||
|
||||
import profile
|
||||
|
||||
p = profile.Profile()
|
||||
getters = {}
|
||||
setters = {}
|
||||
|
||||
# A wrapper around a function - looks like a function,
|
||||
# but actually profiles the delegate.
|
||||
class TracerDelegate:
|
||||
def __init__(self, callme):
|
||||
self.callme = callme
|
||||
def __call__(self, *args):
|
||||
return p.runcall(self.callme, *args)
|
||||
|
||||
# A wrapper around each of our XPCOM objects. All PyXPCOM calls
|
||||
# in are made on this object, which creates a TracerDelagate around
|
||||
# every function. As the function is called, it collects profile info.
|
||||
class Tracer:
|
||||
def __init__(self, ob):
|
||||
self.__dict__['_ob'] = ob
|
||||
def __repr__(self):
|
||||
return "<Tracer around %r>" % (self._ob,)
|
||||
def __str__(self):
|
||||
return "<Tracer around %r>" % (self._ob,)
|
||||
def __getattr__(self, attr):
|
||||
ret = getattr(self._ob, attr) # Attribute error just goes up
|
||||
if callable(ret):
|
||||
return TracerDelegate(ret)
|
||||
else:
|
||||
if not attr.startswith("_com_") and not attr.startswith("_reg_"):
|
||||
getters[attr] = getters.setdefault(attr,0) + 1
|
||||
return ret
|
||||
def __setattr__(self, attr, val):
|
||||
if self.__dict__.has_key(attr):
|
||||
self.__dict__[attr] = val
|
||||
return
|
||||
setters[attr] = setters.setdefault(attr,0) + 1
|
||||
setattr(self._ob, attr, val)
|
||||
|
||||
# Installed as a global XPCOM function that if exists, will be called
|
||||
# to wrap each XPCOM object created.
|
||||
def MakeTracer(ob):
|
||||
# In some cases we may be asked to wrap ourself, so handle that.
|
||||
if isinstance(ob, Tracer):
|
||||
return ob
|
||||
return Tracer(ob)
|
||||
|
||||
def test():
|
||||
import xpcom.server, xpcom.components
|
||||
xpcom.server.tracer = MakeTracer
|
||||
contractid = "Python.TestComponent"
|
||||
for i in range(100):
|
||||
c = xpcom.components.classes[contractid].createInstance().queryInterface(xpcom.components.interfaces.nsIPythonTestInterface)
|
||||
c.boolean_value = 0
|
||||
a = c.boolean_value
|
||||
c.do_boolean(0,1)
|
||||
print "Finshed"
|
||||
p.print_stats()
|
||||
print "%-30s%s" % ("Attribute Gets", "Number")
|
||||
print "-" * 36
|
||||
for name, num in getters.items():
|
||||
print "%-30s%d" % (name, num)
|
||||
print "%-30s%s" % ("Attribute Sets", "Number")
|
||||
print "-" * 36
|
||||
for name, num in setters.items():
|
||||
print "%-30s%d" % (name, num)
|
||||
|
||||
test()
|
||||
202
mozilla/extensions/python/xpcom/xpcom_consts.py
Normal file
202
mozilla/extensions/python/xpcom/xpcom_consts.py
Normal file
@@ -0,0 +1,202 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
# Could maybe later have a process that extracted these enums should they change.
|
||||
# from nsFileLocations.h
|
||||
App_DirectoryBase = 0x00010000
|
||||
App_PrefsDirectory30 = App_DirectoryBase + 1
|
||||
App_PrefsDirectory40 = App_DirectoryBase + 2
|
||||
App_PrefsDirectory50 = App_DirectoryBase + 3
|
||||
App_ResDirectory = App_DirectoryBase + 5
|
||||
App_UserProfileDirectory30 = App_DirectoryBase + 10
|
||||
App_UserProfileDirectory40 = App_DirectoryBase + 11
|
||||
App_UserProfileDirectory50 = App_DirectoryBase + 12
|
||||
App_DefaultUserProfileRoot30 = App_DirectoryBase + 13
|
||||
App_DefaultUserProfileRoot40 = App_DirectoryBase + 14
|
||||
App_DefaultUserProfileRoot50 = App_DirectoryBase + 15
|
||||
App_ProfileDefaultsFolder30 = App_DirectoryBase + 16
|
||||
App_ProfileDefaultsFolder40 = App_DirectoryBase + 17
|
||||
App_ProfileDefaultsFolder50 = App_DirectoryBase + 18
|
||||
App_PrefDefaultsFolder50 = App_DirectoryBase + 19
|
||||
App_DefaultsFolder50 = App_DirectoryBase + 25
|
||||
App_ComponentsDirectory = App_DirectoryBase + 30
|
||||
App_ChromeDirectory = App_DirectoryBase + 31
|
||||
App_PluginsDirectory = App_DirectoryBase + 32
|
||||
App_UserChromeDirectory = App_DirectoryBase + 40
|
||||
App_FileBase = App_DirectoryBase + 1000
|
||||
App_PreferencesFile30 = App_FileBase + 1
|
||||
App_PreferencesFile40 = App_FileBase + 2
|
||||
App_PreferencesFile50 = App_FileBase + 3
|
||||
App_BookmarksFile30 = App_FileBase + 10
|
||||
App_BookmarksFile40 = App_FileBase + 11
|
||||
App_BookmarksFile50 = App_FileBase + 12
|
||||
App_Registry40 = App_FileBase + 20
|
||||
App_Registry50 = App_FileBase + 21
|
||||
App_LocalStore50 = App_FileBase + 30
|
||||
App_History50 = App_FileBase + 40
|
||||
App_MailDirectory50 = App_FileBase + 50
|
||||
App_ImapMailDirectory50 = App_FileBase + 60
|
||||
App_NewsDirectory50 = App_FileBase + 70
|
||||
App_MessengerFolderCache50 = App_FileBase + 80
|
||||
App_UsersPanels50 = App_FileBase + 90
|
||||
App_SearchFile50 = App_FileBase + 100
|
||||
App_SearchDirectory50 = App_FileBase + 101
|
||||
|
||||
# From nsSpecialSystemDirectory.h
|
||||
OS_DriveDirectory = 1
|
||||
OS_TemporaryDirectory = 2
|
||||
OS_CurrentProcessDirectory= 3
|
||||
OS_CurrentWorkingDirectory= 4
|
||||
|
||||
XPCOM_CurrentProcessComponentDirectory= 5
|
||||
XPCOM_CurrentProcessComponentRegistry= 6
|
||||
|
||||
Moz_BinDirectory = 10
|
||||
|
||||
Mac_SystemDirectory = 101
|
||||
Mac_DesktopDirectory = 102
|
||||
Mac_TrashDirectory = 103
|
||||
Mac_StartupDirectory = 104
|
||||
Mac_ShutdownDirectory = 105
|
||||
Mac_AppleMenuDirectory = 106
|
||||
Mac_ControlPanelDirectory = 107
|
||||
Mac_ExtensionDirectory = 108
|
||||
Mac_FontsDirectory = 109
|
||||
Mac_PreferencesDirectory = 110
|
||||
Mac_DocumentsDirectory = 111
|
||||
Mac_InternetSearchDirectory = 112
|
||||
|
||||
Win_SystemDirectory = 201
|
||||
Win_WindowsDirectory = 202
|
||||
|
||||
Win_HomeDirectory = 203
|
||||
Win_Desktop = 204
|
||||
Win_Programs = 205
|
||||
Win_Controls = 206
|
||||
Win_Printers = 207
|
||||
Win_Personal = 208
|
||||
Win_Favorites = 209
|
||||
Win_Startup = 210
|
||||
Win_Recent = 211
|
||||
Win_Sendto = 212
|
||||
Win_Bitbucket = 213
|
||||
Win_Startmenu = 214
|
||||
Win_Desktopdirectory = 215
|
||||
Win_Drives = 216
|
||||
Win_Network = 217
|
||||
Win_Nethood = 218
|
||||
Win_Fonts = 219
|
||||
Win_Templates = 220
|
||||
Win_Common_Startmenu = 221
|
||||
Win_Common_Programs = 222
|
||||
Win_Common_Startup = 223
|
||||
Win_Common_Desktopdirectory = 224
|
||||
Win_Appdata = 225
|
||||
Win_Printhood = 226
|
||||
|
||||
Unix_LocalDirectory = 301
|
||||
Unix_LibDirectory = 302
|
||||
Unix_HomeDirectory = 303
|
||||
|
||||
BeOS_SettingsDirectory = 401
|
||||
BeOS_HomeDirectory = 402
|
||||
BeOS_DesktopDirectory = 403
|
||||
BeOS_SystemDirectory = 404
|
||||
|
||||
OS2_SystemDirectory = 501
|
||||
|
||||
# Type/Variant related constants.
|
||||
TD_INT8 = 0
|
||||
TD_INT16 = 1
|
||||
TD_INT32 = 2
|
||||
TD_INT64 = 3
|
||||
TD_UINT8 = 4
|
||||
TD_UINT16 = 5
|
||||
TD_UINT32 = 6
|
||||
TD_UINT64 = 7
|
||||
TD_FLOAT = 8
|
||||
TD_DOUBLE = 9
|
||||
TD_BOOL = 10
|
||||
TD_CHAR = 11
|
||||
TD_WCHAR = 12
|
||||
TD_VOID = 13
|
||||
TD_PNSIID = 14
|
||||
TD_DOMSTRING = 15
|
||||
TD_PSTRING = 16
|
||||
TD_PWSTRING = 17
|
||||
TD_INTERFACE_TYPE = 18
|
||||
TD_INTERFACE_IS_TYPE = 19
|
||||
TD_ARRAY = 20
|
||||
TD_PSTRING_SIZE_IS = 21
|
||||
TD_PWSTRING_SIZE_IS = 22
|
||||
|
||||
# From xpt_struct.h
|
||||
XPT_TDP_POINTER = 0x80
|
||||
XPT_TDP_UNIQUE_POINTER = 0x40
|
||||
XPT_TDP_REFERENCE = 0x20
|
||||
XPT_TDP_FLAGMASK = 0xe0
|
||||
XPT_TDP_TAGMASK = (~XPT_TDP_FLAGMASK)
|
||||
def XPT_TDP_TAG(tdp): return (tdp & XPT_TDP_TAGMASK)
|
||||
|
||||
def XPT_TDP_IS_POINTER(flags): return (flags & XPT_TDP_POINTER)
|
||||
def XPT_TDP_IS_UNIQUE_POINTER(flags): return (flags & XPT_TDP_UNIQUE_POINTER)
|
||||
def XPT_TDP_IS_REFERENCE(flags): return (flags & XPT_TDP_REFERENCE)
|
||||
|
||||
XPT_ID_SCRIPTABLE = 0x80
|
||||
XPT_ID_FLAGMASK = 0x80
|
||||
XPT_ID_TAGMASK = ~XPT_ID_FLAGMASK
|
||||
def XPT_ID_TAG(id): return id & XPT_ID_TAGMASK
|
||||
|
||||
def XPT_ID_IS_SCRIPTABLE(flags): return flags & XPT_ID_SCRIPTABLE
|
||||
|
||||
XPT_PD_IN = 0x80
|
||||
XPT_PD_OUT = 0x40
|
||||
XPT_PD_RETVAL = 0x20
|
||||
XPT_PD_SHARED = 0x10
|
||||
XPT_PD_DIPPER = 0x08
|
||||
XPT_PD_FLAGMASK = 0xf0
|
||||
|
||||
def XPT_PD_IS_IN(flags): return (flags & XPT_PD_IN)
|
||||
def XPT_PD_IS_OUT(flags): return (flags & XPT_PD_OUT)
|
||||
def XPT_PD_IS_RETVAL(flags): return (flags & XPT_PD_RETVAL)
|
||||
def XPT_PD_IS_SHARED(flags): return (flags & XPT_PD_SHARED)
|
||||
def XPT_PD_IS_DIPPER(flags): return (flags & XPT_PD_DIPPER)
|
||||
|
||||
XPT_MD_GETTER = 0x80
|
||||
XPT_MD_SETTER = 0x40
|
||||
XPT_MD_NOTXPCOM = 0x20
|
||||
XPT_MD_CTOR = 0x10
|
||||
XPT_MD_HIDDEN = 0x08
|
||||
XPT_MD_FLAGMASK = 0xf8
|
||||
|
||||
def XPT_MD_IS_GETTER(flags): return (flags & XPT_MD_GETTER)
|
||||
def XPT_MD_IS_SETTER(flags): return (flags & XPT_MD_SETTER)
|
||||
def XPT_MD_IS_NOTXPCOM(flags): return (flags & XPT_MD_NOTXPCOM)
|
||||
def XPT_MD_IS_CTOR(flags): return (flags & XPT_MD_CTOR)
|
||||
def XPT_MD_IS_HIDDEN(flags): return (flags & XPT_MD_HIDDEN)
|
||||
|
||||
# From xptinfo.h
|
||||
|
||||
T_I8 = TD_INT8
|
||||
T_I16 = TD_INT16
|
||||
T_I32 = TD_INT32
|
||||
T_I64 = TD_INT64
|
||||
T_U8 = TD_UINT8
|
||||
T_U16 = TD_UINT16
|
||||
T_U32 = TD_UINT32
|
||||
T_U64 = TD_UINT64
|
||||
T_FLOAT = TD_FLOAT
|
||||
T_DOUBLE = TD_DOUBLE
|
||||
T_BOOL = TD_BOOL
|
||||
T_CHAR = TD_CHAR
|
||||
T_WCHAR = TD_WCHAR
|
||||
T_VOID = TD_VOID
|
||||
T_IID = TD_PNSIID
|
||||
T_DOMSTRING = TD_DOMSTRING
|
||||
T_CHAR_STR = TD_PSTRING
|
||||
T_WCHAR_STR = TD_PWSTRING
|
||||
T_INTERFACE = TD_INTERFACE_TYPE
|
||||
T_INTERFACE_IS = TD_INTERFACE_IS_TYPE
|
||||
T_ARRAY = TD_ARRAY
|
||||
T_PSTRING_SIZE_IS = TD_PSTRING_SIZE_IS
|
||||
T_PWSTRING_SIZE_IS = TD_PWSTRING_SIZE_IS
|
||||
435
mozilla/extensions/python/xpcom/xpt.py
Normal file
435
mozilla/extensions/python/xpcom/xpt.py
Normal file
@@ -0,0 +1,435 @@
|
||||
# Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
# See the file LICENSE.txt for licensing information.
|
||||
|
||||
"""
|
||||
Program: xpt.py
|
||||
|
||||
Task: describe interfaces etc using XPCOM reflection.
|
||||
|
||||
Subtasks:
|
||||
output (nearly) exactly the same stuff as xpt_dump, for verification
|
||||
output Python source code that can be used as a template for an interface
|
||||
|
||||
Status: Works pretty well if you ask me :-)
|
||||
|
||||
Author:
|
||||
David Ascher did an original version that parsed XPT files
|
||||
directly. Mark Hammond changed it to use the reflection interfaces,
|
||||
but kept most of the printing logic.
|
||||
|
||||
|
||||
Revision:
|
||||
|
||||
0.1: March 6, 2000
|
||||
0.2: April 2000 - Mark removed lots of Davids lovely parsing code in favour
|
||||
of the new xpcom interfaces that provide this info.
|
||||
|
||||
May 2000 - Moved into Perforce - track the log there!
|
||||
|
||||
Todo:
|
||||
Fill out this todo list.
|
||||
|
||||
"""
|
||||
|
||||
import string, sys
|
||||
import xpcom
|
||||
import xpcom._xpcom
|
||||
|
||||
from xpcom_consts import *
|
||||
|
||||
class Interface:
|
||||
def __init__(self, iid):
|
||||
iim = xpcom._xpcom.XPTI_GetInterfaceInfoManager()
|
||||
if hasattr(iid, "upper"): # Is it a stringy thing.
|
||||
item = iim.GetInfoForName(iid)
|
||||
else:
|
||||
item = iim.GetInfoForIID(iid)
|
||||
self.interface_info = item
|
||||
self.namespace = "" # where does this come from?
|
||||
self.methods = Methods(item)
|
||||
self.constants = Constants(item)
|
||||
|
||||
# delegate attributes to the real interface
|
||||
def __getattr__(self, attr):
|
||||
return getattr(self.interface_info, attr)
|
||||
|
||||
def GetParent(self):
|
||||
try:
|
||||
raw_parent = self.interface_info.GetParent()
|
||||
if raw_parent is None:
|
||||
return None
|
||||
return Interface(raw_parent.GetIID())
|
||||
except xpcom.Exception:
|
||||
# Parent interface is probably not scriptable - assume nsISupports.
|
||||
if xpcom.verbose:
|
||||
# The user may be confused as to why this is happening!
|
||||
print "The parent interface of IID '%s' can not be located - assuming nsISupports"
|
||||
return Interface(xpcom._xpcom.IID_nsISupports)
|
||||
|
||||
def Describe_Python(self):
|
||||
method_reprs = []
|
||||
methods = filter(lambda m: not m.IsNotXPCOM(), self.methods)
|
||||
for m in methods:
|
||||
method_reprs.append(m.Describe_Python())
|
||||
method_joiner = "\n"
|
||||
methods_repr = method_joiner.join(method_reprs)
|
||||
return \
|
||||
"""class %s:
|
||||
_com_interfaces_ = xpcom.components.interfaces.%s
|
||||
# If this object needs to be registered, the following 2 are also needed.
|
||||
# _reg_clsid_ = "{a new clsid generated for this object}"
|
||||
# _reg_contractid_ = "The.Object.Name"\n%s""" % (self.GetName(), self.GetIID().name, methods_repr)
|
||||
|
||||
def Describe(self):
|
||||
# Make the IID look like xtp_dump - "(" instead of "{"
|
||||
iid_use = "(" + str(self.GetIID())[1:-1] + ")"
|
||||
s = ' - '+self.namespace+'::'+ self.GetName() + ' ' + iid_use + ':\n'
|
||||
|
||||
parent = self.GetParent()
|
||||
if parent is not None:
|
||||
s = s + ' Parent: ' + parent.namespace + '::' + parent.GetName() + '\n'
|
||||
s = s + ' Flags:\n'
|
||||
if self.IsScriptable(): word = 'TRUE'
|
||||
else: word = 'FALSE'
|
||||
s = s + ' Scriptable: ' + word + '\n'
|
||||
s = s + ' Methods:\n'
|
||||
methods = filter(lambda m: not m.IsNotXPCOM(), self.methods)
|
||||
if len(methods):
|
||||
for m in methods:
|
||||
s = s + ' ' + m.Describe() + '\n'
|
||||
else:
|
||||
s = s + ' No Methods\n'
|
||||
s = s + ' Constants:\n'
|
||||
if self.constants:
|
||||
for c in self.constants:
|
||||
s = s + ' ' + c.Describe() + '\n'
|
||||
else:
|
||||
s = s + ' No Constants\n'
|
||||
|
||||
return s
|
||||
|
||||
# A class that allows caching and iterating of methods.
|
||||
class Methods:
|
||||
def __init__(self, interface_info):
|
||||
self.interface_info = interface_info
|
||||
try:
|
||||
self.items = [None] * interface_info.GetMethodCount()
|
||||
except xpcom.Exception:
|
||||
if xpcom.verbose:
|
||||
print "** GetMethodCount failed?? - assuming no methods"
|
||||
self.items = []
|
||||
def __len__(self):
|
||||
return len(self.items)
|
||||
def __getitem__(self, index):
|
||||
ret = self.items[index]
|
||||
if ret is None:
|
||||
mi = self.interface_info.GetMethodInfo(index)
|
||||
ret = self.items[index] = Method(mi, index, self.interface_info)
|
||||
return ret
|
||||
|
||||
class Method:
|
||||
|
||||
def __init__(self, method_info, method_index, interface_info = None):
|
||||
self.interface_info = interface_info
|
||||
self.method_index = method_index
|
||||
self.flags, self.name, param_descs, self.result_desc = method_info
|
||||
# Build the params.
|
||||
self.params = []
|
||||
pi=0
|
||||
for pd in param_descs:
|
||||
self.params.append( Parameter(pd, pi, method_index, interface_info) )
|
||||
pi = pi + 1
|
||||
# Run over the params setting the "sizeof" params to hidden.
|
||||
for p in self.params:
|
||||
td = p.type_desc
|
||||
tag = XPT_TDP_TAG(td[0])
|
||||
if tag==T_ARRAY and p.IsIn():
|
||||
self.params[td[1]].hidden_indicator = 2
|
||||
elif tag in [T_PSTRING_SIZE_IS, T_PWSTRING_SIZE_IS] and p.IsIn():
|
||||
self.params[td[1]].hidden_indicator = 1
|
||||
|
||||
def IsGetter(self):
|
||||
return (self.flags & XPT_MD_GETTER)
|
||||
def IsSetter(self):
|
||||
return (self.flags & XPT_MD_SETTER)
|
||||
def IsNotXPCOM(self):
|
||||
return (self.flags & XPT_MD_NOTXPCOM)
|
||||
def IsConstructor(self):
|
||||
return (self.flags & XPT_MD_CTOR)
|
||||
def IsHidden(self):
|
||||
return (self.flags & XPT_MD_HIDDEN)
|
||||
|
||||
def Describe_Python(self):
|
||||
if self.method_index < 3: # Ignore QI etc
|
||||
return ""
|
||||
base_name = self.name
|
||||
if self.IsGetter():
|
||||
name = "get_%s" % (base_name,)
|
||||
elif self.IsSetter():
|
||||
name = "set_%s" % (base_name,)
|
||||
else:
|
||||
name = base_name
|
||||
param_decls = ["self"]
|
||||
in_comments = []
|
||||
out_descs = []
|
||||
result_comment = "Result: void - None"
|
||||
for p in self.params:
|
||||
in_desc, in_desc_comments, out_desc, this_result_comment = p.Describe_Python()
|
||||
if in_desc is not None:
|
||||
param_decls.append(in_desc)
|
||||
if in_desc_comments is not None:
|
||||
in_comments.append(in_desc_comments)
|
||||
if out_desc is not None:
|
||||
out_descs.append(out_desc)
|
||||
if this_result_comment is not None:
|
||||
result_comment = this_result_comment
|
||||
joiner = "\n # "
|
||||
in_comment = out_desc = ""
|
||||
if in_comments: in_comment = joiner + joiner.join(in_comments)
|
||||
if out_descs: out_desc = joiner + joiner.join(out_descs)
|
||||
|
||||
return """ def %s( %s ):
|
||||
# %s%s%s
|
||||
pass""" % (name, ", ".join(param_decls), result_comment, in_comment, out_desc)
|
||||
|
||||
def Describe(self):
|
||||
s = ''
|
||||
if self.IsGetter():
|
||||
G = 'G'
|
||||
else:
|
||||
G = ' '
|
||||
if self.IsSetter():
|
||||
S = 'S'
|
||||
else: S = ' '
|
||||
if self.IsHidden():
|
||||
H = 'H'
|
||||
else:
|
||||
H = ' '
|
||||
if self.IsNotXPCOM():
|
||||
N = 'N'
|
||||
else:
|
||||
N = ' '
|
||||
if self.IsConstructor():
|
||||
C = 'C'
|
||||
else:
|
||||
C = ' '
|
||||
|
||||
def desc(a): return a.Describe()
|
||||
method_desc = string.join(map(desc, self.params), ', ')
|
||||
result_type = TypeDescriber(self.result_desc[0], None)
|
||||
return_desc = result_type.Describe()
|
||||
i = string.find(return_desc, 'retval ')
|
||||
if i != -1:
|
||||
return_desc = return_desc[:i] + return_desc[i+len('retval '):]
|
||||
return G+S+H+N+C+' '+return_desc+' '+self.name + '('+ method_desc + ');'
|
||||
|
||||
class Parameter:
|
||||
def __init__(self, param_desc, param_index, method_index, interface_info = None):
|
||||
self.param_flags, self.type_desc = param_desc
|
||||
self.hidden_indicator = 0 # Is this a special "size" type param that will be hidden from Python?
|
||||
self.param_index = param_index
|
||||
self.method_index= method_index
|
||||
self.interface_info = interface_info
|
||||
def __repr__(self):
|
||||
return "<param %(param_index)d (method %(method_index)d) - flags = 0x%(param_flags)x, type = %(type_desc)s>" % self.__dict__
|
||||
def IsIn(self):
|
||||
return XPT_PD_IS_IN(self.param_flags)
|
||||
def IsOut(self):
|
||||
return XPT_PD_IS_OUT(self.param_flags)
|
||||
def IsInOut(self):
|
||||
return self.IsIn() and self.IsOut()
|
||||
def IsRetval(self):
|
||||
return XPT_PD_IS_RETVAL(self.param_flags)
|
||||
def IsShared(self):
|
||||
return XPT_PD_IS_SHARED(self.param_flags)
|
||||
def IsDipper(self):
|
||||
return XPT_PD_IS_DIPPER(self.param_flags)
|
||||
|
||||
def Describe_Python(self):
|
||||
name = "param%d" % (self.param_index,)
|
||||
if self.hidden_indicator:
|
||||
# Could remove the comment - Im trying to tell the user where that param has
|
||||
# gone from the signature!
|
||||
return None, "%s is a hidden parameter" % (name,), None, None
|
||||
t = TypeDescriber(self.type_desc[0], self)
|
||||
decl = in_comment = out_comment = result_comment = None
|
||||
type_desc = t.Describe()
|
||||
if self.IsIn() and not self.IsDipper():
|
||||
decl = name
|
||||
extra=""
|
||||
if self.IsOut():
|
||||
extra = "Out"
|
||||
in_comment = "In%s: %s: %s" % (extra, name, type_desc)
|
||||
elif self.IsOut() or self.IsDipper():
|
||||
if self.IsRetval():
|
||||
result_comment = "Result: %s" % (type_desc,)
|
||||
else:
|
||||
out_comment = "Out: %s" % (type_desc,)
|
||||
return decl, in_comment, out_comment, result_comment
|
||||
|
||||
def Describe(self):
|
||||
parts = []
|
||||
if self.IsInOut():
|
||||
parts.append('inout')
|
||||
elif self.IsIn():
|
||||
parts.append('in')
|
||||
elif self.IsOut():
|
||||
parts.append('out')
|
||||
|
||||
if self.IsDipper(): parts.append("dipper")
|
||||
if self.IsRetval(): parts.append('retval')
|
||||
if self.IsShared(): parts.append('shared')
|
||||
t = TypeDescriber(self.type_desc[0], self)
|
||||
type_str = t.Describe()
|
||||
parts.append(type_str)
|
||||
return string.join(parts)
|
||||
|
||||
# A class that allows caching and iterating of constants.
|
||||
class Constants:
|
||||
def __init__(self, interface_info):
|
||||
self.interface_info = interface_info
|
||||
try:
|
||||
self.items = [None] * interface_info.GetConstantCount()
|
||||
except xpcom.Exception:
|
||||
if xpcom.verbose:
|
||||
print "** GetConstantCount failed?? - assuming no constants"
|
||||
self.items = []
|
||||
def __len__(self):
|
||||
return len(self.items)
|
||||
def __getitem__(self, index):
|
||||
ret = self.items[index]
|
||||
if ret is None:
|
||||
ci = self.interface_info.GetConstant(index)
|
||||
ret = self.items[index] = Constant(ci)
|
||||
return ret
|
||||
|
||||
class Constant:
|
||||
def __init__(self, ci):
|
||||
self.name, self.type, self.value = ci
|
||||
|
||||
def Describe(self):
|
||||
return TypeDescriber(self.type, None).Describe() + ' ' +self.name+' = '+str(self.value)+';'
|
||||
|
||||
__str__ = Describe
|
||||
|
||||
def MakeReprForInvoke(param):
|
||||
tag = param.type_desc[0] & XPT_TDP_TAGMASK
|
||||
if tag == T_INTERFACE:
|
||||
i_info = param.interface_info
|
||||
try:
|
||||
iid = i_info.GetIIDForParam(param.method_index, param.param_index)
|
||||
except xpcom.Exception:
|
||||
# IID not available (probably not scriptable) - just use nsISupports.
|
||||
iid = xpcom._xpcom.IID_nsISupports
|
||||
return param.type_desc[0], 0, 0, str(iid)
|
||||
elif tag == T_ARRAY:
|
||||
i_info = param.interface_info
|
||||
array_desc = i_info.GetTypeForParam(param.method_index, param.param_index, 1)
|
||||
return param.type_desc[:-1] + array_desc[:1]
|
||||
return param.type_desc
|
||||
|
||||
|
||||
class TypeDescriber:
|
||||
def __init__(self, type_flags, param):
|
||||
self.type_flags = type_flags
|
||||
self.tag = XPT_TDP_TAG(self.type_flags)
|
||||
self.param = param
|
||||
def IsPointer(self):
|
||||
return XPT_TDP_IS_POINTER(self.type_flags)
|
||||
def IsUniquePointer(self):
|
||||
return XPT_TDP_IS_UNIQUE_POINTER(self.type_flags)
|
||||
def IsReference(self):
|
||||
return XPT_TDP_IS_REFERENCE(self.type_flags)
|
||||
def repr_for_invoke(self):
|
||||
return (self.type_flags,)
|
||||
def GetName(self):
|
||||
is_ptr = self.IsPointer()
|
||||
data = type_info_map.get(self.tag)
|
||||
if data is None:
|
||||
data = ("unknown",)
|
||||
if self.IsReference():
|
||||
if len(data) > 2:
|
||||
return data[2]
|
||||
return data[0] + " &"
|
||||
if self.IsPointer():
|
||||
if len(data)>1:
|
||||
return data[1]
|
||||
return data[0] + " *"
|
||||
return data[0]
|
||||
|
||||
def Describe(self):
|
||||
if self.tag == T_ARRAY:
|
||||
# NOTE - Adding a type specifier to the array is different from xpt_dump.exe
|
||||
if self.param is None or self.param.interface_info is None:
|
||||
type_desc = "" # Dont have explicit info about the array type :-(
|
||||
else:
|
||||
i_info = self.param.interface_info
|
||||
type_code = i_info.GetTypeForParam(self.param.method_index, self.param.param_index, 1)
|
||||
type_desc = TypeDescriber( type_code[0], None).Describe()
|
||||
return self.GetName() + "[" + type_desc + "]"
|
||||
elif self.tag == T_INTERFACE:
|
||||
if self.param is None or self.param.interface_info is None:
|
||||
return "nsISomething" # Dont have explicit info about the IID :-(
|
||||
i_info = self.param.interface_info
|
||||
m_index = self.param.method_index
|
||||
p_index = self.param.param_index
|
||||
try:
|
||||
iid = i_info.GetIIDForParam(m_index, p_index)
|
||||
return iid.name
|
||||
except xpcom.Exception:
|
||||
return "nsISomething"
|
||||
return self.GetName()
|
||||
|
||||
# These are just for output purposes, so should be
|
||||
# the same as xpt_dump uses
|
||||
type_info_map = {
|
||||
T_I8 : ("int8",),
|
||||
T_I16 : ("int16",),
|
||||
T_I32 : ("int32",),
|
||||
T_I64 : ("int64",),
|
||||
T_U8 : ("uint8",),
|
||||
T_U16 : ("uint16",),
|
||||
T_U32 : ("uint32",),
|
||||
T_U64 : ("uint64",),
|
||||
T_FLOAT : ("float",),
|
||||
T_DOUBLE : ("double",),
|
||||
T_BOOL : ("boolean",),
|
||||
T_CHAR : ("char",),
|
||||
T_WCHAR : ("wchar_t", "wstring"),
|
||||
T_VOID : ("void",),
|
||||
T_IID : ("reserved", "nsIID *", "nsIID &"),
|
||||
T_DOMSTRING : ("DOMString",),
|
||||
T_CHAR_STR : ("reserved", "string"),
|
||||
T_WCHAR_STR : ("reserved", "wstring"),
|
||||
T_INTERFACE : ("reserved", "Interface"),
|
||||
T_INTERFACE_IS : ("reserved", "InterfaceIs *"),
|
||||
T_ARRAY : ("reserved", "Array"),
|
||||
T_PSTRING_SIZE_IS : ("reserved", "string_s"),
|
||||
T_PWSTRING_SIZE_IS : ("reserved", "wstring_s"),
|
||||
}
|
||||
|
||||
def dump_interface(iid, mode):
|
||||
interface = Interface(iid)
|
||||
describer_name = "Describe"
|
||||
if mode == "xptinfo": mode = None
|
||||
if mode is not None:
|
||||
describer_name = describer_name + "_" + mode.capitalize()
|
||||
describer = getattr(interface, describer_name)
|
||||
print describer()
|
||||
|
||||
if __name__=='__main__':
|
||||
if len(sys.argv) == 1:
|
||||
print "Usage: xpt.py [-xptinfo] interface_name, ..."
|
||||
print " -info: Dump in a style similar to the xptdump tool"
|
||||
print "Dumping nsISupports and nsIInterfaceInfo"
|
||||
sys.argv.append('nsIInterfaceInfo')
|
||||
sys.argv.append('-xptinfo')
|
||||
sys.argv.append('nsISupports')
|
||||
sys.argv.append('nsIInterfaceInfo')
|
||||
|
||||
mode = "Python"
|
||||
for i in sys.argv[1:]:
|
||||
if i[0] == "-":
|
||||
mode = i[1:]
|
||||
else:
|
||||
dump_interface(i, mode)
|
||||
Reference in New Issue
Block a user