pax_global_header00006660000000000000000000000064147707311500014517gustar00rootroot0000000000000052 comment=9f327d194b7bc143c0ea2ace20246cf4d20a9bc4 snapd-glib-1.67/000077500000000000000000000000001477073115000134745ustar00rootroot00000000000000snapd-glib-1.67/.clang-format000066400000000000000000000000261477073115000160450ustar00rootroot00000000000000ReflowComments: false snapd-glib-1.67/.github/000077500000000000000000000000001477073115000150345ustar00rootroot00000000000000snapd-glib-1.67/.github/workflows/000077500000000000000000000000001477073115000170715ustar00rootroot00000000000000snapd-glib-1.67/.github/workflows/documentation.yaml000066400000000000000000000025171477073115000226330ustar00rootroot00000000000000name: documentation on: push: branches: - master permissions: contents: read pages: write id-token: write concurrency: group: "pages" cancel-in-progress: false jobs: # Build job build: runs-on: ubuntu-latest container: image: ubuntu:rolling steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v5 - name: Install dependencies (Ubuntu) run: | apt-get update DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends meson ninja-build gi-docgen libgirepository1.0-dev libglib2.0-dev libjson-glib-dev ninja-build python3-pip python3-setuptools python3-wheel valac libsoup-3.0-dev qt6-base-dev qt6-declarative-dev - name: Build documentation run: | meson setup _build -Ddocs=true -Dqt5=false -Dqt6=false ninja -C _build mkdir -p ./_site cp -v -a ./_build/doc/snapd-glib/* ./_site/ - name: Upload artifact uses: actions/upload-pages-artifact@v3 # Deployment job deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: build steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 snapd-glib-1.67/.github/workflows/format.yaml000066400000000000000000000003661477073115000212520ustar00rootroot00000000000000name: Formatting on: pull_request: push: branches: - master jobs: build: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v2 - name: Verify formatting run: | ./format-source.sh check snapd-glib-1.67/.github/workflows/test.yaml000066400000000000000000000100341477073115000207320ustar00rootroot00000000000000name: test on: pull_request: push: branches: - master jobs: test: strategy: fail-fast: false matrix: image: - ubuntu:rolling - fedora:latest soup: - libsoup3 qt: - qt6 doc: - true include: - image: ubuntu:22.04 soup: libsoup2 qt: qt6 doc: false - image: ubuntu:20.04 soup: libsoup2 qt: qt5 doc: false runs-on: ubuntu-latest container: ${{ matrix.image }} steps: - uses: actions/checkout@v4 - name: Initialise parameters id: params run: | artifact_name="logs-$(echo "${{ matrix.image }}" | sed "s/:/-/")" echo "::set-output name=artifact::$artifact_name" - name: Install dependencies (Ubuntu) if: startsWith(matrix.image, 'ubuntu:') run: | apt-get update DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends libgirepository1.0-dev libglib2.0-dev libjson-glib-dev ninja-build python3-pip python3-setuptools python3-wheel valac - name: Install gi-docgen dependencies (Ubuntu) if: startsWith(matrix.image, 'ubuntu:') && matrix.doc run: | DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends gi-docgen - name: Install libsoup3 dependencies (Ubuntu) if: startsWith(matrix.image, 'ubuntu:') && matrix.soup == 'libsoup3' run: | DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends libsoup-3.0-dev - name: Install libsoup2.4 dependencies (Ubuntu) if: startsWith(matrix.image, 'ubuntu:') && matrix.soup == 'libsoup2' run: | DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends libsoup2.4-dev - name: Install Qt5 dependencies (Ubuntu) if: startsWith(matrix.image, 'ubuntu:') && matrix.qt == 'qt5' run: | DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends qtbase5-dev qtdeclarative5-dev - name: Install Qt6 dependencies (Ubuntu) if: startsWith(matrix.image, 'ubuntu:') && matrix.qt == 'qt6' run: | DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends qt6-base-dev qt6-declarative-dev - name: Install dependencies (Fedora) if: startsWith(matrix.image, 'fedora:') run: | dnf install -y gcc gcc-c++ gobject-introspection-devel glib2-devel gi-docgen json-glib-devel libsoup3-devel ninja-build python3-pip qt6-qtbase-devel qt6-qtdeclarative-devel redhat-rpm-config vala - name: Install meson if: matrix.image != 'ubuntu:rolling' run: pip3 install meson - name: Install meson if: matrix.image == 'ubuntu:rolling' run: | DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends meson - name: Configure (with docs) if: matrix.soup == 'libsoup3' && matrix.qt != 'qt5' && matrix.doc run: | meson _build - name: Configure if: matrix.soup == 'libsoup3' && matrix.qt != 'qt5' && !matrix.doc run: | meson _build -Ddocs=false - name: Configure (Qt5) if: matrix.soup == 'libsoup3' && matrix.qt == 'qt5' run: | meson _build -Dqt=5=true -Dqt6=false -Ddocs=false - name: Configure (libsoup2.4) if: matrix.soup == 'libsoup2' && matrix.qt != 'qt5' run: meson _build -Dsoup2=true -Ddocs=false - name: Configure (libsoup2.4 and Qt5) if: matrix.soup == 'libsoup2' && matrix.qt == 'qt5' run: | meson _build -Dsoup2=true -Dqt5=true -Dqt6=false -Ddocs=false - name: Build run: | ninja -C _build - name: Test run: ninja -C _build test - name: Collect logs on failure if: failure() uses: actions/upload-artifact@v4 with: name: ${{ steps.params.outputs.artifact }} path: _build/meson-logs snapd-glib-1.67/COPYING.LGPL2000066400000000000000000000614471477073115000153620ustar00rootroot00000000000000 GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! snapd-glib-1.67/COPYING.LGPL3000066400000000000000000000167431477073115000153620ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. snapd-glib-1.67/NEWS000066400000000000000000000653271477073115000142100ustar00rootroot00000000000000Overview of changes in snapd-glib 1.66 * New API: - snapd_client_notices_set_after_notice - snapd_client_notices_set_since_nanoseconds - snapd_notice_compare_last_occurred - snapd_notice_get_first_occurred2 - snapd_notice_get_last_occurred2 - snapd_notice_get_last_occurred_nanoseconds - snapd_notice_get_last_repeated2 - snapd_notice_get_occurrences - snapd_notices_monitor_new - snapd_notices_monitor_new_with_client - snapd_notices_monitor_start - snapd_notices_monitor_stop - snapd_task_data_get_affected_snaps - snapd_task_get_data - SNAPD_ERROR_ALREADY_RUNNING - SNAPD_ERROR_NOT_RUNNING * Fix error handling in snapd_client_get_change_finish. * Added support for data field in SnapdTask. * Add nanosecond accuracy to SnapdNotice. * Add SnapdNoticesMonitor. * Add SnapdNotice getters that don't return references. * Fix build in 32bit systems. * Updated project URL to github.com/canonical/snapd-glib Overview of changes in snapd-glib 1.65 * New API: - snapd_autorefresh_change_data_get_snap_names - snapd_autorefresh_change_data_get_refresh_forced - snapd_change_get_data - snapd_client_get_notices_async - snapd_client_get_notices_finish - snapd_client_get_notices_sync - snapd_client_get_notices_with_filters_async - snapd_client_get_notices_with_filters_finish - snapd_client_get_notices_with_filters_sync - snapd_notice_get_notice_type - snapd_notice_get_key - snapd_notice_get_first_occurred - snapd_notice_get_last_occurred - snapd_notice_get_last_repeated - snapd_notice_get_occurrences - snapd_notice_get_last_data - snapd_notice_get_repeat_after - snapd_notice_get_expire_after - snapd_snap_get_proceed_time - SNAPD_GET_SNAPS_FLAGS_REFRESH_INHIBITED - SNAPD_NOTICE_TYPE_UNKNOWN - SNAPD_NOTICE_TYPE_CHANGE_UPDATE - SNAPD_NOTICE_TYPE_REFRESH_INHIBIT - SNAPD_NOTICE_TYPE_SNAP_RUN_INHIBIT * Port to Qt 6. * Add support for refresh-inhibited snap parameter. * Add support for DATA parameters in Changes. * Add support for notify interface. Overview of changes in snapd-glib 1.64 * New API: - snapd_category_details_get_name - snapd_category_get_featured - snapd_category_get_name - snapd_client_find_category_async - snapd_client_find_category_finish - snapd_client_find_category_sync - snapd_client_follow_logs_async - snapd_client_follow_logs_finish - snapd_client_follow_logs_sync - snapd_client_get_categories_async - snapd_client_get_categories_finish - snapd_client_get_categories_sync - snapd_client_get_logs_async - snapd_client_get_logs_finish - snapd_client_get_logs_sync - snapd_log_get_message - snapd_log_get_pid - snapd_log_get_sid - snapd_log_get_timestamp - snapd_snap_get_categories - snapd_snap_get_hold - snapd_system_information_get_architecture - SNAPD_ERROR_APP_NOT_FOUND - SNAPD_ERROR_ARCHITECTURE_NOT_AVAILABLE - SNAPD_ERROR_CHANGE_CONFLICT - SNAPD_ERROR_INTERFACES_UNCHANGED * Deprecated API: - snapd_client_find_section_sync - snapd_client_find_section_async - snapd_client_find_section_finish - snapd_client_get_sections_sync * Support snap hold date field. * Support system information architecture field. * Implement snap categories support, replacing sections. * Support getting snap service logs. * Fix buffer overflow reading assertions. * Fix leak in themes API. * Add more snapd errors. * Fix tests failing on glib 2.77. Overview of changes in snapd-glib 1.63 * Fix snapd-qt cmake configuration. Overview of changes in snapd-glib 1.62 * Fix pkg-config file for new snapd-glib version. Overview of changes in snapd-glib 1.61 * New API: - SNAPD_PUBLISHER_VALIDATION_STARRED * Build with soup3 by default, support soup2. * Fix theme installation getting status. * Don't treat unknown publisher validation as verified. * Add support for starred developers. * Add an example that reimplements the snap command line tool. * Add Qt implementation of themes API. Overview of changes in snapd-glib 1.60 * New API: - snapd_client_check_themes_async - snapd_client_check_themes_finish - snapd_client_check_themes_sync - snapd_client_install_themes_async - snapd_client_install_themes_finish - snapd_client_install_themes_sync - snapd_snap_get_store_url * Support store-url snap field. * Ensure async callbacks don't try to access destroyed Qt request objects. * Add new themes API. * Allow empty query in searches. Overview of changes in snapd-glib 1.59 * New API: - snapd_client_run_snapctl2_async - snapd_client_run_snapctl2_finish - snapd_client_run_snapctl2_sync * Support getting snapctl exit code * Fix d_ptr leak in QSnapdMarkdownParser * Stop using g_assert() in tests * Fix deprecation warning using g_time_zone_new Overview of changes in snapd-glib 1.58 * Fix GIR annotations on snapd_client_get_snap_conf * Put more information into error messages for unknown errors Overview of changes in snapd-glib 1.57 * New API: - snapd_interface_make_label * Add snapd_interface_make_label * Add support for new snap types: "core", "base" and "snapd" * Change way GTK documentation is generated to avoid a Meson bug Overview of changes in snapd-glib 1.56 * Fix leak in markdown parser * Fix leak in logout code * Make build reproducible by fixing comment in generated file Overview of changes in snapd-glib 1.55 * New API: - snapd_client_download_sync - snapd_client_download_async - snapd_client_download_finish - snapd_client_logout_sync - snapd_client_logout_async - snapd_client_logout_finish * Add support for snap store logout * Fix QSnapdAuthData () constructor not copying discharge strings correctly * Remove obsolete screenshot parsing code * Make all snapd 404 errors return SNAPD_ERROR_NOT_FOUND Overview of changes in snapd-glib 1.54 * Fix snapd-glib pkg-config file not having correct include Overview of changes in snapd-glib 1.53 * Fix test failures on i386 due to floating point rounding. Overview of changes in snapd-glib 1.52 * Fix private symbols not being hidden Overview of changes in snapd-glib 1.51 * Add back installed test functionality that was lost in the Autotools to Meson migration Overview of changes in snapd-glib 1.50 * New API: - snapd_client_remove2_sync - snapd_client_remove2_async - snapd_client_remove2_finish - snapd_snap_get_website * Deprecated API: - snapd_client_remove_sync - snapd_client_remove_async - snapd_client_remove_finish * Add API to get snap website * Add purge option to remove * Switch build system to Meson * Fix Qt build with optimisation disabled * Fix tests breaking on json-glib < 1.2.4 * Use C99 style variable definitions Overview of changes in snapd-glib 1.49 * New API: - snapd_client_get_connections2_async - snapd_client_get_connections2_finish - snapd_client_get_connections2_sync - SnapdGetConnectionsFlags * Deprecated API: - snapd_client_get_connections_async - snapd_client_get_connections_finish - snapd_client_get_connections_sync * Fix memory leaks * Add snapd_client_get_connections2 to add missing filter fields from snapd_client_get_connections * Use C99 variable style Overview of changes in snapd-glib 1.48 * New API: - snapd_client_get_connections_async - snapd_client_get_connections_finish - snapd_client_get_connections_sync - snapd_client_get_interfaces2_async - snapd_client_get_interfaces2_finish - snapd_client_get_interfaces2_sync - snapd_client_get_snap_conf_async - snapd_client_get_snap_conf_finish - snapd_client_get_snap_conf_sync - snapd_client_set_snap_conf_async - snapd_client_set_snap_conf_finish - snapd_client_set_snap_conf_sync - snapd_connection_get_gadget - snapd_connection_get_interface - snapd_connection_get_manual - snapd_connection_get_plug - snapd_connection_get_plug_attribute - snapd_connection_get_plug_attribute_names - snapd_connection_get_slot - snapd_connection_get_slot_attribute - snapd_connection_get_slot_attribute_names - snapd_connection_has_plug_attribute - snapd_connection_has_slot_attribute - snapd_interface_get_doc_url - snapd_interface_get_name - snapd_interface_get_plugs - snapd_interface_get_slots - snapd_interface_get_summary - snapd_markdown_node_get_children - snapd_markdown_node_get_node_type - snapd_markdown_node_get_text - snapd_markdown_parser_new - snapd_markdown_parser_get_combine_whitespace - snapd_markdown_parser_parse - snapd_markdown_parser_set_combine_whitespace - snapd_plug_get_connected_slots - snapd_plug_ref_get_plug - snapd_plug_ref_get_snap - snapd_slot_get_connected_plugs - snapd_slot_ref_get_slot - snapd_slot_ref_get_snap - SNAPD_ERROR_OPTION_NOT_FOUND * Deprecated API: - snapd_client_get_interfaces_async - snapd_client_get_interfaces_finish - snapd_client_get_interfaces_sync - snapd_connection_get_name - snapd_connection_get_snap - snapd_plug_get_connections - snapd_slot_get_connections * Allow searching via common-id * Add a description markdown parser * Replace SnapdConnection with SnapdPlugRef and SnapdSlotRef * Support updated connections API (/v2/connections) * Support updated /v2/interfaces&select= API * Support snap configuration API * Add Qt interface attribute API * Make snapd_client_set_socket_path revert to the default when NULL passed. * Fix C99 mode not being enabled on older versions of GCC Overview of changes in snapd-glib 1.47 * Remove generated MOC file from tarball Overview of changes in snapd-glib 1.46 * New API: - snapd_channel_get_released_at - SNAPD_ERROR_DNS_FAILURE * Fix tests breaking due to undefined order of results Overview of changes in snapd-glib 1.45 * New API: - snapd_client_get_apps2_sync - snapd_client_get_apps2_async - snapd_client_get_apps2_finish - snapd_client_get_maintenance - snapd_maintenance_get_kind - snapd_maintenance_get_message - snapd_media_get_media_type - snapd_media_get_url - snapd_media_get_width - snapd_media_get_height - snapd_snap_get_base - snapd_snap_get_media - snapd_snap_get_mounted_from - SNAPD_ERROR_NOT_CLASSIC - SNAPD_ERROR_REVISION_NOT_AVAILABLE - SNAPD_ERROR_CHANNEL_NOT_AVAILABLE - SNAPD_ERROR_NOT_A_SNAP * Deprecated API: - snapd_client_get_apps_sync - snapd_client_get_apps_async - snapd_client_get_apps_finish - snapd_snap_get_screenshots * Fix double-unref on cancelled requests * Support new snap media and mounted-from fields * Support filtering when querying apps * Support snapd maintenance information * Support new error codes * Add missing allow-none GIR annotations Overview of changes in snapd-glib 1.44 * Reconnect to snapd if disconnected while trying to send the request * Handle short writes to snapd Overview of changes in snapd-glib 1.43 * New API: - SNAPD_ERROR_AUTH_CANCELLED * Fix small memory leak * Fix compile warnings Overview of changes in snapd-glib 1.42 * New API: - snapd_client_get_snap_async - snapd_client_get_snap_finish - snapd_client_get_snap_sync - snapd_client_get_snaps_async - snapd_client_get_snaps_finish - snapd_client_get_snap_sync - snapd_snap_get_publisher_display_name - snapd_snap_get_publisher_id - snapd_snap_get_publisher_username - snapd_snap_get_publisher_validation - snapd_system_information_get_refresh_hold - snapd_system_information_get_refresh_last - snapd_system_information_get_refresh_next - snapd_system_information_get_refresh_schedule - snapd_system_information_get_refresh_timer - snapd_system_information_get_sandbox_features - SNAPD_FIND_FLAGS_SCOPE_WIDE * Deprecated API: - snapd_client_list_async - snapd_client_list_finish - snapd_client_list_sync Overview of changes in snapd-glib 1.41 * New API: - snapd_app_get_common_id - snapd_snap_get_common_ids Overview of changes in snapd-glib 1.40 * New API: - snapd_system_information_get_build_id * Fix buffer overflows reading HTTP chunked data Overview of changes in snapd-glib 1.39 * Fix memory leak in QSnapdAssertion * Remove cancelled requests from the request queue. * Fix SnapdClient reference leak in each request Overview of changes in snapd-glib 1.38 * Fix snapd_snap_match_channel not matching risks correctly * Fix return value of SnapdSnap::matchChannel when fails to match Overview of changes in snapd-glib 1.37 * Support new snapd errors SNAPD_ERROR_NOT_FOUND, SNAPD_ERROR_NOT_IN_STORE Overview of changes in snapd-glib 1.36 * Fix progress callback scope annotations * Fix reference leak Overview of changes in snapd-glib 1.35 * Fix missing out annotation in find/find_section Overview of changes in snapd-glib 1.34 * Remove deprecated snapd-login-service * Deprecated API: - snapd_login_async - snapd_login_finish - snapd_login_sync Overview of changes in snapd-glib 1.33 * Fix small memory leaks * Fix linking with --no-undefined * Compile snapd-qt with -fPIC to avoid compile failure on Fedora Overview of changes in snapd-glib 1.32 * Fix crash when calling snapd_login_async * Support new bad-query, network-timeout errors from snapd * Support QSnapdClient::find/Section method without flags set * Assert name parameter set in snapd_snap_match_channel Overview of changes in snapd-glib 1.31 * New API: - snapd_channel_get_branch - snapd_channel_get_risk - snapd_channel_get_track * Add methods to extrack track/risk/branch from channel names Overview of changes in snapd-glib 1.30 * New API: - snapd_client_abort_change_async - snapd_client_abort_change_finish - snapd_client_abort_change_sync - snapd_change_get_error * Implement snapd_client_abort_change * Handle incorrectly named tracks field Overview of changes in snapd-glib 1.29 * New API: - snapd_client_get_changes_async - snapd_client_get_changes_finish - snapd_client_get_changes_sync - snapd_client_get_change_async - snapd_client_get_change_finish - snapd_client_get_change_sync * Implement snapd_client_get_changes, snapd_client_get_change Overview of changes in snapd-glib 1.28 * Fix crash on 32 bit architectures Overview of changes in snapd-glib 1.27 * Fix crash accessing freed memory * Fix small memory leaks Overview of changes in snapd-glib 1.26 * New API: - snapd_client_login2_async - snapd_client_login2_finish - snapd_client_login2_sync - snapd_client_switch_async - snapd_client_switch_finish - snapd_client_switch_sync - snapd_client_get_users_async - snapd_client_get_users_finish - snapd_client_get_users_sync * Deprecated API: - snapd_client_login_async - snapd_client_login_finish - snapd_client_login_sync * Implement snapd_client_switch * Implement snapd_client_get_users * Implement new login API * Mark deprecated Qt API Overview of changes in snapd-glib 1.25 * New API: - snapd_client_alias_async - snapd_client_alias_finish - snapd_client_alias_sync - snapd_client_unalias_async - snapd_client_unalias_finish - snapd_client_unalias_sync - snapd_client_prefer_async - snapd_client_prefer_finish - snapd_client_prefer_sync - snapd_client_get_apps_sync - snapd_client_get_apps_finish - snapd_client_get_apps_async - snapd_alias_get_app_auto - snapd_alias_get_command - snapd_alias_get_app_manual - snapd_app_get_active - snapd_app_get_enabled - snapd_app_get_snap - snapd_snap_get_broken * Deprecated API: - snapd_client_enable_aliases_async - snapd_client_enable_aliases_finish - snapd_client_enable_aliases_sync - snapd_client_disable_aliases_async - snapd_client_disable_aliases_finish - snapd_client_disable_aliases_sync - snapd_client_reset_aliases_async - snapd_client_reset_aliases_finish - snapd_client_reset_aliases_sync - snapd_app_get_aliases * Implement v2 alias API * Implement snapd_client_get_apps * Fix memory handling in create user methods * Implement user creation in snapd-qt * Fix memory leaks due to missing destructor chain * Refactor internal message code Overview of changes in snapd-glib 1.24 * New API: - snapd_client_get_socket_path - snapd_client_set_socket_path - snapd_snap_get_channels - snapd_snap_get_tracks - snapd_snap_match_channel - snapd_channel_get_confinement - snapd_channel_get_epoch - snapd_channel_get_name - snapd_channel_get_revision - snapd_channel_get_size - snapd_channel_get_type - snapd_channel_get_version * Deprecated API: - snapd_client_connect_async - snapd_client_connect_finish - snapd_client_connect_sync * Fix QSnapd::install() not working async. * Move Qt enums to an enum class and rename to avoid collisions (API break). * Fix multiple async operations not working at the same time. * When async requests are cancelled abort change in snapd. * Connect to snapd on demand. * Add ability to set snapd socket to connect to. * Add support for channels. * Fix runtime assertion when snapd socket is NULL. * Fix sudoer flag not being correctly set for create-user. * Make clients using provided sockets non-blocking. * Don't install snapd-qt.pc if not compiling snapd-qt. Overview of changes in snapd-glib 1.23 * Fix snapd-login-service crash * Improve failure handling when snapd socket read/writes fail Overview of changes in snapd-glib 1.22 * Make QML module depend on snapd-qt being compiled first * Fix compile warning Overview of changes in snapd-glib 1.21 * Fix MOC detection in Fedora * Handle Qt configure failures Overview of changes in snapd-glib 1.20 * Stop distributing generated files Overview of changes in snapd-glib 1.19 * New API: - snapd_client_get_allow_interaction - snapd_client_set_allow_interaction - snapd_snap_get_license * Add mutex in request queue Overview of changes in snapd-glib 1.18 * Ensure socket reads never block Overview of changes in snapd-glib 1.17 * Fix issues when accessing snapd-glib from threads. * snapd-qt: Emit the complete signal when requests are cancelled. * Reduce json-glib dependency to 1.1.2. * Documentation updates. * Test improvements. Overview of changes in snapd-glib 1.16 * Bring introspection and vapigen m4 macros into the source so can build without them installed. * Fix snapd-qt build failure due to conflict of 'signals' variable with GDBus. * Set a user agent when sending requests to snapd-glib Overview of changes in snapd-glib 1.15 * Marked snapd_system_information_get_confinement as stable * Correctly stop requests if cancelled Overview of changes in snapd-glib 1.14 * New API: - snapd_app_get_desktop_file - snapd_snap_get_title - snapd_system_information_get_confinement (unstable) * Don't timeout waiting for snapd * Add version defines so can do conditional compilation on new features * Fix compilation with PolKit >= 0.114 * Fix snapd-qt compilation in clang * Fix snapd-qt compilation on systems that use different versions of MOC * snapd-qt improvements to better match best practise * Include enum headers in snapd-glib.h * Fix compile warnings using clang * Documentation improvements Overview of changes in snapd-glib 1.13 * New API: - snapd_snap_get_contact * Check minimum versions of dependencies * Fix swapped variable names in snapd_client_find_section header proptotype. Overview of changes in snapd-glib 1.12 * New API: - snapd_client_install2_async - snapd_client_install2_finish - snapd_client_install2_sync * Deprecated API: - snapd_client_install_async - snapd_client_install_finish - snapd_client_install_sync Overview of changes in snapd-glib 1.11 * New API: - snapd_system_information_get_binaries_directory - snapd_system_information_get_kernel_version - snapd_system_information_get_mount_directory * Fix calls not working inside threads. * Fix reference counting error when calling snapd_client_get_interfaces and snapd_client_create_user. Overview of changes in snapd-glib 1.10 * Remove gettext-domain from Polkit files - this is an Ubuntu extension that doesn't work elsewhere. Overview of changes in snapd-glib 1.9 * New API: - snapd_app_get_daemon_type - snapd_client_install_stream_async - snapd_client_install_stream_finish - snapd_client_install_stream_sync - snapd_client_try_async - snapd_client_try_finish - snapd_client_try_sync * Fix iterator double use parsing of apps/aliases * Fix Qt tests not linking against local snapd-glib Overview of changes in snapd-glib 1.8 * New API: - snapd_client_get_assertions_async - snapd_client_get_assertions_finish - snapd_client_get_assertions_sync - snapd_client_add_assertions_async - snapd_client_add_assertions_finish - snapd_client_add_assertions_sync - snapd_client_get_aliases_async - snapd_client_get_aliases_finish - snapd_client_get_aliases_sync - snapd_client_enable_aliases_async - snapd_client_enable_aliases_finish - snapd_client_enable_aliases_sync - snapd_client_disable_aliases_async - snapd_client_disable_aliases_finish - snapd_client_disable_aliases_sync - snapd_client_reset_aliases_async - snapd_client_reset_aliases_finish - snapd_client_reset_aliases_sync - snapd_client_run_snapctl_async - snapd_client_run_snapctl_finish - snapd_client_run_snapctl_sync - snapd_snap_get_jailmode * Add snapd-qt regression tests. * Add missing snapd-qt API * Fix memory leaks in snapd-qt Overview of changes in snapd-glib 1.7 * New API: - snapd_app_get_aliases - snapd_client_get_sections_sync - snapd_client_get_sections_async - snapd_client_get_sections_finish - snapd_snap_get_tracking_channel - snapd_system_information_get_managed - snapd_system_information_get_store Overview of changes in snapd-glib 1.6 * Fix screenshots not working on 32 bit architectures Overview of changes in snapd-glib 1.5 * Add new API: snapd_client_refresh_all, snapd_client_find_refreshable. * Use new objects for progress callbacks - API break, ABI will continue to work. * Add Qt/QML bindings. * Add new errors reported by snapd. * Fix payment errors being detected. * Close socket on unref. * Fix small memory leaks. * Add regression tests. Overview of changes in snapd-glib 1.4 * Fix crash in snapd-login-service when snap stops Overview of changes in snapd-glib 1.3 * Use new payment API (now stable). * Add API to get plug/slot attributes. * Add API for create user API. * Add async version of snapd_client_connect_sync(). * Fix crash when fail to connect to snapd. * Don't fail assertion if attempt to connect while already connected. * Fix transfer notation on GDateTime objects. * Fix build not regenerating .vapi. * Small documentation fixes. * Fix small memory leak. Overview of changes in snapd-glib 1.2 * Use so version 1 now this is stable (should have been done at 1.0 release) Overview of changes in snapd-glib 1.1 * Fix screenshot documentation not being used Overview of changes in snapd-glib 1.0 * Add support for screenshots * Throw exception if not connected instead of using assert * Be more paranoid about invalid SnapdAuthData * Add an autogen.sh * Tidy up configure summary Overview of changes in snapd-glib 0.14 * Fix header guards in snapd-login.h which stopped it being included Overview of changes in snapd-glib 0.13 * Make snapd_client_login() consistent with snapd_login() (API and ABI break) * Complete documentation on all functions / types (fixes make check) * Disable buy support for now - it is being redesigned in snapd. Overview of changes in snapd-glib 0.12 * Rename error codes for consistency (API and ABI break) * Generate documentation using GTK-Doc Overview of changes in snapd-glib 0.11 * Use doubles for price amounts (API and ABI break) * Make Polkit policy translatable * Fix errors not being correct on first use of snapd_login Overview of changes in snapd-glib 0.10 * Fix snapd-login-service D-Bus configuration * Improve documentation about root requirements for snapd_client_login * Distribute license files * Fix compiler warning Overview of changes in snapd-glib 0.9 * Rename SnapdClientError to SnapdError (API and ABI break) * Add a D-Bus service to allow login without root permissions * Add asserts to check we are connected before making requests Overview of changes in snapd-glib 0.8 * Store auth data inside SnapdClient (API and ABI break) * Return suggested currency in find request (API and ABI break) * Only call progress callback if something changes Overview of changes in snapd-glib 0.7 * Return error codes when icons fail to download * Fix sync methods not working inside async callbacks * Use GDateTime for date/time values returned by snapd Overview of changes in snapd-glib 0.6 * Fix memory ownership for returned results from list/find * Add missing docstrings * Fix small memory leaks Overview of changes in snapd-glib 0.5 * Add copyright headers * Mark authentication parameters optional Overview of changes in snapd-glib 0.4 * Limit poll rate to 100ms * Implement progress callbacks * Handle bad responses Overview of changes in snapd-glib 0.3 * Fix some memory management Overview of changes in snapd-glib 0.2 * Drop versioning from libraries Overview of changes in snapd-glib 0.1 * Initial release snapd-glib-1.67/README.md000066400000000000000000000013551477073115000147570ustar00rootroot00000000000000## snapd-glib snapd-glib is a library to allow GLib based applications access to snapd, the daemon that controls Snaps. A snapd-qt library is provided that wraps snapd-glib for Qt based applications. The following languages / platforms are supported: * C * C++ * Vala * Python (using GObject introspection) * Javacript (using GObject introspection) * Qt * QML Documentation is available [online](https://canonical.github.io/snapd-glib/). See [snapcraft.io](https://snapcraft.io) for more information on snapd. ## Reporting bugs If you have found an issue with the application, please [file an issue](https://github.com/canonical/snapd-glib/issues/new) on the [issues list on GitHub](https://github.com/snapcore/snapd-glib/issues). snapd-glib-1.67/doc/000077500000000000000000000000001477073115000142415ustar00rootroot00000000000000snapd-glib-1.67/doc/meson.build000066400000000000000000000015511477073115000164050ustar00rootroot00000000000000if get_option ('docs') docgen = find_program('gi-docgen') doc_conf = configuration_data () doc_conf.set ('PROJECT_VERSION', meson.project_version ()) settings_file = configure_file (input: 'settings.toml.in', output: 'settings.toml', configuration: doc_conf) custom_target('documentation', depends: snapd_glib_gir, command : [docgen, 'generate', '--config', settings_file, '--no-namespace-dir', '--output-dir', join_paths('@OUTDIR@', 'snapd-glib'), join_paths (meson.project_build_root (), 'snapd-glib', 'Snapd-2.gir')], output: 'snapd-glib', build_by_default: true, install: true, install_dir: get_option('prefix') / get_option('datadir') / 'doc',) # installs to PREFIX/share/doc/snapd-glib endif snapd-glib-1.67/doc/settings.toml.in000066400000000000000000000005501477073115000174030ustar00rootroot00000000000000[library] description = "The Snapd-GLib library" license = "LGPL-2, LGPL-3" version = "@PROJECT_VERSION@" repository_url = "https://github.com/canonical/snapd-glib" devhelp = true search_index = true [theme] name = "basic" show_index_summary = true show_class_hierarchy = true [source-location] base_url = "https://github.com/canonical/snapd-glib/tree/main" snapd-glib-1.67/examples/000077500000000000000000000000001477073115000153125ustar00rootroot00000000000000snapd-glib-1.67/examples/meson.build000066400000000000000000000003311477073115000174510ustar00rootroot00000000000000executable ('snap-glib', 'snap-glib.c', dependencies: [snapd_glib_dep, gio_dep]) executable ('snapctl-glib', 'snapctl-glib.c', dependencies: [snapd_glib_dep, gio_dep]) snapd-glib-1.67/examples/snap-glib.c000066400000000000000000000330641477073115000173400ustar00rootroot00000000000000/* * Copyright (C) 2022 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include static void print_table (GPtrArray *columns) { g_autofree size_t *column_widths = g_malloc0 (sizeof (size_t) * columns->len); guint n_rows = 0; for (guint c = 0; c < columns->len; c++) { GPtrArray *row = g_ptr_array_index (columns, c); if (row->len > n_rows) { n_rows = row->len; } for (guint r = 0; r < row->len; r++) { const gchar *value = g_ptr_array_index (row, r); size_t width = strlen (value); if (width > column_widths[c]) { column_widths[c] = width; } } } for (guint r = 0; r < n_rows; r++) { size_t padding_required = 0; for (guint c = 0; c < columns->len; c++) { GPtrArray *row = g_ptr_array_index (columns, c); const gchar *value = r < row->len ? g_ptr_array_index (row, r) : ""; for (size_t i = 0; i < padding_required; i++) { g_printerr (" "); } if (c != 0) { g_printerr (" "); } g_printerr ("%s", value); padding_required = column_widths[c] - g_utf8_strlen (value, -1); } g_printerr ("\n"); } } static void add_to_column (GPtrArray *column, const gchar *value) { g_ptr_array_add (column, value != NULL ? (gpointer) value : "–"); } static int find (int argc, char **argv) { if (argc > 1) { g_printerr ("error: too many arguments for command\n"); return EXIT_FAILURE; } const gchar *query = argc > 0 ? argv[0] : NULL; g_autoptr(SnapdClient) client = snapd_client_new (); g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) snaps = snapd_client_find_category_sync (client, SNAPD_FIND_FLAGS_NONE, NULL, query, NULL, NULL, &error); if (snaps == NULL) { g_printerr ("error: failed to find: %s\n", error->message); return EXIT_FAILURE; } if (snaps->len == 0) { g_printerr ("No matching snaps for \"%s\"\n", query); return EXIT_FAILURE; } g_autoptr(GPtrArray) name_column = g_ptr_array_new (); add_to_column (name_column, "Name"); g_autoptr(GPtrArray) version_column = g_ptr_array_new (); add_to_column (version_column, "Version"); g_autoptr(GPtrArray) publisher_column = g_ptr_array_new (); add_to_column (publisher_column, "Publisher"); g_autoptr(GPtrArray) summary_column = g_ptr_array_new (); add_to_column (summary_column, "Summary"); for (guint i = 0; i < snaps->len; i++) { SnapdSnap *snap = g_ptr_array_index (snaps, i); add_to_column (name_column, snapd_snap_get_name (snap)); add_to_column (version_column, snapd_snap_get_version (snap)); add_to_column (publisher_column, snapd_snap_get_publisher_display_name (snap)); add_to_column (summary_column, snapd_snap_get_summary (snap)); } g_autoptr(GPtrArray) columns = g_ptr_array_new (); g_ptr_array_add (columns, name_column); g_ptr_array_add (columns, version_column); g_ptr_array_add (columns, publisher_column); g_ptr_array_add (columns, summary_column); print_table (columns); return EXIT_SUCCESS; } static int info (int argc, char **argv) { if (argc < 1) { g_printerr ("error: missing snap name(s)\n"); return EXIT_FAILURE; } g_autoptr(SnapdClient) client = snapd_client_new (); for (int i = 0; i < argc; i++) { const char *name = argv[i]; gchar *names[2] = { (gchar*) name, NULL }; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) local_snaps = snapd_client_get_snaps_sync (client, SNAPD_GET_SNAPS_FLAGS_NONE, names, NULL, &error); g_autoptr(GPtrArray) store_snaps = snapd_client_find_category_sync (client, SNAPD_FIND_FLAGS_MATCH_NAME, NULL, name, NULL, NULL, &error); SnapdSnap *local_snap = local_snaps != NULL && local_snaps->len > 0 ? g_ptr_array_index (local_snaps, 0) : NULL; SnapdSnap *store_snap = store_snaps != NULL && store_snaps->len > 0 ? g_ptr_array_index (store_snaps, 0) : NULL; SnapdSnap *snap = store_snap ? store_snap : local_snap; if (snap == NULL) { g_printerr ("error: no snap found for \"%s\"\n", name); } const gchar *publisher = snapd_snap_get_publisher_display_name (snap); const gchar *license = snapd_snap_get_license (snap); if (i != 0) { g_printerr ("---\n"); } g_printerr ("name: %s\n", snapd_snap_get_name (snap)); g_printerr ("summary: %s\n", snapd_snap_get_summary (snap)); g_printerr ("publisher: %s\n", publisher != NULL ? publisher : "–"); if (store_snap != NULL) { g_printerr ("store-url: %s\n", snapd_snap_get_store_url (store_snap)); g_printerr ("contact: %s\n", snapd_snap_get_contact (store_snap)); } g_printerr ("license: %s\n", license != NULL ? license : "unset"); g_printerr ("description: |\n"); g_printerr (" %s\n", snapd_snap_get_description (snap)); if (store_snap != NULL) { g_printerr ("snap-id: %s\n", snapd_snap_get_id (snap)); g_printerr ("tracking: %s\n", snapd_snap_get_tracking_channel (local_snap)); } } return EXIT_SUCCESS; } static int install (int argc, char **argv) { if (argc < 1) { g_printerr ("error: missing snap name(s)\n"); return EXIT_FAILURE; } g_autoptr(SnapdClient) client = snapd_client_new (); for (int i = 0; i < argc; i++) { const char *name = argv[i]; g_autoptr(GError) error = NULL; if (!snapd_client_install2_sync (client, SNAPD_INSTALL_FLAGS_NONE, name, NULL, NULL, NULL, NULL, NULL, &error)) { g_printerr ("error: failed to install \"%s\": %s\n", name, error->message); continue; } gchar *names[2] = { (gchar*) name, NULL }; g_autoptr(GPtrArray) local_snaps = snapd_client_get_snaps_sync (client, SNAPD_GET_SNAPS_FLAGS_NONE, names, NULL, &error); if (local_snaps == NULL || local_snaps->len == 0) { g_printerr ("error: failed to get information on installed snap %s: %s\n", name, error->message); continue; } SnapdSnap *local_snap = g_ptr_array_index (local_snaps, 0); g_printerr ("%s %s from %s (%s) installed\n", name, snapd_snap_get_version (local_snap), snapd_snap_get_publisher_display_name (local_snap), snapd_snap_get_publisher_username (local_snap)); } return EXIT_SUCCESS; } static int remove (int argc, char **argv) { if (argc < 1) { g_printerr ("error: missing snap name(s)\n"); return EXIT_FAILURE; } g_autoptr(SnapdClient) client = snapd_client_new (); for (int i = 0; i < argc; i++) { const char *name = argv[i]; g_autoptr(GError) error = NULL; if (!snapd_client_remove2_sync (client, SNAPD_REMOVE_FLAGS_NONE, name, NULL, NULL, NULL, &error)) { g_printerr ("error: failed to remove \"%s\": %s\n", name, error->message); continue; } g_printerr ("%s removed\n", name); } return EXIT_SUCCESS; } static int list (int argc, char **argv) { if (argc > 1) { g_printerr ("error: too many arguments for command\n"); return EXIT_FAILURE; } const gchar *name = argc > 0 ? argv[0] : NULL; gchar *names[2] = { (gchar*) name, NULL }; g_autoptr(SnapdClient) client = snapd_client_new (); g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) snaps = snapd_client_get_snaps_sync (client, SNAPD_GET_SNAPS_FLAGS_NONE, names, NULL, &error); if (snaps == NULL) { g_printerr ("error: failed to list: %s\n", error->message); return EXIT_FAILURE; } g_autoptr(GPtrArray) name_column = g_ptr_array_new (); add_to_column (name_column, "Name"); g_autoptr(GPtrArray) version_column = g_ptr_array_new (); add_to_column (version_column, "Version"); g_autoptr(GPtrArray) revision_column = g_ptr_array_new (); add_to_column (revision_column, "Rev"); g_autoptr(GPtrArray) tracking_column = g_ptr_array_new (); add_to_column (tracking_column, "Tracking"); g_autoptr(GPtrArray) publisher_column = g_ptr_array_new (); add_to_column (publisher_column, "Publisher"); for (guint i = 0; i < snaps->len; i++) { SnapdSnap *snap = g_ptr_array_index (snaps, i); add_to_column (name_column, snapd_snap_get_name (snap)); add_to_column (version_column, snapd_snap_get_version (snap)); add_to_column (revision_column, snapd_snap_get_revision (snap)); add_to_column (tracking_column, snapd_snap_get_tracking_channel (snap)); add_to_column (publisher_column, snapd_snap_get_publisher_display_name (snap)); } g_autoptr(GPtrArray) columns = g_ptr_array_new (); g_ptr_array_add (columns, name_column); g_ptr_array_add (columns, version_column); g_ptr_array_add (columns, revision_column); g_ptr_array_add (columns, tracking_column); g_ptr_array_add (columns, publisher_column); print_table (columns); return EXIT_SUCCESS; } static void print_log (SnapdLog *log) { g_autofree gchar *timestamp = g_date_time_format (snapd_log_get_timestamp (log), "%Y-%m-%dT%H:%M:%SZ"); g_printerr ("%s %s[%s]: %s\n", timestamp, snapd_log_get_sid (log), snapd_log_get_pid (log), snapd_log_get_message (log)); } static void log_cb (SnapdClient *client, SnapdLog *log, gpointer user_data) { print_log (log); } static int logs (int argc, char **argv) { if (argc < 1) { g_printerr ("error: the required argument ` (at least 1 argument)` was not provided\n"); return EXIT_FAILURE; } gboolean follow = FALSE; g_autoptr(GPtrArray) names_array = g_ptr_array_new (); for (int i = 0; i < argc; i++) { if (strcmp (argv[i], "-f") == 0) { follow = TRUE; } else { g_ptr_array_add (names_array, g_strdup (argv[i])); } } g_ptr_array_add (names_array, NULL); g_auto(GStrv) names = g_steal_pointer ((GStrv *)&names_array->pdata); g_autoptr(SnapdClient) client = snapd_client_new (); if (follow) { g_autoptr(GError) error = NULL; if (!snapd_client_follow_logs_sync (client, names, log_cb, NULL, NULL, &error)) { g_printerr ("error: failed to get logs: %s\n", error->message); return EXIT_FAILURE; } } else { g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) logs = snapd_client_get_logs_sync (client, names, 0, NULL, &error); if (logs == NULL) { g_printerr ("error: failed to get logs: %s\n", error->message); return EXIT_FAILURE; } for (guint i = 0; i < logs->len; i++) { SnapdLog *log = g_ptr_array_index (logs, i); print_log (log); } } return EXIT_SUCCESS; } static int model (int argc, char **argv) { g_autoptr(SnapdClient) client = snapd_client_new (); g_autoptr(GError) error = NULL; g_autofree gchar *model_assertion_text = snapd_client_get_model_assertion_sync (client, NULL, &error); if (model_assertion_text == NULL) { g_printerr ("error: failed to get model assertion: %s\n", error->message); return EXIT_FAILURE; } g_autofree gchar *serial_assertion_text = snapd_client_get_serial_assertion_sync (client, NULL, &error); if (serial_assertion_text == NULL) { g_printerr ("error: failed to get serial assertion: %s\n", error->message); return EXIT_FAILURE; } g_autoptr(SnapdAssertion) model_assertion = snapd_assertion_new (model_assertion_text); g_autoptr(SnapdAssertion) serial_assertion = snapd_assertion_new (serial_assertion_text); g_printerr ("brand %s\n", snapd_assertion_get_header (model_assertion, "brand-id")); g_printerr ("model %s\n", snapd_assertion_get_header (model_assertion, "model")); g_printerr ("serial %s\n", snapd_assertion_get_header (serial_assertion, "serial")); return EXIT_SUCCESS; } static int usage() { g_printerr ("Usage snap-glib [...]\n"); g_printerr ("Commands: find, info, install, remove, list, logs, model, help\n"); return EXIT_SUCCESS; } int main (int argc, char **argv) { if (argc < 2) { return usage (); } const char *command = argv[1]; int command_argc = argc - 2; char **command_argv = argv + 2; if (strcmp (command, "find") == 0) { return find (command_argc, command_argv); } else if (strcmp (command, "info") == 0) { return info (command_argc, command_argv); } else if (strcmp (command, "install") == 0) { return install (command_argc, command_argv); } else if (strcmp (command, "remove") == 0) { return remove (command_argc, command_argv); } else if (strcmp (command, "list") == 0) { return list (command_argc, command_argv); } else if (strcmp (command, "logs") == 0) { return logs (command_argc, command_argv); } else if (strcmp (command, "model") == 0) { return model (command_argc, command_argv); } else if (strcmp (command, "help") == 0) { return usage (); } else { g_printerr ("error: unknown command \"%s\", see 'snap help'.\n", command); return EXIT_FAILURE; } return EXIT_SUCCESS; } snapd-glib-1.67/examples/snapctl-glib.c000066400000000000000000000030511477073115000200340ustar00rootroot00000000000000/* * Copyright (C) 2021 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include #include int main (int argc, char **argv) { g_autoptr(SnapdClient) client = snapd_client_new (); g_autoptr(GError) error = NULL; const char *context; g_autofree GStrv args = NULL; g_autofree gchar *stdout_output = NULL; g_autofree gchar *stderr_output = NULL; int exit_code, i; /* snapctl commands are sent over a different socket that is made * available within the snap sandbox */ snapd_client_set_socket_path (client, "/run/snapd-snap.socket"); /* Take context from the environment if available */ context = g_getenv ("SNAP_COOKIE"); if (!context) context = ""; /* run_snapctl expects a NULL terminated argument array */ args = g_new0 (char *, argc); for (i = 0; i < argc-1; i++) args[i] = argv[i+1]; if (!snapd_client_run_snapctl2_sync (client, context, args, &stdout_output, &stderr_output, &exit_code, NULL, &error)) { fprintf (stderr, "error: %s\n", error->message); return 1; } if (stdout_output) { fputs (stdout_output, stdout); } if (stderr_output) { fputs (stderr_output, stderr); } return exit_code; } snapd-glib-1.67/format-source.sh000077500000000000000000000016231477073115000166230ustar00rootroot00000000000000#!/bin/bash SOURCE_FILES="snapd-glib/*.[ch] snapd-glib/requests/*.[ch] snapd-qt/*.cpp snapd-qt/*.h snapd-qt/Snapd/*.h tests/*.[ch] tests/*.cpp" if [[ "$1" == "pre-commit" ]]; then echo Checking source style PRE_COMMIT=1 else PRE_COMMIT=0 fi passed=true for file in $SOURCE_FILES; do if [ $# -eq 0 ]; then # no parameters? Just apply the changes echo Formating $file clang-format -i $file else # any parameter? check that the formatting is fine clang-format $file > $file.formatted echo Checking $file if [ $PRE_COMMIT -eq 0 ]; then diff $file $file.formatted else diff $file $file.formatted > /dev/null fi if [ $? != 0 ]; then passed=false fi rm $file.formatted fi done if [ $passed = false ]; then echo Failed to pass clang-format check exit 1 fi snapd-glib-1.67/meson.build000066400000000000000000000021501477073115000156340ustar00rootroot00000000000000project ('snapd-glib', [ 'c', 'cpp' ], version: '1.67', meson_version: '>= 0.58.0', default_options : [ 'c_std=c11' ]) glib_dep = dependency ('glib-2.0', version: '>= 2.46') gio_dep = dependency ('gio-2.0', version: '>= 2.46') gio_unix_dep = dependency ('gio-unix-2.0', version: '>= 2.46') build_introspection = get_option ('introspection') if get_option('docs') build_introspection = true endif if get_option('soup2') libsoup_dep = dependency ('libsoup-2.4', version: '>= 2.32') else libsoup_dep = dependency ('libsoup-3.0', version: '>= 2.99.2') endif json_glib_dep = dependency ('json-glib-1.0', version: '>= 1.1.2') datadir = join_paths (get_option ('prefix'), get_option ('datadir')) includedir = join_paths (get_option ('prefix'), get_option ('includedir')) libdir = join_paths (get_option ('prefix'), get_option ('libdir')) subdir ('snapd-glib') if get_option('qt5') or get_option('qt6') subdir ('snapd-qt') endif if get_option ('tests') subdir ('tests') endif if get_option ('examples') subdir ('examples') endif subdir ('po') if get_option('docs') subdir ('doc') endif snapd-glib-1.67/meson_options.txt000066400000000000000000000021041477073115000171260ustar00rootroot00000000000000option('introspection', type: 'boolean', value: true, description: 'Build the introspection data (requires gobject-introspection)') option('docs', type: 'boolean', value: true, description: 'Build the API reference (requires gi-docgen, and gobject-introspection)') option('vala-bindings', type: 'boolean', value: true, description: 'Build the Vala bindings (requires introspection)') option('qt5', type : 'boolean', value : false, description: 'Build the Qt5 bindings') option('qt6', type : 'boolean', value : true, description: 'Build the Qt6 bindings') option('qml-bindings', type: 'boolean', value: true, description: 'Build the QML bindings (requires the Qt bindings)') option('soup2', type: 'boolean', value: false, description: 'Whether to build with libsoup2') option('examples', type: 'boolean', value: true, description: 'Whether to build the examples') option('tests', type: 'boolean', value: true, description: 'Whether to build the tests') snapd-glib-1.67/po/000077500000000000000000000000001477073115000141125ustar00rootroot00000000000000snapd-glib-1.67/po/LINGUAS000066400000000000000000000000001477073115000151250ustar00rootroot00000000000000snapd-glib-1.67/po/POTFILES.in000066400000000000000000000000731477073115000156670ustar00rootroot00000000000000# keep sorted alphabetically! snapd-glib/snapd-interface.c snapd-glib-1.67/po/meson.build000066400000000000000000000001021477073115000162450ustar00rootroot00000000000000i18n = import('i18n') i18n.gettext('snapd-glib', preset: 'glib') snapd-glib-1.67/snapd-glib.doap000066400000000000000000000016331477073115000163640ustar00rootroot00000000000000 snapd-glib Library to allow GLib based applications access to snapd, the daemon that controls Snaps C Robert Ancell snapd-glib-1.67/snapd-glib/000077500000000000000000000000001477073115000155145ustar00rootroot00000000000000snapd-glib-1.67/snapd-glib/meson.build000066400000000000000000000165661477073115000176740ustar00rootroot00000000000000library_name = 'snapd-glib' if not get_option('soup2') library_name += '-2' endif install_header_dir = join_paths (includedir, library_name, 'snapd-glib') source_h = [ 'snapd-alias.h', 'snapd-app.h', 'snapd-assertion.h', 'snapd-auth-data.h', 'snapd-autorefresh-change-data.h', 'snapd-category.h', 'snapd-category-details.h', 'snapd-change.h', 'snapd-change-data.h', 'snapd-channel.h', 'snapd-client.h', 'snapd-connection.h', 'snapd-error.h', 'snapd-icon.h', 'snapd-interface.h', 'snapd-log.h', 'snapd-login.h', 'snapd-maintenance.h', 'snapd-markdown-node.h', 'snapd-markdown-parser.h', 'snapd-media.h', 'snapd-notice.h', 'snapd-notices-monitor.h', 'snapd-plug.h', 'snapd-plug-ref.h', 'snapd-price.h', 'snapd-screenshot.h', 'snapd-slot.h', 'snapd-slot-ref.h', 'snapd-snap.h', 'snapd-system-information.h', 'snapd-task.h', 'snapd-task-data.h', 'snapd-user-information.h', 'snapd-version.h', ] source_private_h = [ 'requests/snapd-json.h', 'requests/snapd-get-aliases.h', 'requests/snapd-get-apps.h', 'requests/snapd-get-assertions.h', 'requests/snapd-get-buy-ready.h', 'requests/snapd-get-categories.h', 'requests/snapd-get-change.h', 'requests/snapd-get-changes.h', 'requests/snapd-get-connections.h', 'requests/snapd-get-find.h', 'requests/snapd-get-icon.h', 'requests/snapd-get-interfaces.h', 'requests/snapd-get-interfaces-legacy.h', 'requests/snapd-get-logs.h', 'requests/snapd-get-model.h', 'requests/snapd-get-model-serial.h', 'requests/snapd-get-notices.h', 'requests/snapd-get-sections.h', 'requests/snapd-get-snap.h', 'requests/snapd-get-snap-conf.h', 'requests/snapd-get-snaps.h', 'requests/snapd-get-system-info.h', 'requests/snapd-get-themes.h', 'requests/snapd-get-users.h', 'requests/snapd-post-aliases.h', 'requests/snapd-post-assertions.h', 'requests/snapd-post-buy.h', 'requests/snapd-post-change.h', 'requests/snapd-post-create-user.h', 'requests/snapd-post-create-users.h', 'requests/snapd-post-download.h', 'requests/snapd-post-interfaces.h', 'requests/snapd-post-login.h', 'requests/snapd-post-logout.h', 'requests/snapd-post-snap.h', 'requests/snapd-post-snap-stream.h', 'requests/snapd-post-snap-try.h', 'requests/snapd-post-snaps.h', 'requests/snapd-post-snapctl.h', 'requests/snapd-post-themes.h', 'requests/snapd-put-snap-conf.h', 'requests/snapd-request.h', 'requests/snapd-request-async.h', ] source_c = [ 'snapd-alias.c', 'snapd-app.c', 'snapd-assertion.c', 'snapd-auth-data.c', 'snapd-autorefresh-change-data.c', 'snapd-category.c', 'snapd-category-details.c', 'snapd-change.c', 'snapd-change-data.c', 'snapd-channel.c', 'snapd-client.c', 'snapd-client-sync.c', 'snapd-connection.c', 'snapd-error.c', 'snapd-icon.c', 'snapd-interface.c', 'snapd-log.c', 'snapd-login.c', 'snapd-maintenance.c', 'snapd-markdown-node.c', 'snapd-markdown-parser.c', 'snapd-media.c', 'snapd-notice.c', 'snapd-notices-monitor.c', 'snapd-plug.c', 'snapd-plug-ref.c', 'snapd-price.c', 'snapd-screenshot.c', 'snapd-slot.c', 'snapd-slot-ref.c', 'snapd-snap.c', 'snapd-system-information.c', 'snapd-task.c', 'snapd-task-data.c', 'snapd-user-information.c', ] source_private_c = [ 'requests/snapd-json.c', 'requests/snapd-get-aliases.c', 'requests/snapd-get-apps.c', 'requests/snapd-get-assertions.c', 'requests/snapd-get-buy-ready.c', 'requests/snapd-get-categories.c', 'requests/snapd-get-change.c', 'requests/snapd-get-changes.c', 'requests/snapd-get-connections.c', 'requests/snapd-get-find.c', 'requests/snapd-get-icon.c', 'requests/snapd-get-interfaces.c', 'requests/snapd-get-interfaces-legacy.c', 'requests/snapd-get-logs.c', 'requests/snapd-get-model.c', 'requests/snapd-get-model-serial.c', 'requests/snapd-get-notices.c', 'requests/snapd-get-sections.c', 'requests/snapd-get-snap.c', 'requests/snapd-get-snap-conf.c', 'requests/snapd-get-snaps.c', 'requests/snapd-get-system-info.c', 'requests/snapd-get-themes.c', 'requests/snapd-get-users.c', 'requests/snapd-post-aliases.c', 'requests/snapd-post-assertions.c', 'requests/snapd-post-buy.c', 'requests/snapd-post-change.c', 'requests/snapd-post-create-user.c', 'requests/snapd-post-create-users.c', 'requests/snapd-post-download.c', 'requests/snapd-post-interfaces.c', 'requests/snapd-post-login.c', 'requests/snapd-post-logout.c', 'requests/snapd-post-snap.c', 'requests/snapd-post-snap-stream.c', 'requests/snapd-post-snap-try.c', 'requests/snapd-post-snaps.c', 'requests/snapd-post-snapctl.c', 'requests/snapd-post-themes.c', 'requests/snapd-put-snap-conf.c', 'requests/snapd-request.c', 'requests/snapd-request-async.c', ] common_cflags = [ '-DSNAPD_COMPILATION=1', '-DVERSION="@0@"'.format (meson.project_version ()), '-DG_LOG_DOMAIN="Snapd"', '-DGETTEXT_PACKAGE="snapd-glib"' ] gnome = import ('gnome') snapd_glib_enums = gnome.mkenums ('snapd-enum-types', sources: source_h, c_template: 'snapd-enum-types.c.in', h_template: 'snapd-enum-types.h.in', install_header: true, install_dir: install_header_dir) snapd_glib_lib = library (library_name, source_private_c + source_c + source_private_h + source_h, snapd_glib_enums, version: '1.0.0', include_directories: include_directories ('..'), dependencies: [ glib_dep, gio_dep, gio_unix_dep, libsoup_dep, json_glib_dep ], c_args: common_cflags, link_depends: 'snapd-glib.map', link_args: '-Wl,--version-script,@0@/@1@'.format (meson.current_source_dir(), 'snapd-glib.map'), install: true) snapd_glib_dep = declare_dependency (link_with: snapd_glib_lib, sources: snapd_glib_enums[1], include_directories: include_directories ('..')) install_headers (source_h + [ 'snapd-glib.h' ], install_dir: install_header_dir) pc = import ('pkgconfig') pc.generate (libraries: [ snapd_glib_lib ], filebase: library_name, name: 'Snapd GLib', description: 'Libary for accessing snapd', version: meson.project_version (), subdirs: library_name) if build_introspection nsversion = '2' if get_option('soup2') nsversion = '1' endif snapd_glib_gir = gnome.generate_gir (snapd_glib_lib, sources: source_c + source_h + snapd_glib_enums, namespace: 'Snapd', nsversion: nsversion, export_packages: 'snapd-glib', header: 'snapd-glib/snapd-glib.h', includes: [ 'GObject-2.0', 'Gio-2.0' ], install: true, extra_args: [ '-DSNAPD_COMPILATION=1' ]) if get_option ('vala-bindings') gnome.generate_vapi (library_name, sources: snapd_glib_gir[0], packages: 'gio-2.0', install: true) endif endif snapd-glib-1.67/snapd-glib/requests/000077500000000000000000000000001477073115000173675ustar00rootroot00000000000000snapd-glib-1.67/snapd-glib/requests/snapd-get-aliases.c000066400000000000000000000066601477073115000230440ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-get-aliases.h" #include "snapd-alias.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdGetAliases { SnapdRequest parent_instance; GPtrArray *aliases; }; G_DEFINE_TYPE(SnapdGetAliases, snapd_get_aliases, snapd_request_get_type()) SnapdGetAliases *_snapd_get_aliases_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return SNAPD_GET_ALIASES(g_object_new( snapd_get_aliases_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); } GPtrArray *_snapd_get_aliases_get_aliases(SnapdGetAliases *self) { return self->aliases; } static SoupMessage *generate_get_aliases_request(SnapdRequest *request, GBytes **body) { return soup_message_new("GET", "http://snapd/v2/aliases"); } static gboolean parse_get_aliases_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetAliases *self = SNAPD_GET_ALIASES(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonObject) result = _snapd_json_get_sync_result_o(response, error); if (result == NULL) return FALSE; g_autoptr(GPtrArray) aliases = g_ptr_array_new_with_free_func(g_object_unref); JsonObjectIter snap_iter; json_object_iter_init(&snap_iter, result); const gchar *snap; JsonNode *snap_node; while (json_object_iter_next(&snap_iter, &snap, &snap_node)) { if (json_node_get_value_type(snap_node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected alias type"); return FALSE; } JsonObjectIter alias_iter; json_object_iter_init(&alias_iter, json_node_get_object(snap_node)); const gchar *name; JsonNode *alias_node; while (json_object_iter_next(&alias_iter, &name, &alias_node)) { SnapdAlias *alias = _snapd_json_parse_alias(alias_node, snap, name, error); if (alias == NULL) return FALSE; g_ptr_array_add(aliases, alias); } } self->aliases = g_steal_pointer(&aliases); return TRUE; } static void snapd_get_aliases_finalize(GObject *object) { SnapdGetAliases *self = SNAPD_GET_ALIASES(object); g_clear_pointer(&self->aliases, g_ptr_array_unref); G_OBJECT_CLASS(snapd_get_aliases_parent_class)->finalize(object); } static void snapd_get_aliases_class_init(SnapdGetAliasesClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_aliases_request; request_class->parse_response = parse_get_aliases_response; gobject_class->finalize = snapd_get_aliases_finalize; } static void snapd_get_aliases_init(SnapdGetAliases *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-aliases.h000066400000000000000000000014441477073115000230440ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetAliases, snapd_get_aliases, SNAPD, GET_ALIASES, SnapdRequest) SnapdGetAliases *_snapd_get_aliases_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *_snapd_get_aliases_get_aliases(SnapdGetAliases *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-apps.c000066400000000000000000000102371477073115000223610ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-apps.h" #include "snapd-json.h" struct _SnapdGetApps { SnapdRequest parent_instance; gchar *select; GStrv snaps; GPtrArray *apps; }; G_DEFINE_TYPE(SnapdGetApps, snapd_get_apps, snapd_request_get_type()) SnapdGetApps *_snapd_get_apps_new(GStrv snaps, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetApps *self = SNAPD_GET_APPS(g_object_new( snapd_get_apps_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); if (snaps != NULL && snaps[0] != NULL) self->snaps = g_strdupv(snaps); return self; } void _snapd_get_apps_set_select(SnapdGetApps *self, const gchar *select) { g_free(self->select); self->select = g_strdup(select); } GPtrArray *_snapd_get_apps_get_apps(SnapdGetApps *self) { return self->apps; } static SoupMessage *generate_get_apps_request(SnapdRequest *request, GBytes **body) { SnapdGetApps *self = SNAPD_GET_APPS(request); g_autoptr(GPtrArray) query_attributes = g_ptr_array_new_with_free_func(g_free); if (self->select != NULL) { g_autoptr(GString) attr = g_string_new("select="); g_string_append_uri_escaped(attr, self->select, NULL, TRUE); g_ptr_array_add(query_attributes, g_strdup(attr->str)); } if (self->snaps != NULL) { g_autoptr(GString) attr = g_string_new("names="); for (guint i = 0; self->snaps[i] != NULL; i++) { if (i != 0) g_string_append(attr, ","); g_string_append_uri_escaped(attr, self->snaps[i], NULL, TRUE); } g_ptr_array_add(query_attributes, g_strdup(attr->str)); } g_autoptr(GString) path = g_string_new("http://snapd/v2/apps"); if (query_attributes->len > 0) { g_string_append_c(path, '?'); for (guint i = 0; i < query_attributes->len; i++) { if (i != 0) g_string_append_c(path, '&'); g_string_append(path, (gchar *)query_attributes->pdata[i]); } } return soup_message_new("GET", path->str); } static gboolean parse_get_apps_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetApps *self = SNAPD_GET_APPS(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonArray) result = _snapd_json_get_sync_result_a(response, error); if (result == NULL) return FALSE; g_autoptr(GPtrArray) apps = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(result); i++) { JsonNode *node = json_array_get_element(result, i); SnapdApp *app = _snapd_json_parse_app(node, NULL, error); if (app == NULL) return FALSE; g_ptr_array_add(apps, app); } self->apps = g_steal_pointer(&apps); return TRUE; } static void snapd_get_apps_finalize(GObject *object) { SnapdGetApps *self = SNAPD_GET_APPS(object); g_clear_pointer(&self->select, g_free); g_clear_pointer(&self->snaps, g_strfreev); g_clear_pointer(&self->apps, g_ptr_array_unref); G_OBJECT_CLASS(snapd_get_apps_parent_class)->finalize(object); } static void snapd_get_apps_class_init(SnapdGetAppsClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_apps_request; request_class->parse_response = parse_get_apps_response; gobject_class->finalize = snapd_get_apps_finalize; } static void snapd_get_apps_init(SnapdGetApps *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-apps.h000066400000000000000000000015331477073115000223650ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetApps, snapd_get_apps, SNAPD, GET_APPS, SnapdRequest) SnapdGetApps *_snapd_get_apps_new(GStrv snaps, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); void _snapd_get_apps_set_select(SnapdGetApps *request, const gchar *select); GPtrArray *_snapd_get_apps_get_apps(SnapdGetApps *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-assertions.c000066400000000000000000000126241477073115000236120ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-get-assertions.h" #include "snapd-assertion.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdGetAssertions { SnapdRequest parent_instance; gchar *type; GStrv assertions; }; G_DEFINE_TYPE(SnapdGetAssertions, snapd_get_assertions, snapd_request_get_type()) SnapdGetAssertions *_snapd_get_assertions_new(const gchar *type, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetAssertions *self = SNAPD_GET_ASSERTIONS(g_object_new( snapd_get_assertions_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->type = g_strdup(type); return self; } GStrv _snapd_get_assertions_get_assertions(SnapdGetAssertions *self) { return self->assertions; } static SoupMessage *generate_get_assertions_request(SnapdRequest *request, GBytes **body) { SnapdGetAssertions *self = SNAPD_GET_ASSERTIONS(request); g_autoptr(GString) path = g_string_new("http://snapd/v2/assertions/"); g_string_append_uri_escaped(path, self->type, NULL, TRUE); return soup_message_new("GET", path->str); } static gssize find_divider(const gchar *data, size_t offset, size_t data_length) { for (size_t i = offset; i < data_length - 1; i++) { if (data[i] == '\n' && data[i + 1] == '\n') return i; } return -1; } static gboolean parse_get_assertions_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetAssertions *self = SNAPD_GET_ASSERTIONS(request); if (g_strcmp0(content_type, "application/json") == 0) { g_autoptr(JsonObject) response = _snapd_json_parse_response( content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonObject) result = _snapd_json_get_sync_result_o(response, error); if (result == NULL) return FALSE; g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unknown response"); return FALSE; } if (status_code != SOUP_STATUS_OK) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Got response %u retrieving assertions", status_code); return FALSE; } if (g_strcmp0(content_type, "application/x.ubuntu.assertion") != 0) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Got unknown content type '%s' retrieving assertions", content_type); return FALSE; } g_autoptr(GPtrArray) assertions = g_ptr_array_new(); gsize data_length, offset = 0; const gchar *data = g_bytes_get_data(body, &data_length); while (offset < data_length) { gsize assertion_start = offset; /* Headers terminated by double newline */ gssize header_end = find_divider(data, offset, data_length); if (header_end < 0) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Invalid assertion header"); return FALSE; } offset = header_end + 2; /* Make a temporary assertion object to decode body length header */ g_autofree gchar *content = g_strndup(data + assertion_start, offset - assertion_start); g_autoptr(SnapdAssertion) assertion = snapd_assertion_new(content); g_autofree gchar *body_length_header = snapd_assertion_get_header(assertion, "body-length"); /* Skip over body */ gsize body_length = body_length_header != NULL ? strtoul(body_length_header, NULL, 10) : 0; if (body_length > 0) offset += body_length + 2; /* Find end of signature */ gssize assertion_end = find_divider(data, offset, data_length); if (assertion_end < 0) { assertion_end = data_length; offset = assertion_end; } else { offset = assertion_end + 2; } g_ptr_array_add(assertions, g_strndup(data + assertion_start, assertion_end - assertion_start)); } g_ptr_array_add(assertions, NULL); self->assertions = g_steal_pointer((GStrv *)&assertions->pdata); return TRUE; } static void snapd_get_assertions_finalize(GObject *object) { SnapdGetAssertions *self = SNAPD_GET_ASSERTIONS(object); g_clear_pointer(&self->type, g_free); g_clear_pointer(&self->assertions, g_strfreev); G_OBJECT_CLASS(snapd_get_assertions_parent_class)->finalize(object); } static void snapd_get_assertions_class_init(SnapdGetAssertionsClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_assertions_request; request_class->parse_response = parse_get_assertions_response; gobject_class->finalize = snapd_get_assertions_finalize; } static void snapd_get_assertions_init(SnapdGetAssertions *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-assertions.h000066400000000000000000000016041477073115000236130ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetAssertions, snapd_get_assertions, SNAPD, GET_ASSERTIONS, SnapdRequest) SnapdGetAssertions *_snapd_get_assertions_new(const gchar *type, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GStrv _snapd_get_assertions_get_assertions(SnapdGetAssertions *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-buy-ready.c000066400000000000000000000035671477073115000233270ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-buy-ready.h" #include "snapd-json.h" struct _SnapdGetBuyReady { SnapdRequest parent_instance; }; G_DEFINE_TYPE(SnapdGetBuyReady, snapd_get_buy_ready, snapd_request_get_type()) SnapdGetBuyReady *_snapd_get_buy_ready_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return SNAPD_GET_BUY_READY(g_object_new( snapd_get_buy_ready_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); } static SoupMessage *generate_get_buy_ready_request(SnapdRequest *request, GBytes **body) { return soup_message_new("GET", "http://snapd/v2/buy/ready"); } static gboolean parse_get_buy_ready_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; return TRUE; } static void snapd_get_buy_ready_class_init(SnapdGetBuyReadyClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); request_class->generate_request = generate_get_buy_ready_request; request_class->parse_response = parse_get_buy_ready_response; } static void snapd_get_buy_ready_init(SnapdGetBuyReady *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-buy-ready.h000066400000000000000000000013541477073115000233240ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetBuyReady, snapd_get_buy_ready, SNAPD, GET_BUY_READY, SnapdRequest) SnapdGetBuyReady *_snapd_get_buy_ready_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-categories.c000066400000000000000000000066221477073115000235460ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-categories.h" #include "snapd-category-details.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdGetCategories { SnapdRequest parent_instance; GPtrArray *categories; }; G_DEFINE_TYPE(SnapdGetCategories, snapd_get_categories, snapd_request_get_type()) SnapdGetCategories *_snapd_get_categories_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return SNAPD_GET_CATEGORIES(g_object_new( snapd_get_categories_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); } GPtrArray *_snapd_get_categories_get_categories(SnapdGetCategories *self) { return self->categories; } static SoupMessage *generate_get_categories_request(SnapdRequest *request, GBytes **body) { return soup_message_new("GET", "http://snapd/v2/categories"); } static gboolean parse_get_categories_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetCategories *self = SNAPD_GET_CATEGORIES(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonArray) result = _snapd_json_get_sync_result_a(response, error); if (result == NULL) return FALSE; g_autoptr(GPtrArray) categories = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(result); i++) { JsonNode *node = json_array_get_element(result, i); const gchar *name; SnapdCategoryDetails *details; if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected snap category details type"); return FALSE; } JsonObject *object = json_node_get_object(node); name = _snapd_json_get_string(object, "name", NULL); details = g_object_new(snapd_category_details_get_type(), "name", name, NULL); g_ptr_array_add(categories, details); } self->categories = g_steal_pointer(&categories); return TRUE; } static void snapd_get_categories_finalize(GObject *object) { SnapdGetCategories *self = SNAPD_GET_CATEGORIES(object); g_clear_pointer(&self->categories, g_ptr_array_unref); G_OBJECT_CLASS(snapd_get_categories_parent_class)->finalize(object); } static void snapd_get_categories_class_init(SnapdGetCategoriesClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_categories_request; request_class->parse_response = parse_get_categories_response; gobject_class->finalize = snapd_get_categories_finalize; } static void snapd_get_categories_init(SnapdGetCategories *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-categories.h000066400000000000000000000015101477073115000235420ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetCategories, snapd_get_categories, SNAPD, GET_CATEGORIES, SnapdRequest) SnapdGetCategories *_snapd_get_categories_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *_snapd_get_categories_get_categories(SnapdGetCategories *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-change.c000066400000000000000000000075771477073115000226600ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-change.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdGetChange { SnapdRequest parent_instance; gchar *change_id; SnapdChange *change; JsonNode *data; gchar *api_path; }; G_DEFINE_TYPE(SnapdGetChange, snapd_get_change, snapd_request_get_type()) SnapdGetChange *_snapd_get_change_new(const gchar *change_id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetChange *self = SNAPD_GET_CHANGE(g_object_new( snapd_get_change_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->change_id = g_strdup(change_id); return self; } const gchar *_snapd_get_change_get_change_id(SnapdGetChange *self) { return self->change_id; } SnapdChange *_snapd_get_change_get_change(SnapdGetChange *self) { return self->change; } JsonNode *_snapd_get_change_get_data(SnapdGetChange *self) { return self->data; } void _snapd_get_change_set_api_path(SnapdGetChange *self, const gchar *api_path) { g_free(self->api_path); self->api_path = g_strdup(api_path); } static SoupMessage *generate_get_change_request(SnapdRequest *request, GBytes **body) { SnapdGetChange *self = SNAPD_GET_CHANGE(request); g_autofree gchar *path = g_strdup_printf( "http://snapd%s/%s", self->api_path ? self->api_path : "/v2/changes", self->change_id); return soup_message_new("GET", path); } static gboolean parse_get_change_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetChange *self = SNAPD_GET_CHANGE(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; /* FIXME: Needs json-glib to be fixed to use json_node_unref */ /*g_autoptr(JsonNode) result = NULL;*/ JsonNode *result = _snapd_json_get_sync_result(response, error); if (result == NULL) return FALSE; self->change = _snapd_json_parse_change(result, error); json_node_unref(result); if (self->change == NULL) return FALSE; if (g_strcmp0(self->change_id, snapd_change_get_id(self->change)) != 0) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected change ID returned"); return FALSE; } if (json_object_has_member(json_node_get_object(result), "data")) self->data = json_node_ref( json_object_get_member(json_node_get_object(result), "data")); return TRUE; } static void snapd_get_change_finalize(GObject *object) { SnapdGetChange *self = SNAPD_GET_CHANGE(object); g_clear_pointer(&self->change_id, g_free); g_clear_object(&self->change); g_clear_pointer(&self->data, json_node_unref); g_clear_pointer(&self->api_path, g_free); G_OBJECT_CLASS(snapd_get_change_parent_class)->finalize(object); } static void snapd_get_change_class_init(SnapdGetChangeClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_change_request; request_class->parse_response = parse_get_change_response; gobject_class->finalize = snapd_get_change_finalize; } static void snapd_get_change_init(SnapdGetChange *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-change.h000066400000000000000000000022251477073115000226460ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include #include "snapd-change.h" #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetChange, snapd_get_change, SNAPD, GET_CHANGE, SnapdRequest) SnapdGetChange *_snapd_get_change_new(const gchar *change_id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); const gchar *_snapd_get_change_get_change_id(SnapdGetChange *request); SnapdChange *_snapd_get_change_get_change(SnapdGetChange *request); JsonNode *_snapd_get_change_get_data(SnapdGetChange *request); void _snapd_get_change_set_api_path(SnapdGetChange *request, const gchar *api_path); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-changes.c000066400000000000000000000101221477073115000230170ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-changes.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdGetChanges { SnapdRequest parent_instance; gchar *select; gchar *snap_name; GPtrArray *changes; }; G_DEFINE_TYPE(SnapdGetChanges, snapd_get_changes, snapd_request_get_type()) SnapdGetChanges *_snapd_get_changes_new(const gchar *select, const gchar *snap_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetChanges *self = SNAPD_GET_CHANGES(g_object_new( snapd_get_changes_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->select = g_strdup(select); self->snap_name = g_strdup(snap_name); return self; } GPtrArray *_snapd_get_changes_get_changes(SnapdGetChanges *self) { return self->changes; } static SoupMessage *generate_get_changes_request(SnapdRequest *request, GBytes **body) { SnapdGetChanges *self = SNAPD_GET_CHANGES(request); g_autoptr(GPtrArray) query_attributes = g_ptr_array_new_with_free_func(g_free); if (self->select != NULL) { g_autoptr(GString) attr = g_string_new("select="); g_string_append_uri_escaped(attr, self->select, NULL, TRUE); g_ptr_array_add(query_attributes, g_strdup(attr->str)); } if (self->snap_name != NULL) { g_autoptr(GString) attr = g_string_new("for="); g_string_append_uri_escaped(attr, self->snap_name, NULL, TRUE); g_ptr_array_add(query_attributes, g_strdup(attr->str)); } g_autoptr(GString) path = g_string_new("http://snapd/v2/changes"); if (query_attributes->len > 0) { g_string_append_c(path, '?'); for (guint i = 0; i < query_attributes->len; i++) { if (i != 0) g_string_append_c(path, '&'); g_string_append(path, (gchar *)query_attributes->pdata[i]); } } return soup_message_new("GET", path->str); } static gboolean parse_get_changes_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetChanges *self = SNAPD_GET_CHANGES(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonArray) result = _snapd_json_get_sync_result_a(response, error); if (result == NULL) return FALSE; g_autoptr(GPtrArray) changes = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(result); i++) { JsonNode *node = json_array_get_element(result, i); SnapdChange *change = _snapd_json_parse_change(node, error); if (change == NULL) return FALSE; g_ptr_array_add(changes, change); } self->changes = g_steal_pointer(&changes); return TRUE; } static void snapd_get_changes_finalize(GObject *object) { SnapdGetChanges *self = SNAPD_GET_CHANGES(object); g_clear_pointer(&self->select, g_free); g_clear_pointer(&self->snap_name, g_free); g_clear_pointer(&self->changes, g_ptr_array_unref); G_OBJECT_CLASS(snapd_get_changes_parent_class)->finalize(object); } static void snapd_get_changes_class_init(SnapdGetChangesClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_changes_request; request_class->parse_response = parse_get_changes_response; gobject_class->finalize = snapd_get_changes_finalize; } static void snapd_get_changes_init(SnapdGetChanges *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-changes.h000066400000000000000000000017031477073115000230310ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetChanges, snapd_get_changes, SNAPD, GET_CHANGES, SnapdRequest) SnapdGetChanges *_snapd_get_changes_new(const gchar *select, const gchar *snap_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *_snapd_get_changes_get_changes(SnapdGetChanges *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-connections.c000066400000000000000000000147241477073115000237450ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-connections.h" #include "snapd-connection.h" #include "snapd-error.h" #include "snapd-json.h" #include "snapd-plug-ref.h" #include "snapd-plug.h" #include "snapd-slot-ref.h" #include "snapd-slot.h" struct _SnapdGetConnections { SnapdRequest parent_instance; gchar *snap; gchar *interface; gchar *select; GPtrArray *established; GPtrArray *plugs; GPtrArray *slots; GPtrArray *undesired; }; G_DEFINE_TYPE(SnapdGetConnections, snapd_get_connections, snapd_request_get_type()) SnapdGetConnections * _snapd_get_connections_new(const gchar *snap, const gchar *interface, const gchar *select, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetConnections *self = SNAPD_GET_CONNECTIONS(g_object_new( snapd_get_connections_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->snap = g_strdup(snap); self->interface = g_strdup(interface); self->select = g_strdup(select); return self; } GPtrArray *_snapd_get_connections_get_established(SnapdGetConnections *self) { return self->established; } GPtrArray *_snapd_get_connections_get_plugs(SnapdGetConnections *self) { return self->plugs; } GPtrArray *_snapd_get_connections_get_slots(SnapdGetConnections *self) { return self->slots; } GPtrArray *_snapd_get_connections_get_undesired(SnapdGetConnections *self) { return self->undesired; } static SoupMessage *generate_get_connections_request(SnapdRequest *request, GBytes **body) { SnapdGetConnections *self = SNAPD_GET_CONNECTIONS(request); g_autoptr(GPtrArray) query_attributes = g_ptr_array_new_with_free_func(g_free); if (self->snap != NULL) g_ptr_array_add(query_attributes, g_strdup_printf("snap=%s", self->snap)); if (self->interface != NULL) g_ptr_array_add(query_attributes, g_strdup_printf("interface=%s", self->interface)); if (self->select != NULL) g_ptr_array_add(query_attributes, g_strdup_printf("select=%s", self->select)); g_autoptr(GString) path = g_string_new("http://snapd/v2/connections"); if (query_attributes->len > 0) { g_string_append_c(path, '?'); for (guint i = 0; i < query_attributes->len; i++) { if (i != 0) g_string_append_c(path, '&'); g_string_append(path, (gchar *)query_attributes->pdata[i]); } } return soup_message_new("GET", path->str); } static gboolean parse_get_connections_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetConnections *self = SNAPD_GET_CONNECTIONS(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonObject) result = _snapd_json_get_sync_result_o(response, error); if (result == NULL) return FALSE; g_autoptr(JsonArray) established = _snapd_json_get_array(result, "established"); g_autoptr(GPtrArray) established_array = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(established); i++) { JsonNode *node = json_array_get_element(established, i); g_autoptr(SnapdConnection) connection = _snapd_json_parse_connection(node, error); if (connection == NULL) return FALSE; g_ptr_array_add(established_array, g_steal_pointer(&connection)); } g_autoptr(JsonArray) undesired = _snapd_json_get_array(result, "undesired"); g_autoptr(GPtrArray) undesired_array = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(undesired); i++) { JsonNode *node = json_array_get_element(undesired, i); SnapdConnection *connection = _snapd_json_parse_connection(node, error); if (connection == NULL) return FALSE; g_ptr_array_add(undesired_array, connection); } g_autoptr(JsonArray) plugs = _snapd_json_get_array(result, "plugs"); g_autoptr(GPtrArray) plug_array = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(plugs); i++) { JsonNode *node = json_array_get_element(plugs, i); SnapdPlug *plug = _snapd_json_parse_plug(node, error); if (plug == NULL) return FALSE; g_ptr_array_add(plug_array, plug); } g_autoptr(JsonArray) slots = _snapd_json_get_array(result, "slots"); g_autoptr(GPtrArray) slot_array = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(slots); i++) { JsonNode *node = json_array_get_element(slots, i); SnapdSlot *slot = _snapd_json_parse_slot(node, error); if (slot == NULL) return FALSE; g_ptr_array_add(slot_array, slot); } self->established = g_steal_pointer(&established_array); self->undesired = g_steal_pointer(&undesired_array); self->plugs = g_steal_pointer(&plug_array); self->slots = g_steal_pointer(&slot_array); return TRUE; } static void snapd_get_connections_finalize(GObject *object) { SnapdGetConnections *self = SNAPD_GET_CONNECTIONS(object); g_clear_pointer(&self->snap, g_free); g_clear_pointer(&self->interface, g_free); g_clear_pointer(&self->select, g_free); g_clear_pointer(&self->established, g_ptr_array_unref); g_clear_pointer(&self->plugs, g_ptr_array_unref); g_clear_pointer(&self->slots, g_ptr_array_unref); g_clear_pointer(&self->undesired, g_ptr_array_unref); G_OBJECT_CLASS(snapd_get_connections_parent_class)->finalize(object); } static void snapd_get_connections_class_init(SnapdGetConnectionsClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_connections_request; request_class->parse_response = parse_get_connections_response; gobject_class->finalize = snapd_get_connections_finalize; } static void snapd_get_connections_init(SnapdGetConnections *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-connections.h000066400000000000000000000021231477073115000237400ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetConnections, snapd_get_connections, SNAPD, GET_CONNECTIONS, SnapdRequest) SnapdGetConnections * _snapd_get_connections_new(const gchar *snap, const gchar *interface, const gchar *select, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *_snapd_get_connections_get_established(SnapdGetConnections *request); GPtrArray *_snapd_get_connections_get_plugs(SnapdGetConnections *request); GPtrArray *_snapd_get_connections_get_slots(SnapdGetConnections *request); GPtrArray *_snapd_get_connections_get_undesired(SnapdGetConnections *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-find.c000066400000000000000000000144641477073115000223440ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-find.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdGetFind { SnapdRequest parent_instance; gchar *common_id; gchar *query; gchar *name; gchar *select; gchar *section; gchar *category; gchar *scope; gchar *suggested_currency; GPtrArray *snaps; }; G_DEFINE_TYPE(SnapdGetFind, snapd_get_find, snapd_request_get_type()) SnapdGetFind *_snapd_get_find_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetFind *self = SNAPD_GET_FIND(g_object_new( snapd_get_find_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); return self; } void _snapd_get_find_set_common_id(SnapdGetFind *self, const gchar *common_id) { g_free(self->common_id); self->common_id = g_strdup(common_id); } void _snapd_get_find_set_query(SnapdGetFind *self, const gchar *query) { g_free(self->query); self->query = g_strdup(query); } void _snapd_get_find_set_name(SnapdGetFind *self, const gchar *name) { g_free(self->name); self->name = g_strdup(name); } void _snapd_get_find_set_select(SnapdGetFind *self, const gchar *select) { g_free(self->select); self->select = g_strdup(select); } void _snapd_get_find_set_section(SnapdGetFind *self, const gchar *section) { g_free(self->section); self->section = g_strdup(section); } void _snapd_get_find_set_category(SnapdGetFind *self, const gchar *category) { g_free(self->category); self->category = g_strdup(category); } void _snapd_get_find_set_scope(SnapdGetFind *self, const gchar *scope) { g_free(self->scope); self->scope = g_strdup(scope); } GPtrArray *_snapd_get_find_get_snaps(SnapdGetFind *self) { return self->snaps; } const gchar *_snapd_get_find_get_suggested_currency(SnapdGetFind *self) { return self->suggested_currency; } static SoupMessage *generate_get_find_request(SnapdRequest *request, GBytes **body) { SnapdGetFind *self = SNAPD_GET_FIND(request); g_autoptr(GPtrArray) query_attributes = g_ptr_array_new_with_free_func(g_free); if (self->common_id != NULL) { g_autoptr(GString) attr = g_string_new("common-id="); g_string_append_uri_escaped(attr, self->common_id, NULL, TRUE); g_ptr_array_add(query_attributes, g_strdup(attr->str)); } if (self->query != NULL) { g_autoptr(GString) attr = g_string_new("q="); g_string_append_uri_escaped(attr, self->query, NULL, TRUE); g_ptr_array_add(query_attributes, g_strdup(attr->str)); } if (self->name != NULL) { g_autoptr(GString) attr = g_string_new("name="); g_string_append_uri_escaped(attr, self->name, NULL, TRUE); g_ptr_array_add(query_attributes, g_strdup(attr->str)); } if (self->select != NULL) { g_autoptr(GString) attr = g_string_new("select="); g_string_append_uri_escaped(attr, self->select, NULL, TRUE); g_ptr_array_add(query_attributes, g_strdup(attr->str)); } if (self->section != NULL) { g_autoptr(GString) attr = g_string_new("section="); g_string_append_uri_escaped(attr, self->section, NULL, TRUE); g_ptr_array_add(query_attributes, g_strdup(attr->str)); } if (self->category != NULL) { g_autoptr(GString) attr = g_string_new("category="); g_string_append_uri_escaped(attr, self->category, NULL, TRUE); g_ptr_array_add(query_attributes, g_strdup(attr->str)); } if (self->scope != NULL) { g_autoptr(GString) attr = g_string_new("scope="); g_string_append_uri_escaped(attr, self->scope, NULL, TRUE); g_ptr_array_add(query_attributes, g_strdup(attr->str)); } g_autoptr(GString) path = g_string_new("http://snapd/v2/find"); if (query_attributes->len > 0) { g_string_append_c(path, '?'); for (guint i = 0; i < query_attributes->len; i++) { if (i != 0) g_string_append_c(path, '&'); g_string_append(path, (gchar *)query_attributes->pdata[i]); } } return soup_message_new("GET", path->str); } static gboolean parse_get_find_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetFind *self = SNAPD_GET_FIND(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonArray) result = _snapd_json_get_sync_result_a(response, error); if (result == NULL) return FALSE; g_autoptr(GPtrArray) snaps = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(result); i++) { JsonNode *node = json_array_get_element(result, i); SnapdSnap *snap; snap = _snapd_json_parse_snap(node, error); if (snap == NULL) return FALSE; g_ptr_array_add(snaps, snap); } self->snaps = g_steal_pointer(&snaps); self->suggested_currency = g_strdup(_snapd_json_get_string(response, "suggested-currency", NULL)); return TRUE; } static void snapd_get_find_finalize(GObject *object) { SnapdGetFind *self = SNAPD_GET_FIND(object); g_free(self->common_id); g_free(self->query); g_free(self->name); g_free(self->select); g_free(self->section); g_free(self->category); g_free(self->scope); g_free(self->suggested_currency); g_clear_pointer(&self->snaps, g_ptr_array_unref); G_OBJECT_CLASS(snapd_get_find_parent_class)->finalize(object); } static void snapd_get_find_class_init(SnapdGetFindClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_find_request; request_class->parse_response = parse_get_find_response; gobject_class->finalize = snapd_get_find_finalize; } static void snapd_get_find_init(SnapdGetFind *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-find.h000066400000000000000000000026271477073115000223470ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetFind, snapd_get_find, SNAPD, GET_FIND, SnapdRequest) SnapdGetFind *_snapd_get_find_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); void _snapd_get_find_set_common_id(SnapdGetFind *request, const gchar *common_id); void _snapd_get_find_set_query(SnapdGetFind *request, const gchar *query); void _snapd_get_find_set_name(SnapdGetFind *request, const gchar *name); void _snapd_get_find_set_select(SnapdGetFind *request, const gchar *select); void _snapd_get_find_set_section(SnapdGetFind *request, const gchar *section); void _snapd_get_find_set_category(SnapdGetFind *request, const gchar *category); void _snapd_get_find_set_scope(SnapdGetFind *request, const gchar *scope); GPtrArray *_snapd_get_find_get_snaps(SnapdGetFind *request); const gchar *_snapd_get_find_get_suggested_currency(SnapdGetFind *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-icon.c000066400000000000000000000065501477073115000223510ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-icon.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdGetIcon { SnapdRequest parent_instance; gchar *name; SnapdIcon *icon; }; G_DEFINE_TYPE(SnapdGetIcon, snapd_get_icon, snapd_request_get_type()) SnapdGetIcon *_snapd_get_icon_new(const gchar *name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetIcon *self = SNAPD_GET_ICON(g_object_new( snapd_get_icon_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->name = g_strdup(name); return self; } SnapdIcon *_snapd_get_icon_get_icon(SnapdGetIcon *self) { return self->icon; } static SoupMessage *generate_get_icon_request(SnapdRequest *request, GBytes **body) { SnapdGetIcon *self = SNAPD_GET_ICON(request); g_autoptr(GString) path = g_string_new("http://snapd/v2/icons/"); g_string_append_uri_escaped(path, self->name, NULL, TRUE); g_string_append(path, "/icon"); return soup_message_new("GET", path->str); } static gboolean parse_get_icon_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetIcon *self = SNAPD_GET_ICON(request); if (g_strcmp0(content_type, "application/json") == 0) { g_autoptr(JsonObject) response = _snapd_json_parse_response( content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonObject) result = _snapd_json_get_sync_result_o(response, error); if (result == NULL) return FALSE; g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unknown response"); return FALSE; } if (status_code != SOUP_STATUS_OK) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Got response %u retrieving icon", status_code); return FALSE; } g_autoptr(SnapdIcon) icon = g_object_new(SNAPD_TYPE_ICON, "mime-type", content_type, "data", body, NULL); self->icon = g_steal_pointer(&icon); return TRUE; } static void snapd_get_icon_finalize(GObject *object) { SnapdGetIcon *self = SNAPD_GET_ICON(object); g_clear_pointer(&self->name, g_free); g_clear_object(&self->icon); G_OBJECT_CLASS(snapd_get_icon_parent_class)->finalize(object); } static void snapd_get_icon_class_init(SnapdGetIconClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_icon_request; request_class->parse_response = parse_get_icon_response; gobject_class->finalize = snapd_get_icon_finalize; } static void snapd_get_icon_init(SnapdGetIcon *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-icon.h000066400000000000000000000014541477073115000223540ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" #include "snapd-icon.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetIcon, snapd_get_icon, SNAPD, GET_ICON, SnapdRequest) SnapdGetIcon *_snapd_get_icon_new(const gchar *name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); SnapdIcon *_snapd_get_icon_get_icon(SnapdGetIcon *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-interfaces-legacy.c000066400000000000000000000075041477073115000250060ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-interfaces-legacy.h" #include "snapd-error.h" #include "snapd-json.h" #include "snapd-plug-ref.h" #include "snapd-plug.h" #include "snapd-slot-ref.h" #include "snapd-slot.h" struct _SnapdGetInterfacesLegacy { SnapdRequest parent_instance; GPtrArray *plugs; GPtrArray *slots; }; G_DEFINE_TYPE(SnapdGetInterfacesLegacy, snapd_get_interfaces_legacy, snapd_request_get_type()) SnapdGetInterfacesLegacy * _snapd_get_interfaces_legacy_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return SNAPD_GET_INTERFACES_LEGACY(g_object_new( snapd_get_interfaces_legacy_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); } GPtrArray * _snapd_get_interfaces_legacy_get_plugs(SnapdGetInterfacesLegacy *self) { return self->plugs; } GPtrArray * _snapd_get_interfaces_legacy_get_slots(SnapdGetInterfacesLegacy *self) { return self->slots; } static SoupMessage * generate_get_interfaces_legacy_request(SnapdRequest *request, GBytes **body) { return soup_message_new("GET", "http://snapd/v2/interfaces"); } static gboolean parse_get_interfaces_legacy_response( SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetInterfacesLegacy *self = SNAPD_GET_INTERFACES_LEGACY(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonObject) result = _snapd_json_get_sync_result_o(response, error); if (result == NULL) return FALSE; g_autoptr(JsonArray) plugs = _snapd_json_get_array(result, "plugs"); g_autoptr(GPtrArray) plug_array = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(plugs); i++) { JsonNode *node = json_array_get_element(plugs, i); SnapdPlug *plug = _snapd_json_parse_plug(node, error); if (plug == NULL) return FALSE; g_ptr_array_add(plug_array, plug); } g_autoptr(JsonArray) slots = _snapd_json_get_array(result, "slots"); g_autoptr(GPtrArray) slot_array = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(slots); i++) { JsonNode *node = json_array_get_element(slots, i); SnapdSlot *slot = _snapd_json_parse_slot(node, error); if (slot == NULL) return FALSE; g_ptr_array_add(slot_array, slot); } self->plugs = g_steal_pointer(&plug_array); self->slots = g_steal_pointer(&slot_array); return TRUE; } static void snapd_get_interfaces_legacy_finalize(GObject *object) { SnapdGetInterfacesLegacy *self = SNAPD_GET_INTERFACES_LEGACY(object); g_clear_pointer(&self->plugs, g_ptr_array_unref); g_clear_pointer(&self->slots, g_ptr_array_unref); G_OBJECT_CLASS(snapd_get_interfaces_legacy_parent_class)->finalize(object); } static void snapd_get_interfaces_legacy_class_init(SnapdGetInterfacesLegacyClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_interfaces_legacy_request; request_class->parse_response = parse_get_interfaces_legacy_response; gobject_class->finalize = snapd_get_interfaces_legacy_finalize; } static void snapd_get_interfaces_legacy_init(SnapdGetInterfacesLegacy *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-interfaces-legacy.h000066400000000000000000000016611477073115000250110ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetInterfacesLegacy, snapd_get_interfaces_legacy, SNAPD, GET_INTERFACES_LEGACY, SnapdRequest) SnapdGetInterfacesLegacy * _snapd_get_interfaces_legacy_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray * _snapd_get_interfaces_legacy_get_plugs(SnapdGetInterfacesLegacy *request); GPtrArray * _snapd_get_interfaces_legacy_get_slots(SnapdGetInterfacesLegacy *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-interfaces.c000066400000000000000000000120411477073115000235340ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-interfaces.h" #include "snapd-error.h" #include "snapd-json.h" #include "snapd-plug.h" #include "snapd-slot.h" struct _SnapdGetInterfaces { SnapdRequest parent_instance; gchar **names; gboolean include_docs; gboolean include_plugs; gboolean include_slots; gboolean only_connected; GPtrArray *interfaces; }; G_DEFINE_TYPE(SnapdGetInterfaces, snapd_get_interfaces, snapd_request_get_type()) SnapdGetInterfaces *_snapd_get_interfaces_new(gchar **names, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetInterfaces *self = g_object_new( snapd_get_interfaces_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL); if (names != NULL && names[0] != NULL) self->names = g_strdupv(names); return self; } void _snapd_get_interfaces_set_include_docs(SnapdGetInterfaces *self, gboolean include_docs) { self->include_docs = include_docs; } void _snapd_get_interfaces_set_include_plugs(SnapdGetInterfaces *self, gboolean include_plugs) { self->include_plugs = include_plugs; } void _snapd_get_interfaces_set_include_slots(SnapdGetInterfaces *self, gboolean include_slots) { self->include_slots = include_slots; } void _snapd_get_interfaces_set_only_connected(SnapdGetInterfaces *self, gboolean only_connected) { self->only_connected = only_connected; } GPtrArray *_snapd_get_interfaces_get_interfaces(SnapdGetInterfaces *self) { return self->interfaces; } static SoupMessage *generate_get_interfaces_request(SnapdRequest *request, GBytes **body) { SnapdGetInterfaces *self = SNAPD_GET_INTERFACES(request); g_autoptr(GPtrArray) query_attributes = g_ptr_array_new_with_free_func(g_free); if (self->names != NULL) { g_autofree gchar *names_list = g_strjoinv(",", self->names); g_ptr_array_add(query_attributes, g_strdup_printf("names=%s", names_list)); } if (self->include_docs) g_ptr_array_add(query_attributes, g_strdup("doc=true")); if (self->include_plugs) g_ptr_array_add(query_attributes, g_strdup("plugs=true")); if (self->include_slots) g_ptr_array_add(query_attributes, g_strdup("slots=true")); g_ptr_array_add( query_attributes, g_strdup_printf("select=%s", self->only_connected ? "connected" : "all")); g_autoptr(GString) path = g_string_new("http://snapd/v2/interfaces?"); for (guint i = 0; i < query_attributes->len; i++) { if (i != 0) g_string_append_c(path, '&'); g_string_append(path, (gchar *)query_attributes->pdata[i]); } return soup_message_new("GET", path->str); } static gboolean parse_get_interfaces_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetInterfaces *self = SNAPD_GET_INTERFACES(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, NULL, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonArray) result = _snapd_json_get_sync_result_a(response, error); if (result == NULL) return FALSE; g_autoptr(GPtrArray) interfaces = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(result); i++) { JsonNode *node = json_array_get_element(result, i); SnapdInterface *interface; interface = _snapd_json_parse_interface(node, error); if (interface == NULL) return FALSE; g_ptr_array_add(interfaces, interface); } self->interfaces = g_steal_pointer(&interfaces); return TRUE; } static void snapd_get_interfaces_finalize(GObject *object) { SnapdGetInterfaces *self = SNAPD_GET_INTERFACES(object); g_clear_pointer(&self->names, g_strfreev); g_clear_pointer(&self->interfaces, g_ptr_array_unref); G_OBJECT_CLASS(snapd_get_interfaces_parent_class)->finalize(object); } static void snapd_get_interfaces_class_init(SnapdGetInterfacesClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_interfaces_request; request_class->parse_response = parse_get_interfaces_response; gobject_class->finalize = snapd_get_interfaces_finalize; } static void snapd_get_interfaces_init(SnapdGetInterfaces *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-interfaces.h000066400000000000000000000027111477073115000235440ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetInterfaces, snapd_get_interfaces, SNAPD, GET_INTERFACES, SnapdRequest) SnapdGetInterfaces *_snapd_get_interfaces_new(gchar **names, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); void _snapd_get_interfaces_set_include_docs(SnapdGetInterfaces *request, gboolean include_docs); void _snapd_get_interfaces_set_include_plugs(SnapdGetInterfaces *request, gboolean include_plugs); void _snapd_get_interfaces_set_include_slots(SnapdGetInterfaces *request, gboolean include_slots); void _snapd_get_interfaces_set_only_connected(SnapdGetInterfaces *request, gboolean only_connected); GPtrArray *_snapd_get_interfaces_get_interfaces(SnapdGetInterfaces *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-logs.c000066400000000000000000000126211477073115000223610ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-logs.h" #include "snapd-error.h" #include "snapd-json.h" #include "snapd-log.h" struct _SnapdGetLogs { SnapdRequest parent_instance; gchar **names; size_t n; gboolean follow; SnapdGetLogsLogCallback log_callback; gpointer log_callback_data; GDestroyNotify log_callback_destroy_notify; GPtrArray *logs; }; G_DEFINE_TYPE(SnapdGetLogs, snapd_get_logs, snapd_request_get_type()) SnapdGetLogs *_snapd_get_logs_new(gchar **names, size_t n, gboolean follow, SnapdGetLogsLogCallback log_callback, gpointer log_callback_data, GDestroyNotify log_callback_destroy_notify, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetLogs *self = SNAPD_GET_LOGS(g_object_new( snapd_get_logs_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); if (names != NULL && names[0] != NULL) self->names = g_strdupv(names); self->n = n; self->follow = follow; self->log_callback = log_callback; self->log_callback_data = log_callback_data; self->log_callback_destroy_notify = log_callback_destroy_notify; return self; } GPtrArray *_snapd_get_logs_get_logs(SnapdGetLogs *self) { return self->logs; } static SoupMessage *generate_get_logs_request(SnapdRequest *request, GBytes **body) { SnapdGetLogs *self = SNAPD_GET_LOGS(request); g_autoptr(GPtrArray) query_attributes = g_ptr_array_new_with_free_func(g_free); if (self->names != NULL) { g_autofree gchar *names_list = g_strjoinv(",", self->names); g_ptr_array_add(query_attributes, g_strdup_printf("names=%s", names_list)); } if (self->n != 0) { g_ptr_array_add(query_attributes, g_strdup_printf("n=%zi", self->n)); } if (self->follow) { g_ptr_array_add(query_attributes, g_strdup("follow=true")); } g_autoptr(GString) path = g_string_new("http://snapd/v2/logs"); if (query_attributes->len > 0) { g_string_append_c(path, '?'); for (guint i = 0; i < query_attributes->len; i++) { if (i != 0) g_string_append_c(path, '&'); g_string_append(path, (gchar *)query_attributes->pdata[i]); } } return soup_message_new("GET", path->str); } static gboolean parse_get_logs_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, NULL, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonArray) result = _snapd_json_get_sync_result_a(response, error); if (result != NULL) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected snap log response"); } return FALSE; } static gboolean parse_get_logs_json_seq(SnapdRequest *request, JsonNode *seq, GError **error) { g_autoptr(GDateTime) timestamp = NULL; const gchar *message, *sid, *pid; g_autoptr(SnapdLog) log = NULL; SnapdGetLogs *self = SNAPD_GET_LOGS(request); if (!JSON_NODE_HOLDS_OBJECT(seq)) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected snap log type"); return FALSE; } JsonObject *object = json_node_get_object(seq); timestamp = _snapd_json_get_date_time(object, "timestamp", NULL); message = _snapd_json_get_string(object, "message", NULL); sid = _snapd_json_get_string(object, "sid", NULL); pid = _snapd_json_get_string(object, "pid", NULL); log = g_object_new(snapd_log_get_type(), "timestamp", timestamp, "message", message, "sid", sid, "pid", pid, NULL); if (self->log_callback != NULL) { self->log_callback(self, log, self->log_callback_data); } else { g_ptr_array_add(self->logs, g_steal_pointer(&log)); } return TRUE; } static void snapd_get_logs_finalize(GObject *object) { SnapdGetLogs *self = SNAPD_GET_LOGS(object); g_clear_pointer(&self->names, g_strfreev); g_clear_pointer(&self->logs, g_ptr_array_unref); if (self->log_callback_destroy_notify) { self->log_callback_destroy_notify(self->log_callback_data); } G_OBJECT_CLASS(snapd_get_logs_parent_class)->finalize(object); } static void snapd_get_logs_class_init(SnapdGetLogsClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_logs_request; request_class->parse_response = parse_get_logs_response; request_class->parse_json_seq = parse_get_logs_json_seq; gobject_class->finalize = snapd_get_logs_finalize; } static void snapd_get_logs_init(SnapdGetLogs *self) { self->logs = g_ptr_array_new_with_free_func(g_object_unref); } snapd-glib-1.67/snapd-glib/requests/snapd-get-logs.h000066400000000000000000000023031477073115000223620ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-log.h" #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetLogs, snapd_get_logs, SNAPD, GET_LOGS, SnapdRequest) typedef void (*SnapdGetLogsLogCallback)(SnapdGetLogs *request, SnapdLog *log, gpointer user_data); SnapdGetLogs *_snapd_get_logs_new(gchar **names, size_t n, gboolean follow, SnapdGetLogsLogCallback log_callback, gpointer log_callback_data, GDestroyNotify log_callback_destroy_notify, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *_snapd_get_logs_get_logs(SnapdGetLogs *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-model-serial.c000066400000000000000000000053261477073115000237760ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-model-serial.h" #include "snapd-error.h" struct _SnapdGetModelSerial { SnapdRequest parent_instance; gchar *serial_assertion; }; G_DEFINE_TYPE(SnapdGetModelSerial, snapd_get_model_serial, snapd_request_get_type()) SnapdGetModelSerial *_snapd_get_model_serial_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return SNAPD_GET_MODEL_SERIAL(g_object_new( snapd_get_model_serial_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); } const gchar * _snapd_get_model_serial_get_serial_assertion(SnapdGetModelSerial *self) { return self->serial_assertion; } static SoupMessage *generate_get_model_serial_request(SnapdRequest *request, GBytes **body) { return soup_message_new("GET", "http://snapd/v2/model/serial"); } static gboolean parse_get_model_serial_response( SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetModelSerial *self = SNAPD_GET_MODEL_SERIAL(request); if (g_strcmp0(content_type, "application/x.ubuntu.assertion") != 0) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Got unknown content type '%s' retrieving serial assertion", content_type); return FALSE; } gsize data_length; const gchar *data = g_bytes_get_data(body, &data_length); self->serial_assertion = g_strndup(data, data_length); return TRUE; } static void snapd_get_model_serial_finalize(GObject *object) { SnapdGetModelSerial *self = SNAPD_GET_MODEL_SERIAL(object); g_clear_pointer(&self->serial_assertion, g_free); G_OBJECT_CLASS(snapd_get_model_serial_parent_class)->finalize(object); } static void snapd_get_model_serial_class_init(SnapdGetModelSerialClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_model_serial_request; request_class->parse_response = parse_get_model_serial_response; gobject_class->finalize = snapd_get_model_serial_finalize; } static void snapd_get_model_serial_init(SnapdGetModelSerial *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-model-serial.h000066400000000000000000000015421477073115000237770ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetModelSerial, snapd_get_model_serial, SNAPD, GET_MODEL_SERIAL, SnapdRequest) SnapdGetModelSerial *_snapd_get_model_serial_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); const gchar * _snapd_get_model_serial_get_serial_assertion(SnapdGetModelSerial *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-model.c000066400000000000000000000051321477073115000225140ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-model.h" #include "snapd-error.h" struct _SnapdGetModel { SnapdRequest parent_instance; gchar *model_assertion; }; G_DEFINE_TYPE(SnapdGetModel, snapd_get_model, snapd_request_get_type()) SnapdGetModel *_snapd_get_model_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return SNAPD_GET_MODEL(g_object_new(snapd_get_model_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); } const gchar *_snapd_get_model_get_model_assertion(SnapdGetModel *self) { return self->model_assertion; } static SoupMessage *generate_get_model_request(SnapdRequest *request, GBytes **body) { return soup_message_new("GET", "http://snapd/v2/model"); } static gboolean parse_get_model_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetModel *self = SNAPD_GET_MODEL(request); if (g_strcmp0(content_type, "application/x.ubuntu.assertion") != 0) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Got unknown content type '%s' retrieving model assertion", content_type); return FALSE; } gsize data_length; const gchar *data = g_bytes_get_data(body, &data_length); self->model_assertion = g_strndup(data, data_length); return TRUE; } static void snapd_get_model_finalize(GObject *object) { SnapdGetModel *self = SNAPD_GET_MODEL(object); g_clear_pointer(&self->model_assertion, g_free); G_OBJECT_CLASS(snapd_get_model_parent_class)->finalize(object); } static void snapd_get_model_class_init(SnapdGetModelClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_model_request; request_class->parse_response = parse_get_model_response; gobject_class->finalize = snapd_get_model_finalize; } static void snapd_get_model_init(SnapdGetModel *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-model.h000066400000000000000000000014301477073115000225160ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetModel, snapd_get_model, SNAPD, GET_MODEL, SnapdRequest) SnapdGetModel *_snapd_get_model_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); const gchar *_snapd_get_model_get_model_assertion(SnapdGetModel *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-notices.c000066400000000000000000000142141477073115000230610ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-notices.h" #include "snapd-json.h" struct _SnapdGetNotices { SnapdRequest parent_instance; gchar *user_id; gchar *users; gchar *types; gchar *keys; GDateTime *since_date_time; GTimeSpan timeout; int since_date_time_nanoseconds; GPtrArray *notices; }; G_DEFINE_TYPE(SnapdGetNotices, snapd_get_notices, snapd_request_get_type()) SnapdGetNotices * _snapd_get_notices_new(gchar *user_id, gchar *users, gchar *types, gchar *keys, GDateTime *since_date_time, int since_date_time_nanoseconds, GTimeSpan timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetNotices *self = SNAPD_GET_NOTICES(g_object_new( snapd_get_notices_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->user_id = g_strdup(user_id); self->users = g_strdup(users); self->types = g_strdup(types); self->keys = g_strdup(keys); self->since_date_time = since_date_time == NULL ? NULL : g_date_time_ref(since_date_time); self->timeout = timeout; self->since_date_time_nanoseconds = since_date_time_nanoseconds; return self; } static void add_uri_parameter_base(GString *query, const gchar *name) { if (query->len != 0) g_string_append(query, "&"); g_string_append(query, name); g_string_append(query, "="); } static void add_uri_parameter(GString *query, const gchar *name, const gchar *value) { if ((value == NULL) || (*value == 0)) return; add_uri_parameter_base(query, name); g_autofree gchar *value_escaped = g_uri_escape_string(value, NULL, TRUE); g_string_append(query, value_escaped); } static SoupMessage *generate_get_snap_request(SnapdRequest *request, GBytes **body) { SnapdGetNotices *self = SNAPD_GET_NOTICES(request); g_autoptr(GString) query = g_string_new(""); add_uri_parameter(query, "user-id", self->user_id); add_uri_parameter(query, "users", self->users); add_uri_parameter(query, "types", self->types); add_uri_parameter(query, "keys", self->keys); if (self->since_date_time != NULL) { g_autofree gchar *date_time = NULL; if (self->since_date_time_nanoseconds == -1) { #if GLIB_CHECK_VERSION(2, 66, 0) date_time = g_date_time_format(self->since_date_time, "%FT%T.%f%:z"); #else // g_date_time_format doesn't support %f before GLib 2.66 g_autofree gchar *date_time_tmp = g_date_time_format(self->since_date_time, "%FT%T.%%06d%:z"); date_time = g_strdup_printf( date_time_tmp, g_date_time_get_microsecond(self->since_date_time)); #endif } else { if (self->since_date_time_nanoseconds == 0) { date_time = g_date_time_format(self->since_date_time, "%FT%T%:z"); } else { // create a temporal date-time string with a %09d between seconds and // timezone g_autofree gchar *date_time_tmp = g_date_time_format(self->since_date_time, "%FT%T.%%09d%:z"); // Now use that %s to include the nanoseconds date_time = g_strdup_printf(date_time_tmp, self->since_date_time_nanoseconds); } } add_uri_parameter(query, "after", date_time); self->since_date_time_nanoseconds = -1; } if (self->timeout != 0) { add_uri_parameter_base(query, "timeout"); // timeout in microseconds. self->timeout is a GTimeSpan, which is a typedef // into a gint64 type g_string_append_printf(query, "%" G_GINT64_FORMAT "us", self->timeout); } if (query->len != 0) g_string_prepend(query, "?"); g_string_prepend(query, "http://snapd/v2/notices"); return soup_message_new("GET", query->str); } static gboolean parse_get_snap_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetNotices *self = SNAPD_GET_NOTICES(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; /* FIXME: Needs json-glib to be fixed to use json_node_unref */ /*g_autoptr(JsonNode) result = NULL;*/ JsonNode *result = _snapd_json_get_sync_result(response, error); if (result == NULL) return FALSE; g_autoptr(GPtrArray) notices = _snapd_json_parse_notices(result, error); json_node_unref(result); if (notices == NULL) return FALSE; g_clear_pointer(&self->notices, g_ptr_array_unref); self->notices = g_steal_pointer(¬ices); return TRUE; } static void snapd_get_notices_finalize(GObject *object) { SnapdGetNotices *self = SNAPD_GET_NOTICES(object); g_clear_pointer(&self->user_id, g_free); g_clear_pointer(&self->users, g_free); g_clear_pointer(&self->types, g_free); g_clear_pointer(&self->keys, g_free); g_clear_pointer(&self->since_date_time, g_date_time_unref); g_clear_pointer(&self->notices, g_ptr_array_unref); G_OBJECT_CLASS(snapd_get_notices_parent_class)->finalize(object); } GPtrArray *_snapd_get_notices_get_notices(SnapdGetNotices *self) { g_return_val_if_fail(SNAPD_IS_GET_NOTICES(self), NULL); return self->notices; } static void snapd_get_notices_class_init(SnapdGetNoticesClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_snap_request; request_class->parse_response = parse_get_snap_response; gobject_class->finalize = snapd_get_notices_finalize; } static void snapd_get_notices_init(SnapdGetNotices *self) { self->since_date_time_nanoseconds = -1; } snapd-glib-1.67/snapd-glib/requests/snapd-get-notices.h000066400000000000000000000017231477073115000230670ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" #include "snapd-notice.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetNotices, snapd_get_notices, SNAPD, GET_NOTICES, SnapdRequest) SnapdGetNotices * _snapd_get_notices_new(gchar *user_id, gchar *users, gchar *types, gchar *keys, GDateTime *from_date_time, int from_date_time_nanoseconds, GTimeSpan timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *_snapd_get_notices_get_notices(SnapdGetNotices *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-sections.c000066400000000000000000000060301477073115000232410ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-sections.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdGetSections { SnapdRequest parent_instance; GStrv sections; }; G_DEFINE_TYPE(SnapdGetSections, snapd_get_sections, snapd_request_get_type()) SnapdGetSections *_snapd_get_sections_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return SNAPD_GET_SECTIONS(g_object_new( snapd_get_sections_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); } GStrv _snapd_get_sections_get_sections(SnapdGetSections *self) { return self->sections; } static SoupMessage *generate_get_sections_request(SnapdRequest *request, GBytes **body) { return soup_message_new("GET", "http://snapd/v2/sections"); } static gboolean parse_get_sections_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetSections *self = SNAPD_GET_SECTIONS(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonArray) result = _snapd_json_get_sync_result_a(response, error); if (result == NULL) return FALSE; g_autoptr(GPtrArray) sections = g_ptr_array_new(); for (guint i = 0; i < json_array_get_length(result); i++) { JsonNode *node = json_array_get_element(result, i); if (json_node_get_value_type(node) != G_TYPE_STRING) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected snap name type"); return FALSE; } g_ptr_array_add(sections, g_strdup(json_node_get_string(node))); } g_ptr_array_add(sections, NULL); self->sections = g_steal_pointer((GStrv *)§ions->pdata); return TRUE; } static void snapd_get_sections_finalize(GObject *object) { SnapdGetSections *self = SNAPD_GET_SECTIONS(object); g_clear_pointer(&self->sections, g_strfreev); G_OBJECT_CLASS(snapd_get_sections_parent_class)->finalize(object); } static void snapd_get_sections_class_init(SnapdGetSectionsClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_sections_request; request_class->parse_response = parse_get_sections_response; gobject_class->finalize = snapd_get_sections_finalize; } static void snapd_get_sections_init(SnapdGetSections *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-sections.h000066400000000000000000000014531477073115000232520ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetSections, snapd_get_sections, SNAPD, GET_SECTIONS, SnapdRequest) SnapdGetSections *_snapd_get_sections_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GStrv _snapd_get_sections_get_sections(SnapdGetSections *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-snap-conf.c000066400000000000000000000071731477073115000233070ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-snap-conf.h" #include "snapd-json.h" struct _SnapdGetSnapConf { SnapdRequest parent_instance; gchar *name; GStrv keys; GHashTable *conf; }; G_DEFINE_TYPE(SnapdGetSnapConf, snapd_get_snap_conf, snapd_request_get_type()) SnapdGetSnapConf *_snapd_get_snap_conf_new(const gchar *name, GStrv keys, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetSnapConf *self = SNAPD_GET_SNAP_CONF(g_object_new( snapd_get_snap_conf_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->name = g_strdup(name); if (keys != NULL && keys[0] != NULL) self->keys = g_strdupv(keys); return self; } GHashTable *_snapd_get_snap_conf_get_conf(SnapdGetSnapConf *self) { return self->conf; } static SoupMessage *generate_get_snap_conf_request(SnapdRequest *request, GBytes **body) { SnapdGetSnapConf *self = SNAPD_GET_SNAP_CONF(request); g_autoptr(GPtrArray) query_attributes = g_ptr_array_new_with_free_func(g_free); if (self->keys != NULL) { g_autofree gchar *keys_list = g_strjoinv(",", self->keys); g_ptr_array_add(query_attributes, g_strdup_printf("keys=%s", keys_list)); } g_autoptr(GString) path = g_string_new("http://snapd/v2/snaps/"); g_string_append_uri_escaped(path, self->name, NULL, TRUE); g_string_append(path, "/conf"); if (query_attributes->len > 0) { g_string_append_c(path, '?'); for (guint i = 0; i < query_attributes->len; i++) { if (i != 0) g_string_append_c(path, '&'); g_string_append(path, (gchar *)query_attributes->pdata[i]); } } return soup_message_new("GET", path->str); } static gboolean parse_get_snap_conf_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetSnapConf *self = SNAPD_GET_SNAP_CONF(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonObject) result = _snapd_json_get_sync_result_o(response, error); if (result == NULL) return FALSE; self->conf = _snapd_json_parse_object(result, error); if (self->conf == NULL) return FALSE; return TRUE; } static void snapd_get_snap_conf_finalize(GObject *object) { SnapdGetSnapConf *self = SNAPD_GET_SNAP_CONF(object); g_clear_pointer(&self->name, g_free); g_clear_pointer(&self->keys, g_strfreev); g_clear_pointer(&self->conf, g_hash_table_unref); G_OBJECT_CLASS(snapd_get_snap_conf_parent_class)->finalize(object); } static void snapd_get_snap_conf_class_init(SnapdGetSnapConfClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_snap_conf_request; request_class->parse_response = parse_get_snap_conf_response; gobject_class->finalize = snapd_get_snap_conf_finalize; } static void snapd_get_snap_conf_init(SnapdGetSnapConf *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-snap-conf.h000066400000000000000000000015751477073115000233140ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetSnapConf, snapd_get_snap_conf, SNAPD, GET_SNAP_CONF, SnapdRequest) SnapdGetSnapConf *_snapd_get_snap_conf_new(const gchar *name, GStrv keys, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GHashTable *_snapd_get_snap_conf_get_conf(SnapdGetSnapConf *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-snap.c000066400000000000000000000057631477073115000223670ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-snap.h" #include "snapd-json.h" struct _SnapdGetSnap { SnapdRequest parent_instance; gchar *name; SnapdSnap *snap; }; G_DEFINE_TYPE(SnapdGetSnap, snapd_get_snap, snapd_request_get_type()) SnapdGetSnap *_snapd_get_snap_new(const gchar *name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetSnap *self = SNAPD_GET_SNAP(g_object_new( snapd_get_snap_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->name = g_strdup(name); return self; } SnapdSnap *_snapd_get_snap_get_snap(SnapdGetSnap *self) { return self->snap; } static SoupMessage *generate_get_snap_request(SnapdRequest *request, GBytes **body) { SnapdGetSnap *self = SNAPD_GET_SNAP(request); g_autoptr(GString) path = g_string_new("http://snapd/v2/snaps/"); g_string_append_uri_escaped(path, self->name, NULL, TRUE); return soup_message_new("GET", path->str); } static gboolean parse_get_snap_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetSnap *self = SNAPD_GET_SNAP(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; /* FIXME: Needs json-glib to be fixed to use json_node_unref */ /*g_autoptr(JsonNode) result = NULL;*/ JsonNode *result = _snapd_json_get_sync_result(response, error); if (result == NULL) return FALSE; g_autoptr(SnapdSnap) snap = _snapd_json_parse_snap(result, error); json_node_unref(result); if (snap == NULL) return FALSE; self->snap = g_steal_pointer(&snap); return TRUE; } static void snapd_get_snap_finalize(GObject *object) { SnapdGetSnap *self = SNAPD_GET_SNAP(object); g_clear_pointer(&self->name, g_free); g_clear_object(&self->snap); G_OBJECT_CLASS(snapd_get_snap_parent_class)->finalize(object); } static void snapd_get_snap_class_init(SnapdGetSnapClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_snap_request; request_class->parse_response = parse_get_snap_response; gobject_class->finalize = snapd_get_snap_finalize; } static void snapd_get_snap_init(SnapdGetSnap *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-snap.h000066400000000000000000000014541477073115000223650ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" #include "snapd-snap.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetSnap, snapd_get_snap, SNAPD, GET_SNAP, SnapdRequest) SnapdGetSnap *_snapd_get_snap_new(const gchar *name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); SnapdSnap *_snapd_get_snap_get_snap(SnapdGetSnap *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-snaps.c000066400000000000000000000075761477073115000225560ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-snaps.h" #include "snapd-json.h" struct _SnapdGetSnaps { SnapdRequest parent_instance; gchar *select; GStrv names; GPtrArray *snaps; }; G_DEFINE_TYPE(SnapdGetSnaps, snapd_get_snaps, snapd_request_get_type()) SnapdGetSnaps *_snapd_get_snaps_new(GCancellable *cancellable, GStrv names, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetSnaps *self = SNAPD_GET_SNAPS(g_object_new( snapd_get_snaps_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); if (names != NULL && names[0] != NULL) self->names = g_strdupv(names); return self; } void _snapd_get_snaps_set_select(SnapdGetSnaps *self, const gchar *select) { g_free(self->select); self->select = g_strdup(select); } GPtrArray *_snapd_get_snaps_get_snaps(SnapdGetSnaps *self) { return self->snaps; } static SoupMessage *generate_get_snaps_request(SnapdRequest *request, GBytes **body) { SnapdGetSnaps *self = SNAPD_GET_SNAPS(request); g_autoptr(GPtrArray) query_attributes = g_ptr_array_new_with_free_func(g_free); if (self->select != NULL) g_ptr_array_add(query_attributes, g_strdup_printf("select=%s", self->select)); if (self->names != NULL) { g_autofree gchar *names_list = g_strjoinv(",", self->names); g_ptr_array_add(query_attributes, g_strdup_printf("snaps=%s", names_list)); } g_autoptr(GString) path = g_string_new("http://snapd/v2/snaps"); if (query_attributes->len > 0) { g_string_append_c(path, '?'); for (guint i = 0; i < query_attributes->len; i++) { if (i != 0) g_string_append_c(path, '&'); g_string_append(path, (gchar *)query_attributes->pdata[i]); } } return soup_message_new("GET", path->str); } static gboolean parse_get_snaps_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetSnaps *self = SNAPD_GET_SNAPS(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonArray) result = _snapd_json_get_sync_result_a(response, error); if (result == NULL) return FALSE; g_autoptr(GPtrArray) snaps = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(result); i++) { JsonNode *node = json_array_get_element(result, i); SnapdSnap *snap; snap = _snapd_json_parse_snap(node, error); if (snap == NULL) return FALSE; g_ptr_array_add(snaps, snap); } self->snaps = g_steal_pointer(&snaps); return TRUE; } static void snapd_get_snaps_finalize(GObject *object) { SnapdGetSnaps *self = SNAPD_GET_SNAPS(object); g_clear_pointer(&self->select, g_free); g_clear_pointer(&self->names, g_strfreev); g_clear_pointer(&self->snaps, g_ptr_array_unref); G_OBJECT_CLASS(snapd_get_snaps_parent_class)->finalize(object); } static void snapd_get_snaps_class_init(SnapdGetSnapsClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_snaps_request; request_class->parse_response = parse_get_snaps_response; gobject_class->finalize = snapd_get_snaps_finalize; } static void snapd_get_snaps_init(SnapdGetSnaps *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-snaps.h000066400000000000000000000015511477073115000225460ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetSnaps, snapd_get_snaps, SNAPD, GET_SNAPS, SnapdRequest) SnapdGetSnaps *_snapd_get_snaps_new(GCancellable *cancellable, GStrv names, GAsyncReadyCallback callback, gpointer user_data); void _snapd_get_snaps_set_select(SnapdGetSnaps *request, const gchar *select); GPtrArray *_snapd_get_snaps_get_snaps(SnapdGetSnaps *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-system-info.c000066400000000000000000000060351477073115000236740ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-get-system-info.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdGetSystemInfo { SnapdRequest parent_instance; SnapdSystemInformation *system_information; }; G_DEFINE_TYPE(SnapdGetSystemInfo, snapd_get_system_info, snapd_request_get_type()) SnapdGetSystemInfo *_snapd_get_system_info_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return SNAPD_GET_SYSTEM_INFO(g_object_new( snapd_get_system_info_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); } SnapdSystemInformation * _snapd_get_system_info_get_system_information(SnapdGetSystemInfo *self) { return self->system_information; } static SoupMessage *generate_get_system_info_request(SnapdRequest *request, GBytes **body) { return soup_message_new("GET", "http://snapd/v2/system-info"); } static gboolean parse_get_system_info_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetSystemInfo *self = SNAPD_GET_SYSTEM_INFO(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; /* FIXME: Needs json-glib to be fixed to use json_node_unref */ /*g_autoptr(JsonNode) result = NULL;*/ JsonNode *result = _snapd_json_get_sync_result(response, error); if (result == NULL) return FALSE; g_autoptr(SnapdSystemInformation) system_information = _snapd_json_parse_system_information(result, error); json_node_unref(result); if (system_information == NULL) return FALSE; self->system_information = g_steal_pointer(&system_information); return TRUE; } static void snapd_get_system_info_finalize(GObject *object) { SnapdGetSystemInfo *self = SNAPD_GET_SYSTEM_INFO(object); g_clear_object(&self->system_information); G_OBJECT_CLASS(snapd_get_system_info_parent_class)->finalize(object); } static void snapd_get_system_info_class_init(SnapdGetSystemInfoClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_system_info_request; request_class->parse_response = parse_get_system_info_response; gobject_class->finalize = snapd_get_system_info_finalize; } static void snapd_get_system_info_init(SnapdGetSystemInfo *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-system-info.h000066400000000000000000000016131477073115000236760ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" #include "snapd-system-information.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetSystemInfo, snapd_get_system_info, SNAPD, GET_SYSTEM_INFO, SnapdRequest) SnapdGetSystemInfo *_snapd_get_system_info_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); SnapdSystemInformation * _snapd_get_system_info_get_system_information(SnapdGetSystemInfo *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-themes.c000066400000000000000000000132761477073115000227110ustar00rootroot00000000000000/* * Copyright (C) 2021 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-themes.h" #include "snapd-client.h" #include "snapd-json.h" struct _SnapdGetThemes { SnapdRequest parent_instance; GStrv gtk_theme_names; GStrv icon_theme_names; GStrv sound_theme_names; GHashTable *gtk_theme_status; GHashTable *icon_theme_status; GHashTable *sound_theme_status; }; G_DEFINE_TYPE(SnapdGetThemes, snapd_get_themes, snapd_request_get_type()) SnapdGetThemes * _snapd_get_themes_new(GStrv gtk_theme_names, GStrv icon_theme_names, GStrv sound_theme_names, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdGetThemes *self = SNAPD_GET_THEMES(g_object_new( snapd_get_themes_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->gtk_theme_names = g_strdupv(gtk_theme_names); self->icon_theme_names = g_strdupv(icon_theme_names); self->sound_theme_names = g_strdupv(sound_theme_names); return self; } GHashTable *_snapd_get_themes_get_gtk_theme_status(SnapdGetThemes *self) { return self->gtk_theme_status; } GHashTable *_snapd_get_themes_get_icon_theme_status(SnapdGetThemes *self) { return self->icon_theme_status; } GHashTable *_snapd_get_themes_get_sound_theme_status(SnapdGetThemes *self) { return self->sound_theme_status; } static void add_theme_names(GString *path, gboolean *first_param, const char *theme_type, GStrv theme_names) { if (theme_names == NULL) return; for (gchar *const *name = theme_names; *name != NULL; name++) { g_string_append_c(path, *first_param ? '?' : '&'); *first_param = FALSE; g_string_append(path, theme_type); g_string_append_uri_escaped(path, *name, NULL, TRUE); } } static SoupMessage *generate_get_themes_request(SnapdRequest *request, GBytes **body) { SnapdGetThemes *self = SNAPD_GET_THEMES(request); g_autoptr(GString) path = g_string_new("http://snapd/v2/accessories/themes"); gboolean first_param = TRUE; add_theme_names(path, &first_param, "gtk-theme=", self->gtk_theme_names); add_theme_names(path, &first_param, "icon-theme=", self->icon_theme_names); add_theme_names(path, &first_param, "sound-theme=", self->sound_theme_names); return soup_message_new("GET", path->str); } static GHashTable *parse_theme_status(JsonNode *status_object) { g_autoptr(GHashTable) status = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); if (status_object == NULL || json_node_get_value_type(status_object) != JSON_TYPE_OBJECT) return NULL; JsonObjectIter iter; json_object_iter_init(&iter, json_node_get_object(status_object)); const char *theme_name; JsonNode *node; while (json_object_iter_next(&iter, &theme_name, &node)) { const char *value = json_node_get_string(node); SnapdThemeStatus theme_status = SNAPD_THEME_STATUS_UNAVAILABLE; if (g_strcmp0(value, "installed") == 0) { theme_status = SNAPD_THEME_STATUS_INSTALLED; } else if (g_strcmp0(value, "available") == 0) { theme_status = SNAPD_THEME_STATUS_AVAILABLE; } else if (g_strcmp0(value, "unavailable") == 0) { theme_status = SNAPD_THEME_STATUS_UNAVAILABLE; } g_hash_table_insert(status, g_strdup(theme_name), GINT_TO_POINTER(theme_status)); } return g_steal_pointer(&status); } static gboolean parse_get_themes_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetThemes *self = SNAPD_GET_THEMES(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; /* FIXME: Needs json-glib to be fixed to use json_node_unref */ /*g_autoptr(JsonNode) result = NULL;*/ JsonNode *result = _snapd_json_get_sync_result(response, error); if (result == NULL) return FALSE; JsonObject *object = json_node_get_object(result); self->gtk_theme_status = parse_theme_status(json_object_get_member(object, "gtk-themes")); self->icon_theme_status = parse_theme_status(json_object_get_member(object, "icon-themes")); self->sound_theme_status = parse_theme_status(json_object_get_member(object, "sound-themes")); json_node_unref(result); return TRUE; } static void snapd_get_themes_finalize(GObject *object) { SnapdGetThemes *self = SNAPD_GET_THEMES(object); g_clear_pointer(&self->gtk_theme_names, g_strfreev); g_clear_pointer(&self->icon_theme_names, g_strfreev); g_clear_pointer(&self->sound_theme_names, g_strfreev); g_clear_pointer(&self->gtk_theme_status, g_hash_table_unref); g_clear_pointer(&self->icon_theme_status, g_hash_table_unref); g_clear_pointer(&self->sound_theme_status, g_hash_table_unref); G_OBJECT_CLASS(snapd_get_themes_parent_class)->finalize(object); } static void snapd_get_themes_class_init(SnapdGetThemesClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_themes_request; request_class->parse_response = parse_get_themes_response; gobject_class->finalize = snapd_get_themes_finalize; } static void snapd_get_themes_init(SnapdGetThemes *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-themes.h000066400000000000000000000017511477073115000227110ustar00rootroot00000000000000/* * Copyright (C) 2021 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetThemes, snapd_get_themes, SNAPD, GET_THEMES, SnapdRequest) SnapdGetThemes * _snapd_get_themes_new(GStrv gtk_theme_names, GStrv icon_theme_names, GStrv sound_theme_names, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GHashTable *_snapd_get_themes_get_gtk_theme_status(SnapdGetThemes *request); GHashTable *_snapd_get_themes_get_icon_theme_status(SnapdGetThemes *request); GHashTable *_snapd_get_themes_get_sound_theme_status(SnapdGetThemes *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-get-users.c000066400000000000000000000060021477073115000225520ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-get-users.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdGetUsers { SnapdRequest parent_instance; GPtrArray *users_information; }; G_DEFINE_TYPE(SnapdGetUsers, snapd_get_users, snapd_request_get_type()) SnapdGetUsers *_snapd_get_users_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return SNAPD_GET_USERS(g_object_new(snapd_get_users_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); } GPtrArray *_snapd_get_users_get_users_information(SnapdGetUsers *self) { return self->users_information; } static SoupMessage *generate_get_users_request(SnapdRequest *request, GBytes **body) { return soup_message_new("GET", "http://snapd/v2/users"); } static gboolean parse_get_users_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdGetUsers *self = SNAPD_GET_USERS(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonArray) result = _snapd_json_get_sync_result_a(response, error); if (result == NULL) return FALSE; g_autoptr(GPtrArray) users_information = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(result); i++) { JsonNode *node = json_array_get_element(result, i); SnapdUserInformation *user_information = _snapd_json_parse_user_information(node, error); if (user_information == NULL) return FALSE; g_ptr_array_add(users_information, user_information); } self->users_information = g_steal_pointer(&users_information); return TRUE; } static void snapd_get_users_finalize(GObject *object) { SnapdGetUsers *self = SNAPD_GET_USERS(object); g_clear_pointer(&self->users_information, g_ptr_array_unref); G_OBJECT_CLASS(snapd_get_users_parent_class)->finalize(object); } static void snapd_get_users_class_init(SnapdGetUsersClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_get_users_request; request_class->parse_response = parse_get_users_response; gobject_class->finalize = snapd_get_users_finalize; } static void snapd_get_users_init(SnapdGetUsers *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-get-users.h000066400000000000000000000014301477073115000225570ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdGetUsers, snapd_get_users, SNAPD, GET_USERS, SnapdRequest) SnapdGetUsers *_snapd_get_users_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *_snapd_get_users_get_users_information(SnapdGetUsers *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-json.c000066400000000000000000001622551477073115000216220ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include #include "snapd-json.h" #include "snapd-app.h" #include "snapd-category.h" #include "snapd-error.h" #include "snapd-media.h" #include "snapd-screenshot.h" #include "snapd-task.h" void _snapd_json_set_body(SoupMessage *message, JsonBuilder *builder, GBytes **body) { #if SOUP_CHECK_VERSION(2, 99, 2) SoupMessageHeaders *request_headers = soup_message_get_request_headers(message); #else SoupMessageHeaders *request_headers = message->request_headers; #endif soup_message_headers_set_content_type(request_headers, "application/json", NULL); g_autoptr(JsonNode) json_root = json_builder_get_root(builder); g_autoptr(JsonGenerator) json_generator = json_generator_new(); json_generator_set_pretty(json_generator, TRUE); json_generator_set_root(json_generator, json_root); gsize data_length; g_autofree guchar *data = (guchar *)json_generator_to_data(json_generator, &data_length); *body = g_bytes_new_take(g_steal_pointer(&data), data_length); } gboolean _snapd_json_get_bool(JsonObject *object, const gchar *name, gboolean default_value) { JsonNode *node = json_object_get_member(object, name); if (node != NULL && json_node_get_value_type(node) == G_TYPE_BOOLEAN) return json_node_get_boolean(node); else return default_value; } gint64 _snapd_json_get_int(JsonObject *object, const gchar *name, gint64 default_value) { JsonNode *node = json_object_get_member(object, name); if (node != NULL && json_node_get_value_type(node) == G_TYPE_INT64) return json_node_get_int(node); else return default_value; } const gchar *_snapd_json_get_string(JsonObject *object, const gchar *name, const gchar *default_value) { JsonNode *node = json_object_get_member(object, name); if (node != NULL && json_node_get_value_type(node) == G_TYPE_STRING) return json_node_get_string(node); else return default_value; } JsonArray *_snapd_json_get_array(JsonObject *object, const gchar *name) { JsonNode *node = json_object_get_member(object, name); if (node != NULL && json_node_get_value_type(node) == JSON_TYPE_ARRAY) return json_array_ref(json_node_get_array(node)); else return json_array_new(); } JsonObject *_snapd_json_get_object(JsonObject *object, const gchar *name) { JsonNode *node = json_object_get_member(object, name); if (node != NULL && json_node_get_value_type(node) == JSON_TYPE_OBJECT) return json_node_get_object(node); else return NULL; } gboolean _snapd_json_parse_time_span(const gchar *time_span_string, GTimeSpan *time_span) { /* Examples: 3y 1y5d 4h32m2s Valid time units: y w d h m s ms us µs ns Since GTimeSpan is in microseconds, ns will be discarded. */ GTimeSpan current_value = 0; if (time_span_string == NULL) return FALSE; gchar *p = (gchar *)time_span_string; *time_span = 0; if (*p == '-') p++; for (; *p != 0; p++) { switch (*p) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': current_value *= 10; current_value += (GTimeSpan)((*p) - '0'); break; case 'y': *time_span += current_value * 365 * G_TIME_SPAN_DAY; current_value = 0; break; case 'w': *time_span += current_value * 7 * G_TIME_SPAN_DAY; current_value = 0; break; case 'd': *time_span += current_value * G_TIME_SPAN_DAY; current_value = 0; break; case 'h': *time_span += current_value * G_TIME_SPAN_HOUR; current_value = 0; break; case 'm': if (*(p + 1) == 's') { *time_span += current_value * G_TIME_SPAN_MILLISECOND; p++; } else { *time_span += current_value * G_TIME_SPAN_MINUTE; } current_value = 0; break; case 's': *time_span += current_value * G_TIME_SPAN_SECOND; current_value = 0; break; case '\xc2': // first byte of µ p++; if (*p != '\xb5') { // it's not µ *time_span = 0; return FALSE; } // continue like it is 'u' case 'u': p++; if (*p == 's') { *time_span += current_value; // microseconds current_value = 0; } else { *time_span = 0; return FALSE; } break; case 'n': p++; if (*p == 's') { current_value = 0; } else { *time_span = 0; return FALSE; } break; default: *time_span = 0; return FALSE; } } if (*time_span_string == '-') { *time_span *= -1; } return TRUE; } static gboolean parse_date(const gchar *date_string, gint *year, gint *month, gint *day) { /* Example: 2016-05-17 */ if (strchr(date_string, '-') != NULL) { g_auto(GStrv) tokens = g_strsplit(date_string, "-", -1); if (g_strv_length(tokens) != 3) return FALSE; *year = atoi(tokens[0]); *month = atoi(tokens[1]); *day = atoi(tokens[2]); return TRUE; } /* Example: 20160517 */ else if (strlen(date_string) == 8) { // FIXME: Implement return FALSE; } else return FALSE; } static gboolean parse_time(const gchar *time_string, gint *hour, gint *minute, gdouble *seconds) { /* Example: 09:36:53.682 or 09:36:53 or 09:36 */ if (strchr(time_string, ':') != NULL) { g_auto(GStrv) tokens = g_strsplit(time_string, ":", 3); *hour = atoi(tokens[0]); if (tokens[1] == NULL) return FALSE; *minute = atoi(tokens[1]); if (tokens[2] != NULL) { *seconds = g_ascii_strtod(tokens[2], NULL); } else { *seconds = 0.0; } return TRUE; } /* Example: 093653.682 or 093653 or 0936 */ else { // FIXME: Implement return FALSE; } } static gboolean is_timezone_prefix(gchar c) { return c == '+' || c == '-' || c == 'Z'; } static int parse_nanoseconds(gchar *token) { gchar *nanostr; int nanosecs; size_t nanostr_len; // find the decimal dot for (nanostr = token; (*nanostr != '.') && (*nanostr != 0); nanostr++) ; // no decimal value if (*nanostr == 0) return 0; nanostr++; // jump over the dot nanosecs = atoi(nanostr); // RFC3999 removes trailing zeros, so we must complete up to nine decimals nanostr_len = strlen(nanostr); if (nanostr_len < 9) for (int i = 0; i < (9 - nanostr_len); i++) nanosecs *= 10; return nanosecs; } GDateTime *_snapd_json_get_date_time(JsonObject *object, const gchar *name, int *nanoseconds) { const gchar *value = _snapd_json_get_string(object, name, NULL); if (value == NULL) return NULL; /* Example: 2016-05-17T09:36:53+12:00 */ g_auto(GStrv) tokens = g_strsplit(value, "T", 2); gint year = 0, month = 0, day = 0; if (!parse_date(tokens[0], &year, &month, &day)) return NULL; g_autoptr(GTimeZone) timezone = NULL; gint hour = 0, minute = 0; gdouble seconds = 0.0; if (tokens[1] != NULL) { gchar *timezone_start; /* Timezone is either Z (UTC) +hh:mm or -hh:mm */ timezone_start = tokens[1]; while (*timezone_start != '\0' && !is_timezone_prefix(*timezone_start)) timezone_start++; if (*timezone_start != '\0') { #ifdef GLIB_VERSION_2_68 timezone = g_time_zone_new_identifier(timezone_start); if (timezone == NULL) timezone = g_time_zone_new_utc(); #else timezone = g_time_zone_new(timezone_start); #endif } /* Strip off timezone */ *timezone_start = '\0'; if (!parse_time(tokens[1], &hour, &minute, &seconds)) return NULL; } if (timezone == NULL) timezone = g_time_zone_new_local(); if (nanoseconds != NULL) *nanoseconds = parse_nanoseconds(tokens[1]); return g_date_time_new(timezone, year, month, day, hour, minute, seconds); } static void parse_error_response(JsonObject *root, JsonNode **error_value, GError **error) { JsonObject *result = _snapd_json_get_object(root, "result"); gint64 status_code = _snapd_json_get_int(root, "status-code", 0); const gchar *kind = result != NULL ? _snapd_json_get_string(result, "kind", NULL) : NULL; const gchar *message = result != NULL ? _snapd_json_get_string(result, "message", NULL) : NULL; if (error_value != NULL) { *error_value = result != NULL ? json_object_get_member(result, "value") : NULL; if (*error_value != NULL) json_node_ref(*error_value); } if (g_strcmp0(kind, "login-required") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_AUTH_DATA_REQUIRED, message); else if (g_strcmp0(kind, "invalid-auth-data") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_AUTH_DATA_INVALID, message); else if (g_strcmp0(kind, "two-factor-required") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_TWO_FACTOR_REQUIRED, message); else if (g_strcmp0(kind, "two-factor-failed") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_TWO_FACTOR_INVALID, message); else if (g_strcmp0(kind, "terms-not-accepted") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_TERMS_NOT_ACCEPTED, message); else if (g_strcmp0(kind, "no-payment-methods") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_PAYMENT_NOT_SETUP, message); else if (g_strcmp0(kind, "payment-declined") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_PAYMENT_DECLINED, message); else if (g_strcmp0(kind, "snap-already-installed") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_ALREADY_INSTALLED, message); else if (g_strcmp0(kind, "snap-not-installed") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_NOT_INSTALLED, message); else if (g_strcmp0(kind, "snap-not-found") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_NOT_FOUND, message); else if (g_strcmp0(kind, "snap-local") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_NOT_IN_STORE, message); else if (g_strcmp0(kind, "snap-no-update-available") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_NO_UPDATE_AVAILABLE, message); else if (g_strcmp0(kind, "password-policy") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_PASSWORD_POLICY_ERROR, message); else if (g_strcmp0(kind, "snap-needs-devmode") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_NEEDS_DEVMODE, message); else if (g_strcmp0(kind, "snap-needs-classic") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_NEEDS_CLASSIC, message); else if (g_strcmp0(kind, "snap-needs-classic-system") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_NEEDS_CLASSIC_SYSTEM, message); else if (g_strcmp0(kind, "bad-query") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_BAD_QUERY, message); else if (g_strcmp0(kind, "network-timeout") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_NETWORK_TIMEOUT, message); else if (g_strcmp0(kind, "auth-cancelled") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_AUTH_CANCELLED, message); else if (g_strcmp0(kind, "snap-not-classic") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_NOT_CLASSIC, message); else if (g_strcmp0(kind, "snap-revision-not-available") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_REVISION_NOT_AVAILABLE, message); else if (g_strcmp0(kind, "snap-channel-not-available") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_CHANNEL_NOT_AVAILABLE, message); else if (g_strcmp0(kind, "snap-not-a-snap") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_NOT_A_SNAP, message); else if (g_strcmp0(kind, "dns-failure") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_DNS_FAILURE, message); else if (g_strcmp0(kind, "option-not-found") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_OPTION_NOT_FOUND, message); else if (g_strcmp0(kind, "unsuccessful") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_UNSUCCESSFUL, message); else if (g_strcmp0(kind, "app-not-found") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_APP_NOT_FOUND, message); else if (g_strcmp0(kind, "snap-architecture-not-available") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_ARCHITECTURE_NOT_AVAILABLE, message); else if (g_strcmp0(kind, "snap-change-conflict") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_CHANGE_CONFLICT, message); else if (g_strcmp0(kind, "interfaces-unchanged") == 0) g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_INTERFACES_UNCHANGED, message); else { switch (status_code) { case SOUP_STATUS_BAD_REQUEST: g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_REQUEST, "%s: %s", kind, message); break; case SOUP_STATUS_UNAUTHORIZED: g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_AUTH_DATA_REQUIRED, "%s: %s", kind, message); break; case SOUP_STATUS_FORBIDDEN: g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_PERMISSION_DENIED, "%s: %s", kind, message); break; case SOUP_STATUS_NOT_FOUND: g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_FOUND, "%s: %s", kind, message); break; /* Other response codes currently produced by snapd: case SOUP_STATUS_METHOD_NOT_ALLOWED: case SOUP_STATUS_NOT_IMPLEMENTED: case SOUP_STATUS_CONFLICT: */ default: g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_FAILED, "status-code=%" G_GINT64_FORMAT " kind=%s message=%s", status_code, kind, message); } } } JsonObject *_snapd_json_parse_response(const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, JsonNode **error_value, GError **error) { if (content_type == NULL) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_RESPONSE, "snapd returned no content type"); return NULL; } if (g_strcmp0(content_type, "application/json") != 0) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_RESPONSE, "snapd returned unexpected content type %s", content_type); return NULL; } g_autoptr(JsonParser) parser = json_parser_new(); g_autoptr(GError) error_local = NULL; if (!json_parser_load_from_data(parser, g_bytes_get_data(body, NULL), g_bytes_get_size(body), &error_local)) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_RESPONSE, "Unable to parse snapd response: %s", error_local->message); return NULL; } if (!JSON_NODE_HOLDS_OBJECT(json_parser_get_root(parser))) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_RESPONSE, "snapd response does is not a valid JSON object"); return NULL; } JsonObject *root = json_node_get_object(json_parser_get_root(parser)); JsonNode *type_node = json_object_get_member(root, "type"); if (type_node == NULL || json_node_get_value_type(type_node) != G_TYPE_STRING) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_RESPONSE, "snapd response does not have a type"); return NULL; } if (json_object_has_member(root, "maintenance") && maintenance != NULL) { JsonObject *m = json_object_get_object_member(root, "maintenance"); const gchar *kind = _snapd_json_get_string(m, "kind", NULL); SnapdMaintenanceKind maintenance_kind = SNAPD_MAINTENANCE_KIND_UNKNOWN; if (g_strcmp0(kind, "daemon-restart") == 0) maintenance_kind = SNAPD_MAINTENANCE_KIND_DAEMON_RESTART; else if (g_strcmp0(kind, "system-restart") == 0) maintenance_kind = SNAPD_MAINTENANCE_KIND_SYSTEM_RESTART; *maintenance = g_object_new( SNAPD_TYPE_MAINTENANCE, "kind", maintenance_kind, "message", _snapd_json_get_string(m, "message", NULL), NULL); } if (strcmp(json_node_get_string(type_node), "error") == 0) { parse_error_response(root, error_value, error); return NULL; } return json_object_ref(root); } JsonNode *_snapd_json_get_sync_result(JsonObject *response, GError **error) { const gchar *type = json_object_get_string_member(response, "type"); if (strcmp(type, "sync") != 0) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected response '%s' returned for sync request", type); return NULL; } if (!json_object_has_member(response, "result")) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "No result returned"); return NULL; } return json_node_ref(json_object_get_member(response, "result")); } JsonObject *_snapd_json_get_sync_result_o(JsonObject *response, GError **error) { /* FIXME: Needs json-glib to be fixed to use json_node_unref */ /*g_autoptr(JsonNode) result = _snapd_json_get_sync_result (response, * error);*/ JsonNode *result = _snapd_json_get_sync_result(response, error); if (result == NULL) return NULL; if (!JSON_NODE_HOLDS_OBJECT(result)) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Result is not an object"); json_node_unref(result); return NULL; } JsonObject *r = json_object_ref(json_node_get_object(result)); json_node_unref(result); return r; } JsonArray *_snapd_json_get_sync_result_a(JsonObject *response, GError **error) { /* FIXME: Needs json-glib to be fixed to use json_node_unref */ /*g_autoptr(JsonNode) result = _snapd_json_get_sync_result (response, * error);*/ JsonNode *result = _snapd_json_get_sync_result(response, error); if (result == NULL) return NULL; if (!JSON_NODE_HOLDS_ARRAY(result)) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Result is not an array"); json_node_unref(result); return NULL; } JsonArray *r = json_array_ref(json_node_get_array(result)); json_node_unref(result); return r; } gchar *_snapd_json_get_async_result(JsonObject *response, GError **error) { const gchar *type = json_object_get_string_member(response, "type"); if (strcmp(type, "async") != 0) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected response '%s' returned for async request", type); return NULL; } JsonNode *change_node = json_object_get_member(response, "change"); if (change_node == NULL || json_node_get_value_type(change_node) != G_TYPE_STRING) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "No change returned for async request"); return NULL; } return g_strdup(json_node_get_string(change_node)); } static GStrv create_str_array_from_jsonarray(JsonArray *data) { if (data == NULL) return NULL; guint len = json_array_get_length(data); GStrv list = g_malloc0_n(1 + len, sizeof(gchar *)); for (guint i = 0; i < len; i++) { JsonNode *node = json_array_get_element(data, i); if (node == NULL || json_node_get_value_type(node) != G_TYPE_STRING) { g_strfreev(list); return NULL; } list[i] = g_strdup(json_node_get_string(node)); } return list; } static gchar *get_int_as_string(JsonObject *object, const gchar *name) { JsonNode *node = json_object_get_member(object, name); if (node == NULL) return NULL; if (json_node_get_value_type(node) == G_TYPE_INT64) return g_strdup_printf("%" G_GINT64_FORMAT, json_node_get_int(node)); else if (json_node_get_value_type(node) == G_TYPE_STRING) return g_strdup(json_node_get_string(node)); return NULL; } static SnapdNotice *parse_notice(JsonObject *object) { int last_occurred_nanoseconds = 0; g_autoptr(GDateTime) first_occurred = _snapd_json_get_date_time(object, "first-occurred", NULL); g_autoptr(GDateTime) last_occurred = _snapd_json_get_date_time( object, "last-occurred", &last_occurred_nanoseconds); g_autoptr(GDateTime) last_repeated = _snapd_json_get_date_time(object, "last-repeated", NULL); GTimeSpan expire_after = 0, repeat_after = 0; _snapd_json_parse_time_span( _snapd_json_get_string(object, "expire-after", NULL), &expire_after); _snapd_json_parse_time_span( _snapd_json_get_string(object, "repeat-after", NULL), &repeat_after); const gchar *notice_type_string = _snapd_json_get_string(object, "type", NULL); SnapdNoticeType notice_type; if (notice_type_string == NULL) notice_type = SNAPD_NOTICE_TYPE_UNKNOWN; else if (g_str_equal(notice_type_string, "change-update")) notice_type = SNAPD_NOTICE_TYPE_CHANGE_UPDATE; else if (g_str_equal(notice_type_string, "refresh-inhibit")) notice_type = SNAPD_NOTICE_TYPE_REFRESH_INHIBIT; else if (g_str_equal(notice_type_string, "snap-run-inhibit")) notice_type = SNAPD_NOTICE_TYPE_SNAP_RUN_INHIBIT; else notice_type = SNAPD_NOTICE_TYPE_UNKNOWN; g_autoptr(GHashTable) last_data = NULL; if (json_object_has_member(object, "last-data")) { last_data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); JsonObject *data_dict = _snapd_json_get_object(object, "last-data"); JsonObjectIter iter; json_object_iter_init(&iter, data_dict); const gchar *member_name; JsonNode *member_node; while (json_object_iter_next(&iter, &member_name, &member_node)) g_hash_table_insert(last_data, g_strdup(member_name), g_strdup(json_node_get_string(member_node))); } g_autofree gchar *user_id = get_int_as_string(object, "user-id"); return g_object_new( SNAPD_TYPE_NOTICE, "id", _snapd_json_get_string(object, "id", NULL), "user-id", user_id, "notice-type", notice_type, "key", _snapd_json_get_string(object, "key", NULL), "first-occurred", first_occurred, "last-occurred", last_occurred, "last-occurred-nanoseconds", last_occurred_nanoseconds, "last-repeated", last_repeated, "occurrences", _snapd_json_get_int(object, "occurrences", -1), "expire-after", expire_after, "repeat-after", repeat_after, "last-data", last_data, NULL); } GPtrArray *_snapd_json_parse_notices(JsonNode *node, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_ARRAY) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected change type"); return NULL; } JsonArray *array = json_node_get_array(node); g_autoptr(GPtrArray) notices = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(array); i++) { JsonNode *node = json_array_get_element(array, i); if (!JSON_NODE_HOLDS_OBJECT(node)) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_RESPONSE, "Invalid notice"); return NULL; } JsonObject *object = json_node_get_object(node); g_ptr_array_add(notices, parse_notice(object)); } return g_steal_pointer(¬ices); } SnapdChange *_snapd_json_parse_change(JsonNode *node, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected change type"); return NULL; } JsonObject *object = json_node_get_object(node); g_autoptr(JsonArray) array = _snapd_json_get_array(object, "tasks"); g_autoptr(GPtrArray) tasks = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(array); i++) { JsonNode *node = json_array_get_element(array, i); if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected task type"); return NULL; } JsonObject *object = json_node_get_object(node); JsonObject *progress = _snapd_json_get_object(object, "progress"); g_autoptr(GDateTime) spawn_time = _snapd_json_get_date_time(object, "spawn-time", NULL); g_autoptr(GDateTime) ready_time = _snapd_json_get_date_time(object, "ready-time", NULL); JsonObject *data = _snapd_json_get_object(object, "data"); g_autoptr(SnapdTaskData) task_data = NULL; if (data != NULL) { JsonNode *affected_snaps_node = json_object_get_member(data, "affected-snaps"); if (affected_snaps_node != NULL) { if (json_node_get_value_type(affected_snaps_node) != JSON_TYPE_ARRAY) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected affected-snaps type"); return NULL; } JsonArray *affected_snaps = json_node_get_array(affected_snaps_node); g_auto(GStrv) affected_snaps_array = create_str_array_from_jsonarray(affected_snaps); task_data = g_object_new(SNAPD_TYPE_TASK_DATA, "affected-snaps", affected_snaps_array, NULL); } } g_autoptr(SnapdTask) t = g_object_new( SNAPD_TYPE_TASK, "id", _snapd_json_get_string(object, "id", NULL), "kind", _snapd_json_get_string(object, "kind", NULL), "summary", _snapd_json_get_string(object, "summary", NULL), "status", _snapd_json_get_string(object, "status", NULL), "progress-label", progress != NULL ? _snapd_json_get_string(progress, "label", NULL) : NULL, "progress-done", progress != NULL ? _snapd_json_get_int(progress, "done", 0) : 0, "progress-total", progress != NULL ? _snapd_json_get_int(progress, "total", 0) : 0, "spawn-time", spawn_time, "ready-time", ready_time, "data", task_data, NULL); g_ptr_array_add(tasks, g_steal_pointer(&t)); } g_autoptr(GDateTime) main_spawn_time = _snapd_json_get_date_time(object, "spawn-time", NULL); g_autoptr(GDateTime) main_ready_time = _snapd_json_get_date_time(object, "ready-time", NULL); g_autoptr(SnapdChangeData) data = NULL; JsonObject *autorefresh_data = _snapd_json_get_object(object, "data"); const gchar *kind = _snapd_json_get_string(object, "kind", ""); // Currently, only one kind of Change can have DATA field, so this is quite // "hardcoded". When more Change kinds have DATA field, new subclasses of // SNAPD_TYPE_CHANGE_DATA must be created, and the code in QT's // snapd-change-data.c file must be completed to manage the new types. if (g_str_equal(kind, "auto-refresh") && (autorefresh_data != NULL)) { g_autoptr(JsonArray) snap_names_json = _snapd_json_get_array(autorefresh_data, "snap-names"); g_auto(GStrv) snap_names = create_str_array_from_jsonarray(snap_names_json); g_autoptr(JsonArray) refresh_forced_json = _snapd_json_get_array(autorefresh_data, "refresh-forced"); g_auto(GStrv) refresh_forced = create_str_array_from_jsonarray(refresh_forced_json); data = g_object_new(SNAPD_TYPE_AUTOREFRESH_CHANGE_DATA, "snap-names", snap_names, "refresh-forced", refresh_forced, NULL); } return g_object_new( SNAPD_TYPE_CHANGE, "id", _snapd_json_get_string(object, "id", NULL), "kind", _snapd_json_get_string(object, "kind", NULL), "summary", _snapd_json_get_string(object, "summary", NULL), "status", _snapd_json_get_string(object, "status", NULL), "tasks", tasks, "ready", _snapd_json_get_bool(object, "ready", FALSE), "spawn-time", main_spawn_time, "ready-time", main_ready_time, "error", _snapd_json_get_string(object, "err", NULL), "data", data, NULL); } static SnapdConfinement parse_confinement(const gchar *value) { if (strcmp(value, "strict") == 0) return SNAPD_CONFINEMENT_STRICT; else if (strcmp(value, "classic") == 0) return SNAPD_CONFINEMENT_CLASSIC; else if (strcmp(value, "devmode") == 0) return SNAPD_CONFINEMENT_DEVMODE; else return SNAPD_CONFINEMENT_UNKNOWN; } SnapdSystemInformation *_snapd_json_parse_system_information(JsonNode *node, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected system information type"); return NULL; } JsonObject *object = json_node_get_object(node); const gchar *architecture = _snapd_json_get_string(object, "architecture", ""); const gchar *confinement_string = _snapd_json_get_string(object, "confinement", ""); SnapdSystemConfinement confinement = SNAPD_SYSTEM_CONFINEMENT_UNKNOWN; if (strcmp(confinement_string, "strict") == 0) confinement = SNAPD_SYSTEM_CONFINEMENT_STRICT; else if (strcmp(confinement_string, "partial") == 0) confinement = SNAPD_SYSTEM_CONFINEMENT_PARTIAL; JsonObject *os_release = _snapd_json_get_object(object, "os-release"); JsonObject *locations = _snapd_json_get_object(object, "locations"); JsonObject *refresh = _snapd_json_get_object(object, "refresh"); JsonObject *sandbox_features = _snapd_json_get_object(object, "sandbox-features"); g_autoptr(GHashTable) sandbox_features_hash = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_strfreev); if (sandbox_features != NULL) { JsonObjectIter iter; json_object_iter_init(&iter, sandbox_features); const gchar *name; JsonNode *features_node; while (json_object_iter_next(&iter, &name, &features_node)) { if (json_node_get_value_type(features_node) != JSON_TYPE_ARRAY) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected sandbox features type"); return FALSE; } JsonArray *features_array = json_node_get_array(features_node); g_autoptr(GPtrArray) features_ptr_array = g_ptr_array_new(); for (guint i = 0; i < json_array_get_length(features_array); i++) { JsonNode *node = json_array_get_element(features_array, i); if (json_node_get_value_type(node) != G_TYPE_STRING) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected sandbox feature type"); return FALSE; } g_ptr_array_add(features_ptr_array, (gpointer)json_node_get_string(node)); } g_ptr_array_add(features_ptr_array, NULL); g_hash_table_insert(sandbox_features_hash, g_strdup(name), g_strdupv((GStrv)features_ptr_array->pdata)); } } g_autoptr(GDateTime) refresh_hold = _snapd_json_get_date_time(refresh, "hold", NULL); g_autoptr(GDateTime) refresh_last = _snapd_json_get_date_time(refresh, "last", NULL); g_autoptr(GDateTime) refresh_next = _snapd_json_get_date_time(refresh, "next", NULL); return g_object_new( SNAPD_TYPE_SYSTEM_INFORMATION, "architecture", architecture, "binaries-directory", locations != NULL ? _snapd_json_get_string(locations, "snap-bin-dir", NULL) : NULL, "build-id", _snapd_json_get_string(object, "build-id", NULL), "confinement", confinement, "kernel-version", _snapd_json_get_string(object, "kernel-version", NULL), "managed", _snapd_json_get_bool(object, "managed", FALSE), "mount-directory", locations != NULL ? _snapd_json_get_string(locations, "snap-mount-dir", NULL) : NULL, "on-classic", _snapd_json_get_bool(object, "on-classic", FALSE), "os-id", os_release != NULL ? _snapd_json_get_string(os_release, "id", NULL) : NULL, "os-version", os_release != NULL ? _snapd_json_get_string(os_release, "version-id", NULL) : NULL, "sandbox-features", sandbox_features_hash, "series", _snapd_json_get_string(object, "series", NULL), "store", _snapd_json_get_string(object, "store", NULL), "version", _snapd_json_get_string(object, "version", NULL), "refresh-hold", refresh_hold, "refresh-last", refresh_last, "refresh-next", refresh_next, "refresh-schedule", _snapd_json_get_string(refresh, "schedule", NULL), "refresh-timer", _snapd_json_get_string(refresh, "timer", NULL), NULL); } SnapdSnap *_snapd_json_parse_snap(JsonNode *node, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected snap type"); return NULL; } JsonObject *object = json_node_get_object(node); const gchar *name = _snapd_json_get_string(object, "name", NULL); SnapdConfinement confinement = parse_confinement(_snapd_json_get_string(object, "confinement", "")); const gchar *snap_type_string = _snapd_json_get_string(object, "type", ""); SnapdSnapType snap_type = SNAPD_SNAP_TYPE_UNKNOWN; if (strcmp(snap_type_string, "app") == 0) snap_type = SNAPD_SNAP_TYPE_APP; else if (strcmp(snap_type_string, "kernel") == 0) snap_type = SNAPD_SNAP_TYPE_KERNEL; else if (strcmp(snap_type_string, "gadget") == 0) snap_type = SNAPD_SNAP_TYPE_GADGET; else if (strcmp(snap_type_string, "os") == 0) snap_type = SNAPD_SNAP_TYPE_OS; else if (strcmp(snap_type_string, "core") == 0) snap_type = SNAPD_SNAP_TYPE_CORE; else if (strcmp(snap_type_string, "base") == 0) snap_type = SNAPD_SNAP_TYPE_BASE; else if (strcmp(snap_type_string, "snapd") == 0) snap_type = SNAPD_SNAP_TYPE_SNAPD; const gchar *snap_status_string = _snapd_json_get_string(object, "status", ""); SnapdSnapStatus snap_status = SNAPD_SNAP_STATUS_UNKNOWN; if (strcmp(snap_status_string, "available") == 0) snap_status = SNAPD_SNAP_STATUS_AVAILABLE; else if (strcmp(snap_status_string, "priced") == 0) snap_status = SNAPD_SNAP_STATUS_PRICED; else if (strcmp(snap_status_string, "installed") == 0) snap_status = SNAPD_SNAP_STATUS_INSTALLED; else if (strcmp(snap_status_string, "active") == 0) snap_status = SNAPD_SNAP_STATUS_ACTIVE; g_autoptr(JsonArray) apps = _snapd_json_get_array(object, "apps"); g_autoptr(GPtrArray) apps_array = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(apps); i++) { JsonNode *node = json_array_get_element(apps, i); SnapdApp *app = _snapd_json_parse_app(node, name, error); if (app == NULL) return NULL; g_ptr_array_add(apps_array, app); } g_autoptr(JsonArray) categories = _snapd_json_get_array(object, "categories"); g_autoptr(GPtrArray) categories_array = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(categories); i++) { JsonNode *node = json_array_get_element(categories, i); if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected categories type"); return NULL; } JsonObject *c = json_node_get_object(node); g_autoptr(SnapdCategory) category = g_object_new(SNAPD_TYPE_CATEGORY, "featured", _snapd_json_get_bool(c, "featured", FALSE), "name", _snapd_json_get_string(c, "name", NULL), NULL); g_ptr_array_add(categories_array, g_steal_pointer(&category)); } JsonObject *channels = _snapd_json_get_object(object, "channels"); g_autoptr(GPtrArray) channels_array = g_ptr_array_new_with_free_func(g_object_unref); if (channels != NULL) { JsonObjectIter iter; json_object_iter_init(&iter, channels); const gchar *name; JsonNode *channel_node; while (json_object_iter_next(&iter, &name, &channel_node)) { if (json_node_get_value_type(channel_node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected channel type"); return NULL; } JsonObject *c = json_node_get_object(channel_node); SnapdConfinement confinement = parse_confinement(_snapd_json_get_string(c, "confinement", "")); g_autoptr(GDateTime) released_at = _snapd_json_get_date_time(c, "released-at", NULL); g_autoptr(SnapdChannel) channel = g_object_new( SNAPD_TYPE_CHANNEL, "confinement", confinement, "epoch", _snapd_json_get_string(c, "epoch", NULL), "name", _snapd_json_get_string(c, "channel", NULL), "released-at", released_at, "revision", _snapd_json_get_string(c, "revision", NULL), "size", _snapd_json_get_int(c, "size", 0), "version", _snapd_json_get_string(c, "version", NULL), NULL); g_ptr_array_add(channels_array, g_steal_pointer(&channel)); } } g_autoptr(JsonArray) common_ids = _snapd_json_get_array(object, "common-ids"); g_autoptr(GPtrArray) common_ids_array = g_ptr_array_new(); for (guint i = 0; i < json_array_get_length(common_ids); i++) { JsonNode *node = json_array_get_element(common_ids, i); if (json_node_get_value_type(node) != G_TYPE_STRING) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected common ID type"); return NULL; } g_ptr_array_add(common_ids_array, (gpointer)json_node_get_string(node)); } g_ptr_array_add(common_ids_array, NULL); g_autoptr(GDateTime) install_date = _snapd_json_get_date_time(object, "install-date", NULL); g_autoptr(GDateTime) hold = _snapd_json_get_date_time(object, "hold", NULL); JsonObject *prices = _snapd_json_get_object(object, "prices"); g_autoptr(GPtrArray) prices_array = g_ptr_array_new_with_free_func(g_object_unref); if (prices != NULL) { JsonObjectIter iter; json_object_iter_init(&iter, prices); const gchar *currency; JsonNode *amount_node; while (json_object_iter_next(&iter, ¤cy, &amount_node)) { if (json_node_get_value_type(amount_node) != G_TYPE_DOUBLE) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected price type"); return NULL; } g_autoptr(SnapdPrice) price = g_object_new( SNAPD_TYPE_PRICE, "amount", json_node_get_double(amount_node), "currency", currency, NULL); g_ptr_array_add(prices_array, g_steal_pointer(&price)); } } g_autoptr(JsonArray) media = _snapd_json_get_array(object, "media"); g_autoptr(GPtrArray) media_array = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(media); i++) { JsonNode *node = json_array_get_element(media, i); if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected media type"); return NULL; } JsonObject *s = json_node_get_object(node); g_autoptr(SnapdMedia) media = g_object_new( SNAPD_TYPE_MEDIA, "type", _snapd_json_get_string(s, "type", NULL), "url", _snapd_json_get_string(s, "url", NULL), "width", (guint)_snapd_json_get_int(s, "width", 0), "height", (guint)_snapd_json_get_int(s, "height", 0), NULL); g_ptr_array_add(media_array, g_steal_pointer(&media)); } g_autoptr(GPtrArray) screenshots_array = g_ptr_array_new_with_free_func(g_object_unref); /* The tracks field was originally incorrectly named, fixed in snapd 61ad9ed * (2.29.5) */ g_autoptr(JsonArray) tracks = NULL; if (json_object_has_member(object, "Tracks")) tracks = _snapd_json_get_array(object, "Tracks"); else tracks = _snapd_json_get_array(object, "tracks"); g_autoptr(GPtrArray) track_array = g_ptr_array_new(); for (guint i = 0; i < json_array_get_length(tracks); i++) { JsonNode *node = json_array_get_element(tracks, i); if (json_node_get_value_type(node) != G_TYPE_STRING) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected track type"); return NULL; } g_ptr_array_add(track_array, (gpointer)json_node_get_string(node)); } g_ptr_array_add(track_array, NULL); /* The developer field originally contained the publisher username */ const gchar *publisher_username = _snapd_json_get_string(object, "developer", NULL); JsonObject *publisher = _snapd_json_get_object(object, "publisher"); const gchar *publisher_display_name = NULL; const gchar *publisher_id = NULL; SnapdPublisherValidation publisher_validation = SNAPD_PUBLISHER_VALIDATION_UNKNOWN; if (publisher != NULL) { publisher_display_name = _snapd_json_get_string(publisher, "display-name", NULL); publisher_id = _snapd_json_get_string(publisher, "id", NULL); publisher_username = _snapd_json_get_string(publisher, "username", publisher_username); const gchar *validation = _snapd_json_get_string(publisher, "validation", NULL); if (g_strcmp0(validation, "unproven") == 0) publisher_validation = SNAPD_PUBLISHER_VALIDATION_UNPROVEN; else if (g_strcmp0(validation, "starred") == 0) publisher_validation = SNAPD_PUBLISHER_VALIDATION_STARRED; else if (g_strcmp0(validation, "verified") == 0) publisher_validation = SNAPD_PUBLISHER_VALIDATION_VERIFIED; else publisher_validation = SNAPD_PUBLISHER_VALIDATION_UNKNOWN; } JsonObject *refresh_inhibit = _snapd_json_get_object(object, "refresh-inhibit"); g_autoptr(GDateTime) proceed_time = NULL; if (refresh_inhibit != NULL) proceed_time = _snapd_json_get_date_time(refresh_inhibit, "proceed-time", NULL); return g_object_new( SNAPD_TYPE_SNAP, "apps", apps_array, "base", _snapd_json_get_string(object, "base", NULL), "broken", _snapd_json_get_string(object, "broken", NULL), "categories", categories_array, "channel", _snapd_json_get_string(object, "channel", NULL), "channels", channels_array, "common-ids", (GStrv)common_ids_array->pdata, "confinement", confinement, "contact", _snapd_json_get_string(object, "contact", NULL), "description", _snapd_json_get_string(object, "description", NULL), "devmode", _snapd_json_get_bool(object, "devmode", FALSE), "download-size", _snapd_json_get_int(object, "download-size", 0), "hold", hold, "icon", _snapd_json_get_string(object, "icon", NULL), "id", _snapd_json_get_string(object, "id", NULL), "install-date", install_date, "installed-size", _snapd_json_get_int(object, "installed-size", 0), "jailmode", _snapd_json_get_bool(object, "jailmode", FALSE), "license", _snapd_json_get_string(object, "license", NULL), "media", media_array, "mounted-from", _snapd_json_get_string(object, "mounted-from", NULL), "name", name, "prices", prices_array, "private", _snapd_json_get_bool(object, "private", FALSE), "publisher-id", publisher_id, "publisher-username", publisher_username, "publisher-display-name", publisher_display_name, "publisher-validation", publisher_validation, "revision", _snapd_json_get_string(object, "revision", NULL), "screenshots", screenshots_array, "snap-type", snap_type, "status", snap_status, "store-url", _snapd_json_get_string(object, "store-url", NULL), "summary", _snapd_json_get_string(object, "summary", NULL), "title", _snapd_json_get_string(object, "title", NULL), "tracking-channel", _snapd_json_get_string(object, "tracking-channel", NULL), "tracks", (GStrv)track_array->pdata, "trymode", _snapd_json_get_bool(object, "trymode", FALSE), "version", _snapd_json_get_string(object, "version", NULL), "website", _snapd_json_get_string(object, "website", NULL), "proceed-time", proceed_time, NULL); } SnapdApp *_snapd_json_parse_app(JsonNode *node, const gchar *snap_name, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected app type"); return NULL; } JsonObject *object = json_node_get_object(node); const gchar *daemon = _snapd_json_get_string(object, "daemon", NULL); SnapdDaemonType daemon_type = SNAPD_DAEMON_TYPE_NONE; if (daemon == NULL) daemon_type = SNAPD_DAEMON_TYPE_NONE; else if (strcmp(daemon, "simple") == 0) daemon_type = SNAPD_DAEMON_TYPE_SIMPLE; else if (strcmp(daemon, "forking") == 0) daemon_type = SNAPD_DAEMON_TYPE_FORKING; else if (strcmp(daemon, "oneshot") == 0) daemon_type = SNAPD_DAEMON_TYPE_ONESHOT; else if (strcmp(daemon, "dbus") == 0) daemon_type = SNAPD_DAEMON_TYPE_DBUS; else if (strcmp(daemon, "notify") == 0) daemon_type = SNAPD_DAEMON_TYPE_NOTIFY; else daemon_type = SNAPD_DAEMON_TYPE_UNKNOWN; const gchar *app_snap_name = _snapd_json_get_string(object, "snap", NULL); return g_object_new( SNAPD_TYPE_APP, "name", _snapd_json_get_string(object, "name", NULL), "active", _snapd_json_get_bool(object, "active", FALSE), "common-id", _snapd_json_get_string(object, "common-id", NULL), "daemon-type", daemon_type, "desktop-file", _snapd_json_get_string(object, "desktop-file", NULL), "enabled", _snapd_json_get_bool(object, "enabled", FALSE), "snap", snap_name ? snap_name : app_snap_name, NULL); } SnapdAlias *_snapd_json_parse_alias(JsonNode *node, const gchar *snap_name, const gchar *name, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected alias type"); return FALSE; } JsonObject *object = json_node_get_object(node); const gchar *status_string = _snapd_json_get_string(object, "status", NULL); SnapdAliasStatus status = SNAPD_ALIAS_STATUS_UNKNOWN; if (strcmp(status_string, "disabled") == 0) status = SNAPD_ALIAS_STATUS_DISABLED; else if (strcmp(status_string, "auto") == 0) status = SNAPD_ALIAS_STATUS_AUTO; else if (strcmp(status_string, "manual") == 0) status = SNAPD_ALIAS_STATUS_MANUAL; else status = SNAPD_ALIAS_STATUS_UNKNOWN; return g_object_new(SNAPD_TYPE_ALIAS, "snap", snap_name, "app-auto", _snapd_json_get_string(object, "auto", NULL), "app-manual", _snapd_json_get_string(object, "manual", NULL), "command", _snapd_json_get_string(object, "command", NULL), "name", name, "status", status, NULL); } SnapdUserInformation *_snapd_json_parse_user_information(JsonNode *node, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected user information type"); return NULL; } JsonObject *object = json_node_get_object(node); g_autoptr(JsonArray) ssh_keys = _snapd_json_get_array(object, "ssh-keys"); g_autoptr(GPtrArray) ssh_key_array = g_ptr_array_new(); for (guint i = 0; i < json_array_get_length(ssh_keys); i++) { JsonNode *node = json_array_get_element(ssh_keys, i); if (json_node_get_value_type(node) != G_TYPE_STRING) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected SSH key type"); return NULL; } g_ptr_array_add(ssh_key_array, (gpointer)json_node_get_string(node)); } g_ptr_array_add(ssh_key_array, NULL); g_autoptr(SnapdAuthData) auth_data = NULL; if (json_object_has_member(object, "macaroon")) { g_autoptr(JsonArray) discharges = _snapd_json_get_array(object, "discharges"); g_autoptr(GPtrArray) discharge_array = g_ptr_array_new(); for (guint i = 0; i < json_array_get_length(discharges); i++) { JsonNode *node = json_array_get_element(discharges, i); if (json_node_get_value_type(node) != G_TYPE_STRING) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected discharge type"); return FALSE; } g_ptr_array_add(discharge_array, (gpointer)json_node_get_string(node)); } g_ptr_array_add(discharge_array, NULL); auth_data = snapd_auth_data_new(_snapd_json_get_string(object, "macaroon", NULL), (GStrv)discharge_array->pdata); } return g_object_new( SNAPD_TYPE_USER_INFORMATION, "id", _snapd_json_get_int(object, "id", -1), "username", _snapd_json_get_string(object, "username", NULL), "email", _snapd_json_get_string(object, "email", NULL), "ssh-keys", (GStrv)ssh_key_array->pdata, "auth-data", auth_data, NULL); } GHashTable *_snapd_json_parse_object(JsonObject *object, GError **error) { g_autoptr(GHashTable) attributes = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref); JsonObjectIter iter; json_object_iter_init(&iter, object); const gchar *attribute_name; JsonNode *node; while (json_object_iter_next(&iter, &attribute_name, &node)) { GVariant *variant = json_gvariant_deserialize(node, NULL, error); if (variant == NULL) return NULL; g_hash_table_insert(attributes, g_strdup(attribute_name), g_variant_ref_sink(variant)); } return g_steal_pointer(&attributes); } GHashTable *_snapd_json_parse_attributes(JsonNode *node, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected attributes type"); return NULL; } return _snapd_json_parse_object(json_node_get_object(node), error); } SnapdSlot *_snapd_json_parse_slot(JsonNode *node, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected slot type"); return NULL; } JsonObject *object = json_node_get_object(node); g_autoptr(JsonArray) connections = _snapd_json_get_array(object, "connections"); g_autoptr(GPtrArray) plug_refs = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(connections); i++) { JsonNode *node = json_array_get_element(connections, i); SnapdPlugRef *plug_ref = _snapd_json_parse_plug_ref(node, error); if (plug_ref == NULL) return NULL; g_ptr_array_add(plug_refs, plug_ref); } g_autoptr(GHashTable) attributes = NULL; if (json_object_has_member(object, "attrs")) { attributes = _snapd_json_parse_attributes( json_object_get_member(object, "attrs"), error); if (attributes == NULL) return FALSE; } else attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref); return g_object_new(SNAPD_TYPE_SLOT, "name", _snapd_json_get_string(object, "slot", NULL), "snap", _snapd_json_get_string(object, "snap", NULL), "interface", _snapd_json_get_string(object, "interface", NULL), "label", _snapd_json_get_string(object, "label", NULL), "connections", plug_refs, "attributes", attributes, // FIXME: apps NULL); } SnapdPlug *_snapd_json_parse_plug(JsonNode *node, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected plug type"); return NULL; } JsonObject *object = json_node_get_object(node); g_autoptr(JsonArray) connections = _snapd_json_get_array(object, "connections"); g_autoptr(GPtrArray) slot_refs = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(connections); i++) { JsonNode *node = json_array_get_element(connections, i); SnapdSlotRef *slot_ref = _snapd_json_parse_slot_ref(node, error); if (slot_ref == NULL) return NULL; g_ptr_array_add(slot_refs, slot_ref); } g_autoptr(GHashTable) attributes = NULL; if (json_object_has_member(object, "attrs")) { attributes = _snapd_json_parse_attributes( json_object_get_member(object, "attrs"), error); if (attributes == NULL) return FALSE; } else attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref); return g_object_new(SNAPD_TYPE_PLUG, "name", _snapd_json_get_string(object, "plug", NULL), "snap", _snapd_json_get_string(object, "snap", NULL), "interface", _snapd_json_get_string(object, "interface", NULL), "label", _snapd_json_get_string(object, "label", NULL), "connections", slot_refs, "attributes", attributes, // FIXME: apps NULL); } SnapdSlotRef *_snapd_json_parse_slot_ref(JsonNode *node, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected slot ref type"); return NULL; } JsonObject *object = json_node_get_object(node); return g_object_new(SNAPD_TYPE_SLOT_REF, "slot", _snapd_json_get_string(object, "slot", NULL), "snap", _snapd_json_get_string(object, "snap", NULL), NULL); } SnapdPlugRef *_snapd_json_parse_plug_ref(JsonNode *node, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected plug ref type"); return NULL; } JsonObject *object = json_node_get_object(node); return g_object_new(SNAPD_TYPE_PLUG_REF, "plug", _snapd_json_get_string(object, "plug", NULL), "snap", _snapd_json_get_string(object, "snap", NULL), NULL); } SnapdConnection *_snapd_json_parse_connection(JsonNode *node, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected connection type"); return NULL; } JsonObject *object = json_node_get_object(node); g_autoptr(SnapdSlotRef) slot_ref = NULL; if (json_object_has_member(object, "slot")) { slot_ref = _snapd_json_parse_slot_ref( json_object_get_member(object, "slot"), error); if (slot_ref == NULL) return NULL; } g_autoptr(SnapdPlugRef) plug_ref = NULL; if (json_object_has_member(object, "plug")) { plug_ref = _snapd_json_parse_plug_ref( json_object_get_member(object, "plug"), error); if (plug_ref == NULL) return NULL; } g_autoptr(GHashTable) slot_attributes = NULL; if (json_object_has_member(object, "slot-attrs")) { slot_attributes = _snapd_json_parse_attributes( json_object_get_member(object, "slot-attrs"), error); if (slot_attributes == NULL) return FALSE; } else slot_attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref); g_autoptr(GHashTable) plug_attributes = NULL; if (json_object_has_member(object, "plug-attrs")) { plug_attributes = _snapd_json_parse_attributes( json_object_get_member(object, "plug-attrs"), error); if (plug_attributes == NULL) return FALSE; } else plug_attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref); return g_object_new( SNAPD_TYPE_CONNECTION, "slot", slot_ref, "plug", plug_ref, "interface", _snapd_json_get_string(object, "interface", NULL), "manual", _snapd_json_get_bool(object, "manual", FALSE), "gadget", _snapd_json_get_bool(object, "gadget", FALSE), "slot-attrs", slot_attributes, "plug-attrs", plug_attributes, NULL); } SnapdInterface *_snapd_json_parse_interface(JsonNode *node, GError **error) { if (json_node_get_value_type(node) != JSON_TYPE_OBJECT) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected interface type"); return NULL; } JsonObject *object = json_node_get_object(node); g_autoptr(JsonArray) plugs = _snapd_json_get_array(object, "plugs"); g_autoptr(GPtrArray) plug_array = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(plugs); i++) { JsonNode *node = json_array_get_element(plugs, i); SnapdPlug *plug = _snapd_json_parse_plug(node, error); if (plug == NULL) return FALSE; g_ptr_array_add(plug_array, plug); } g_autoptr(JsonArray) slots = _snapd_json_get_array(object, "slots"); g_autoptr(GPtrArray) slot_array = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(slots); i++) { JsonNode *node = json_array_get_element(slots, i); SnapdSlot *slot = _snapd_json_parse_slot(node, error); if (slot == NULL) return FALSE; g_ptr_array_add(slot_array, slot); } return g_object_new(SNAPD_TYPE_INTERFACE, "name", _snapd_json_get_string(object, "name", NULL), "summary", _snapd_json_get_string(object, "summary", NULL), "doc-url", _snapd_json_get_string(object, "doc-url", NULL), "plugs", plug_array, "slots", slot_array, NULL); } snapd-glib-1.67/snapd-glib/requests/snapd-json.h000066400000000000000000000067411477073115000216240ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include #include #include "snapd-alias.h" #include "snapd-app.h" #include "snapd-change.h" #include "snapd-connection.h" #include "snapd-interface.h" #include "snapd-maintenance.h" #include "snapd-notice.h" #include "snapd-plug-ref.h" #include "snapd-plug.h" #include "snapd-slot-ref.h" #include "snapd-slot.h" #include "snapd-snap.h" #include "snapd-system-information.h" #include "snapd-user-information.h" G_BEGIN_DECLS void _snapd_json_set_body(SoupMessage *message, JsonBuilder *builder, GBytes **body); gboolean _snapd_json_get_bool(JsonObject *object, const gchar *name, gboolean default_value); gint64 _snapd_json_get_int(JsonObject *object, const gchar *name, gint64 default_value); const gchar *_snapd_json_get_string(JsonObject *object, const gchar *name, const gchar *default_value); JsonArray *_snapd_json_get_array(JsonObject *object, const gchar *name); JsonObject *_snapd_json_get_object(JsonObject *object, const gchar *name); GDateTime *_snapd_json_get_date_time(JsonObject *object, const gchar *name, int *nanoseconds); JsonObject *_snapd_json_parse_response(const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, JsonNode **error_value, GError **error); JsonNode *_snapd_json_get_sync_result(JsonObject *response, GError **error); JsonObject *_snapd_json_get_sync_result_o(JsonObject *response, GError **error); JsonArray *_snapd_json_get_sync_result_a(JsonObject *response, GError **error); gchar *_snapd_json_get_async_result(JsonObject *response, GError **error); GPtrArray *_snapd_json_parse_notices(JsonNode *node, GError **error); SnapdChange *_snapd_json_parse_change(JsonNode *node, GError **error); SnapdSystemInformation *_snapd_json_parse_system_information(JsonNode *node, GError **error); SnapdSnap *_snapd_json_parse_snap(JsonNode *node, GError **error); SnapdApp *_snapd_json_parse_app(JsonNode *node, const gchar *snap_name, GError **error); SnapdAlias *_snapd_json_parse_alias(JsonNode *node, const gchar *snap_name, const gchar *name, GError **error); SnapdUserInformation *_snapd_json_parse_user_information(JsonNode *node, GError **error); GHashTable *_snapd_json_parse_object(JsonObject *node, GError **error); GHashTable *_snapd_json_parse_attributes(JsonNode *node, GError **error); SnapdSlot *_snapd_json_parse_slot(JsonNode *node, GError **error); SnapdPlug *_snapd_json_parse_plug(JsonNode *node, GError **error); SnapdSlotRef *_snapd_json_parse_slot_ref(JsonNode *node, GError **error); SnapdPlugRef *_snapd_json_parse_plug_ref(JsonNode *node, GError **error); SnapdConnection *_snapd_json_parse_connection(JsonNode *node, GError **error); SnapdInterface *_snapd_json_parse_interface(JsonNode *node, GError **error); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-aliases.c000066400000000000000000000061211477073115000232420ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-post-aliases.h" #include "snapd-json.h" struct _SnapdPostAliases { SnapdRequestAsync parent_instance; gchar *action; gchar *snap; gchar *app; gchar *alias; }; G_DEFINE_TYPE(SnapdPostAliases, snapd_post_aliases, snapd_request_async_get_type()) SnapdPostAliases *_snapd_post_aliases_new( const gchar *action, const gchar *snap, const gchar *app, const gchar *alias, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostAliases *self = SNAPD_POST_ALIASES( g_object_new(snapd_post_aliases_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, "progress-callback", progress_callback, "progress-callback-data", progress_callback_data, NULL)); self->action = g_strdup(action); self->snap = g_strdup(snap); self->app = g_strdup(app); self->alias = g_strdup(alias); return self; } static SoupMessage *generate_post_aliases_request(SnapdRequest *request, GBytes **body) { SnapdPostAliases *self = SNAPD_POST_ALIASES(request); SoupMessage *message = soup_message_new("POST", "http://snapd/v2/aliases"); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "action"); json_builder_add_string_value(builder, self->action); if (self->snap != NULL) { json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, self->snap); } if (self->app != NULL) { json_builder_set_member_name(builder, "app"); json_builder_add_string_value(builder, self->app); } if (self->alias != NULL) { json_builder_set_member_name(builder, "alias"); json_builder_add_string_value(builder, self->alias); } json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static void snapd_post_aliases_finalize(GObject *object) { SnapdPostAliases *self = SNAPD_POST_ALIASES(object); g_clear_pointer(&self->action, g_free); g_clear_pointer(&self->snap, g_free); g_clear_pointer(&self->app, g_free); g_clear_pointer(&self->alias, g_free); G_OBJECT_CLASS(snapd_post_aliases_parent_class)->finalize(object); } static void snapd_post_aliases_class_init(SnapdPostAliasesClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_aliases_request; gobject_class->finalize = snapd_post_aliases_finalize; } static void snapd_post_aliases_init(SnapdPostAliases *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-aliases.h000066400000000000000000000015421477073115000232510ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request-async.h" #include "snapd-client.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostAliases, snapd_post_aliases, SNAPD, POST_ALIASES, SnapdRequestAsync) SnapdPostAliases *_snapd_post_aliases_new( const gchar *action, const gchar *snap, const gchar *app, const gchar *alias, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-assertions.c000066400000000000000000000060011477073115000240100ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-post-assertions.h" #include "snapd-json.h" struct _SnapdPostAssertions { SnapdRequest parent_instance; GStrv assertions; }; G_DEFINE_TYPE(SnapdPostAssertions, snapd_post_assertions, snapd_request_get_type()) SnapdPostAssertions *_snapd_post_assertions_new(GStrv assertions, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostAssertions *self = SNAPD_POST_ASSERTIONS(g_object_new( snapd_post_assertions_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->assertions = g_strdupv(assertions); return self; } static SoupMessage *generate_post_assertions_request(SnapdRequest *request, GBytes **body) { SnapdPostAssertions *self = SNAPD_POST_ASSERTIONS(request); SoupMessage *message = soup_message_new("POST", "http://snapd/v2/assertions"); #if SOUP_CHECK_VERSION(2, 99, 2) SoupMessageHeaders *request_headers = soup_message_get_request_headers(message); #else SoupMessageHeaders *request_headers = message->request_headers; #endif soup_message_headers_set_content_type( request_headers, "application/x.ubuntu.assertion", NULL); // FIXME g_autofree gchar *assertions = g_strjoinv("\n\n", self->assertions); *body = g_bytes_new(assertions, strlen(assertions)); return message; } static gboolean parse_post_assertions_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; return TRUE; } static void snapd_post_assertions_finalize(GObject *object) { SnapdPostAssertions *self = SNAPD_POST_ASSERTIONS(object); g_clear_pointer(&self->assertions, g_strfreev); G_OBJECT_CLASS(snapd_post_assertions_parent_class)->finalize(object); } static void snapd_post_assertions_class_init(SnapdPostAssertionsClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_assertions_request; request_class->parse_response = parse_post_assertions_response; gobject_class->finalize = snapd_post_assertions_finalize; } static void snapd_post_assertions_init(SnapdPostAssertions *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-assertions.h000066400000000000000000000015041477073115000240200ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostAssertions, snapd_post_assertions, SNAPD, POST_ASSERTIONS, SnapdRequest) SnapdPostAssertions *_snapd_post_assertions_new(GStrv assertions, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-buy.c000066400000000000000000000061471477073115000224300ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-post-buy.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdPostBuy { SnapdRequest parent_instance; gchar *id; gdouble amount; gchar *currency; }; G_DEFINE_TYPE(SnapdPostBuy, snapd_post_buy, snapd_request_get_type()) SnapdPostBuy *_snapd_post_buy_new(const gchar *id, gdouble amount, const gchar *currency, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostBuy *self = SNAPD_POST_BUY(g_object_new( snapd_post_buy_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->id = g_strdup(id); self->amount = amount; self->currency = g_strdup(currency); return self; } static SoupMessage *generate_post_buy_request(SnapdRequest *request, GBytes **body) { SnapdPostBuy *self = SNAPD_POST_BUY(request); SoupMessage *message = soup_message_new("POST", "http://snapd/v2/buy"); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap-id"); json_builder_add_string_value(builder, self->id); json_builder_set_member_name(builder, "price"); json_builder_add_double_value(builder, self->amount); json_builder_set_member_name(builder, "currency"); json_builder_add_string_value(builder, self->currency); json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static gboolean parse_post_buy_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; return TRUE; } static void snapd_post_buy_finalize(GObject *object) { SnapdPostBuy *self = SNAPD_POST_BUY(object); g_clear_pointer(&self->id, g_free); g_clear_pointer(&self->currency, g_free); G_OBJECT_CLASS(snapd_post_buy_parent_class)->finalize(object); } static void snapd_post_buy_class_init(SnapdPostBuyClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_buy_request; request_class->parse_response = parse_post_buy_response; gobject_class->finalize = snapd_post_buy_finalize; } static void snapd_post_buy_init(SnapdPostBuy *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-buy.h000066400000000000000000000014771477073115000224360ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostBuy, snapd_post_buy, SNAPD, POST_BUY, SnapdRequest) SnapdPostBuy *_snapd_post_buy_new(const gchar *id, gdouble amount, const gchar *currency, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-change.c000066400000000000000000000106071477073115000230520ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-post-change.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdPostChange { SnapdRequest parent_instance; gchar *change_id; gchar *action; SnapdChange *change; JsonNode *data; gchar *api_path; }; G_DEFINE_TYPE(SnapdPostChange, snapd_post_change, snapd_request_get_type()) SnapdPostChange *_snapd_post_change_new(const gchar *change_id, const gchar *action, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostChange *self = SNAPD_POST_CHANGE(g_object_new( snapd_post_change_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->change_id = g_strdup(change_id); self->action = g_strdup(action); return self; } const gchar *_snapd_post_change_get_change_id(SnapdPostChange *self) { return self->change_id; } SnapdChange *_snapd_post_change_get_change(SnapdPostChange *self) { return self->change; } JsonNode *_snapd_post_change_get_data(SnapdPostChange *self) { return self->data; } void _snapd_post_change_set_api_path(SnapdPostChange *self, const gchar *api_path) { g_free(self->api_path); self->api_path = g_strdup(api_path); } static SoupMessage *generate_post_change_request(SnapdRequest *request, GBytes **body) { SnapdPostChange *self = SNAPD_POST_CHANGE(request); g_autofree gchar *path = g_strdup_printf( "http://snapd%s/%s", self->api_path ? self->api_path : "/v2/changes", self->change_id); SoupMessage *message = soup_message_new("POST", path); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "action"); json_builder_add_string_value(builder, self->action); json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static gboolean parse_post_change_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdPostChange *self = SNAPD_POST_CHANGE(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; /* FIXME: Needs json-glib to be fixed to use json_node_unref */ /*g_autoptr(JsonNode) result = NULL;*/ JsonNode *result = _snapd_json_get_sync_result(response, error); if (result == NULL) return FALSE; self->change = _snapd_json_parse_change(result, error); json_node_unref(result); if (self->change == NULL) return FALSE; if (g_strcmp0(self->change_id, snapd_change_get_id(self->change)) != 0) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected change ID returned"); return FALSE; } if (json_object_has_member(json_node_get_object(result), "data")) self->data = json_node_ref( json_object_get_member(json_node_get_object(result), "data")); return TRUE; } static void snapd_post_change_finalize(GObject *object) { SnapdPostChange *self = SNAPD_POST_CHANGE(object); g_clear_pointer(&self->change_id, g_free); g_clear_pointer(&self->action, g_free); g_clear_object(&self->change); g_clear_pointer(&self->data, json_node_unref); g_clear_pointer(&self->api_path, g_free); G_OBJECT_CLASS(snapd_post_change_parent_class)->finalize(object); } static void snapd_post_change_class_init(SnapdPostChangeClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_change_request; request_class->parse_response = parse_post_change_response; gobject_class->finalize = snapd_post_change_finalize; } static void snapd_post_change_init(SnapdPostChange *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-change.h000066400000000000000000000023471477073115000230610ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include #include "snapd-change.h" #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostChange, snapd_post_change, SNAPD, POST_CHANGE, SnapdRequest) SnapdPostChange *_snapd_post_change_new(const gchar *change_id, const gchar *action, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); const gchar *_snapd_post_change_get_change_id(SnapdPostChange *request); SnapdChange *_snapd_post_change_get_change(SnapdPostChange *request); JsonNode *_snapd_post_change_get_data(SnapdPostChange *request); void _snapd_post_change_set_api_path(SnapdPostChange *request, const gchar *api_path); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-create-user.c000066400000000000000000000102031477073115000240340ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-post-create-user.h" #include "snapd-json.h" #include "snapd-user-information.h" struct _SnapdPostCreateUser { SnapdRequest parent_instance; gchar *email; gboolean sudoer; gboolean known; SnapdUserInformation *user_information; }; G_DEFINE_TYPE(SnapdPostCreateUser, snapd_post_create_user, snapd_request_get_type()) SnapdPostCreateUser *_snapd_post_create_user_new(const gchar *email, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostCreateUser *self = SNAPD_POST_CREATE_USER(g_object_new( snapd_post_create_user_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->email = g_strdup(email); return self; } void _snapd_post_create_user_set_sudoer(SnapdPostCreateUser *self, gboolean sudoer) { self->sudoer = sudoer; } void _snapd_post_create_user_set_known(SnapdPostCreateUser *self, gboolean known) { self->known = known; } SnapdUserInformation * _snapd_post_create_user_get_user_information(SnapdPostCreateUser *self) { return self->user_information; } static SoupMessage *generate_post_create_user_request(SnapdRequest *request, GBytes **body) { SnapdPostCreateUser *self = SNAPD_POST_CREATE_USER(request); SoupMessage *message = soup_message_new("POST", "http://snapd/v2/create-user"); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "email"); json_builder_add_string_value(builder, self->email); if (self->sudoer) { json_builder_set_member_name(builder, "sudoer"); json_builder_add_boolean_value(builder, TRUE); } if (self->known) { json_builder_set_member_name(builder, "known"); json_builder_add_boolean_value(builder, TRUE); } json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static gboolean parse_post_create_user_response( SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdPostCreateUser *self = SNAPD_POST_CREATE_USER(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; /* FIXME: Needs json-glib to be fixed to use json_node_unref */ /*g_autoptr(JsonNode) result = NULL;*/ JsonNode *result = _snapd_json_get_sync_result(response, error); if (result == NULL) return FALSE; g_autoptr(SnapdUserInformation) user_information = _snapd_json_parse_user_information(result, error); json_node_unref(result); if (user_information == NULL) return FALSE; self->user_information = g_steal_pointer(&user_information); return TRUE; } static void snapd_post_create_user_finalize(GObject *object) { SnapdPostCreateUser *self = SNAPD_POST_CREATE_USER(object); g_clear_pointer(&self->email, g_free); g_clear_object(&self->user_information); G_OBJECT_CLASS(snapd_post_create_user_parent_class)->finalize(object); } static void snapd_post_create_user_class_init(SnapdPostCreateUserClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_create_user_request; request_class->parse_response = parse_post_create_user_response; gobject_class->finalize = snapd_post_create_user_finalize; } static void snapd_post_create_user_init(SnapdPostCreateUser *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-create-user.h000066400000000000000000000023231477073115000240450ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" #include "snapd-user-information.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostCreateUser, snapd_post_create_user, SNAPD, POST_CREATE_USER, SnapdRequest) SnapdPostCreateUser *_snapd_post_create_user_new(const gchar *email, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); void _snapd_post_create_user_set_sudoer(SnapdPostCreateUser *request, gboolean sudoer); void _snapd_post_create_user_set_known(SnapdPostCreateUser *request, gboolean known); SnapdUserInformation * _snapd_post_create_user_get_user_information(SnapdPostCreateUser *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-create-users.c000066400000000000000000000067411477073115000242330ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-post-create-users.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdPostCreateUsers { SnapdRequest parent_instance; GPtrArray *users_information; }; G_DEFINE_TYPE(SnapdPostCreateUsers, snapd_post_create_users, snapd_request_get_type()) SnapdPostCreateUsers *_snapd_post_create_users_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return SNAPD_POST_CREATE_USERS(g_object_new( snapd_post_create_users_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); } GPtrArray * _snapd_post_create_users_get_users_information(SnapdPostCreateUsers *self) { return self->users_information; } static SoupMessage *generate_post_create_users_request(SnapdRequest *request, GBytes **body) { SoupMessage *message = soup_message_new("POST", "http://snapd/v2/create-user"); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "known"); json_builder_add_boolean_value(builder, TRUE); json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static gboolean parse_post_create_users_response( SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdPostCreateUsers *self = SNAPD_POST_CREATE_USERS(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autoptr(JsonArray) result = _snapd_json_get_sync_result_a(response, error); if (result == NULL) return FALSE; g_autoptr(GPtrArray) users_information = g_ptr_array_new_with_free_func(g_object_unref); for (guint i = 0; i < json_array_get_length(result); i++) { JsonNode *node = json_array_get_element(result, i); SnapdUserInformation *user_information; user_information = _snapd_json_parse_user_information(node, error); if (user_information == NULL) return FALSE; g_ptr_array_add(users_information, user_information); } self->users_information = g_steal_pointer(&users_information); return TRUE; } static void snapd_post_create_users_finalize(GObject *object) { SnapdPostCreateUsers *self = SNAPD_POST_CREATE_USERS(object); g_clear_pointer(&self->users_information, g_ptr_array_unref); G_OBJECT_CLASS(snapd_post_create_users_parent_class)->finalize(object); } static void snapd_post_create_users_class_init(SnapdPostCreateUsersClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_create_users_request; request_class->parse_response = parse_post_create_users_response; gobject_class->finalize = snapd_post_create_users_finalize; } static void snapd_post_create_users_init(SnapdPostCreateUsers *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-create-users.h000066400000000000000000000015541477073115000242350ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostCreateUsers, snapd_post_create_users, SNAPD, POST_CREATE_USERS, SnapdRequest) SnapdPostCreateUsers *_snapd_post_create_users_new(GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray * _snapd_post_create_users_get_users_information(SnapdPostCreateUsers *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-download.c000066400000000000000000000070321477073115000234320ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-post-download.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdPostDownload { SnapdRequest parent_instance; gchar *name; gchar *channel; gchar *revision; GBytes *data; }; G_DEFINE_TYPE(SnapdPostDownload, snapd_post_download, snapd_request_get_type()) SnapdPostDownload * _snapd_post_download_new(const gchar *name, const gchar *channel, const gchar *revision, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostDownload *self = SNAPD_POST_DOWNLOAD(g_object_new( snapd_post_download_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->name = g_strdup(name); self->channel = g_strdup(channel); self->revision = g_strdup(revision); return self; } static SoupMessage *generate_post_download_request(SnapdRequest *request, GBytes **body) { SnapdPostDownload *self = SNAPD_POST_DOWNLOAD(request); SoupMessage *message = soup_message_new("POST", "http://snapd/v2/download"); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap-name"); json_builder_add_string_value(builder, self->name); if (self->channel != NULL) { json_builder_set_member_name(builder, "channel"); json_builder_add_string_value(builder, self->channel); } if (self->revision != NULL) { json_builder_set_member_name(builder, "revision"); json_builder_add_string_value(builder, self->revision); } json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static gboolean parse_post_download_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdPostDownload *self = SNAPD_POST_DOWNLOAD(request); if (g_strcmp0(content_type, "application/octet-stream") != 0) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unknown response"); return FALSE; } self->data = g_bytes_ref(body); return TRUE; } static void snapd_post_download_finalize(GObject *object) { SnapdPostDownload *self = SNAPD_POST_DOWNLOAD(object); g_clear_pointer(&self->name, g_free); g_clear_pointer(&self->channel, g_free); g_clear_pointer(&self->revision, g_free); g_clear_pointer(&self->data, g_bytes_unref); G_OBJECT_CLASS(snapd_post_download_parent_class)->finalize(object); } static void snapd_post_download_class_init(SnapdPostDownloadClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_download_request; request_class->parse_response = parse_post_download_response; gobject_class->finalize = snapd_post_download_finalize; } static void snapd_post_download_init(SnapdPostDownload *self) {} GBytes *_snapd_post_download_get_data(SnapdPostDownload *self) { g_return_val_if_fail(SNAPD_IS_POST_DOWNLOAD(self), NULL); return self->data; } snapd-glib-1.67/snapd-glib/requests/snapd-post-download.h000066400000000000000000000015171477073115000234410ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostDownload, snapd_post_download, SNAPD, POST_DOWNLOAD, SnapdRequest) SnapdPostDownload * _snapd_post_download_new(const gchar *name, const gchar *channel, const gchar *revision, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GBytes *_snapd_post_download_get_data(SnapdPostDownload *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-interfaces.c000066400000000000000000000074011477073115000237460ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-post-interfaces.h" #include "snapd-json.h" struct _SnapdPostInterfaces { SnapdRequestAsync parent_instance; gchar *action; gchar *plug_snap; gchar *plug_name; gchar *slot_snap; gchar *slot_name; }; G_DEFINE_TYPE(SnapdPostInterfaces, snapd_post_interfaces, snapd_request_async_get_type()) SnapdPostInterfaces *_snapd_post_interfaces_new( const gchar *action, const gchar *plug_snap, const gchar *plug_name, const gchar *slot_snap, const gchar *slot_name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostInterfaces *self = SNAPD_POST_INTERFACES( g_object_new(snapd_post_interfaces_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, "progress-callback", progress_callback, "progress-callback-data", progress_callback_data, NULL)); self->action = g_strdup(action); self->plug_snap = g_strdup(plug_snap); self->plug_name = g_strdup(plug_name); self->slot_snap = g_strdup(slot_snap); self->slot_name = g_strdup(slot_name); return self; } static SoupMessage *generate_post_interfaces_request(SnapdRequest *request, GBytes **body) { SnapdPostInterfaces *self = SNAPD_POST_INTERFACES(request); SoupMessage *message = soup_message_new("POST", "http://snapd/v2/interfaces"); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "action"); json_builder_add_string_value(builder, self->action); json_builder_set_member_name(builder, "plugs"); json_builder_begin_array(builder); json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, self->plug_snap); json_builder_set_member_name(builder, "plug"); json_builder_add_string_value(builder, self->plug_name); json_builder_end_object(builder); json_builder_end_array(builder); json_builder_set_member_name(builder, "slots"); json_builder_begin_array(builder); json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, self->slot_snap); json_builder_set_member_name(builder, "slot"); json_builder_add_string_value(builder, self->slot_name); json_builder_end_object(builder); json_builder_end_array(builder); json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static void snapd_post_interfaces_finalize(GObject *object) { SnapdPostInterfaces *self = SNAPD_POST_INTERFACES(object); g_clear_pointer(&self->action, g_free); g_clear_pointer(&self->plug_snap, g_free); g_clear_pointer(&self->plug_name, g_free); g_clear_pointer(&self->slot_snap, g_free); g_clear_pointer(&self->slot_name, g_free); G_OBJECT_CLASS(snapd_post_interfaces_parent_class)->finalize(object); } static void snapd_post_interfaces_class_init(SnapdPostInterfacesClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_interfaces_request; gobject_class->finalize = snapd_post_interfaces_finalize; } static void snapd_post_interfaces_init(SnapdPostInterfaces *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-interfaces.h000066400000000000000000000016341477073115000237550ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request-async.h" #include "snapd-client.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostInterfaces, snapd_post_interfaces, SNAPD, POST_INTERFACES, SnapdRequestAsync) SnapdPostInterfaces *_snapd_post_interfaces_new( const gchar *action, const gchar *plug_snap, const gchar *plug_name, const gchar *slot_snap, const gchar *slot_name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-login.c000066400000000000000000000076621477073115000227440ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-post-login.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdPostLogin { SnapdRequest parent_instance; gchar *email; gchar *password; gchar *otp; SnapdUserInformation *user_information; }; G_DEFINE_TYPE(SnapdPostLogin, snapd_post_login, snapd_request_get_type()) SnapdPostLogin *_snapd_post_login_new(const gchar *email, const gchar *password, const gchar *otp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostLogin *self = SNAPD_POST_LOGIN(g_object_new( snapd_post_login_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->email = g_strdup(email); self->password = g_strdup(password); self->otp = g_strdup(otp); return self; } SnapdUserInformation * _snapd_post_login_get_user_information(SnapdPostLogin *self) { return self->user_information; } static SoupMessage *generate_post_login_request(SnapdRequest *request, GBytes **body) { SnapdPostLogin *self = SNAPD_POST_LOGIN(request); SoupMessage *message = soup_message_new("POST", "http://snapd/v2/login"); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "email"); json_builder_add_string_value(builder, self->email); /* Send legacy username field for snapd < 2.16 */ json_builder_set_member_name(builder, "username"); json_builder_add_string_value(builder, self->email); json_builder_set_member_name(builder, "password"); json_builder_add_string_value(builder, self->password); if (self->otp != NULL) { json_builder_set_member_name(builder, "otp"); json_builder_add_string_value(builder, self->otp); } json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static gboolean parse_post_login_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdPostLogin *self = SNAPD_POST_LOGIN(request); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; /* FIXME: Needs json-glib to be fixed to use json_node_unref */ /*g_autoptr(JsonNode) result = NULL;*/ JsonNode *result = _snapd_json_get_sync_result(response, error); if (result == NULL) return FALSE; self->user_information = _snapd_json_parse_user_information(result, error); json_node_unref(result); if (self->user_information == NULL) return FALSE; return TRUE; } static void snapd_post_login_finalize(GObject *object) { SnapdPostLogin *self = SNAPD_POST_LOGIN(object); g_clear_pointer(&self->email, g_free); g_clear_pointer(&self->password, g_free); g_clear_pointer(&self->otp, g_free); g_clear_object(&self->user_information); G_OBJECT_CLASS(snapd_post_login_parent_class)->finalize(object); } static void snapd_post_login_class_init(SnapdPostLoginClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_login_request; request_class->parse_response = parse_post_login_response; gobject_class->finalize = snapd_post_login_finalize; } static void snapd_post_login_init(SnapdPostLogin *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-login.h000066400000000000000000000017341477073115000227430ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" #include "snapd-user-information.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostLogin, snapd_post_login, SNAPD, POST_LOGIN, SnapdRequest) SnapdPostLogin *_snapd_post_login_new(const gchar *email, const gchar *password, const gchar *otp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); SnapdUserInformation * _snapd_post_login_get_user_information(SnapdPostLogin *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-logout.c000066400000000000000000000050161477073115000231340ustar00rootroot00000000000000/* * Copyright (C) 2020 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-post-logout.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdPostLogout { SnapdRequest parent_instance; gint64 id; }; G_DEFINE_TYPE(SnapdPostLogout, snapd_post_logout, snapd_request_get_type()) SnapdPostLogout *_snapd_post_logout_new(gint64 id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostLogout *self = SNAPD_POST_LOGOUT(g_object_new( snapd_post_logout_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->id = id; return self; } static SoupMessage *generate_post_logout_request(SnapdRequest *request, GBytes **body) { SnapdPostLogout *self = SNAPD_POST_LOGOUT(request); SoupMessage *message = soup_message_new("POST", "http://snapd/v2/logout"); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "id"); json_builder_add_int_value(builder, self->id); json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static gboolean parse_post_logout_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; /* FIXME: Needs json-glib to be fixed to use json_node_unref */ /*g_autoptr(JsonNode) result = NULL;*/ JsonNode *result = _snapd_json_get_sync_result(response, error); if (result == NULL) return FALSE; json_node_unref(result); return TRUE; } static void snapd_post_logout_class_init(SnapdPostLogoutClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); request_class->generate_request = generate_post_logout_request; request_class->parse_response = parse_post_logout_response; } static void snapd_post_logout_init(SnapdPostLogout *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-logout.h000066400000000000000000000014661477073115000231460ustar00rootroot00000000000000/* * Copyright (C) 2020 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostLogout, snapd_post_logout, SNAPD, POST_LOGOUT, SnapdRequest) SnapdPostLogout *_snapd_post_logout_new(gint64 id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean _snapd_post_logout_get_user_information(SnapdPostLogout *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-snap-stream.c000066400000000000000000000132551477073115000240610ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-post-snap-stream.h" #include "snapd-json.h" struct _SnapdPostSnapStream { SnapdRequestAsync parent_instance; gboolean classic; gboolean dangerous; gboolean devmode; gboolean jailmode; GByteArray *snap_contents; }; G_DEFINE_TYPE(SnapdPostSnapStream, snapd_post_snap_stream, snapd_request_async_get_type()) SnapdPostSnapStream * _snapd_post_snap_stream_new(SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostSnapStream *self = SNAPD_POST_SNAP_STREAM(g_object_new( snapd_post_snap_stream_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, "progress-callback", progress_callback, "progress-callback-data", progress_callback_data, NULL)); return self; } void _snapd_post_snap_stream_set_classic(SnapdPostSnapStream *self, gboolean classic) { self->classic = classic; } void _snapd_post_snap_stream_set_dangerous(SnapdPostSnapStream *self, gboolean dangerous) { self->dangerous = dangerous; } void _snapd_post_snap_stream_set_devmode(SnapdPostSnapStream *self, gboolean devmode) { self->devmode = devmode; } void _snapd_post_snap_stream_set_jailmode(SnapdPostSnapStream *self, gboolean jailmode) { self->jailmode = jailmode; } void _snapd_post_snap_stream_append_data(SnapdPostSnapStream *self, const guint8 *data, guint len) { g_byte_array_append(self->snap_contents, data, len); } static void append_multipart_value(SoupMultipart *multipart, const gchar *name, const gchar *value) { g_autoptr(SoupMessageHeaders) headers = soup_message_headers_new(SOUP_MESSAGE_HEADERS_MULTIPART); g_autoptr(GHashTable) params = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); g_hash_table_insert(params, g_strdup("name"), g_strdup(name)); soup_message_headers_set_content_disposition(headers, "form-data", params); #if SOUP_CHECK_VERSION(2, 99, 2) g_autoptr(GBytes) buffer = g_bytes_new(value, strlen(value)); #else g_autoptr(SoupBuffer) buffer = soup_buffer_new_take((guchar *)g_strdup(value), strlen(value)); #endif soup_multipart_append_part(multipart, headers, buffer); } static SoupMessage *generate_post_snap_stream_request(SnapdRequest *request, GBytes **body) { SnapdPostSnapStream *self = SNAPD_POST_SNAP_STREAM(request); SoupMessage *message = soup_message_new("POST", "http://snapd/v2/snaps"); g_autoptr(SoupMultipart) multipart = soup_multipart_new("multipart/form-data"); if (self->classic) append_multipart_value(multipart, "classic", "true"); if (self->dangerous) append_multipart_value(multipart, "dangerous", "true"); if (self->devmode) append_multipart_value(multipart, "devmode", "true"); if (self->jailmode) append_multipart_value(multipart, "jailmode", "true"); g_autoptr(GHashTable) params = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); g_hash_table_insert(params, g_strdup("name"), g_strdup("snap")); g_hash_table_insert(params, g_strdup("filename"), g_strdup("x")); #if SOUP_CHECK_VERSION(2, 99, 2) SoupMessageHeaders *request_headers = soup_message_get_request_headers(message); #else SoupMessageHeaders *request_headers = message->request_headers; #endif soup_message_headers_set_content_disposition(request_headers, "form-data", params); soup_message_headers_set_content_type(request_headers, "application/vnd.snap", NULL); #if SOUP_CHECK_VERSION(2, 99, 2) g_autoptr(GBytes) part_buffer = g_bytes_new_static(self->snap_contents->data, self->snap_contents->len); #else g_autoptr(SoupBuffer) part_buffer = soup_buffer_new( SOUP_MEMORY_STATIC, self->snap_contents->data, self->snap_contents->len); #endif soup_multipart_append_part(multipart, request_headers, part_buffer); #if SOUP_CHECK_VERSION(2, 99, 2) soup_multipart_to_message(multipart, request_headers, body); #else g_autoptr(SoupMessageBody) b = soup_message_body_new(); soup_multipart_to_message(multipart, request_headers, b); g_autoptr(SoupBuffer) buffer = soup_message_body_flatten(b); *body = g_bytes_new(buffer->data, buffer->length); #endif return message; } static void snapd_post_snap_stream_finalize(GObject *object) { SnapdPostSnapStream *self = SNAPD_POST_SNAP_STREAM(object); g_clear_pointer(&self->snap_contents, g_byte_array_unref); G_OBJECT_CLASS(snapd_post_snap_stream_parent_class)->finalize(object); } static void snapd_post_snap_stream_class_init(SnapdPostSnapStreamClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_snap_stream_request; gobject_class->finalize = snapd_post_snap_stream_finalize; } static void snapd_post_snap_stream_init(SnapdPostSnapStream *self) { self->snap_contents = g_byte_array_new(); } snapd-glib-1.67/snapd-glib/requests/snapd-post-snap-stream.h000066400000000000000000000030241477073115000240570ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request-async.h" #include "snapd-client.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostSnapStream, snapd_post_snap_stream, SNAPD, POST_SNAP_STREAM, SnapdRequestAsync) SnapdPostSnapStream * _snapd_post_snap_stream_new(SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); void _snapd_post_snap_stream_set_classic(SnapdPostSnapStream *request, gboolean classic); void _snapd_post_snap_stream_set_dangerous(SnapdPostSnapStream *request, gboolean dangerous); void _snapd_post_snap_stream_set_devmode(SnapdPostSnapStream *request, gboolean devmode); void _snapd_post_snap_stream_set_jailmode(SnapdPostSnapStream *request, gboolean jailmode); void _snapd_post_snap_stream_append_data(SnapdPostSnapStream *request, const guint8 *data, guint len); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-snap-try.c000066400000000000000000000067121477073115000234040ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-post-snap-try.h" #include "snapd-json.h" struct _SnapdPostSnapTry { SnapdRequestAsync parent_instance; gchar *path; }; G_DEFINE_TYPE(SnapdPostSnapTry, snapd_post_snap_try, snapd_request_async_get_type()) SnapdPostSnapTry *_snapd_post_snap_try_new( const gchar *path, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostSnapTry *self = SNAPD_POST_SNAP_TRY( g_object_new(snapd_post_snap_try_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, "progress-callback", progress_callback, "progress-callback-data", progress_callback_data, NULL)); self->path = g_strdup(path); return self; } static void append_multipart_value(SoupMultipart *multipart, const gchar *name, const gchar *value) { g_autoptr(SoupMessageHeaders) headers = soup_message_headers_new(SOUP_MESSAGE_HEADERS_MULTIPART); g_autoptr(GHashTable) params = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); g_hash_table_insert(params, g_strdup("name"), g_strdup(name)); soup_message_headers_set_content_disposition(headers, "form-data", params); #if SOUP_CHECK_VERSION(2, 99, 2) g_autoptr(GBytes) buffer = g_bytes_new(value, strlen(value)); #else g_autoptr(SoupBuffer) buffer = soup_buffer_new_take((guchar *)g_strdup(value), strlen(value)); #endif soup_multipart_append_part(multipart, headers, buffer); } static SoupMessage *generate_post_snap_try_request(SnapdRequest *request, GBytes **body) { SnapdPostSnapTry *self = SNAPD_POST_SNAP_TRY(request); SoupMessage *message = soup_message_new("POST", "http://snapd/v2/snaps"); g_autoptr(SoupMultipart) multipart = soup_multipart_new("multipart/form-data"); append_multipart_value(multipart, "action", "try"); append_multipart_value(multipart, "snap-path", self->path); #if SOUP_CHECK_VERSION(2, 99, 2) soup_multipart_to_message(multipart, soup_message_get_request_headers(message), body); #else g_autoptr(SoupMessageBody) b = soup_message_body_new(); soup_multipart_to_message(multipart, message->request_headers, b); g_autoptr(SoupBuffer) buffer = soup_message_body_flatten(b); *body = g_bytes_new(buffer->data, buffer->length); #endif return message; } static void snapd_post_snap_try_finalize(GObject *object) { SnapdPostSnapTry *self = SNAPD_POST_SNAP_TRY(object); g_clear_pointer(&self->path, g_free); G_OBJECT_CLASS(snapd_post_snap_try_parent_class)->finalize(object); } static void snapd_post_snap_try_class_init(SnapdPostSnapTryClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_snap_try_request; gobject_class->finalize = snapd_post_snap_try_finalize; } static void snapd_post_snap_try_init(SnapdPostSnapTry *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-snap-try.h000066400000000000000000000014461477073115000234100ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request-async.h" #include "snapd-client.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostSnapTry, snapd_post_snap_try, SNAPD, POST_SNAP_TRY, SnapdRequestAsync) SnapdPostSnapTry *_snapd_post_snap_try_new( const gchar *path, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-snap.c000066400000000000000000000111671477073115000225700ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-post-snap.h" #include "snapd-json.h" struct _SnapdPostSnap { SnapdRequestAsync parent_instance; gchar *name; gchar *action; gchar *channel; gchar *revision; gboolean classic; gboolean dangerous; gboolean devmode; gboolean jailmode; gboolean purge; }; G_DEFINE_TYPE(SnapdPostSnap, snapd_post_snap, snapd_request_async_get_type()) SnapdPostSnap *_snapd_post_snap_new(const gchar *name, const gchar *action, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostSnap *self = SNAPD_POST_SNAP( g_object_new(snapd_post_snap_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, "progress-callback", progress_callback, "progress-callback-data", progress_callback_data, NULL)); self->name = g_strdup(name); self->action = g_strdup(action); return self; } void _snapd_post_snap_set_channel(SnapdPostSnap *self, const gchar *channel) { g_free(self->channel); self->channel = g_strdup(channel); } void _snapd_post_snap_set_revision(SnapdPostSnap *self, const gchar *revision) { g_free(self->revision); self->revision = g_strdup(revision); } void _snapd_post_snap_set_classic(SnapdPostSnap *self, gboolean classic) { self->classic = classic; } void _snapd_post_snap_set_dangerous(SnapdPostSnap *self, gboolean dangerous) { self->dangerous = dangerous; } void _snapd_post_snap_set_devmode(SnapdPostSnap *self, gboolean devmode) { self->devmode = devmode; } void _snapd_post_snap_set_jailmode(SnapdPostSnap *self, gboolean jailmode) { self->jailmode = jailmode; } void _snapd_post_snap_set_purge(SnapdPostSnap *self, gboolean purge) { self->purge = purge; } static SoupMessage *generate_post_snap_request(SnapdRequest *request, GBytes **body) { SnapdPostSnap *self = SNAPD_POST_SNAP(request); g_autoptr(GString) path = g_string_new("http://snapd/v2/snaps/"); g_string_append_uri_escaped(path, self->name, NULL, TRUE); SoupMessage *message = soup_message_new("POST", path->str); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "action"); json_builder_add_string_value(builder, self->action); if (self->channel != NULL) { json_builder_set_member_name(builder, "channel"); json_builder_add_string_value(builder, self->channel); } if (self->revision != NULL) { json_builder_set_member_name(builder, "revision"); json_builder_add_string_value(builder, self->revision); } if (self->classic) { json_builder_set_member_name(builder, "classic"); json_builder_add_boolean_value(builder, TRUE); } if (self->dangerous) { json_builder_set_member_name(builder, "dangerous"); json_builder_add_boolean_value(builder, TRUE); } if (self->devmode) { json_builder_set_member_name(builder, "devmode"); json_builder_add_boolean_value(builder, TRUE); } if (self->jailmode) { json_builder_set_member_name(builder, "jailmode"); json_builder_add_boolean_value(builder, TRUE); } if (self->purge) { json_builder_set_member_name(builder, "purge"); json_builder_add_boolean_value(builder, TRUE); } json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static void snapd_post_snap_finalize(GObject *object) { SnapdPostSnap *self = SNAPD_POST_SNAP(object); g_clear_pointer(&self->name, g_free); g_clear_pointer(&self->action, g_free); g_clear_pointer(&self->channel, g_free); g_clear_pointer(&self->revision, g_free); G_OBJECT_CLASS(snapd_post_snap_parent_class)->finalize(object); } static void snapd_post_snap_class_init(SnapdPostSnapClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_snap_request; gobject_class->finalize = snapd_post_snap_finalize; } static void snapd_post_snap_init(SnapdPostSnap *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-snap.h000066400000000000000000000030411477073115000225650ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request-async.h" #include "snapd-client.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostSnap, snapd_post_snap, SNAPD, POST_SNAP, SnapdRequestAsync) SnapdPostSnap *_snapd_post_snap_new(const gchar *name, const gchar *action, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); void _snapd_post_snap_set_channel(SnapdPostSnap *request, const gchar *channel); void _snapd_post_snap_set_revision(SnapdPostSnap *request, const gchar *revision); void _snapd_post_snap_set_classic(SnapdPostSnap *request, gboolean classic); void _snapd_post_snap_set_dangerous(SnapdPostSnap *request, gboolean dangerous); void _snapd_post_snap_set_devmode(SnapdPostSnap *request, gboolean devmode); void _snapd_post_snap_set_jailmode(SnapdPostSnap *request, gboolean jailmode); void _snapd_post_snap_set_purge(SnapdPostSnap *request, gboolean purge); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-snapctl.c000066400000000000000000000106671477073115000232770ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-post-snapctl.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdPostSnapctl { SnapdRequest parent_instance; gchar *context_id; GStrv args; gchar *stdout_output; gchar *stderr_output; int exit_code; }; G_DEFINE_TYPE(SnapdPostSnapctl, snapd_post_snapctl, snapd_request_get_type()) SnapdPostSnapctl *_snapd_post_snapctl_new(const gchar *context_id, GStrv args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostSnapctl *self = SNAPD_POST_SNAPCTL(g_object_new( snapd_post_snapctl_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->context_id = g_strdup(context_id); self->args = g_strdupv(args); return self; } const gchar *_snapd_post_snapctl_get_stdout_output(SnapdPostSnapctl *self) { return self->stdout_output; } const gchar *_snapd_post_snapctl_get_stderr_output(SnapdPostSnapctl *self) { return self->stderr_output; } int _snapd_post_snapctl_get_exit_code(SnapdPostSnapctl *self) { return self->exit_code; } static SoupMessage *generate_post_snapctl_request(SnapdRequest *request, GBytes **body) { SnapdPostSnapctl *self = SNAPD_POST_SNAPCTL(request); SoupMessage *message = soup_message_new("POST", "http://snapd/v2/snapctl"); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "context-id"); json_builder_add_string_value(builder, self->context_id); json_builder_set_member_name(builder, "args"); json_builder_begin_array(builder); for (int i = 0; self->args[i] != NULL; i++) json_builder_add_string_value(builder, self->args[i]); json_builder_end_array(builder); json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static gboolean parse_post_snapctl_response(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdPostSnapctl *self = SNAPD_POST_SNAPCTL(request); g_autoptr(JsonNode) error_value = NULL; g_autoptr(JsonObject) response = _snapd_json_parse_response( content_type, body, maintenance, &error_value, error); if (response == NULL) { if (g_error_matches(*error, SNAPD_ERROR, SNAPD_ERROR_UNSUCCESSFUL) && error_value != NULL && json_node_get_value_type(error_value) == JSON_TYPE_OBJECT) { JsonObject *object = json_node_get_object(error_value); self->stdout_output = g_strdup(_snapd_json_get_string(object, "stdout", NULL)); self->stderr_output = g_strdup(_snapd_json_get_string(object, "stderr", NULL)); self->exit_code = _snapd_json_get_int(object, "exit-code", 0); } return FALSE; } g_autoptr(JsonObject) result = _snapd_json_get_sync_result_o(response, error); if (result == NULL) return FALSE; self->stdout_output = g_strdup(_snapd_json_get_string(result, "stdout", NULL)); self->stderr_output = g_strdup(_snapd_json_get_string(result, "stderr", NULL)); return TRUE; } static void snapd_post_snapctl_finalize(GObject *object) { SnapdPostSnapctl *self = SNAPD_POST_SNAPCTL(object); g_clear_pointer(&self->context_id, g_free); g_clear_pointer(&self->args, g_strfreev); g_clear_pointer(&self->stdout_output, g_free); g_clear_pointer(&self->stderr_output, g_free); G_OBJECT_CLASS(snapd_post_snapctl_parent_class)->finalize(object); } static void snapd_post_snapctl_class_init(SnapdPostSnapctlClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_snapctl_request; request_class->parse_response = parse_post_snapctl_response; gobject_class->finalize = snapd_post_snapctl_finalize; } static void snapd_post_snapctl_init(SnapdPostSnapctl *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-snapctl.h000066400000000000000000000020311477073115000232660ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostSnapctl, snapd_post_snapctl, SNAPD, POST_SNAPCTL, SnapdRequest) SnapdPostSnapctl *_snapd_post_snapctl_new(const gchar *context_id, GStrv args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); const gchar *_snapd_post_snapctl_get_stdout_output(SnapdPostSnapctl *request); const gchar *_snapd_post_snapctl_get_stderr_output(SnapdPostSnapctl *request); int _snapd_post_snapctl_get_exit_code(SnapdPostSnapctl *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-snaps.c000066400000000000000000000100471477073115000227470ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-post-snaps.h" #include "snapd-error.h" #include "snapd-json.h" struct _SnapdPostSnaps { SnapdRequestAsync parent_instance; gchar *action; GStrv snap_names; }; G_DEFINE_TYPE(SnapdPostSnaps, snapd_post_snaps, snapd_request_async_get_type()) SnapdPostSnaps *_snapd_post_snaps_new(const gchar *action, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostSnaps *self = SNAPD_POST_SNAPS( g_object_new(snapd_post_snaps_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, "progress-callback", progress_callback, "progress-callback-data", progress_callback_data, NULL)); self->action = g_strdup(action); return self; } GStrv _snapd_post_snaps_get_snap_names(SnapdPostSnaps *self) { return self->snap_names; } static SoupMessage *generate_post_snaps_request(SnapdRequest *request, GBytes **body) { SnapdPostSnaps *self = SNAPD_POST_SNAPS(request); SoupMessage *message = soup_message_new("POST", "http://snapd/v2/snaps"); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "action"); json_builder_add_string_value(builder, self->action); json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static gboolean parse_post_snaps_result(SnapdRequestAsync *request, JsonNode *result, GError **error) { SnapdPostSnaps *self = SNAPD_POST_SNAPS(request); if (result == NULL || json_node_get_value_type(result) != JSON_TYPE_OBJECT) { g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected result type"); return FALSE; } JsonObject *o = json_node_get_object(result); if (o == NULL) { g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "No result returned"); return FALSE; } g_autoptr(JsonArray) a = _snapd_json_get_array(o, "snap-names"); g_autoptr(GPtrArray) snap_names = g_ptr_array_new(); for (guint i = 0; i < json_array_get_length(a); i++) { JsonNode *node = json_array_get_element(a, i); if (json_node_get_value_type(node) != G_TYPE_STRING) { g_set_error_literal(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unexpected snap name type"); return FALSE; } g_ptr_array_add(snap_names, g_strdup(json_node_get_string(node))); } g_ptr_array_add(snap_names, NULL); self->snap_names = (GStrv)g_steal_pointer(&snap_names->pdata); return TRUE; } static void snapd_post_snaps_finalize(GObject *object) { SnapdPostSnaps *self = SNAPD_POST_SNAPS(object); g_clear_pointer(&self->action, g_free); g_clear_pointer(&self->snap_names, g_strfreev); G_OBJECT_CLASS(snapd_post_snaps_parent_class)->finalize(object); } static void snapd_post_snaps_class_init(SnapdPostSnapsClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); SnapdRequestAsyncClass *request_async_class = SNAPD_REQUEST_ASYNC_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_snaps_request; request_async_class->parse_result = parse_post_snaps_result; gobject_class->finalize = snapd_post_snaps_finalize; } static void snapd_post_snaps_init(SnapdPostSnaps *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-snaps.h000066400000000000000000000020161477073115000227510ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request-async.h" #include "snapd-client.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostSnaps, snapd_post_snaps, SNAPD, POST_SNAPS, SnapdRequestAsync) SnapdPostSnaps *_snapd_post_snaps_new(const gchar *action, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GStrv _snapd_post_snaps_get_snap_names(SnapdPostSnaps *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-post-themes.c000066400000000000000000000064161477073115000231150ustar00rootroot00000000000000/* * Copyright (C) 2021 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-post-themes.h" #include "snapd-json.h" struct _SnapdPostThemes { SnapdRequestAsync parent_instance; GStrv gtk_theme_names; GStrv icon_theme_names; GStrv sound_theme_names; }; G_DEFINE_TYPE(SnapdPostThemes, snapd_post_themes, snapd_request_async_get_type()) SnapdPostThemes *_snapd_post_themes_new( GStrv gtk_theme_names, GStrv icon_theme_names, GStrv sound_theme_names, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPostThemes *self = SNAPD_POST_THEMES( g_object_new(snapd_post_themes_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, "progress-callback", progress_callback, "progress-callback-data", progress_callback_data, "change-api-path", "/v2/accessories/changes", NULL)); self->gtk_theme_names = g_strdupv(gtk_theme_names); self->icon_theme_names = g_strdupv(icon_theme_names); self->sound_theme_names = g_strdupv(sound_theme_names); return self; } static void add_themes(JsonBuilder *builder, const char *member_name, GStrv theme_names) { char *const *name; if (theme_names == NULL) return; json_builder_set_member_name(builder, member_name); json_builder_begin_array(builder); for (name = theme_names; *name != NULL; name++) { json_builder_add_string_value(builder, *name); } json_builder_end_array(builder); } static SoupMessage *generate_post_themes_request(SnapdRequest *request, GBytes **body) { SnapdPostThemes *self = SNAPD_POST_THEMES(request); SoupMessage *message = soup_message_new("POST", "http://snapd/v2/accessories/themes"); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); add_themes(builder, "gtk-themes", self->gtk_theme_names); add_themes(builder, "icon-themes", self->icon_theme_names); add_themes(builder, "sound-themes", self->sound_theme_names); json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static void snapd_post_themes_finalize(GObject *object) { SnapdPostThemes *self = SNAPD_POST_THEMES(object); g_clear_pointer(&self->gtk_theme_names, g_strfreev); g_clear_pointer(&self->icon_theme_names, g_strfreev); g_clear_pointer(&self->sound_theme_names, g_strfreev); G_OBJECT_CLASS(snapd_post_themes_parent_class)->finalize(object); } static void snapd_post_themes_class_init(SnapdPostThemesClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_post_themes_request; gobject_class->finalize = snapd_post_themes_finalize; } static void snapd_post_themes_init(SnapdPostThemes *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-post-themes.h000066400000000000000000000014741477073115000231210ustar00rootroot00000000000000/* * Copyright (C) 2021 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request-async.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPostThemes, snapd_post_themes, SNAPD, POST_THEMES, SnapdRequestAsync) SnapdPostThemes *_snapd_post_themes_new( GStrv gtk_theme_names, GStrv icon_theme_names, GStrv sound_theme_names, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-put-snap-conf.c000066400000000000000000000055441477073115000233400ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-put-snap-conf.h" #include "snapd-json.h" struct _SnapdPutSnapConf { SnapdRequestAsync parent_instance; gchar *name; GHashTable *key_values; }; G_DEFINE_TYPE(SnapdPutSnapConf, snapd_put_snap_conf, snapd_request_async_get_type()) SnapdPutSnapConf *_snapd_put_snap_conf_new(const gchar *name, GHashTable *key_values, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SnapdPutSnapConf *self = SNAPD_PUT_SNAP_CONF(g_object_new( snapd_put_snap_conf_get_type(), "cancellable", cancellable, "ready-callback", callback, "ready-callback-data", user_data, NULL)); self->name = g_strdup(name); self->key_values = g_hash_table_ref(key_values); return self; } static SoupMessage *generate_put_snap_conf_request(SnapdRequest *request, GBytes **body) { SnapdPutSnapConf *self = SNAPD_PUT_SNAP_CONF(request); g_autoptr(GString) path = g_string_new("http://snapd/v2/snaps/"); g_string_append_uri_escaped(path, self->name, NULL, TRUE); g_string_append(path, "/conf"); SoupMessage *message = soup_message_new("PUT", path->str); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); GHashTableIter iter; g_hash_table_iter_init(&iter, self->key_values); gpointer key, value; while (g_hash_table_iter_next(&iter, &key, &value)) { const gchar *conf_key = key; GVariant *conf_value = value; json_builder_set_member_name(builder, conf_key); json_builder_add_value(builder, json_gvariant_serialize(conf_value)); } json_builder_end_object(builder); _snapd_json_set_body(message, builder, body); return message; } static void snapd_put_snap_conf_finalize(GObject *object) { SnapdPutSnapConf *self = SNAPD_PUT_SNAP_CONF(object); g_clear_pointer(&self->name, g_free); g_clear_pointer(&self->key_values, g_hash_table_unref); G_OBJECT_CLASS(snapd_put_snap_conf_parent_class)->finalize(object); } static void snapd_put_snap_conf_class_init(SnapdPutSnapConfClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->generate_request = generate_put_snap_conf_request; gobject_class->finalize = snapd_put_snap_conf_finalize; } static void snapd_put_snap_conf_init(SnapdPutSnapConf *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-put-snap-conf.h000066400000000000000000000015701477073115000233400ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include "snapd-request-async.h" G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdPutSnapConf, snapd_put_snap_conf, SNAPD, PUT_SNAP_CONF, SnapdRequestAsync) SnapdPutSnapConf *_snapd_put_snap_conf_new(const gchar *name, GHashTable *key_values, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-request-async.c000066400000000000000000000207241477073115000234460ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-request-async.h" #include "snapd-client.h" #include "snapd-json.h" #include "snapd-task.h" enum { PROP_PROGRESS_CALLBACK = 1, PROP_PROGRESS_CALLBACK_DATA, PROP_CHANGE_API_PATH, PROP_LAST }; typedef struct { SnapdProgressCallback progress_callback; gpointer progress_callback_data; gchar *change_api_path; /* Returned change ID for this request */ gchar *change_id; /* Last reported change (so we don't send duplicates) */ SnapdChange *change; } SnapdRequestAsyncPrivate; G_DEFINE_TYPE_WITH_PRIVATE(SnapdRequestAsync, snapd_request_async, snapd_request_get_type()) const gchar *_snapd_request_async_get_change_id(SnapdRequestAsync *self) { SnapdRequestAsyncPrivate *priv = snapd_request_async_get_instance_private(self); return priv->change_id; } gboolean _snapd_request_async_parse_result(SnapdRequestAsync *self, JsonNode *result, GError **error) { if (SNAPD_REQUEST_ASYNC_GET_CLASS(self)->parse_result == NULL) return TRUE; return SNAPD_REQUEST_ASYNC_GET_CLASS(self)->parse_result(self, result, error); } static gboolean parse_async_response(SnapdRequest *self, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error) { SnapdRequestAsync *r = SNAPD_REQUEST_ASYNC(self); SnapdRequestAsyncPrivate *priv = snapd_request_async_get_instance_private(r); g_autoptr(JsonObject) response = _snapd_json_parse_response(content_type, body, maintenance, NULL, error); if (response == NULL) return FALSE; g_autofree gchar *change_id = _snapd_json_get_async_result(response, error); if (change_id == NULL) return FALSE; priv->change_id = g_strdup(change_id); return TRUE; } static gboolean times_equal(GDateTime *time1, GDateTime *time2) { if (time1 == NULL || time2 == NULL) return time1 == time2; return g_date_time_equal(time1, time2); } static gboolean tasks_equal(SnapdTask *task1, SnapdTask *task2) { return g_strcmp0(snapd_task_get_id(task1), snapd_task_get_id(task2)) == 0 && g_strcmp0(snapd_task_get_kind(task1), snapd_task_get_kind(task2)) == 0 && g_strcmp0(snapd_task_get_summary(task1), snapd_task_get_summary(task2)) == 0 && g_strcmp0(snapd_task_get_status(task1), snapd_task_get_status(task2)) == 0 && g_strcmp0(snapd_task_get_progress_label(task1), snapd_task_get_progress_label(task2)) == 0 && snapd_task_get_progress_done(task1) == snapd_task_get_progress_done(task2) && snapd_task_get_progress_total(task1) == snapd_task_get_progress_total(task2) && times_equal(snapd_task_get_spawn_time(task1), snapd_task_get_spawn_time(task2)) && times_equal(snapd_task_get_spawn_time(task1), snapd_task_get_spawn_time(task2)); } static gboolean changes_equal(SnapdChange *change1, SnapdChange *change2) { if (change1 == NULL || change2 == NULL) return change1 == change2; GPtrArray *tasks1 = snapd_change_get_tasks(change1); GPtrArray *tasks2 = snapd_change_get_tasks(change2); if (tasks1 == NULL || tasks2 == NULL) { if (tasks1 != tasks2) return FALSE; } else { if (tasks1->len != tasks2->len) return FALSE; for (int i = 0; i < tasks1->len; i++) { SnapdTask *t1 = tasks1->pdata[i], *t2 = tasks2->pdata[i]; if (!tasks_equal(t1, t2)) return FALSE; } } return g_strcmp0(snapd_change_get_id(change1), snapd_change_get_id(change2)) == 0 && g_strcmp0(snapd_change_get_kind(change1), snapd_change_get_kind(change2)) == 0 && g_strcmp0(snapd_change_get_summary(change1), snapd_change_get_summary(change2)) == 0 && g_strcmp0(snapd_change_get_status(change1), snapd_change_get_status(change2)) == 0 && !!snapd_change_get_ready(change1) == !!snapd_change_get_ready(change2) && times_equal(snapd_change_get_spawn_time(change1), snapd_change_get_spawn_time(change2)) && times_equal(snapd_change_get_spawn_time(change1), snapd_change_get_spawn_time(change2)); return TRUE; } void _snapd_request_async_report_progress(SnapdRequestAsync *self, SnapdClient *client, SnapdChange *change) { SnapdRequestAsyncPrivate *priv = snapd_request_async_get_instance_private(self); if (!changes_equal(priv->change, change)) { g_set_object(&priv->change, change); if (priv->progress_callback != NULL) priv->progress_callback( client, change, snapd_change_get_tasks( change), // Passed for ABI compatibility, is deprecated priv->progress_callback_data); } } SnapdGetChange * _snapd_request_async_make_get_change_request(SnapdRequestAsync *self) { SnapdRequestAsyncPrivate *priv = snapd_request_async_get_instance_private(self); SnapdGetChange *request = _snapd_get_change_new(priv->change_id, NULL, NULL, NULL); _snapd_get_change_set_api_path(request, priv->change_api_path); return request; } SnapdPostChange * _snapd_request_async_make_post_change_request(SnapdRequestAsync *self) { SnapdRequestAsyncPrivate *priv = snapd_request_async_get_instance_private(self); SnapdPostChange *request = _snapd_post_change_new(priv->change_id, "abort", NULL, NULL, NULL); _snapd_post_change_set_api_path(request, priv->change_api_path); return request; } static void snapd_request_async_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdRequestAsync *self = SNAPD_REQUEST_ASYNC(object); SnapdRequestAsyncPrivate *priv = snapd_request_async_get_instance_private(self); switch (prop_id) { case PROP_PROGRESS_CALLBACK: priv->progress_callback = g_value_get_pointer(value); break; case PROP_PROGRESS_CALLBACK_DATA: priv->progress_callback_data = g_value_get_pointer(value); break; case PROP_CHANGE_API_PATH: g_free(priv->change_api_path); priv->change_api_path = g_value_dup_string(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_request_async_finalize(GObject *object) { SnapdRequestAsync *self = SNAPD_REQUEST_ASYNC(object); SnapdRequestAsyncPrivate *priv = snapd_request_async_get_instance_private(self); g_clear_pointer(&priv->change_api_path, g_free); g_clear_pointer(&priv->change_id, g_free); g_clear_object(&priv->change); G_OBJECT_CLASS(snapd_request_async_parent_class)->finalize(object); } static void snapd_request_async_class_init(SnapdRequestAsyncClass *klass) { SnapdRequestClass *request_class = SNAPD_REQUEST_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass); request_class->parse_response = parse_async_response; gobject_class->set_property = snapd_request_async_set_property; gobject_class->finalize = snapd_request_async_finalize; g_object_class_install_property( gobject_class, PROP_PROGRESS_CALLBACK, g_param_spec_pointer("progress-callback", "progress-callback", "Progress callback", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property( gobject_class, PROP_PROGRESS_CALLBACK_DATA, g_param_spec_pointer("progress-callback-data", "progress-callback-data", "Data for progress callback", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property( gobject_class, PROP_CHANGE_API_PATH, g_param_spec_string("change-api-path", "change-api-path", "change-api-path", NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); } static void snapd_request_async_init(SnapdRequestAsync *self) {} snapd-glib-1.67/snapd-glib/requests/snapd-request-async.h000066400000000000000000000027621477073115000234550ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include #include #include "snapd-change.h" #include "snapd-client.h" #include "snapd-get-change.h" #include "snapd-post-change.h" #include "snapd-request.h" G_BEGIN_DECLS G_DECLARE_DERIVABLE_TYPE(SnapdRequestAsync, snapd_request_async, SNAPD, REQUEST_ASYNC, SnapdRequest) struct _SnapdRequestAsyncClass { SnapdRequestClass parent_class; gboolean (*parse_result)(SnapdRequestAsync *request, JsonNode *result, GError **error); }; const gchar *_snapd_request_async_get_change_id(SnapdRequestAsync *request); gboolean _snapd_request_async_parse_result(SnapdRequestAsync *request, JsonNode *result, GError **error); void _snapd_request_async_report_progress(SnapdRequestAsync *request, SnapdClient *client, SnapdChange *change); SnapdGetChange * _snapd_request_async_make_get_change_request(SnapdRequestAsync *request); SnapdPostChange * _snapd_request_async_make_post_change_request(SnapdRequestAsync *request); G_END_DECLS snapd-glib-1.67/snapd-glib/requests/snapd-request.c000066400000000000000000000145701477073115000223350ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-request.h" enum { PROP_SOURCE_OBJECT = 1, PROP_CANCELLABLE, PROP_READY_CALLBACK, PROP_READY_CALLBACK_DATA, PROP_LAST }; typedef struct { GObject *source_object; /* Context request was made from */ GMainContext *context; SoupMessage *message; GBytes *body; GCancellable *cancellable; gboolean responded; GAsyncReadyCallback ready_callback; gpointer ready_callback_data; GError *error; } SnapdRequestPrivate; static void snapd_request_async_result_init(GAsyncResultIface *iface); G_DEFINE_TYPE_WITH_CODE(SnapdRequest, snapd_request, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(G_TYPE_ASYNC_RESULT, snapd_request_async_result_init) G_ADD_PRIVATE(SnapdRequest)) GMainContext *_snapd_request_get_context(SnapdRequest *self) { SnapdRequestPrivate *priv = snapd_request_get_instance_private(self); return priv->context; } GCancellable *_snapd_request_get_cancellable(SnapdRequest *self) { SnapdRequestPrivate *priv = snapd_request_get_instance_private(SNAPD_REQUEST(self)); return priv->cancellable; } void _snapd_request_set_source_object(SnapdRequest *self, GObject *object) { SnapdRequestPrivate *priv = snapd_request_get_instance_private(SNAPD_REQUEST(self)); priv->source_object = g_object_ref(object); } SoupMessage *_snapd_request_get_message(SnapdRequest *self, GBytes **body) { SnapdRequestPrivate *priv = snapd_request_get_instance_private(SNAPD_REQUEST(self)); if (priv->message == NULL) { g_clear_object(&priv->body); priv->message = SNAPD_REQUEST_GET_CLASS(self)->generate_request(self, &priv->body); } if (body != NULL) *body = priv->body != NULL ? g_bytes_ref(priv->body) : NULL; return priv->message; } static gboolean respond_cb(gpointer user_data) { SnapdRequest *self = SNAPD_REQUEST(user_data); SnapdRequestPrivate *priv = snapd_request_get_instance_private(self); if (priv->ready_callback != NULL) priv->ready_callback(priv->source_object, G_ASYNC_RESULT(self), priv->ready_callback_data); return G_SOURCE_REMOVE; } void _snapd_request_return(SnapdRequest *self, GError *error) { SnapdRequestPrivate *priv = snapd_request_get_instance_private(self); if (priv->responded) return; priv->responded = TRUE; if (error != NULL) priv->error = g_error_copy(error); g_autoptr(GSource) source = g_idle_source_new(); g_source_set_callback(source, respond_cb, g_object_ref(self), g_object_unref); g_source_attach(source, _snapd_request_get_context(self)); } gboolean _snapd_request_propagate_error(SnapdRequest *self, GError **error) { SnapdRequestPrivate *priv = snapd_request_get_instance_private(self); if (priv->error != NULL) { g_propagate_error(error, priv->error); priv->error = NULL; return FALSE; } /* If no error provided from snapd, use a generic cancelled error */ if (g_cancellable_set_error_if_cancelled(priv->cancellable, error)) return FALSE; return TRUE; } static GObject *snapd_get_source_object(GAsyncResult *result) { SnapdRequestPrivate *priv = snapd_request_get_instance_private(SNAPD_REQUEST(result)); return g_object_ref(priv->source_object); } static void snapd_request_async_result_init(GAsyncResultIface *iface) { iface->get_source_object = snapd_get_source_object; } static void snapd_request_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdRequest *self = SNAPD_REQUEST(object); SnapdRequestPrivate *priv = snapd_request_get_instance_private(self); switch (prop_id) { case PROP_SOURCE_OBJECT: g_set_object(&priv->source_object, g_value_get_object(value)); break; case PROP_CANCELLABLE: g_set_object(&priv->cancellable, g_value_get_object(value)); break; case PROP_READY_CALLBACK: priv->ready_callback = g_value_get_pointer(value); break; case PROP_READY_CALLBACK_DATA: priv->ready_callback_data = g_value_get_pointer(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_request_finalize(GObject *object) { SnapdRequest *self = SNAPD_REQUEST(object); SnapdRequestPrivate *priv = snapd_request_get_instance_private(self); g_clear_object(&priv->source_object); g_clear_object(&priv->message); g_clear_pointer(&priv->body, g_bytes_unref); g_clear_object(&priv->cancellable); g_clear_pointer(&priv->error, g_error_free); g_clear_pointer(&priv->context, g_main_context_unref); G_OBJECT_CLASS(snapd_request_parent_class)->finalize(object); } static void snapd_request_class_init(SnapdRequestClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_request_set_property; gobject_class->finalize = snapd_request_finalize; g_object_class_install_property( gobject_class, PROP_SOURCE_OBJECT, g_param_spec_object("source-object", "source-object", "Source object", G_TYPE_OBJECT, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property( gobject_class, PROP_CANCELLABLE, g_param_spec_object("cancellable", "cancellable", "Cancellable", G_TYPE_CANCELLABLE, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property( gobject_class, PROP_READY_CALLBACK, g_param_spec_pointer("ready-callback", "ready-callback", "Ready callback", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property( gobject_class, PROP_READY_CALLBACK_DATA, g_param_spec_pointer("ready-callback-data", "ready-callback-data", "Ready callback data", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); } static void snapd_request_init(SnapdRequest *self) { SnapdRequestPrivate *priv = snapd_request_get_instance_private(self); priv->context = g_main_context_ref_thread_default(); } snapd-glib-1.67/snapd-glib/requests/snapd-request.h000066400000000000000000000030251477073115000223330ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #pragma once #include #include #include #include "snapd-maintenance.h" G_BEGIN_DECLS G_DECLARE_DERIVABLE_TYPE(SnapdRequest, snapd_request, SNAPD, REQUEST, GObject) struct _SnapdRequestClass { GObjectClass parent_class; SoupMessage *(*generate_request)(SnapdRequest *request, GBytes **body); gboolean (*parse_response)(SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body, SnapdMaintenance **maintenance, GError **error); gboolean (*parse_json_seq)(SnapdRequest *request, JsonNode *seq, GError **error); }; void _snapd_request_set_source_object(SnapdRequest *request, GObject *object); GMainContext *_snapd_request_get_context(SnapdRequest *request); GCancellable *_snapd_request_get_cancellable(SnapdRequest *request); void _snapd_request_generate(SnapdRequest *request); SoupMessage *_snapd_request_get_message(SnapdRequest *request, GBytes **body); void _snapd_request_return(SnapdRequest *request, GError *error); gboolean _snapd_request_propagate_error(SnapdRequest *request, GError **error); G_END_DECLS snapd-glib-1.67/snapd-glib/snapd-alias.c000066400000000000000000000201011477073115000200460ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-alias.h" #include "snapd-enum-types.h" /** * SECTION: snapd-alias * @short_description: App aliases. * @include: snapd-glib/snapd-glib.h * * A #SnapdAlias represents an optional alias that can be used for an app. * Aliases can be queried using snapd_client_get_aliases_sync() and are used in * snapd_client_enable_aliases_sync(), snapd_client_disable_aliases_sync() and * snapd_client_reset_aliases_sync(). */ /** * SnapdAlias: * * #SnapdAlias contains alias information for a Snap. * * Aliases are used to provide alternative binary names for Snap apps. * * Since: 1.8 */ struct _SnapdAlias { GObject parent_instance; gchar *command; gchar *name; gchar *snap; gchar *app_auto; gchar *app_manual; SnapdAliasStatus status; }; enum { PROP_NAME = 1, PROP_SNAP, PROP_STATUS, PROP_COMMAND, PROP_APP_AUTO, PROP_APP_MANUAL, PROP_LAST }; G_DEFINE_TYPE(SnapdAlias, snapd_alias, G_TYPE_OBJECT) /** * snapd_alias_get_app: * @alias: a #SnapdAlias. * * Get the app this is an alias for. * * Returns: (allow-none): an app name or %NULL. * * Since: 1.8 * Deprecated: 1.25: Use snapd_alias_get_app_manual() or * snapd_alias_get_app_auto(). */ const gchar *snapd_alias_get_app(SnapdAlias *self) { g_return_val_if_fail(SNAPD_IS_ALIAS(self), NULL); return NULL; } /** * snapd_alias_get_app_auto: * @alias: a #SnapdAlias. * * Get the app this alias has been automatically set to (status is * %SNAPD_ALIAS_STATUS_AUTO). Can be overridden when status is * %SNAPD_ALIAS_STATUS_MANUAL. * * Returns: (allow-none): an app name or %NULL. * * Since: 1.25 */ const gchar *snapd_alias_get_app_auto(SnapdAlias *self) { g_return_val_if_fail(SNAPD_IS_ALIAS(self), NULL); return self->app_auto; } /** * snapd_alias_get_app_manual: * @alias: a #SnapdAlias. * * Get the app this alias has been manually set to (status is * %SNAPD_ALIAS_STATUS_MANUAL). This overrides the app from * snapd_alias_get_app_auto(). * * Returns: (allow-none): an app name or %NULL. * * Since: 1.25 */ const gchar *snapd_alias_get_app_manual(SnapdAlias *self) { g_return_val_if_fail(SNAPD_IS_ALIAS(self), NULL); return self->app_manual; } /** * snapd_alias_get_command: * @alias: a #SnapdAlias. * * Get the command this alias runs. * * Returns: a command. * * Since: 1.25 */ const gchar *snapd_alias_get_command(SnapdAlias *self) { g_return_val_if_fail(SNAPD_IS_ALIAS(self), NULL); return self->command; } /** * snapd_alias_get_name: * @alias: a #SnapdAlias. * * Get the name of this alias. * * Returns: an alias name. * * Since: 1.8 */ const gchar *snapd_alias_get_name(SnapdAlias *self) { g_return_val_if_fail(SNAPD_IS_ALIAS(self), NULL); return self->name; } /** * snapd_alias_get_snap: * @alias: a #SnapdAlias. * * Get the snap this alias is for. * * Returns: a snap name. * * Since: 1.8 */ const gchar *snapd_alias_get_snap(SnapdAlias *self) { g_return_val_if_fail(SNAPD_IS_ALIAS(self), NULL); return self->snap; } /** * snapd_alias_get_status: * @alias: a #SnapdAlias. * * Get the status of this alias. * * Return: a #SnapdAliasStatus. * * Since: 1.8 */ SnapdAliasStatus snapd_alias_get_status(SnapdAlias *self) { g_return_val_if_fail(SNAPD_IS_ALIAS(self), SNAPD_ALIAS_STATUS_UNKNOWN); return self->status; } static void snapd_alias_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdAlias *self = SNAPD_ALIAS(object); switch (prop_id) { case PROP_APP_AUTO: g_free(self->app_auto); self->app_auto = g_strdup(g_value_get_string(value)); break; case PROP_APP_MANUAL: g_free(self->app_manual); self->app_manual = g_strdup(g_value_get_string(value)); break; case PROP_COMMAND: g_free(self->command); self->command = g_strdup(g_value_get_string(value)); break; case PROP_NAME: g_free(self->name); self->name = g_strdup(g_value_get_string(value)); break; case PROP_SNAP: g_free(self->snap); self->snap = g_strdup(g_value_get_string(value)); break; case PROP_STATUS: self->status = g_value_get_enum(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_alias_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdAlias *self = SNAPD_ALIAS(object); switch (prop_id) { case PROP_APP_AUTO: g_value_set_string(value, self->app_auto); break; case PROP_APP_MANUAL: g_value_set_string(value, self->app_manual); break; case PROP_COMMAND: g_value_set_string(value, self->command); break; case PROP_NAME: g_value_set_string(value, self->name); break; case PROP_SNAP: g_value_set_string(value, self->snap); break; case PROP_STATUS: g_value_set_enum(value, self->status); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_alias_finalize(GObject *object) { SnapdAlias *self = SNAPD_ALIAS(object); g_clear_pointer(&self->app_auto, g_free); g_clear_pointer(&self->app_manual, g_free); g_clear_pointer(&self->command, g_free); g_clear_pointer(&self->name, g_free); g_clear_pointer(&self->snap, g_free); G_OBJECT_CLASS(snapd_alias_parent_class)->finalize(object); } static void snapd_alias_class_init(SnapdAliasClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_alias_set_property; gobject_class->get_property = snapd_alias_get_property; gobject_class->finalize = snapd_alias_finalize; g_object_class_install_property( gobject_class, PROP_APP_AUTO, g_param_spec_string( "app-auto", "app-auto", "App this alias is for (when status is SNAPD_ALIAS_STATUS_AUTO)", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_APP_MANUAL, g_param_spec_string( "app-manual", "app-manual", "App this alias is for (when status is SNAPD_ALIAS_STATUS_MANUAL)", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_COMMAND, g_param_spec_string("command", "command", "Command this alias runs", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_NAME, g_param_spec_string("name", "name", "Name of alias", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SNAP, g_param_spec_string("snap", "snap", "Snap this alias is for", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_STATUS, g_param_spec_enum("status", "status", "Alias status", SNAPD_TYPE_ALIAS_STATUS, SNAPD_ALIAS_STATUS_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_alias_init(SnapdAlias *self) {} snapd-glib-1.67/snapd-glib/snapd-alias.h000066400000000000000000000034211477073115000200610ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_ALIAS_H__ #define __SNAPD_ALIAS_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_ALIAS (snapd_alias_get_type()) G_DECLARE_FINAL_TYPE(SnapdAlias, snapd_alias, SNAPD, ALIAS, GObject) /** * SnapdAliasStatus: * @SNAPD_ALIAS_STATUS_UNKNOWN: the alias status is unknown. * @SNAPD_ALIAS_STATUS_DEFAULT: deprecated, do not use. * @SNAPD_ALIAS_STATUS_ENABLED: deprecated, do not use. * @SNAPD_ALIAS_STATUS_DISABLED: the alias is disabled. * @SNAPD_ALIAS_STATUS_AUTO: the alias is automatically enabled. * @SNAPD_ALIAS_STATUS_MANUAL: the alias is manually enabled. * * Status of an alias. * * Since: 1.8 */ typedef enum { SNAPD_ALIAS_STATUS_UNKNOWN, SNAPD_ALIAS_STATUS_DEFAULT, SNAPD_ALIAS_STATUS_ENABLED, SNAPD_ALIAS_STATUS_DISABLED, SNAPD_ALIAS_STATUS_AUTO, SNAPD_ALIAS_STATUS_MANUAL } SnapdAliasStatus; const gchar *snapd_alias_get_app(SnapdAlias *alias) G_DEPRECATED; const gchar *snapd_alias_get_app_auto(SnapdAlias *alias); const gchar *snapd_alias_get_command(SnapdAlias *alias); const gchar *snapd_alias_get_app_manual(SnapdAlias *alias); const gchar *snapd_alias_get_name(SnapdAlias *alias); const gchar *snapd_alias_get_snap(SnapdAlias *alias); SnapdAliasStatus snapd_alias_get_status(SnapdAlias *alias); G_END_DECLS #endif /* __SNAPD_ALIAS_H__ */ snapd-glib-1.67/snapd-glib/snapd-app.c000066400000000000000000000213271477073115000175500ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-app.h" #include "snapd-enum-types.h" /** * SECTION:snapd-app * @short_description: Application metadata * @include: snapd-glib/snapd-glib.h * * A #SnapdApp contains information about an application that snapd provides. * Apps are retrieved using snapd_snap_get_apps(). */ /** * SnapdApp: * * #SnapdApp contains information about an app in a Snap. * * Snaps can contain apps which is a single binary executable. * * Since: 1.0 */ struct _SnapdApp { GObject parent_instance; SnapdDaemonType daemon_type; gchar *name; gchar *snap; gchar *common_id; gchar *desktop_file; gboolean enabled; gboolean active; }; enum { PROP_NAME = 1, PROP_ALIASES, PROP_DAEMON_TYPE, PROP_DESKTOP_FILE, PROP_SNAP, PROP_ACTIVE, PROP_ENABLED, PROP_COMMON_ID, PROP_LAST }; G_DEFINE_TYPE(SnapdApp, snapd_app, G_TYPE_OBJECT) /** * snapd_app_get_name: * @app: a #SnapdApp. * * Get the name of this app. * * Returns: a name. * * Since: 1.0 */ const gchar *snapd_app_get_name(SnapdApp *self) { g_return_val_if_fail(SNAPD_IS_APP(self), NULL); return self->name; } /** * snapd_app_get_active: * @app: a #SnapdApp. * * Get if this service is active. * * Returns: %TRUE if active. * * Since: 1.25 */ gboolean snapd_app_get_active(SnapdApp *self) { g_return_val_if_fail(SNAPD_IS_APP(self), FALSE); return self->active; } /** * snapd_app_get_aliases: * @app: a #SnapdApp. * * Get the aliases for this app. * * Returns: (transfer none) (array zero-terminated=1): the alias names. * * Since: 1.7 * Deprecated: 1.25 */ GStrv snapd_app_get_aliases(SnapdApp *self) { g_return_val_if_fail(SNAPD_IS_APP(self), NULL); return NULL; } /** * snapd_app_get_common_id: * @app: a #SnapdApp. * * Get the common ID associated with this app. * * Returns: (allow-none): an ID or %NULL. * * Since: 1.41 */ const gchar *snapd_app_get_common_id(SnapdApp *self) { g_return_val_if_fail(SNAPD_IS_APP(self), NULL); return self->common_id; } /** * snapd_app_get_daemon_type: * @app: a #SnapdApp. * * Get the daemon type for this app. * * Returns: (allow-none): the daemon type or %NULL. * * Since: 1.9 */ SnapdDaemonType snapd_app_get_daemon_type(SnapdApp *self) { g_return_val_if_fail(SNAPD_IS_APP(self), SNAPD_DAEMON_TYPE_NONE); return self->daemon_type; } /** * snapd_app_get_desktop_file: * @app: a #SnapdApp. * * Get the path to the desktop file for this app. * * Returns: (allow-none): a path or %NULL. * * Since: 1.14 */ const gchar *snapd_app_get_desktop_file(SnapdApp *self) { g_return_val_if_fail(SNAPD_IS_APP(self), NULL); return self->desktop_file; } /** * snapd_app_get_enabled: * @app: a #SnapdApp. * * Get if this service is enabled. * * Returns: %TRUE if enabled. * * Since: 1.25 */ gboolean snapd_app_get_enabled(SnapdApp *self) { g_return_val_if_fail(SNAPD_IS_APP(self), FALSE); return self->enabled; } /** * snapd_app_get_snap: * @app: a #SnapdApp. * * Get the snap this app is associated with. * * Returns: a snap name. * * Since: 1.25 */ const gchar *snapd_app_get_snap(SnapdApp *self) { g_return_val_if_fail(SNAPD_IS_APP(self), NULL); return self->snap; } static void snapd_app_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdApp *self = SNAPD_APP(object); switch (prop_id) { case PROP_NAME: g_free(self->name); self->name = g_strdup(g_value_get_string(value)); break; case PROP_ALIASES: break; case PROP_COMMON_ID: g_free(self->common_id); self->common_id = g_strdup(g_value_get_string(value)); break; case PROP_DAEMON_TYPE: self->daemon_type = g_value_get_enum(value); break; case PROP_DESKTOP_FILE: g_free(self->desktop_file); self->desktop_file = g_strdup(g_value_get_string(value)); break; case PROP_SNAP: g_free(self->snap); self->snap = g_strdup(g_value_get_string(value)); break; case PROP_ACTIVE: self->active = g_value_get_boolean(value); break; case PROP_ENABLED: self->enabled = g_value_get_boolean(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_app_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdApp *self = SNAPD_APP(object); switch (prop_id) { case PROP_NAME: g_value_set_string(value, self->name); break; case PROP_ALIASES: g_value_set_boxed(value, NULL); break; case PROP_COMMON_ID: g_value_set_string(value, self->common_id); break; case PROP_DAEMON_TYPE: g_value_set_enum(value, self->daemon_type); break; case PROP_DESKTOP_FILE: g_value_set_string(value, self->desktop_file); break; case PROP_SNAP: g_value_set_string(value, self->snap); break; case PROP_ACTIVE: g_value_set_boolean(value, self->active); break; case PROP_ENABLED: g_value_set_boolean(value, self->enabled); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_app_finalize(GObject *object) { SnapdApp *self = SNAPD_APP(object); g_clear_pointer(&self->name, g_free); g_clear_pointer(&self->common_id, g_free); g_clear_pointer(&self->desktop_file, g_free); g_clear_pointer(&self->snap, g_free); G_OBJECT_CLASS(snapd_app_parent_class)->finalize(object); } static void snapd_app_class_init(SnapdAppClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_app_set_property; gobject_class->get_property = snapd_app_get_property; gobject_class->finalize = snapd_app_finalize; g_object_class_install_property( gobject_class, PROP_NAME, g_param_spec_string("name", "name", "App name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_ALIASES, g_param_spec_boxed("aliases", "aliases", "App aliases", G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_COMMON_ID, g_param_spec_string("common-id", "common-id", "Common ID", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_DAEMON_TYPE, g_param_spec_enum("daemon-type", "daemon-type", "Daemon type", SNAPD_TYPE_DAEMON_TYPE, SNAPD_DAEMON_TYPE_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_DESKTOP_FILE, g_param_spec_string( "desktop-file", "desktop-file", "App desktop file path", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SNAP, g_param_spec_string("snap", "snap", "Snap name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_ACTIVE, g_param_spec_boolean("active", "active", "TRUE if active", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_ENABLED, g_param_spec_boolean("enabled", "enabled", "TRUE if enabled", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_app_init(SnapdApp *self) {} snapd-glib-1.67/snapd-glib/snapd-app.h000066400000000000000000000033501477073115000175510ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_APP_H__ #define __SNAPD_APP_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_APP (snapd_app_get_type()) G_DECLARE_FINAL_TYPE(SnapdApp, snapd_app, SNAPD, APP, GObject) /** * SnapdDaemonType: * @SNAPD_DAEMON_TYPE_NONE: Not a daemon * @SNAPD_DAEMON_TYPE_UNKNOWN: Unknown daemon type * @SNAPD_DAEMON_TYPE_SIMPLE: Simple daemon * @SNAPD_DAEMON_TYPE_FORKING: Forking daemon * @SNAPD_DAEMON_TYPE_ONESHOT: One-shot daemon * @SNAPD_DAEMON_TYPE_DBUS: D-Bus daemon * @SNAPD_DAEMON_TYPE_NOTIFY: Notify daemon * * Type of daemon. * * Since: 1.9 */ typedef enum { SNAPD_DAEMON_TYPE_NONE, SNAPD_DAEMON_TYPE_UNKNOWN, SNAPD_DAEMON_TYPE_SIMPLE, SNAPD_DAEMON_TYPE_FORKING, SNAPD_DAEMON_TYPE_ONESHOT, SNAPD_DAEMON_TYPE_DBUS, SNAPD_DAEMON_TYPE_NOTIFY } SnapdDaemonType; const gchar *snapd_app_get_name(SnapdApp *app); gboolean snapd_app_get_active(SnapdApp *app); GStrv snapd_app_get_aliases(SnapdApp *app) G_DEPRECATED; const gchar *snapd_app_get_common_id(SnapdApp *app); SnapdDaemonType snapd_app_get_daemon_type(SnapdApp *app); const gchar *snapd_app_get_desktop_file(SnapdApp *app); gboolean snapd_app_get_enabled(SnapdApp *app); const gchar *snapd_app_get_snap(SnapdApp *app); G_END_DECLS #endif /* __SNAPD_APP_H__ */ snapd-glib-1.67/snapd-glib/snapd-assertion.c000066400000000000000000000177271477073115000210100ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include #include #include "snapd-assertion.h" /** * SECTION: snapd-assertion * @short_description: Assertions * @include: snapd-glib/snapd-glib.h * * A #SnapdAssertion represents an digitally signed documents that express a * fact or policy by a particular authority about a particular object in the * snap universe. Assertions can be queried using * snapd_client_get_assertions_sync(). New assertions can be provided using * snapd_client_add_assertions_sync(). */ /** * SnapdAssertion: * * #SnapdAssertion contains information about a Snap assertion. * * Assertions are digitally signed documents that allow Snaps to have secure * trust and control features. * * Since: 1.0 */ struct _SnapdAssertion { GObject parent_instance; gchar *content; }; enum { PROP_CONTENT = 1, PROP_LAST }; G_DEFINE_TYPE(SnapdAssertion, snapd_assertion, G_TYPE_OBJECT) /** * snapd_assertion_new: * @content: the text content of the assertion. * * Create a new assertion. * * Returns: a new #SnapdAssertion * * Since: 1.0 **/ SnapdAssertion *snapd_assertion_new(const gchar *content) { SnapdAssertion *self = g_object_new(SNAPD_TYPE_ASSERTION, NULL); self->content = g_strdup(content); return self; } static gboolean get_header(const gchar *content, gsize *offset, gsize *name_start, gsize *name_length, gsize *value_start, gsize *value_length) { /* Name separated from value by colon */ if (name_start != NULL) *name_start = *offset; while (content[*offset] && content[*offset] != ':' && content[*offset] != '\n') (*offset)++; if (content[*offset] == '\0' || content[*offset] != ':') return FALSE; if (name_start != NULL && name_length != NULL) *name_length = *offset - *name_start; (*offset)++; /* Value terminated by newline */ while (content[*offset] && content[*offset] != '\n' && isspace(content[*offset])) (*offset)++; if (value_start != NULL) *value_start = *offset; while (content[*offset] && content[*offset] != '\n') (*offset)++; if (content[*offset] == '\0' || content[*offset] != '\n') return FALSE; (*offset)++; /* Value continued by lines starting with spaces */ while (content[*offset] && content[*offset] == ' ') { while (content[*offset]) { if (content[*offset] == '\n') { (*offset)++; break; } (*offset)++; } } if (value_start != NULL && value_length != NULL) *value_length = *offset - *value_start - 1; return TRUE; } /** * snapd_assertion_get_headers: * @assertion: a #SnapdAssertion. * * Get the headers provided by this assertion. * * Returns: (transfer full) (array zero-terminated=1): array of header names. * * Since: 1.0 */ GStrv snapd_assertion_get_headers(SnapdAssertion *self) { g_return_val_if_fail(SNAPD_IS_ASSERTION(self), NULL); gsize offset = 0; g_autoptr(GPtrArray) headers = g_ptr_array_new(); while (TRUE) { /* Headers terminated by double newline or EOF */ gsize name_start, name_length; if (self->content[offset] == '\0' || self->content[offset] == '\n' || !get_header(self->content, &offset, &name_start, &name_length, NULL, NULL)) break; g_ptr_array_add(headers, g_strndup(self->content + name_start, name_length)); } g_ptr_array_add(headers, NULL); return g_steal_pointer((GStrv *)&headers->pdata); } /** * snapd_assertion_get_header: * @assertion: a #SnapdAssertion. * @name: name of the header. * * Get a header from an assertion. * * Returns: (transfer full) (allow-none): header value or %NULL if undefined. * * Since: 1.0 */ gchar *snapd_assertion_get_header(SnapdAssertion *self, const gchar *name) { g_return_val_if_fail(SNAPD_IS_ASSERTION(self), NULL); g_return_val_if_fail(name != NULL, NULL); gsize offset = 0; while (TRUE) { /* Headers terminated by double newline or EOF */ if (self->content[offset] == '\0' || self->content[offset] == '\n') return NULL; gsize name_start, name_length, value_start, value_length; if (!get_header(self->content, &offset, &name_start, &name_length, &value_start, &value_length)) return NULL; /* Return value if header we're looking for */ if (strncmp(self->content + name_start, name, name_length) == 0) return g_strndup(self->content + value_start, value_length); } return NULL; } static gsize get_headers_length(SnapdAssertion *self) { /* Headers terminated by double newline */ gchar *divider = strstr(self->content, "\n\n"); if (divider == NULL) return 0; return divider - self->content; } static gsize get_body_length(SnapdAssertion *self) { g_autofree gchar *body_length_header = snapd_assertion_get_header(self, "body-length"); if (body_length_header == NULL) return 0; return strtoul(body_length_header, NULL, 10); } /** * snapd_assertion_get_body: * @assertion: a #SnapdAssertion. * * Get the body of the assertion. * * Returns: (transfer full) (allow-none): assertion body or %NULL. * * Since: 1.0 */ gchar *snapd_assertion_get_body(SnapdAssertion *self) { g_return_val_if_fail(SNAPD_IS_ASSERTION(self), NULL); gsize body_length = get_body_length(self); if (body_length == 0) return NULL; return g_strndup(self->content + get_headers_length(self) + 2, body_length); } /** * snapd_assertion_get_signature: * @assertion: a #SnapdAssertion. * * Get the signature of the assertion. * * Returns: assertion signature. * * Since: 1.0 */ gchar *snapd_assertion_get_signature(SnapdAssertion *self) { g_return_val_if_fail(SNAPD_IS_ASSERTION(self), NULL); gsize body_length = get_body_length(self); if (body_length > 0) return g_strdup(self->content + get_headers_length(self) + 2 + body_length + 2); else return g_strdup(self->content + get_headers_length(self) + 2); } static void snapd_assertion_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdAssertion *self = SNAPD_ASSERTION(object); switch (prop_id) { case PROP_CONTENT: g_free(self->content); self->content = g_strdup(g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_assertion_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdAssertion *self = SNAPD_ASSERTION(object); switch (prop_id) { case PROP_CONTENT: g_value_set_string(value, self->content); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_assertion_finalize(GObject *object) { SnapdAssertion *self = SNAPD_ASSERTION(object); g_clear_pointer(&self->content, g_free); G_OBJECT_CLASS(snapd_assertion_parent_class)->finalize(object); } static void snapd_assertion_class_init(SnapdAssertionClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_assertion_set_property; gobject_class->get_property = snapd_assertion_get_property; gobject_class->finalize = snapd_assertion_finalize; g_object_class_install_property( gobject_class, PROP_CONTENT, g_param_spec_string("content", "content", "Assertion content", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_assertion_init(SnapdAssertion *self) {} snapd-glib-1.67/snapd-glib/snapd-assertion.h000066400000000000000000000021351477073115000210000ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_ASSERTION_H__ #define __SNAPD_ASSERTION_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_ASSERTION (snapd_assertion_get_type()) G_DECLARE_FINAL_TYPE(SnapdAssertion, snapd_assertion, SNAPD, ASSERTION, GObject) SnapdAssertion *snapd_assertion_new(const gchar *content); GStrv snapd_assertion_get_headers(SnapdAssertion *assertion); gchar *snapd_assertion_get_header(SnapdAssertion *assertion, const gchar *name); gchar *snapd_assertion_get_body(SnapdAssertion *assertion); gchar *snapd_assertion_get_signature(SnapdAssertion *assertion); G_END_DECLS #endif /* __SNAPD_ASSERTION_H__ */ snapd-glib-1.67/snapd-glib/snapd-auth-data.c000066400000000000000000000116661477073115000206450ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-auth-data.h" /** * SECTION: snapd-auth-data * @short_description: Authorization data * @include: snapd-glib/snapd-glib.h * * A #SnapdAuthData contains authorization data to communicate with snapd. * Authenticating with snapd_login_sync() or snapd_client_login_sync() returns * authorization data that can be used for requests by calling * snapd_client_set_auth_data(). * * It is recommended that the data is securely stored between sessions so * authentication is not required to be repeated. The authorization data is * made up of printable strings that can be easily written to a file/database. */ /** * SnapdAuthData: * * #SnapdAuthData contains authorization data used to communicate with snapd. * * The authorization data is in the form of a * [Macaroon](https://research.google.com/pubs/pub41892.html). * * Since: 1.0 */ struct _SnapdAuthData { GObject parent_instance; gchar *macaroon; GStrv discharges; }; enum { PROP_MACAROON = 1, PROP_DISCHARGES, PROP_LAST }; G_DEFINE_TYPE(SnapdAuthData, snapd_auth_data, G_TYPE_OBJECT) /** * snapd_auth_data_new: * @macaroon: serialized macaroon used to authorize access to snapd. * @discharges: (array zero-terminated=1): serialized discharges. * * Create some authorization data. * * Returns: a new #SnapdAuthData * * Since: 1.0 **/ SnapdAuthData *snapd_auth_data_new(const gchar *macaroon, GStrv discharges) { g_return_val_if_fail(macaroon != NULL, NULL); return g_object_new(SNAPD_TYPE_AUTH_DATA, "macaroon", macaroon, "discharges", discharges, NULL); } /** * snapd_auth_data_get_macaroon: * @auth_data: a #SnapdAuthData. * * Get the Macaroon that this authorization uses. * * Returns: the serialized Macaroon used to authorize access to snapd. * * Since: 1.0 */ const gchar *snapd_auth_data_get_macaroon(SnapdAuthData *self) { g_return_val_if_fail(SNAPD_IS_AUTH_DATA(self), NULL); return self->macaroon; } /** * snapd_auth_data_get_discharges: * @auth_data: a #SnapdAuthData. * * Get the discharges that this authorization uses. * * Returns: (transfer none) (array zero-terminated=1): the discharges as * serialized strings. * * Since: 1.0 */ GStrv snapd_auth_data_get_discharges(SnapdAuthData *self) { g_return_val_if_fail(SNAPD_IS_AUTH_DATA(self), NULL); return self->discharges; } static void snapd_auth_data_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdAuthData *self = SNAPD_AUTH_DATA(object); switch (prop_id) { case PROP_MACAROON: g_free(self->macaroon); self->macaroon = g_strdup(g_value_get_string(value)); break; case PROP_DISCHARGES: g_strfreev(self->discharges); self->discharges = g_strdupv(g_value_get_boxed(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_auth_data_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdAuthData *self = SNAPD_AUTH_DATA(object); switch (prop_id) { case PROP_MACAROON: g_value_set_string(value, self->macaroon); break; case PROP_DISCHARGES: g_value_set_boxed(value, self->discharges); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_auth_data_finalize(GObject *object) { SnapdAuthData *self = SNAPD_AUTH_DATA(object); g_clear_pointer(&self->macaroon, g_free); g_clear_pointer(&self->discharges, g_strfreev); G_OBJECT_CLASS(snapd_auth_data_parent_class)->finalize(object); } static void snapd_auth_data_class_init(SnapdAuthDataClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_auth_data_set_property; gobject_class->get_property = snapd_auth_data_get_property; gobject_class->finalize = snapd_auth_data_finalize; g_object_class_install_property( gobject_class, PROP_MACAROON, g_param_spec_string("macaroon", "macaroon", "Serialized macaroon", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_DISCHARGES, g_param_spec_boxed("discharges", "discharges", "Serialized discharges", G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_auth_data_init(SnapdAuthData *self) {} snapd-glib-1.67/snapd-glib/snapd-auth-data.h000066400000000000000000000017451477073115000206470ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_AUTH_DATA_H__ #define __SNAPD_AUTH_DATA_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_AUTH_DATA (snapd_auth_data_get_type()) G_DECLARE_FINAL_TYPE(SnapdAuthData, snapd_auth_data, SNAPD, AUTH_DATA, GObject) SnapdAuthData *snapd_auth_data_new(const gchar *macaroon, GStrv discharges); const gchar *snapd_auth_data_get_macaroon(SnapdAuthData *auth_data); GStrv snapd_auth_data_get_discharges(SnapdAuthData *auth_data); G_END_DECLS #endif /* __SNAPD_AUTH_DATA_H__ */ snapd-glib-1.67/snapd-glib/snapd-autorefresh-change-data.c000066400000000000000000000126241477073115000234510ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-autorefresh-change-data.h" /** * SECTION: snapd-autorefresh-change-data * @short_description: Custom data from a #SnapdChange of kind 'autorefresh' * @include: snapd-glib/snapd-glib.h * * A #SnapdAutorefreshChangeData contains the data from the 'data' field of a * #SnapdChange of kind 'auto-refresh'. */ /** * SnapdAutorefreshChangeData: * * #SnapdAutoRefreshChangeData contains the data from the 'data' field of a * #SnapdChange of kind 'auto-refresh'. * * Since: 1.65 */ struct _SnapdAutorefreshChangeData { SnapdChangeData parent_instance; GStrv snap_names; GStrv refresh_forced; }; G_DEFINE_TYPE(SnapdAutorefreshChangeData, snapd_autorefresh_change_data, SNAPD_TYPE_CHANGE_DATA) /** * SnapdAutorefreshChangeData:snap-names * * Contains the list of snaps that have a pending update but are inhibited * because they have a running program. * * Since: 1.65 */ /** * SnapdAutorefreshChangeData:refresh-forced * * Contains the list of snaps that were inhibited for too long, and * now are having a forced refresh. * * Since: 1.65 */ enum { PROP_SNAP_NAMES = 1, PROP_REFRESH_FORCED, N_PROPERTIES }; /** * snapd_autorefresh_change_data_get_snap_names: * @change_data: a #SnapdAutorefreshChangeData * * Returns the list of snaps that have a pending update but are inhibited * because they have a running program. * * return: (transfer none): a GStrv with the snap names, or NULL if the property * wasn't defined * * Since: 1.65 */ GStrv snapd_autorefresh_change_data_get_snap_names( SnapdAutorefreshChangeData *self) { g_return_val_if_fail(SNAPD_IS_AUTOREFRESH_CHANGE_DATA(self), NULL); return self->snap_names; } /** * snapd_autorefresh_change_data_get_refresh_forced: * @change_data: a #SnapdAutorefreshChangeData * * Returns the list of snaps that were inhibited for too long, and * now are having a forced refresh. * * return: (transfer none): a GStrv with the snap names, or NULL if the property * wasn't defined * * Since: 1.65 */ GStrv snapd_autorefresh_change_data_get_refresh_forced( SnapdAutorefreshChangeData *self) { g_return_val_if_fail(SNAPD_IS_AUTOREFRESH_CHANGE_DATA(self), NULL); return self->refresh_forced; } static void snapd_autorefresh_change_data_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdAutorefreshChangeData *self = SNAPD_AUTOREFRESH_CHANGE_DATA(object); switch (prop_id) { case PROP_SNAP_NAMES: g_strfreev(self->snap_names); self->snap_names = g_strdupv(g_value_get_boxed(value)); break; case PROP_REFRESH_FORCED: g_strfreev(self->refresh_forced); self->refresh_forced = g_strdupv(g_value_get_boxed(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_autorefresh_change_data_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdAutorefreshChangeData *self = SNAPD_AUTOREFRESH_CHANGE_DATA(object); switch (prop_id) { case PROP_SNAP_NAMES: g_value_set_boxed(value, self->snap_names); break; case PROP_REFRESH_FORCED: g_value_set_boxed(value, self->refresh_forced); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_autorefresh_change_data_finalize(GObject *object) { SnapdAutorefreshChangeData *self = SNAPD_AUTOREFRESH_CHANGE_DATA(object); g_clear_pointer(&self->snap_names, g_strfreev); g_clear_pointer(&self->refresh_forced, g_strfreev); G_OBJECT_CLASS(snapd_autorefresh_change_data_parent_class)->finalize(object); } static void snapd_autorefresh_change_data_class_init( SnapdAutorefreshChangeDataClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_autorefresh_change_data_set_property; gobject_class->get_property = snapd_autorefresh_change_data_get_property; gobject_class->finalize = snapd_autorefresh_change_data_finalize; g_object_class_install_property( gobject_class, PROP_SNAP_NAMES, g_param_spec_boxed( "snap-names", "Snap Names", "Names of the snaps that have been autorefreshed.", G_TYPE_STRV, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_REFRESH_FORCED, g_param_spec_boxed( "refresh-forced", "Refresh forced", "Names of the snaps that have been forced to autorefresh.", G_TYPE_STRV, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_autorefresh_change_data_init(SnapdAutorefreshChangeData *self) {} snapd-glib-1.67/snapd-glib/snapd-autorefresh-change-data.h000066400000000000000000000020371477073115000234530ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_AUTOREFRESH_CHANGE_DATA_H__ #define __SNAPD_AUTOREFRESH_CHANGE_DATA_H__ #include "snapd-change-data.h" #include G_BEGIN_DECLS #define SNAPD_TYPE_AUTOREFRESH_CHANGE_DATA \ (snapd_autorefresh_change_data_get_type()) G_DECLARE_FINAL_TYPE(SnapdAutorefreshChangeData, snapd_autorefresh_change_data, SNAPD, AUTOREFRESH_CHANGE_DATA, SnapdChangeData) GStrv snapd_autorefresh_change_data_get_snap_names( SnapdAutorefreshChangeData *change_data); GStrv snapd_autorefresh_change_data_get_refresh_forced( SnapdAutorefreshChangeData *change_data); G_END_DECLS #endif /* __SNAPD_AUTOREFRESH_CHANGE_DATA_H__ */ snapd-glib-1.67/snapd-glib/snapd-category-details.c000066400000000000000000000063631477073115000222330ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-category-details.h" /** * SECTION:snapd-category-details * @short_description: Snap category details metadata * @include: snapd-glib/snapd-glib.h * * A #SnapdCategoryDetails contains the metadata for a given snap category as * returned using snapd_client_get_categories_sync(). */ /** * SnapdCategoryDetails: * * #SnapdCategoryDetails is an opaque data structure and can only be accessed * using the provided functions. * * Since: 1.64 */ struct _SnapdCategoryDetails { GObject parent_instance; gchar *name; }; enum { PROP_NAME = 1, PROP_LAST }; G_DEFINE_TYPE(SnapdCategoryDetails, snapd_category_details, G_TYPE_OBJECT) /** * snapd_category_details_get_name: * @category_details: a #SnapdCategoryDetails. * * Get the name of this category, e.g. "social". * * Returns: a name. * * Since: 1.64 */ const gchar *snapd_category_details_get_name(SnapdCategoryDetails *self) { g_return_val_if_fail(SNAPD_IS_CATEGORY_DETAILS(self), NULL); return self->name; } static void snapd_category_details_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdCategoryDetails *self = SNAPD_CATEGORY_DETAILS(object); switch (prop_id) { case PROP_NAME: g_free(self->name); self->name = g_strdup(g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_category_details_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdCategoryDetails *self = SNAPD_CATEGORY_DETAILS(object); switch (prop_id) { case PROP_NAME: g_value_set_string(value, self->name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_category_details_finalize(GObject *object) { SnapdCategoryDetails *self = SNAPD_CATEGORY_DETAILS(object); g_clear_pointer(&self->name, g_free); G_OBJECT_CLASS(snapd_category_details_parent_class)->finalize(object); } static void snapd_category_details_class_init(SnapdCategoryDetailsClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_category_details_set_property; gobject_class->get_property = snapd_category_details_get_property; gobject_class->finalize = snapd_category_details_finalize; g_object_class_install_property( gobject_class, PROP_NAME, g_param_spec_string("name", "name", "The category name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_category_details_init(SnapdCategoryDetails *self) {} snapd-glib-1.67/snapd-glib/snapd-category-details.h000066400000000000000000000016651477073115000222400ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_CATEGORY_DETAILS_H__ #define __SNAPD_CATEGORY_DETAILS_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_CATEGORY_DETAILS (snapd_category_details_get_type()) G_DECLARE_FINAL_TYPE(SnapdCategoryDetails, snapd_category_details, SNAPD, CATEGORY_DETAILS, GObject) const gchar * snapd_category_details_get_name(SnapdCategoryDetails *category_details); G_END_DECLS #endif /* __SNAPD_CATEGORY_DETAILS_H__ */ snapd-glib-1.67/snapd-glib/snapd-category.c000066400000000000000000000074561477073115000206140ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-category.h" #include "snapd-enum-types.h" /** * SECTION:snapd-category * @short_description: Snap category metadata * @include: snapd-glib/snapd-glib.h * * A #SnapdCategory contains the metadata for a category membership as returned * using snapd_snap_get_categories(). */ /** * SnapdCategory: * * #SnapdCategory is an opaque data structure and can only be accessed * using the provided functions. * * Since: 1.64 */ struct _SnapdCategory { GObject parent_instance; gboolean featured; gchar *name; }; enum { PROP_FEATURED = 1, PROP_NAME, PROP_LAST }; G_DEFINE_TYPE(SnapdCategory, snapd_category, G_TYPE_OBJECT) /** * snapd_category_get_featured: * @category: a #SnapdCategory. * * Get if this snap is featured in this category. * * Returns: %TRUE if this snap is featured in this category. * * Since: 1.64 */ gboolean snapd_category_get_featured(SnapdCategory *self) { g_return_val_if_fail(SNAPD_IS_CATEGORY(self), FALSE); return self->featured; } /** * snapd_category_get_name: * @category: a #SnapdCategory. * * Get the name of this category, e.g. "social". * * Returns: a name. * * Since: 1.64 */ const gchar *snapd_category_get_name(SnapdCategory *self) { g_return_val_if_fail(SNAPD_IS_CATEGORY(self), NULL); return self->name; } static void snapd_category_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdCategory *self = SNAPD_CATEGORY(object); switch (prop_id) { case PROP_FEATURED: self->featured = g_value_get_boolean(value); break; case PROP_NAME: g_free(self->name); self->name = g_strdup(g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_category_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdCategory *self = SNAPD_CATEGORY(object); switch (prop_id) { case PROP_FEATURED: g_value_set_boolean(value, self->featured); break; case PROP_NAME: g_value_set_string(value, self->name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_category_finalize(GObject *object) { SnapdCategory *self = SNAPD_CATEGORY(object); g_clear_pointer(&self->name, g_free); G_OBJECT_CLASS(snapd_category_parent_class)->finalize(object); } static void snapd_category_class_init(SnapdCategoryClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_category_set_property; gobject_class->get_property = snapd_category_get_property; gobject_class->finalize = snapd_category_finalize; g_object_class_install_property( gobject_class, PROP_FEATURED, g_param_spec_boolean( "featured", "featured", "TRUE if this category is featured", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_NAME, g_param_spec_string("name", "name", "The category name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_category_init(SnapdCategory *self) {} snapd-glib-1.67/snapd-glib/snapd-category.h000066400000000000000000000016111477073115000206040ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_CATEGORY_H__ #define __SNAPD_CATEGORY_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_CATEGORY (snapd_category_get_type()) G_DECLARE_FINAL_TYPE(SnapdCategory, snapd_category, SNAPD, CATEGORY, GObject) gboolean snapd_category_get_featured(SnapdCategory *category); const gchar *snapd_category_get_name(SnapdCategory *category); G_END_DECLS #endif /* __SNAPD_CATEGORY_H__ */ snapd-glib-1.67/snapd-glib/snapd-change-data.c000066400000000000000000000020561477073115000211220ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-change-data.h" /** * SECTION: snapd-change-data * @short_description: Base class for custom data from a change * @include: snapd-glib/snapd-glib.h * * A #SnapdChangeData is the base class for the `data` field from * a #SnapdChange. Each kind of #SnapdChange will return a different * subclass of this one with the specific data of that kind of change. */ /** * SnapdChangeData: * * A #SnapdChangeData is the base class for the `data` field from * a #SnapdChange. * * Since: 1.65 */ G_DEFINE_TYPE(SnapdChangeData, snapd_change_data, G_TYPE_OBJECT) static void snapd_change_data_class_init(SnapdChangeDataClass *klass) {} static void snapd_change_data_init(SnapdChangeData *self) {} snapd-glib-1.67/snapd-glib/snapd-change-data.h000066400000000000000000000013551477073115000211300ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_CHANGE_DATA_H__ #define __SNAPD_CHANGE_DATA_H__ #include G_BEGIN_DECLS #define SNAPD_TYPE_CHANGE_DATA snapd_change_data_get_type() G_DECLARE_DERIVABLE_TYPE(SnapdChangeData, snapd_change_data, SNAPD, CHANGE_DATA, GObject) struct _SnapdChangeDataClass { GObjectClass parent_class; }; G_END_DECLS #endif /* __SNAPD_CHANGE_DATA_H__ */ snapd-glib-1.67/snapd-glib/snapd-change.c000066400000000000000000000264271477073115000202230ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-change.h" /** * SECTION: snapd-change * @short_description: Change progress * @include: snapd-glib/snapd-glib.h * * A #SnapdChange contains information on how a request is progressing. Progress * information is returned in a #SnapdProgressCallback. */ /** * SnapdChange: * * #SnapdChange contains information on a current Snap transaction. * * Since: 1.5 */ struct _SnapdChange { GObject parent_instance; gchar *id; gchar *kind; gchar *summary; gchar *status; GPtrArray *tasks; gboolean ready; GDateTime *spawn_time; GDateTime *ready_time; gchar *error; SnapdChangeData *data; }; enum { PROP_ID = 1, PROP_KIND, PROP_SUMMARY, PROP_STATUS, PROP_TASKS, PROP_READY, PROP_SPAWN_TIME, PROP_READY_TIME, PROP_ERROR, PROP_DATA, PROP_LAST }; G_DEFINE_TYPE(SnapdChange, snapd_change, G_TYPE_OBJECT) /** * snapd_change_get_id: * @change: a #SnapdChange. * * Get the unique ID for this change. * * Returns: an ID. * * Since: 1.5 */ const gchar *snapd_change_get_id(SnapdChange *self) { g_return_val_if_fail(SNAPD_IS_CHANGE(self), NULL); return self->id; } /** * snapd_change_get_kind: * @change: a #SnapdChange. * * Gets the kind of change this is. * * Returns: the kind of change. * * Since: 1.5 */ const gchar *snapd_change_get_kind(SnapdChange *self) { g_return_val_if_fail(SNAPD_IS_CHANGE(self), NULL); return self->kind; } /** * snapd_change_get_summary: * @change: a #SnapdChange. * * Get a human readable description of the change. * * Returns: a string describing the change. * * Since: 1.5 */ const gchar *snapd_change_get_summary(SnapdChange *self) { g_return_val_if_fail(SNAPD_IS_CHANGE(self), NULL); return self->summary; } /** * snapd_change_get_status: * @change: a #SnapdChange. * * Get the status of the change. * * Returns: a status string. * * Since: 1.5 */ const gchar *snapd_change_get_status(SnapdChange *self) { g_return_val_if_fail(SNAPD_IS_CHANGE(self), NULL); return self->status; } /** * snapd_change_get_tasks: * @change: a #SnapdChange. * * Get the tasks that are in this change. * * Returns: (transfer none) (element-type SnapdTask): an array of #SnapdTask. * * Since: 1.5 */ GPtrArray *snapd_change_get_tasks(SnapdChange *self) { g_return_val_if_fail(SNAPD_IS_CHANGE(self), NULL); return self->tasks; } /** * snapd_change_get_data: * @change: a #SnapdChange. * * Get the data field for this change. * * Returns: (transfer none): a #SnapdChangeData object with all the data, or * NULL if the field isn't defined * * Since: 1.65 */ SnapdChangeData *snapd_change_get_data(SnapdChange *self) { g_return_val_if_fail(SNAPD_IS_CHANGE(self), NULL); return self->data; } /** * snapd_change_get_ready: * @change: a #SnapdChange. * * Get if this change is completed. * * Returns: %TRUE if this change is complete. * * Since: 1.5 */ gboolean snapd_change_get_ready(SnapdChange *self) { g_return_val_if_fail(SNAPD_IS_CHANGE(self), FALSE); return self->ready; } /** * snapd_change_get_spawn_time: * @change: a #SnapdChange. * * Get the time this change started. * * Returns: (transfer none): a #GDateTime. * * Since: 1.5 */ GDateTime *snapd_change_get_spawn_time(SnapdChange *self) { g_return_val_if_fail(SNAPD_IS_CHANGE(self), NULL); return self->spawn_time; } /** * snapd_change_get_ready_time: * @change: a #SnapdChange. * * Get the time this task completed or %NULL if not yet completed. * * Returns: (transfer none) (allow-none): a #GDateTime or %NULL. * * Since: 1.5 */ GDateTime *snapd_change_get_ready_time(SnapdChange *self) { g_return_val_if_fail(SNAPD_IS_CHANGE(self), NULL); return self->ready_time; } /** * snapd_change_get_error: * @change: a #SnapdChange. * * Gets the error string associated with this change. * * Returns: (allow-none): an error string or %NULL. * * Since: 1.30 */ const gchar *snapd_change_get_error(SnapdChange *self) { g_return_val_if_fail(SNAPD_IS_CHANGE(self), NULL); return self->error; } static void snapd_change_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdChange *self = SNAPD_CHANGE(object); switch (prop_id) { case PROP_ID: g_free(self->id); self->id = g_strdup(g_value_get_string(value)); break; case PROP_KIND: g_free(self->kind); self->kind = g_strdup(g_value_get_string(value)); break; case PROP_SUMMARY: g_free(self->summary); self->summary = g_strdup(g_value_get_string(value)); break; case PROP_STATUS: g_free(self->status); self->status = g_strdup(g_value_get_string(value)); break; case PROP_TASKS: g_clear_pointer(&self->tasks, g_ptr_array_unref); if (g_value_get_boxed(value) != NULL) self->tasks = g_ptr_array_ref(g_value_get_boxed(value)); break; case PROP_DATA: g_clear_pointer(&self->data, g_object_unref); if (g_value_get_object(value) != NULL) self->data = g_object_ref(g_value_get_object(value)); break; case PROP_READY: self->ready = g_value_get_boolean(value); break; case PROP_SPAWN_TIME: g_clear_pointer(&self->spawn_time, g_date_time_unref); if (g_value_get_boxed(value) != NULL) self->spawn_time = g_date_time_ref(g_value_get_boxed(value)); break; case PROP_READY_TIME: g_clear_pointer(&self->ready_time, g_date_time_unref); if (g_value_get_boxed(value) != NULL) self->ready_time = g_date_time_ref(g_value_get_boxed(value)); break; case PROP_ERROR: g_free(self->error); self->error = g_strdup(g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_change_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdChange *self = SNAPD_CHANGE(object); switch (prop_id) { case PROP_ID: g_value_set_string(value, self->id); break; case PROP_KIND: g_value_set_string(value, self->kind); break; case PROP_SUMMARY: g_value_set_string(value, self->summary); break; case PROP_STATUS: g_value_set_string(value, self->status); break; case PROP_TASKS: g_value_set_boxed(value, self->tasks); break; case PROP_DATA: g_value_set_object(value, self->data); break; case PROP_READY: g_value_set_boolean(value, self->ready); break; case PROP_SPAWN_TIME: g_value_set_boxed(value, self->spawn_time); break; case PROP_READY_TIME: g_value_set_boxed(value, self->ready_time); break; case PROP_ERROR: g_value_set_string(value, self->error); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_change_finalize(GObject *object) { SnapdChange *self = SNAPD_CHANGE(object); g_clear_pointer(&self->id, g_free); g_clear_pointer(&self->kind, g_free); g_clear_pointer(&self->summary, g_free); g_clear_pointer(&self->status, g_free); g_clear_pointer(&self->tasks, g_ptr_array_unref); g_clear_pointer(&self->data, g_object_unref); g_clear_pointer(&self->spawn_time, g_date_time_unref); g_clear_pointer(&self->ready_time, g_date_time_unref); g_clear_pointer(&self->error, g_free); G_OBJECT_CLASS(snapd_change_parent_class)->finalize(object); } static void snapd_change_class_init(SnapdChangeClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_change_set_property; gobject_class->get_property = snapd_change_get_property; gobject_class->finalize = snapd_change_finalize; g_object_class_install_property( gobject_class, PROP_ID, g_param_spec_string("id", "id", "ID of change", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_KIND, g_param_spec_string("kind", "kind", "Kind of change", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SUMMARY, g_param_spec_string("summary", "summary", "Summary of change", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_STATUS, g_param_spec_string("status", "status", "Status of change", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_TASKS, g_param_spec_boxed( "tasks", "tasks", "Tasks in this change", G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_READY, g_param_spec_boolean("ready", "ready", "TRUE when change complete", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SPAWN_TIME, g_param_spec_boxed("spawn-time", "spawn-time", "Time this change started", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_READY_TIME, g_param_spec_boxed("ready-time", "ready-time", "Time this change completed", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_ERROR, g_param_spec_string( "error", "error", "Error associated with change", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_DATA, g_param_spec_object("data", "data", "Data field", SNAPD_TYPE_CHANGE_DATA, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_change_init(SnapdChange *self) {} snapd-glib-1.67/snapd-glib/snapd-change.h000066400000000000000000000026231477073115000202200ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_CHANGE_H__ #define __SNAPD_CHANGE_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include "snapd-autorefresh-change-data.h" #include "snapd-change-data.h" #include G_BEGIN_DECLS #define SNAPD_TYPE_CHANGE (snapd_change_get_type()) G_DECLARE_FINAL_TYPE(SnapdChange, snapd_change, SNAPD, CHANGE, GObject) const gchar *snapd_change_get_id(SnapdChange *change); const gchar *snapd_change_get_kind(SnapdChange *change); const gchar *snapd_change_get_summary(SnapdChange *change); const gchar *snapd_change_get_status(SnapdChange *change); gboolean snapd_change_get_ready(SnapdChange *change); GPtrArray *snapd_change_get_tasks(SnapdChange *change); GDateTime *snapd_change_get_spawn_time(SnapdChange *change); GDateTime *snapd_change_get_ready_time(SnapdChange *change); const gchar *snapd_change_get_error(SnapdChange *change); SnapdChangeData *snapd_change_get_data(SnapdChange *change); G_END_DECLS #endif /* __SNAPD_CHANGE_H__ */ snapd-glib-1.67/snapd-glib/snapd-channel.c000066400000000000000000000263271477073115000204050ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-channel.h" #include "snapd-enum-types.h" /** * SECTION:snapd-channel * @short_description: Snap channel metadata * @include: snapd-glib/snapd-glib.h * * A #SnapdChannel contains the metadata for a given snap channel as returned * using snapd_snap_get_channels(). */ /** * SnapdChannel: * * #SnapdChannel is an opaque data structure and can only be accessed * using the provided functions. * * Since: 1.22 */ struct _SnapdChannel { GObject parent_instance; SnapdConfinement confinement; gchar *branch; gchar *epoch; gchar *name; GDateTime *released_at; gchar *revision; gchar *risk; gint64 size; gchar *track; gchar *version; }; enum { PROP_CONFINEMENT = 1, PROP_EPOCH, PROP_NAME, PROP_REVISION, PROP_SIZE, PROP_VERSION, PROP_RELEASED_AT, PROP_LAST }; G_DEFINE_TYPE(SnapdChannel, snapd_channel, G_TYPE_OBJECT) /** * snapd_channel_get_branch: * @channel: a #SnapdChannel. * * Get the branch this channel is tracking. * * Returns: (allow-none): a branch name or %NULL if not a branch. * * Since: 1.31 */ const gchar *snapd_channel_get_branch(SnapdChannel *self) { g_return_val_if_fail(SNAPD_IS_CHANNEL(self), NULL); return self->branch; } /** * snapd_channel_get_confinement: * @channel: a #SnapdChannel. * * Get the confinement this snap is using, e.g. %SNAPD_CONFINEMENT_STRICT. * * Returns: a #SnapdConfinement. * * Since: 1.22 */ SnapdConfinement snapd_channel_get_confinement(SnapdChannel *self) { g_return_val_if_fail(SNAPD_IS_CHANNEL(self), SNAPD_CONFINEMENT_UNKNOWN); return self->confinement; } /** * snapd_channel_get_epoch: * @channel: a #SnapdChannel. * * Get the epoch used on this channel, e.g. "1". * * Returns: an epoch. * * Since: 1.22 */ const gchar *snapd_channel_get_epoch(SnapdChannel *self) { g_return_val_if_fail(SNAPD_IS_CHANNEL(self), NULL); return self->epoch; } /** * snapd_channel_get_name: * @channel: a #SnapdChannel. * * Get the name of this channel, e.g. "stable". * * Channel names are in the form `track/risk/branch` * * `track` is the name of the feature track. Defaults to `latest` and is implied * if the track is not present. * `risk` is the risk of the channel, one of `stable`, `candidate`, `beta` or * `edge`. `branch` is an optional branch name. * * Example names: * `beta` (alias to `latest/beta`) * `xenial/stable` (stable release on xenial track) * `latest/stable/red-button` (red button feature branch) * * Returns: a name. * * Since: 1.22 */ const gchar *snapd_channel_get_name(SnapdChannel *self) { g_return_val_if_fail(SNAPD_IS_CHANNEL(self), NULL); return self->name; } /** * snapd_channel_get_released_at: * @channel: a #SnapdChannel. * * Get the date this revision was released into the channel or %NULL if unknown. * * Returns: (transfer none) (allow-none): a #GDateTime. * * Since: 1.46 */ GDateTime *snapd_channel_get_released_at(SnapdChannel *self) { g_return_val_if_fail(SNAPD_IS_CHANNEL(self), NULL); return self->released_at; } /** * snapd_channel_get_revision: * @channel: a #SnapdChannel. * * Get the revision for this snap. The format of the string is undefined. * See also snapd_channel_get_version(). * * Returns: a revision string. * * Since: 1.22 */ const gchar *snapd_channel_get_revision(SnapdChannel *self) { g_return_val_if_fail(SNAPD_IS_CHANNEL(self), NULL); return self->revision; } /** * snapd_channel_get_risk: * @channel: a #SnapdChannel. * * Get the risk this channel is on, one of `stable`, `candidate`, `beta` or * `edge`. * * Returns: a risk name. * * Since: 1.31 */ const gchar *snapd_channel_get_risk(SnapdChannel *self) { g_return_val_if_fail(SNAPD_IS_CHANNEL(self), NULL); return self->risk; } /** * snapd_channel_get_size: * @channel: a #SnapdChannel. * * Get the download size of this snap. * * Returns: a byte count. * * Since: 1.22 */ gint64 snapd_channel_get_size(SnapdChannel *self) { g_return_val_if_fail(SNAPD_IS_CHANNEL(self), 0); return self->size; } /** * snapd_channel_get_track: * @channel: a #SnapdChannel. * * Get the track this channel is on. * * Returns: a track name. * * Since: 1.31 */ const gchar *snapd_channel_get_track(SnapdChannel *self) { g_return_val_if_fail(SNAPD_IS_CHANNEL(self), NULL); return self->track; } /** * snapd_channel_get_version: * @channel: a #SnapdChannel. * * Get the version for this snap. The format of the string is undefined. * See also snapd_channel_get_revision(). * * Returns: a version string. * * Since: 1.22 */ const gchar *snapd_channel_get_version(SnapdChannel *self) { g_return_val_if_fail(SNAPD_IS_CHANNEL(self), NULL); return self->version; } static gboolean is_risk(const gchar *risk) { return g_strcmp0(risk, "stable") == 0 || g_strcmp0(risk, "candidate") == 0 || g_strcmp0(risk, "beta") == 0 || g_strcmp0(risk, "edge") == 0; } static void set_name(SnapdChannel *self, const gchar *name) { g_free(self->name); self->name = g_strdup(name); g_clear_pointer(&self->track, g_free); g_clear_pointer(&self->risk, g_free); g_clear_pointer(&self->branch, g_free); g_auto(GStrv) tokens = g_strsplit(name, "/", -1); switch (g_strv_length(tokens)) { case 1: if (is_risk(tokens[0])) { self->track = g_strdup("latest"); self->risk = g_strdup(tokens[0]); } else { self->track = g_strdup(tokens[0]); self->risk = g_strdup("stable"); } break; case 2: if (is_risk(tokens[0])) { self->track = g_strdup("latest"); self->risk = g_strdup(tokens[0]); self->branch = g_strdup(tokens[1]); } else { self->track = g_strdup(tokens[0]); self->risk = g_strdup(tokens[1]); } break; case 3: self->track = g_strdup(tokens[0]); self->risk = g_strdup(tokens[1]); self->branch = g_strdup(tokens[2]); break; default: break; } } static void snapd_channel_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdChannel *self = SNAPD_CHANNEL(object); switch (prop_id) { case PROP_CONFINEMENT: self->confinement = g_value_get_enum(value); break; case PROP_EPOCH: g_free(self->epoch); self->epoch = g_strdup(g_value_get_string(value)); break; case PROP_NAME: set_name(self, g_value_get_string(value)); break; case PROP_RELEASED_AT: g_clear_pointer(&self->released_at, g_date_time_unref); if (g_value_get_boxed(value) != NULL) self->released_at = g_date_time_ref(g_value_get_boxed(value)); break; case PROP_REVISION: g_free(self->revision); self->revision = g_strdup(g_value_get_string(value)); break; case PROP_SIZE: self->size = g_value_get_int64(value); break; case PROP_VERSION: g_free(self->version); self->version = g_strdup(g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_channel_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdChannel *self = SNAPD_CHANNEL(object); switch (prop_id) { case PROP_CONFINEMENT: g_value_set_enum(value, self->confinement); break; case PROP_EPOCH: g_value_set_string(value, self->epoch); break; case PROP_NAME: g_value_set_string(value, self->name); break; case PROP_RELEASED_AT: g_value_set_boxed(value, self->released_at); break; case PROP_REVISION: g_value_set_string(value, self->revision); break; case PROP_SIZE: g_value_set_int64(value, self->size); break; case PROP_VERSION: g_value_set_string(value, self->version); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_channel_finalize(GObject *object) { SnapdChannel *self = SNAPD_CHANNEL(object); g_clear_pointer(&self->branch, g_free); g_clear_pointer(&self->epoch, g_free); g_clear_pointer(&self->name, g_free); g_clear_pointer(&self->revision, g_free); g_clear_pointer(&self->released_at, g_date_time_unref); g_clear_pointer(&self->risk, g_free); g_clear_pointer(&self->track, g_free); g_clear_pointer(&self->version, g_free); G_OBJECT_CLASS(snapd_channel_parent_class)->finalize(object); } static void snapd_channel_class_init(SnapdChannelClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_channel_set_property; gobject_class->get_property = snapd_channel_get_property; gobject_class->finalize = snapd_channel_finalize; g_object_class_install_property( gobject_class, PROP_CONFINEMENT, g_param_spec_enum( "confinement", "confinement", "Confinement requested by the snap", SNAPD_TYPE_CONFINEMENT, SNAPD_CONFINEMENT_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_EPOCH, g_param_spec_string("epoch", "epoch", "Epoch of this snap", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_NAME, g_param_spec_string("name", "name", "The channel name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_REVISION, g_param_spec_string("revision", "revision", "Revision of this snap", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_RELEASED_AT, g_param_spec_boxed( "released-at", "released-at", "Date revision was released into channel", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SIZE, g_param_spec_int64( "size", "size", "Download size in bytes", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_VERSION, g_param_spec_string("version", "version", "Snap version", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_channel_init(SnapdChannel *self) {} snapd-glib-1.67/snapd-glib/snapd-channel.h000066400000000000000000000035621477073115000204060ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_CHANNEL_H__ #define __SNAPD_CHANNEL_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_CHANNEL (snapd_channel_get_type()) G_DECLARE_FINAL_TYPE(SnapdChannel, snapd_channel, SNAPD, CHANNEL, GObject) /** * SnapdConfinement: * @SNAPD_CONFINEMENT_UNKNOWN: the confinement of the snap is unknown. * @SNAPD_CONFINEMENT_STRICT: the snap is using confinement. * @SNAPD_CONFINEMENT_DEVMODE: the snap is in dev mode (i.e. unconfined). * @SNAPD_CONFINEMENT_CLASSIC: the snap is using classic confinement. * * Confinement used by a snap. * * Since: 1.0 */ typedef enum { SNAPD_CONFINEMENT_UNKNOWN, SNAPD_CONFINEMENT_STRICT, SNAPD_CONFINEMENT_DEVMODE, SNAPD_CONFINEMENT_CLASSIC } SnapdConfinement; const gchar *snapd_channel_get_branch(SnapdChannel *channel); SnapdConfinement snapd_channel_get_confinement(SnapdChannel *channel); const gchar *snapd_channel_get_epoch(SnapdChannel *channel); const gchar *snapd_channel_get_name(SnapdChannel *channel); const gchar *snapd_channel_get_revision(SnapdChannel *channel); GDateTime *snapd_channel_get_released_at(SnapdChannel *channel); const gchar *snapd_channel_get_risk(SnapdChannel *channel); gint64 snapd_channel_get_size(SnapdChannel *channel); const gchar *snapd_channel_get_track(SnapdChannel *channel); const gchar *snapd_channel_get_version(SnapdChannel *channel); G_END_DECLS #endif /* __SNAPD_CHANNEL_H__ */ snapd-glib-1.67/snapd-glib/snapd-client-sync.c000066400000000000000000002325101477073115000212160ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-client.h" #include "snapd-error.h" typedef struct { GMainContext *context; GMainLoop *loop; GAsyncResult *result; } SyncData; static void start_sync(SyncData *data) { data->context = g_main_context_new(); data->loop = g_main_loop_new(data->context, FALSE); g_main_context_push_thread_default(data->context); } static void end_sync(SyncData *data) { if (data->loop != NULL) g_main_loop_run(data->loop); g_main_context_pop_thread_default(data->context); } static void sync_data_clear(SyncData *data) { g_clear_pointer(&data->loop, g_main_loop_unref); g_clear_pointer(&data->context, g_main_context_unref); g_clear_object(&data->result); } G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(SyncData, sync_data_clear) static void sync_cb(GObject *object, GAsyncResult *result, gpointer user_data) { SyncData *data = user_data; data->result = g_object_ref(result); g_main_loop_quit(data->loop); g_clear_pointer(&data->loop, g_main_loop_unref); } /** * snapd_client_connect_sync: * @client: a #SnapdClient * @cancellable: (allow-none): a #GCancellable or %NULL * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * This method is no longer required and does nothing, snapd-glib now connects * on demand. * * Returns: %TRUE if successfully connected to snapd. * * Since: 1.0 */ gboolean snapd_client_connect_sync(SnapdClient *self, GCancellable *cancellable, GError **error) { return TRUE; } /** * snapd_client_login_sync: * @client: a #SnapdClient. * @email: email address to log in with. * @password: password to log in with. * @otp: (allow-none): response to one-time password challenge. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Log in to snapd and get authorization to install/remove snaps. * * Returns: (transfer full): a #SnapdAuthData or %NULL on error. * * Since: 1.0 * Deprecated: 1.26: Use snapd_client_login2_sync() */ SnapdAuthData *snapd_client_login_sync(SnapdClient *self, const gchar *email, const gchar *password, const gchar *otp, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(email != NULL, NULL); g_return_val_if_fail(password != NULL, NULL); g_auto(SyncData) data = {0}; start_sync(&data); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_login_async(self, email, password, otp, cancellable, sync_cb, &data); G_GNUC_END_IGNORE_DEPRECATIONS end_sync(&data); G_GNUC_BEGIN_IGNORE_DEPRECATIONS return snapd_client_login_finish(self, data.result, error); G_GNUC_END_IGNORE_DEPRECATIONS } /** * snapd_client_login2_sync: * @client: a #SnapdClient. * @email: email address to log in with. * @password: password to log in with. * @otp: (allow-none): response to one-time password challenge. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Log in to snapd and get authorization to install/remove snaps. * * Returns: (transfer full): a #SnapdUserInformation or %NULL on error. * * Since: 1.26 */ SnapdUserInformation * snapd_client_login2_sync(SnapdClient *self, const gchar *email, const gchar *password, const gchar *otp, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(email != NULL, NULL); g_return_val_if_fail(password != NULL, NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_login2_async(self, email, password, otp, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_login2_finish(self, data.result, error); } /** * snapd_client_logout_sync: * @client: a #SnapdClient. * @id: login ID to use. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Log out from snapd. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.55 */ gboolean snapd_client_logout_sync(SnapdClient *self, gint64 id, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_logout_async(self, id, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_logout_finish(self, data.result, error); } /** * snapd_client_get_changes_sync: * @client: a #SnapdClient. * @filter: changes to filter on. * @snap_name: (allow-none): name of snap to filter on or %NULL for changes for * any snap. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get changes that have occurred / are occurring on the snap daemon. * * Returns: (transfer container) (element-type SnapdChange): an array of * #SnapdChange or %NULL on error. * * Since: 1.29 */ GPtrArray *snapd_client_get_changes_sync(SnapdClient *self, SnapdChangeFilter filter, const gchar *snap_name, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_changes_async(self, filter, snap_name, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_changes_finish(self, data.result, error); } /** * snapd_client_get_change_sync: * @client: a #SnapdClient. * @id: a change ID to get information on. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get information on a change. * * Returns: (transfer full): a #SnapdChange or %NULL on error. * * Since: 1.29 */ SnapdChange *snapd_client_get_change_sync(SnapdClient *self, const gchar *id, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(id != NULL, NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_change_async(self, id, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_change_finish(self, data.result, error); } /** * snapd_client_abort_change_sync: * @client: a #SnapdClient. * @id: a change ID to abort. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get information on a change. * * Returns: (transfer full): a #SnapdChange or %NULL on error. * * Since: 1.30 */ SnapdChange *snapd_client_abort_change_sync(SnapdClient *self, const gchar *id, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(id != NULL, NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_abort_change_async(self, id, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_abort_change_finish(self, data.result, error); } /** * snapd_client_get_system_information_sync: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Request system information from snapd. * While this blocks, snapd is expected to return the information quickly. * * Returns: (transfer full): a #SnapdSystemInformation or %NULL on error. * * Since: 1.0 */ SnapdSystemInformation *snapd_client_get_system_information_sync( SnapdClient *self, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_system_information_async(self, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_system_information_finish(self, data.result, error); } /** * snapd_client_list_one_sync: * @client: a #SnapdClient. * @name: name of snap to get. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get information of a single installed snap. * * Returns: (transfer full): a #SnapdSnap or %NULL on error. * * Since: 1.0 * Deprecated: 1.42: Use snapd_client_get_snap_sync() */ SnapdSnap *snapd_client_list_one_sync(SnapdClient *self, const gchar *name, GCancellable *cancellable, GError **error) { return snapd_client_get_snap_sync(self, name, cancellable, error); } /** * snapd_client_get_snap_sync: * @client: a #SnapdClient. * @name: name of snap to get. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get information of a single installed snap. If the snap does not exist an * error occurs. * * Returns: (transfer full): a #SnapdSnap or %NULL on error. * * Since: 1.42 */ SnapdSnap *snapd_client_get_snap_sync(SnapdClient *self, const gchar *name, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_snap_async(self, name, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_snap_finish(self, data.result, error); } /** * snapd_client_get_snap_conf_sync: * @client: a #SnapdClient. * @name: name of snap to get configuration from. * @keys: (allow-none): keys to returns or %NULL to return all. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get configuration for a snap. System configuration is stored using the name * "system". * * Returns: (transfer container) (element-type utf8 GVariant): a table of * configuration values or %NULL on error. * * Since: 1.48 */ GHashTable *snapd_client_get_snap_conf_sync(SnapdClient *self, const gchar *name, GStrv keys, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(name != NULL, NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_snap_conf_async(self, name, keys, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_snap_conf_finish(self, data.result, error); } /** * snapd_client_set_snap_conf_sync: * @client: a #SnapdClient. * @name: name of snap to set configuration for. * @key_values: (element-type utf8 GVariant): Keys to set. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Set configuration for a snap. System configuration is stored using the name * "system". * * Returns: %TRUE if configuration successfully applied. * * Since: 1.48 */ gboolean snapd_client_set_snap_conf_sync(SnapdClient *self, const gchar *name, GHashTable *key_values, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(name != NULL, FALSE); g_return_val_if_fail(key_values != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_set_snap_conf_async(self, name, key_values, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_set_snap_conf_finish(self, data.result, error); } /** * snapd_client_get_apps_sync: * @client: a #SnapdClient. * @flags: a set of #SnapdGetAppsFlags to control what results are returned. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get information on installed apps. * * Returns: (transfer container) (element-type SnapdApp): an array of #SnapdApp * or %NULL on error. * * Since: 1.25 * Deprecated: 1.45: Use snapd_client_get_apps2_sync() */ GPtrArray *snapd_client_get_apps_sync(SnapdClient *self, SnapdGetAppsFlags flags, GCancellable *cancellable, GError **error) { return snapd_client_get_apps2_sync(self, flags, NULL, cancellable, error); } /** * snapd_client_get_apps2_sync: * @client: a #SnapdClient. * @flags: a set of #SnapdGetAppsFlags to control what results are returned. * @snaps: (allow-none): A list of snap names to return results for. If %NULL or * empty then apps for all installed snaps are returned. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get information on installed apps. * * Returns: (transfer container) (element-type SnapdApp): an array of #SnapdApp * or %NULL on error. * * Since: 1.45 */ GPtrArray *snapd_client_get_apps2_sync(SnapdClient *self, SnapdGetAppsFlags flags, GStrv snaps, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_apps2_async(self, flags, snaps, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_apps2_finish(self, data.result, error); } /** * snapd_client_get_icon_sync: * @client: a #SnapdClient. * @name: name of snap to get icon for. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get the icon for an installed snap. * * Returns: (transfer full): a #SnapdIcon or %NULL on error. * * Since: 1.0 */ SnapdIcon *snapd_client_get_icon_sync(SnapdClient *self, const gchar *name, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_icon_async(self, name, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_icon_finish(self, data.result, error); } /** * snapd_client_list_sync: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get information on all installed snaps. * * Returns: (transfer container) (element-type SnapdSnap): an array of * #SnapdSnap or %NULL on error. * * Since: 1.0 * Deprecated: 1.42: Use snapd_client_get_snaps_sync() */ GPtrArray *snapd_client_list_sync(SnapdClient *self, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_list_async(self, cancellable, sync_cb, &data); G_GNUC_END_IGNORE_DEPRECATIONS end_sync(&data); G_GNUC_BEGIN_IGNORE_DEPRECATIONS return snapd_client_list_finish(self, data.result, error); G_GNUC_END_IGNORE_DEPRECATIONS } /** * snapd_client_get_snaps_sync: * @client: a #SnapdClient. * @flags: a set of #SnapdGetSnapsFlags to control what results are returned. * @names: (allow-none): A list of snap names or %NULL. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get information on installed snaps (snaps with status * %SNAPD_SNAP_STATUS_ACTIVE). If @flags contains * %SNAPD_GET_SNAPS_FLAGS_INCLUDE_INACTIVE then also return snaps with status * %SNAPD_SNAP_STATUS_INSTALLED. * * If @flags contains %SNAPD_GET_SNAPS_FLAGS_REFRESH_INHIBITED, then it will * return only those snaps that are inhibited from being refreshed, for example * due to having a running instace. * * If @names is not %NULL and contains at least one name only snaps that match * these names are returned. If a snap is not installed it is not returned (no * error is generated). * * Returns: (transfer container) (element-type SnapdSnap): an array of * #SnapdSnap or %NULL on error. * * Since: 1.42 */ GPtrArray *snapd_client_get_snaps_sync(SnapdClient *self, SnapdGetSnapsFlags flags, GStrv names, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_snaps_async(self, flags, names, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_snaps_finish(self, data.result, error); } /** * snapd_client_get_assertions_sync: * @client: a #SnapdClient. * @type: assertion type to get. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get assertions. * * Returns: (transfer full) (array zero-terminated=1): an array of assertions or * %NULL on error. * * Since: 1.8 */ GStrv snapd_client_get_assertions_sync(SnapdClient *self, const gchar *type, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_assertions_async(self, type, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_assertions_finish(self, data.result, error); } /** * snapd_client_add_assertions_sync: * @client: a #SnapdClient. * @assertions: assertions to add. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Add an assertion. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.8 */ gboolean snapd_client_add_assertions_sync(SnapdClient *self, GStrv assertions, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(assertions != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_add_assertions_async(self, assertions, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_add_assertions_finish(self, data.result, error); } /** * snapd_client_get_interfaces_sync: * @client: a #SnapdClient. * @plugs: (out) (allow-none) (transfer container) (element-type SnapdPlug): the * location to store the array of #SnapdPlug or %NULL. * @slots: (out) (allow-none) (transfer container) (element-type SnapdSlot): the * location to store the array of #SnapdSlot or %NULL. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get the installed snap interfaces. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 * Deprecated: 1.48: Use snapd_client_get_connections_sync() */ gboolean snapd_client_get_interfaces_sync(SnapdClient *self, GPtrArray **plugs, GPtrArray **slots, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_auto(SyncData) data = {0}; start_sync(&data); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_get_interfaces_async(self, cancellable, sync_cb, &data); G_GNUC_END_IGNORE_DEPRECATIONS end_sync(&data); G_GNUC_BEGIN_IGNORE_DEPRECATIONS return snapd_client_get_interfaces_finish(self, data.result, plugs, slots, error); G_GNUC_END_IGNORE_DEPRECATIONS } /** * snapd_client_get_interfaces2_sync: * @client: a #SnapdClient. * @flags: a set of #SnapdGetInterfacesFlags to control what information is * returned about the interfaces. * @names: (allow-none) (array zero-terminated=1): a null-terminated array of * interface names or %NULL. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get information about the available snap interfaces. * * Returns: (transfer container) (element-type SnapdInterface): the available * interfaces. * * Since: 1.48 */ GPtrArray *snapd_client_get_interfaces2_sync(SnapdClient *self, SnapdGetInterfacesFlags flags, GStrv names, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_interfaces2_async(self, flags, names, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_interfaces2_finish(self, data.result, error); } /** * snapd_client_get_connections_sync: * @client: a #SnapdClient. * @established: (out) (allow-none) (transfer container) (element-type SnapdConnection): * the location to store the array of connections or %NULL. * @undesired: (out) (allow-none) (transfer container) (element-type SnapdConnection): * the location to store the array of auto-connected * connections that have been manually disconnected or %NULL. * @plugs: (out) (allow-none) (transfer container) (element-type SnapdPlug): the * location to store the array of #SnapdPlug or %NULL. * @slots: (out) (allow-none) (transfer container) (element-type SnapdSlot): the * location to store the array of #SnapdSlot or %NULL. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get the installed snap connections. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.48 * Deprecated: 1.49: Use snapd_client_get_connections2_sync() */ gboolean snapd_client_get_connections_sync(SnapdClient *self, GPtrArray **established, GPtrArray **undesired, GPtrArray **plugs, GPtrArray **slots, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_auto(SyncData) data = {0}; start_sync(&data); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_get_connections_async(self, cancellable, sync_cb, &data); G_GNUC_END_IGNORE_DEPRECATIONS end_sync(&data); G_GNUC_BEGIN_IGNORE_DEPRECATIONS return snapd_client_get_connections_finish(self, data.result, established, undesired, plugs, slots, error); G_GNUC_END_IGNORE_DEPRECATIONS } /** * snapd_client_get_connections2_sync: * @client: a #SnapdClient. * @flags: a set of #SnapdGetConnectionsFlags to control what results are * returned. * @snap: (allow-none): the name of the snap to get connections for or %NULL for * all snaps. * @interface: (allow-none): the name of the interface to get connections for or * %NULL for all interfaces. * @established: (out) (allow-none) (transfer container) (element-type SnapdConnection): * the location to store the array of connections or %NULL. * @undesired: (out) (allow-none) (transfer container) (element-type SnapdConnection): * the location to store the array of auto-connected * connections that have been manually disconnected or %NULL. * @plugs: (out) (allow-none) (transfer container) (element-type SnapdPlug): the * location to store the array of #SnapdPlug or %NULL. * @slots: (out) (allow-none) (transfer container) (element-type SnapdSlot): the * location to store the array of #SnapdSlot or %NULL. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get the installed snap connections. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.49 */ gboolean snapd_client_get_connections2_sync( SnapdClient *self, SnapdGetConnectionsFlags flags, const gchar *snap, const gchar *interface, GPtrArray **established, GPtrArray **undesired, GPtrArray **plugs, GPtrArray **slots, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_connections2_async(self, flags, snap, interface, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_connections2_finish(self, data.result, established, undesired, plugs, slots, error); } /** * snapd_client_connect_interface_sync: * @client: a #SnapdClient. * @plug_snap: name of snap containing plug. * @plug_name: name of plug to connect. * @slot_snap: name of snap containing socket. * @slot_name: name of slot to connect. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Connect two interfaces together. * An asynchronous version of this function is * snapd_client_connect_interface_async(). * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 */ gboolean snapd_client_connect_interface_sync( SnapdClient *self, const gchar *plug_snap, const gchar *plug_name, const gchar *slot_snap, const gchar *slot_name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_connect_interface_async( self, plug_snap, plug_name, slot_snap, slot_name, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_connect_interface_finish(self, data.result, error); } /** * snapd_client_disconnect_interface_sync: * @client: a #SnapdClient. * @plug_snap: name of snap containing plug. * @plug_name: name of plug to disconnect. * @slot_snap: name of snap containing socket. * @slot_name: name of slot to disconnect. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Disconnect two interfaces. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 */ gboolean snapd_client_disconnect_interface_sync( SnapdClient *self, const gchar *plug_snap, const gchar *plug_name, const gchar *slot_snap, const gchar *slot_name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_disconnect_interface_async( self, plug_snap, plug_name, slot_snap, slot_name, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_disconnect_interface_finish(self, data.result, error); } /** * snapd_client_find_sync: * @client: a #SnapdClient. * @flags: a set of #SnapdFindFlags to control how the find is performed. * @query: (allow-none): query string to send or %NULL to return featured snaps. * @suggested_currency: (out) (allow-none): location to store the ISO 4217 * currency that is suggested to purchase with. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Find snaps in the store. * * Returns: (transfer container) (element-type SnapdSnap): an array of * #SnapdSnap or %NULL on error. * * Since: 1.0 */ GPtrArray *snapd_client_find_sync(SnapdClient *self, SnapdFindFlags flags, const gchar *query, gchar **suggested_currency, GCancellable *cancellable, GError **error) { return snapd_client_find_category_sync( self, flags, NULL, query, suggested_currency, cancellable, error); } /** * snapd_client_find_section_sync: * @client: a #SnapdClient. * @flags: a set of #SnapdFindFlags to control how the find is performed. * @section: (allow-none): store section to search in or %NULL to search in all * sections. * @query: (allow-none): query string to send or %NULL to get all snaps from the * given section. * @suggested_currency: (out) (allow-none): location to store the ISO 4217 * currency that is suggested to purchase with. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Find snaps in the store. * * Returns: (transfer container) (element-type SnapdSnap): an array of * #SnapdSnap or %NULL on error. * * Since: 1.7 * Deprecated: 1.64: Use snapd_client_find_category_sync() */ GPtrArray * snapd_client_find_section_sync(SnapdClient *self, SnapdFindFlags flags, const gchar *section, const gchar *query, gchar **suggested_currency, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_find_section_async(self, flags, section, query, cancellable, sync_cb, &data); G_GNUC_END_IGNORE_DEPRECATIONS end_sync(&data); G_GNUC_BEGIN_IGNORE_DEPRECATIONS return snapd_client_find_section_finish(self, data.result, suggested_currency, error); G_GNUC_END_IGNORE_DEPRECATIONS } /** * snapd_client_find_category_sync: * @client: a #SnapdClient. * @flags: a set of #SnapdFindFlags to control how the find is performed. * @category: (allow-none): store category to search in or %NULL to search in * all categories. * @query: (allow-none): query string to send or %NULL to get all snaps from the * given category. * @suggested_currency: (out) (allow-none): location to store the ISO 4217 * currency that is suggested to purchase with. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Find snaps in the store. * * Returns: (transfer container) (element-type SnapdSnap): an array of * #SnapdSnap or %NULL on error. * * Since: 1.64 */ GPtrArray * snapd_client_find_category_sync(SnapdClient *self, SnapdFindFlags flags, const gchar *category, const gchar *query, gchar **suggested_currency, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_find_category_async(self, flags, category, query, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_find_category_finish(self, data.result, suggested_currency, error); } /** * snapd_client_find_refreshable_sync: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Find snaps in store that are newer revisions than locally installed versions. * * Returns: (transfer container) (element-type SnapdSnap): an array of * #SnapdSnap or %NULL on error. * * Since: 1.8 */ GPtrArray *snapd_client_find_refreshable_sync(SnapdClient *self, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_find_refreshable_async(self, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_find_refreshable_finish(self, data.result, error); } /** * snapd_client_install_sync: * @client: a #SnapdClient. * @name: name of snap to install. * @channel: (allow-none): channel to install from or %NULL for default. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Install a snap from the store. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 * Deprecated: 1.12: Use snapd_client_install2_sync() */ gboolean snapd_client_install_sync(SnapdClient *self, const gchar *name, const gchar *channel, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { return snapd_client_install2_sync(self, SNAPD_INSTALL_FLAGS_NONE, name, channel, NULL, progress_callback, progress_callback_data, cancellable, error); } /** * snapd_client_install2_sync: * @client: a #SnapdClient. * @flags: a set of #SnapdInstallFlags to control install options. * @name: name of snap to install. * @channel: (allow-none): channel to install from or %NULL for default. * @revision: (allow-none): revision to install or %NULL for default. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Install a snap from the store. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.12 */ gboolean snapd_client_install2_sync(SnapdClient *self, SnapdInstallFlags flags, const gchar *name, const gchar *channel, const gchar *revision, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(name != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_install2_async(self, flags, name, channel, revision, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_install2_finish(self, data.result, error); } /** * snapd_client_install_stream_sync: * @client: a #SnapdClient. * @flags: a set of #SnapdInstallFlags to control install options. * @stream: a #GInputStream containing the snap file contents to install. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Install a snap. The snap contents are provided in the form of an input * stream. To install from a local file, do the following: * * |[ * g_autoptr(GFile) file = g_file_new_for_path (path_to_snap_file); * g_autoptr(GInputStream) stream = g_file_read (file, cancellable, &error); * snapd_client_install_stream_sync (self, stream, progress_cb, NULL, * cancellable, &error); * \] * * Or if you have the file in memory you can use: * * |[ * g_autoptr(GInputStream) stream = g_memory_input_stream_new_from_data (data, * data_length, free_data); snapd_client_install_stream_sync (self, stream, * progress_cb, NULL, cancellable, &error); * \] * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.9 */ gboolean snapd_client_install_stream_sync( SnapdClient *self, SnapdInstallFlags flags, GInputStream *stream, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(G_IS_INPUT_STREAM(stream), FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_install_stream_async(self, flags, stream, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_install_stream_finish(self, data.result, error); } /** * snapd_client_try_sync: * @client: a #SnapdClient. * @path: path to snap directory to try. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Try a snap. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.9 */ gboolean snapd_client_try_sync(SnapdClient *self, const gchar *path, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(path != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_try_async(self, path, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_try_finish(self, data.result, error); } /** * snapd_client_refresh_sync: * @client: a #SnapdClient. * @name: name of snap to refresh. * @channel: (allow-none): channel to refresh from or %NULL for default. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Ensure an installed snap is at the latest version. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 */ gboolean snapd_client_refresh_sync(SnapdClient *self, const gchar *name, const gchar *channel, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(name != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_refresh_async(self, name, channel, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_refresh_finish(self, data.result, error); } /** * snapd_client_refresh_all_sync: * @client: a #SnapdClient. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Update all installed snaps to their latest version. * * Returns: (transfer full): a %NULL-terminated array of the snap names * refreshed or %NULL on error. * * Since: 1.5 */ GStrv snapd_client_refresh_all_sync(SnapdClient *self, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_refresh_all_async(self, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_refresh_all_finish(self, data.result, error); } /** * snapd_client_remove_sync: * @client: a #SnapdClient. * @name: name of snap to remove. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Uninstall a snap. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 * Deprecated: 1.50: Use snapd_client_remove2_sync() */ gboolean snapd_client_remove_sync(SnapdClient *self, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { return snapd_client_remove2_sync(self, SNAPD_REMOVE_FLAGS_NONE, name, progress_callback, progress_callback_data, cancellable, error); } /** * snapd_client_remove2_sync: * @client: a #SnapdClient. * @flags: a set of #SnapdRemoveFlags to control remove options. * @name: name of snap to remove. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Uninstall a snap. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.50 */ gboolean snapd_client_remove2_sync(SnapdClient *self, SnapdRemoveFlags flags, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(name != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_remove2_async(self, flags, name, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_remove2_finish(self, data.result, error); } /** * snapd_client_enable_sync: * @client: a #SnapdClient. * @name: name of snap to enable. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Enable an installed snap. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 */ gboolean snapd_client_enable_sync(SnapdClient *self, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(name != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_enable_async(self, name, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_enable_finish(self, data.result, error); } /** * snapd_client_disable_sync: * @client: a #SnapdClient. * @name: name of snap to disable. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Disable an installed snap. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 */ gboolean snapd_client_disable_sync(SnapdClient *self, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(name != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_disable_async(self, name, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_disable_finish(self, data.result, error); } /** * snapd_client_switch_sync: * @client: a #SnapdClient. * @name: name of snap to switch channel. * @channel: channel to track. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Set the tracking channel on an installed snap. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.26 */ gboolean snapd_client_switch_sync(SnapdClient *self, const gchar *name, const gchar *channel, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(name != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_switch_async(self, name, channel, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_switch_finish(self, data.result, error); } /** * snapd_client_check_buy_sync: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Check if able to buy snaps. * * Returns: %TRUE if able to buy snaps or %FALSE on error. * * Since: 1.3 */ gboolean snapd_client_check_buy_sync(SnapdClient *self, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_check_buy_async(self, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_check_buy_finish(self, data.result, error); } /** * snapd_client_buy_sync: * @client: a #SnapdClient. * @id: id of snap to buy. * @amount: amount of currency to spend, e.g. 0.99. * @currency: the currency to buy with as an ISO 4217 currency code, e.g. "NZD". * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Buy a snap from the store. Once purchased, this snap can be installed with * snapd_client_install2_sync(). * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.3 */ gboolean snapd_client_buy_sync(SnapdClient *self, const gchar *id, gdouble amount, const gchar *currency, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(id != NULL, FALSE); g_return_val_if_fail(currency != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_buy_async(self, id, amount, currency, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_buy_finish(self, data.result, error); } /** * snapd_client_create_user_sync: * @client: a #SnapdClient. * @email: the email of the user to create. * @flags: a set of #SnapdCreateUserFlags to control how the user account is * created. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Create a local user account for the given user. * * Returns: (transfer full): a #SnapdUserInformation or %NULL on error. * * Since: 1.3 */ SnapdUserInformation *snapd_client_create_user_sync(SnapdClient *self, const gchar *email, SnapdCreateUserFlags flags, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(email != NULL, NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_create_user_async(self, email, flags, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_create_user_finish(self, data.result, error); } /** * snapd_client_create_users_sync: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Create local user accounts using the system-user assertions that are valid * for this device. * * Returns: (transfer container) (element-type SnapdUserInformation): an array * of #SnapdUserInformation or %NULL on error. * * Since: 1.3 */ GPtrArray *snapd_client_create_users_sync(SnapdClient *self, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_create_users_async(self, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_create_users_finish(self, data.result, error); } /** * snapd_client_get_users_sync: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get user accounts that are valid for this device. * * Returns: (transfer container) (element-type SnapdUserInformation): an array * of #SnapdUserInformation or %NULL on error. * * Since: 1.26 */ GPtrArray *snapd_client_get_users_sync(SnapdClient *self, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_users_async(self, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_users_finish(self, data.result, error); } /** * snapd_client_get_sections_sync: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get the store sections. * * Returns: (transfer full) (array zero-terminated=1): an array of section names * or %NULL on error. * * Since: 1.7 * Deprecated: 1.64: Use snapd_client_get_categories_sync() */ GStrv snapd_client_get_sections_sync(SnapdClient *self, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_get_sections_async(self, cancellable, sync_cb, &data); G_GNUC_END_IGNORE_DEPRECATIONS end_sync(&data); G_GNUC_BEGIN_IGNORE_DEPRECATIONS return snapd_client_get_sections_finish(self, data.result, error); G_GNUC_END_IGNORE_DEPRECATIONS } /** * snapd_client_get_categories_sync: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get the store categories. * * Returns: (transfer container) (element-type SnapdCategoryDetails): an array * of #SnapdCategoryDetails or %NULL on error. * * Since: 1.64 */ GPtrArray *snapd_client_get_categories_sync(SnapdClient *self, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_categories_async(self, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_categories_finish(self, data.result, error); } /** * snapd_client_get_aliases_sync: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get the available aliases. * * Returns: (transfer container) (element-type SnapdAlias): an array of * #SnapdAlias or %NULL on error. * * Since: 1.8 */ GPtrArray *snapd_client_get_aliases_sync(SnapdClient *self, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_aliases_async(self, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_aliases_finish(self, data.result, error); } /** * snapd_client_alias_sync: * @client: a #SnapdClient. * @snap: the name of the snap to modify. * @app: an app in the snap to make the alias to. * @alias: the name of the alias (i.e. the command that will run this app). * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Create an alias to an app. * * Since: 1.25 */ gboolean snapd_client_alias_sync(SnapdClient *self, const gchar *snap, const gchar *app, const gchar *alias, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(snap != NULL, FALSE); g_return_val_if_fail(app != NULL, FALSE); g_return_val_if_fail(alias != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_alias_async(self, snap, app, alias, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_alias_finish(self, data.result, error); } /** * snapd_client_unalias_sync: * @client: a #SnapdClient. * @snap: (allow-none): the name of the snap to modify or %NULL. * @alias: (allow-none): the name of the alias to remove or %NULL to remove all * aliases for the given snap. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Remove an alias from an app. * * Since: 1.25 */ gboolean snapd_client_unalias_sync(SnapdClient *self, const gchar *snap, const gchar *alias, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(alias != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_unalias_async(self, snap, alias, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_unalias_finish(self, data.result, error); } /** * snapd_client_prefer_sync: * @client: a #SnapdClient. * @snap: the name of the snap to modify. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * ??? * * Since: 1.25 */ gboolean snapd_client_prefer_sync(SnapdClient *self, const gchar *snap, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(snap != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_prefer_async(self, snap, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_prefer_finish(self, data.result, error); } /** * snapd_client_enable_aliases_sync: * @client: a #SnapdClient. * @snap: the name of the snap to modify. * @aliases: the aliases to modify. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Change the state of aliases. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.8 * Deprecated: 1.25: Use snapd_client_alias_sync() */ gboolean snapd_client_enable_aliases_sync( SnapdClient *self, const gchar *snap, GStrv aliases, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_FAILED, "snapd_client_enable_aliases_async is deprecated"); return FALSE; } /** * snapd_client_disable_aliases_sync: * @client: a #SnapdClient. * @snap: the name of the snap to modify. * @aliases: the aliases to modify. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Change the state of aliases. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.8 * Deprecated: 1.25: Use snapd_client_unalias_sync() */ gboolean snapd_client_disable_aliases_sync( SnapdClient *self, const gchar *snap, GStrv aliases, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_FAILED, "snapd_client_disable_aliases_async is deprecated"); return FALSE; } /** * snapd_client_reset_aliases_sync: * @client: a #SnapdClient. * @snap: the name of the snap to modify. * @aliases: the aliases to modify. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Change the state of aliases. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.8 * Deprecated: 1.25: Use snapd_client_disable_aliases_sync() */ gboolean snapd_client_reset_aliases_sync( SnapdClient *self, const gchar *snap, GStrv aliases, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_FAILED, "snapd_client_reset_aliases_async is deprecated"); return FALSE; } /** * snapd_client_run_snapctl_sync: * @client: a #SnapdClient. * @context_id: context for this call. * @args: the arguments to pass to snapctl. * @stdout_output: (out) (allow-none): the location to write the stdout from the * command or %NULL. * @stderr_output: (out) (allow-none): the location to write the stderr from the * command or %NULL. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Run a snapctl command. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.8 * Deprecated: 1.59: Use snapd_client_run_snapctl2_async() */ gboolean snapd_client_run_snapctl_sync(SnapdClient *self, const gchar *context_id, GStrv args, gchar **stdout_output, gchar **stderr_output, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(context_id != NULL, FALSE); g_return_val_if_fail(args != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_run_snapctl_async(self, context_id, args, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_run_snapctl_finish(self, data.result, stdout_output, stderr_output, error); G_GNUC_END_IGNORE_DEPRECATIONS } /** * snapd_client_run_snapctl2_sync: * @client: a #SnapdClient. * @context_id: context for this call. * @args: the arguments to pass to snapctl. * @stdout_output: (out) (allow-none): the location to write the stdout from the * command or %NULL. * @stderr_output: (out) (allow-none): the location to write the stderr from the * command or %NULL. * @exit_code: (out) (allow-none): the location to write the exit code of the * command or %NULL. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Run a snapctl command. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.59 */ gboolean snapd_client_run_snapctl2_sync(SnapdClient *self, const gchar *context_id, GStrv args, gchar **stdout_output, gchar **stderr_output, int *exit_code, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(context_id != NULL, FALSE); g_return_val_if_fail(args != NULL, FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_run_snapctl2_async(self, context_id, args, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_run_snapctl2_finish(self, data.result, stdout_output, stderr_output, exit_code, error); } /** * snapd_client_download_sync: * @client: a #SnapdClient. * @name: name of snap to download. * @channel: (allow-none): channel to download from. * @revision: (allow-none): revision to download. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Download the given snap. * * Returns: the snap contents or %NULL on error. * * Since: 1.54 */ GBytes *snapd_client_download_sync(SnapdClient *self, const gchar *name, const gchar *channel, const gchar *revision, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(name != NULL, NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_download_async(self, name, channel, revision, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_download_finish(self, data.result, error); } /** * snapd_client_check_themes_sync: * @client: a #SnapdClient. * @gtk_theme_names: (allow-none): a list of GTK theme names. * @icon_theme_names: (allow-none): a list of icon theme names. * @sound_theme_names: (allow-none): a list of sound theme names. * @gtk_theme_status: (out) (transfer container) (element-type utf8 SnapdThemeStatus): * status of GTK themes. * @icon_theme_status: (out) (transfer container) (element-type utf8 SnapdThemeStatus): * status of icon themes. * @sound_theme_status: (out) (transfer container) (element-type utf8 SnapdThemeStatus): * status of sound themes. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Check the status of snap packaged versions of named desktop * themes. For each theme, it will determine whether it is already * installed, uninstalled but available on the store, or unavailable. * * Since: 1.60 */ gboolean snapd_client_check_themes_sync( SnapdClient *self, GStrv gtk_theme_names, GStrv icon_theme_names, GStrv sound_theme_names, GHashTable **gtk_theme_status, GHashTable **icon_theme_status, GHashTable **sound_theme_status, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_check_themes_async(self, gtk_theme_names, icon_theme_names, sound_theme_names, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_check_themes_finish(self, data.result, gtk_theme_status, icon_theme_status, sound_theme_status, error); } /** * snapd_client_install_themes_sync: * @client: a #SnapdClient. * @gtk_theme_names: (allow-none): a list of GTK theme names. * @icon_theme_names: (allow-none): a list of icon theme names. * @sound_theme_names: (allow-none): a list of sound theme names. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Install snaps that provide the named desktop themes. If all the * named themes are in the "installed" or "unavailable" states, then * an error will be returned. * * Since: 1.60 */ gboolean snapd_client_install_themes_sync( SnapdClient *self, GStrv gtk_theme_names, GStrv icon_theme_names, GStrv sound_theme_names, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_install_themes_async( self, gtk_theme_names, icon_theme_names, sound_theme_names, progress_callback, progress_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_install_themes_finish(self, data.result, error); } /** * snapd_client_get_logs_sync: * @client: a #SnapdClient. * @names: (allow-none) (array zero-terminated=1): a null-terminated array of * service names or %NULL. * @n: the number of logs to return or 0 for default. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Get logs for snap services. * * Returns: (transfer container) (element-type SnapdLog): an array of #SnapdLog * or %NULL on error. * * Since: 1.64 */ GPtrArray *snapd_client_get_logs_sync(SnapdClient *self, GStrv names, size_t n, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_logs_async(self, names, n, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_logs_finish(self, data.result, error); } /** * snapd_client_follow_logs_sync: * @client: a #SnapdClient. * @names: (allow-none) (array zero-terminated=1): a null-terminated array of * service names or %NULL. * @log_callback: (scope async): a #SnapdLogCallback to call when a log is * received. * @log_callback_data: (closure): the data to pass to @log_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Follow logs for snap services. This call will only complete if snapd closes * the connection and will stop any other request on this client from being * sent. * * Returns: %TRUE on success. * * Since: 1.64 */ gboolean snapd_client_follow_logs_sync(SnapdClient *self, GStrv names, SnapdLogCallback log_callback, gpointer log_callback_data, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_follow_logs_async(self, names, log_callback, log_callback_data, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_follow_logs_finish(self, data.result, error); } /** * snapd_client_get_notices_sync: * @client: a #SnapdClient. * @since_date_time: send only the notices generated after this moment (NULL for * all). * @timeout: time, in microseconds, to wait for a new notice (zero to return * immediately). * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Synchronously get notifications that have occurred / are occurring on the * snap daemon. * * The @since_date_time field, being a GDateTime, has a resolution of * microseconds, so, if nanosecond resolution is needed, it is mandatory to call * #snapd_client_notices_set_after_notice before calling this method. * * Returns: (transfer container) (element-type SnapdNotice): a #GPtrArray object * containing the requested notices, or NULL in case of error. * * Since: 1.65 */ GPtrArray *snapd_client_get_notices_sync(SnapdClient *self, GDateTime *since_date_time, GTimeSpan timeout, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_notices_async(self, since_date_time, timeout, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_notices_finish(self, data.result, error); } /** * snapd_client_get_notices_with_filters_sync: * @client: a #SnapdClient. * @user_id: filter by this user-id (NULL for no filter). * @users: filter by this comma-separated list of users (NULL for no filter). * @types: filter by this comma-separated list of types (NULL for no filter). * @keys: filter by this comma-separated list of keys (NULL for no filter). * @since_date_time: send only the notices generated after this moment (NULL for * all). * @timeout: time, in microseconds, to wait for a new notice (zero to return * immediately). * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Synchronously get notifications that have occurred / are occurring on the * snap daemon, allowing to filter the results with several options. * * The @since_date_time field, being a GDateTime, has a resolution of * microseconds, so, if nanosecond resolution is needed, it is mandatory to call * #snapd_client_notices_set_after_notice before calling this method. * * Returns: (transfer container) (element-type SnapdNotice): a #GPtrArray object * containing the requested notices, or NULL in case of error. * * Since: 1.65 */ GPtrArray *snapd_client_get_notices_with_filters_sync( SnapdClient *self, gchar *user_id, gchar *users, gchar *types, gchar *keys, GDateTime *since_date_time, GTimeSpan timeout, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_notices_with_filters_async(self, user_id, users, types, keys, since_date_time, timeout, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_notices_with_filters_finish(self, data.result, error); } /** * snapd_client_get_model_assertion_sync: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Synchronously get the active model assertion for this device. * * Returns: (transfer full): an assertion or %NULL on error. * * Since: 1.67 */ gchar *snapd_client_get_model_assertion_sync(SnapdClient *self, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_model_assertion_async(self, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_model_assertion_finish(self, data.result, error); } /** * snapd_client_get_serial_assertion_sync: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Synchronously get the active serial assertion for this device. * * Returns: (transfer full): an assertion or %NULL on error. * * Since: 1.67 */ gchar *snapd_client_get_serial_assertion_sync(SnapdClient *self, GCancellable *cancellable, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_auto(SyncData) data = {0}; start_sync(&data); snapd_client_get_serial_assertion_async(self, cancellable, sync_cb, &data); end_sync(&data); return snapd_client_get_serial_assertion_finish(self, data.result, error); } snapd-glib-1.67/snapd-glib/snapd-client.c000066400000000000000000005531671477073115000202620ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include #include #include #include "snapd-client.h" #include "requests/snapd-get-aliases.h" #include "requests/snapd-get-apps.h" #include "requests/snapd-get-assertions.h" #include "requests/snapd-get-buy-ready.h" #include "requests/snapd-get-categories.h" #include "requests/snapd-get-change.h" #include "requests/snapd-get-changes.h" #include "requests/snapd-get-connections.h" #include "requests/snapd-get-find.h" #include "requests/snapd-get-icon.h" #include "requests/snapd-get-interfaces-legacy.h" #include "requests/snapd-get-interfaces.h" #include "requests/snapd-get-logs.h" #include "requests/snapd-get-model-serial.h" #include "requests/snapd-get-model.h" #include "requests/snapd-get-notices.h" #include "requests/snapd-get-sections.h" #include "requests/snapd-get-snap-conf.h" #include "requests/snapd-get-snap.h" #include "requests/snapd-get-snaps.h" #include "requests/snapd-get-system-info.h" #include "requests/snapd-get-themes.h" #include "requests/snapd-get-users.h" #include "requests/snapd-post-aliases.h" #include "requests/snapd-post-assertions.h" #include "requests/snapd-post-buy.h" #include "requests/snapd-post-change.h" #include "requests/snapd-post-create-user.h" #include "requests/snapd-post-create-users.h" #include "requests/snapd-post-download.h" #include "requests/snapd-post-interfaces.h" #include "requests/snapd-post-login.h" #include "requests/snapd-post-logout.h" #include "requests/snapd-post-snap-stream.h" #include "requests/snapd-post-snap-try.h" #include "requests/snapd-post-snap.h" #include "requests/snapd-post-snapctl.h" #include "requests/snapd-post-snaps.h" #include "requests/snapd-post-themes.h" #include "requests/snapd-put-snap-conf.h" #include "snapd-error.h" /** * SECTION:snapd-client * @short_description: Client connection to snapd * @include: snapd-glib/snapd-glib.h * * A #SnapdClient is the means of talking to snapd. * * To communicate with snapd create a client with snapd_client_new() then * send requests. * * Some requests require authorization which can be set with * snapd_client_set_auth_data(). */ /** * SnapdClient: * * #SnapdClient contains connection state with snapd. * * Since: 1.0 */ /** * SnapdClientClass: * * Class structure for #SnapdClient. */ /** * SECTION:snapd-version * @short_description: Library version information * @include: snapd-glib/snapd-glib.h * * Programs can check if snapd-glib feature is enabled by checking for the * existence of a define called SNAPD_GLIB_VERSION_<version>, i.e. * * |[ * #ifdef SNAPD_GLIB_VERSION_1_14 * confinement = snapd_system_information_get_confinement (info); * #endif * ]| */ typedef struct { /* Socket path to connect to */ gchar *socket_path; /* Socket to communicate with snapd */ GSocket *snapd_socket; /* User agent to send to snapd */ gchar *user_agent; /* Authentication data to send with requests to snapd */ SnapdAuthData *auth_data; /* Outstanding requests */ GMutex requests_mutex; GPtrArray *requests; /* Whether to send the X-Allow-Interaction request header */ gboolean allow_interaction; /* Data received from snapd */ GMutex buffer_mutex; GByteArray *buffer; /* Processed HTTP response */ guint response_status_code; SoupMessageHeaders *response_headers; GByteArray *response_body; gsize response_body_used; /* Maintenance information returned from snapd */ SnapdMaintenance *maintenance; /* Nanoseconds for the since_date_time field, or -1 if not defined */ int since_date_time_nanoseconds; } SnapdClientPrivate; G_DEFINE_TYPE_WITH_PRIVATE(SnapdClient, snapd_client, G_TYPE_OBJECT) /* snapd API documentation is at https://forum.snapcraft.io/t/snapd-rest-api */ /* Default socket to connect to */ #define SNAPD_SOCKET "/run/snapd.socket" #define SNAPD_SNAP_SOCKET_OLD "/run/snapd-snap.socket" #define SNAPD_SNAP_SOCKET "@/snapd/snapd-snap.socket" /* Number of bytes to read at a time */ #define READ_SIZE 1024 /* Number of milliseconds to poll for status in asynchronous operations */ #define ASYNC_POLL_TIME 100 typedef struct { int ref_count; SnapdClient *client; SnapdRequest *request; GSource *read_source; GSource *poll_source; gulong cancelled_id; } RequestData; static RequestData *request_data_new(SnapdClient *client, SnapdRequest *request) { RequestData *data = g_slice_new0(RequestData); data->ref_count = 1; data->client = client; data->request = g_object_ref(request); return data; } static RequestData *request_data_ref(RequestData *data) { data->ref_count++; return data; } static void request_data_unref(RequestData *data) { data->ref_count--; if (data->ref_count > 0) return; if (data->read_source != NULL) g_source_destroy(data->read_source); g_clear_pointer(&data->read_source, g_source_unref); if (data->poll_source != NULL) g_source_destroy(data->poll_source); g_clear_pointer(&data->poll_source, g_source_unref); if (data->cancelled_id != 0) g_cancellable_disconnect(_snapd_request_get_cancellable(data->request), data->cancelled_id); data->cancelled_id = 0; g_clear_object(&data->request); g_slice_free(RequestData, data); } G_DEFINE_AUTOPTR_CLEANUP_FUNC(RequestData, request_data_unref) static void send_request(SnapdClient *self, SnapdRequest *request); static RequestData *get_request_data(SnapdClient *self, SnapdRequest *request) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); for (guint i = 0; i < priv->requests->len; i++) { RequestData *data = g_ptr_array_index(priv->requests, i); if (data->request == request) return data; } return NULL; } static void complete_request_unlocked(SnapdClient *self, SnapdRequest *request, GError *error) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); _snapd_request_return(request, error); RequestData *data = get_request_data(self, request); g_ptr_array_remove(priv->requests, data); } static void complete_request(SnapdClient *self, SnapdRequest *request, GError *error) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&priv->requests_mutex); complete_request_unlocked(self, request, error); } static gboolean async_poll_cb(gpointer data) { RequestData *d = data; g_autoptr(SnapdGetChange) change_request = _snapd_request_async_make_get_change_request( SNAPD_REQUEST_ASYNC(d->request)); send_request(d->client, SNAPD_REQUEST(change_request)); if (d->poll_source != NULL) g_source_destroy(d->poll_source); g_clear_pointer(&d->poll_source, g_source_unref); return G_SOURCE_REMOVE; } static void schedule_poll(SnapdClient *self, SnapdRequestAsync *request) { RequestData *data = get_request_data(self, SNAPD_REQUEST(request)); if (data->poll_source != NULL) g_source_destroy(data->poll_source); g_clear_pointer(&data->poll_source, g_source_unref); data->poll_source = g_timeout_source_new(ASYNC_POLL_TIME); g_source_set_callback(data->poll_source, async_poll_cb, data, NULL); g_source_attach(data->poll_source, _snapd_request_get_context(SNAPD_REQUEST(request))); } static void complete_all_requests(SnapdClient *self, GError *error) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&priv->requests_mutex); /* Disconnect socket - we will reconnect on demand */ if (priv->snapd_socket != NULL) g_socket_close(priv->snapd_socket, NULL); g_clear_object(&priv->snapd_socket); /* Cancel synchronous requests (we'll never know the result); reschedule async * ones (can reconnect to check result) */ g_autoptr(GPtrArray) requests_copy = g_ptr_array_new_with_free_func((GDestroyNotify)request_data_unref); for (guint i = 0; i < priv->requests->len; i++) g_ptr_array_add(requests_copy, request_data_ref(g_ptr_array_index(priv->requests, i))); for (guint i = 0; i < requests_copy->len; i++) { RequestData *data = g_ptr_array_index(requests_copy, i); if (SNAPD_IS_REQUEST_ASYNC(data->request)) schedule_poll(self, SNAPD_REQUEST_ASYNC(data->request)); else complete_request_unlocked(self, data->request, error); } } static void append_string(GByteArray *array, const gchar *value) { g_byte_array_append(array, (const guint8 *)value, strlen(value)); } /* Converts a language in POSIX format and to be RFC2616 compliant */ static gchar *posix_lang_to_rfc2616(const gchar *language) { /* Don't include charset variants, etc */ if (strchr(language, '.') || strchr(language, '@')) return NULL; /* Ignore "C" locale, which g_get_language_names() always includes as a * fallback. */ if (strcmp(language, "C") == 0) return NULL; return g_strdelimit(g_ascii_strdown(language, -1), "_", '-'); } /* Converts @quality from 0-100 to 0.0-1.0 and appends to @str */ static gchar *add_quality_value(const gchar *str, int quality) { g_return_val_if_fail(str != NULL, NULL); if (quality >= 0 && quality < 100) { /* We don't use %.02g because of "." vs "," locale issues */ if (quality % 10) return g_strdup_printf("%s;q=0.%02d", str, quality); else return g_strdup_printf("%s;q=0.%d", str, quality / 10); } else return g_strdup(str); } /* Returns a RFC2616 compliant languages list from system locales */ /* Copied from libsoup */ static gchar *get_accept_languages(void) { const char *const *lang_names = g_get_language_names(); g_return_val_if_fail(lang_names != NULL, NULL); /* Build the array of languages */ g_autoptr(GPtrArray) langs = g_ptr_array_new_with_free_func(g_free); for (guint i = 0; lang_names[i] != NULL; i++) { gchar *lang = posix_lang_to_rfc2616(lang_names[i]); if (lang != NULL) g_ptr_array_add(langs, lang); } /* Add quality values */ int delta; if (langs->len < 10) delta = 10; else if (langs->len < 20) delta = 5; else delta = 1; for (guint i = 0; i < langs->len; i++) { g_autofree gchar *lang = langs->pdata[i]; langs->pdata[i] = add_quality_value(lang, 100 - i * delta); } /* Fallback to "en" if list is empty */ if (langs->len == 0) return g_strdup("en"); g_ptr_array_add(langs, NULL); return g_strjoinv(", ", (char **)langs->pdata); } static SnapdPostChange *find_post_change_request(SnapdClient *self, const gchar *change_id) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&priv->requests_mutex); for (guint i = 0; i < priv->requests->len; i++) { RequestData *data = g_ptr_array_index(priv->requests, i); if (SNAPD_IS_POST_CHANGE(data->request) && g_strcmp0(_snapd_request_async_get_change_id( SNAPD_REQUEST_ASYNC(data->request)), change_id) == 0) return SNAPD_POST_CHANGE(data->request); } return NULL; } static void send_cancel(SnapdClient *self, SnapdRequestAsync *request) { g_autoptr(SnapdPostChange) change_request = find_post_change_request( self, _snapd_request_async_get_change_id(request)); if (change_request != NULL) return; change_request = _snapd_request_async_make_post_change_request(request); send_request(self, SNAPD_REQUEST(change_request)); } static SnapdRequestAsync *find_change_request(SnapdClient *self, const gchar *change_id) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&priv->requests_mutex); for (guint i = 0; i < priv->requests->len; i++) { RequestData *data = g_ptr_array_index(priv->requests, i); if (SNAPD_IS_REQUEST_ASYNC(data->request) && g_strcmp0(_snapd_request_async_get_change_id( SNAPD_REQUEST_ASYNC(data->request)), change_id) == 0) return SNAPD_REQUEST_ASYNC(data->request); } return NULL; } static SnapdRequest *get_first_request(SnapdClient *self) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&priv->requests_mutex); for (guint i = 0; i < priv->requests->len; i++) { RequestData *data = g_ptr_array_index(priv->requests, i); /* Return first non-async request or async request without change id */ if (SNAPD_IS_REQUEST_ASYNC(data->request)) { if (_snapd_request_async_get_change_id( SNAPD_REQUEST_ASYNC(data->request)) == NULL) return data->request; } else return data->request; } return NULL; } static gboolean read_chunk_header(const gchar *body, gsize body_length, gsize *chunk_header_length, gsize *chunk_length) { const gchar *chunk_start = g_strstr_len(body, body_length, "\r\n"); if (chunk_start == NULL) return FALSE; *chunk_header_length = chunk_start - body + 2; *chunk_length = strtoul(body, NULL, 16); return TRUE; } static void complete_change(SnapdClient *self, const gchar *change_id, GError *error) { SnapdRequestAsync *request = find_change_request(self, change_id); if (request != NULL) complete_request(self, SNAPD_REQUEST(request), error); } static void update_changes(SnapdClient *self, SnapdChange *change, JsonNode *data) { SnapdRequestAsync *request = find_change_request(self, snapd_change_get_id(change)); if (request == NULL) return; _snapd_request_async_report_progress(request, self, change); /* Complete parent */ if (snapd_change_get_ready(change)) { g_autoptr(GError) error = NULL; if (!_snapd_request_async_parse_result(request, data, &error)) { complete_request(self, SNAPD_REQUEST(request), error); return; } if (g_cancellable_set_error_if_cancelled( _snapd_request_get_cancellable(SNAPD_REQUEST(request)), &error)) { complete_request(self, SNAPD_REQUEST(request), error); return; } if (snapd_change_get_error(change) != NULL) { g_set_error_literal(&error, SNAPD_ERROR, SNAPD_ERROR_FAILED, snapd_change_get_error(change)); complete_request(self, SNAPD_REQUEST(request), error); return; } complete_request(self, SNAPD_REQUEST(request), NULL); return; } /* Poll for updates */ schedule_poll(self, request); } static void parse_response(SnapdClient *self, SnapdRequest *request, guint status_code, const gchar *content_type, GBytes *body) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_clear_object(&priv->maintenance); g_autoptr(GError) error = NULL; if (!SNAPD_REQUEST_GET_CLASS(request)->parse_response( request, status_code, content_type, body, &priv->maintenance, &error)) { if (SNAPD_IS_GET_CHANGE(request)) { complete_change( self, _snapd_get_change_get_change_id(SNAPD_GET_CHANGE(request)), error); complete_request(self, request, error); } else if (SNAPD_IS_POST_CHANGE(request)) { complete_change( self, _snapd_post_change_get_change_id(SNAPD_POST_CHANGE(request)), error); complete_request(self, request, error); } else complete_request(self, request, error); return; } if (SNAPD_IS_GET_CHANGE(request)) update_changes(self, _snapd_get_change_get_change(SNAPD_GET_CHANGE(request)), _snapd_get_change_get_data(SNAPD_GET_CHANGE(request))); else if (SNAPD_IS_POST_CHANGE(request)) update_changes(self, _snapd_post_change_get_change(SNAPD_POST_CHANGE(request)), _snapd_post_change_get_data(SNAPD_POST_CHANGE(request))); if (SNAPD_IS_REQUEST_ASYNC(request)) { /* Immediately cancel if requested, otherwise poll for updates */ if (g_cancellable_is_cancelled(_snapd_request_get_cancellable(request))) send_cancel(self, SNAPD_REQUEST_ASYNC(request)); else schedule_poll(self, SNAPD_REQUEST_ASYNC(request)); } else complete_request(self, request, NULL); } static gboolean parse_seq(SnapdClient *self, SnapdRequest *request, const char *data, gsize data_length, GError **error) { g_autoptr(JsonParser) parser = json_parser_new(); g_autoptr(GError) json_error = NULL; if (!json_parser_load_from_data(parser, data, data_length, error)) { return FALSE; } if (SNAPD_REQUEST_GET_CLASS(request)->parse_json_seq == NULL) { return TRUE; } return SNAPD_REQUEST_GET_CLASS(request)->parse_json_seq( request, json_parser_get_root(parser), error); } static gboolean read_cb(GSocket *socket, GIOCondition condition, SnapdClient *self) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&priv->buffer_mutex); gsize orig_length = priv->buffer->len; g_byte_array_set_size(priv->buffer, orig_length + READ_SIZE); g_autoptr(GError) error = NULL; gssize n_read = g_socket_receive(socket, (gchar *)priv->buffer->data + orig_length, READ_SIZE, NULL, &error); g_byte_array_set_size(priv->buffer, orig_length + (n_read >= 0 ? n_read : 0)); if (n_read == 0) { g_autoptr(GError) e = g_error_new(SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "snapd connection closed"); complete_all_requests(self, e); return G_SOURCE_REMOVE; } if (n_read < 0) { if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) return G_SOURCE_CONTINUE; g_autoptr(GError) e = g_error_new(SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Failed to read from snapd: %s", error->message); complete_all_requests(self, e); return G_SOURCE_REMOVE; } while (TRUE) { /* Process headers */ if (priv->response_headers == NULL) { gchar *body = g_strstr_len((gchar *)priv->buffer->data, priv->buffer->len, "\r\n\r\n"); if (body == NULL) return G_SOURCE_CONTINUE; body += 4; gsize header_length = body - (gchar *)priv->buffer->data; priv->response_headers = soup_message_headers_new(SOUP_MESSAGE_HEADERS_RESPONSE); if (!soup_headers_parse_response((gchar *)priv->buffer->data, header_length, priv->response_headers, NULL, &priv->response_status_code, NULL)) { g_autoptr(GError) e = g_error_new(SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Failed to parse headers from snapd"); complete_all_requests(self, e); return G_SOURCE_REMOVE; } /* Remove headers from buffer */ g_byte_array_remove_range(priv->buffer, 0, header_length); } /* Read response body */ gboolean is_complete = FALSE; gsize offset = 0, chunk_header_length, chunk_length, content_length, n; g_autoptr(GError) e = NULL; switch (soup_message_headers_get_encoding(priv->response_headers)) { case SOUP_ENCODING_EOF: g_byte_array_append(priv->response_body, priv->buffer->data, priv->buffer->len); g_byte_array_set_size(priv->buffer, 0); is_complete = g_socket_is_closed(priv->snapd_socket); break; case SOUP_ENCODING_CHUNKED: while (offset < priv->buffer->len && read_chunk_header((const gchar *)priv->buffer->data + offset, priv->buffer->len - offset, &chunk_header_length, &chunk_length)) { gsize chunk_trailer_length = 2; gsize chunk_data_offset = offset + chunk_header_length; gsize chunk_trailer_offset = chunk_data_offset + chunk_length; gsize chunk_end = chunk_trailer_offset + chunk_trailer_length; // Haven't yet received all chunk data. if (chunk_end > priv->buffer->len) { break; } const gchar *chunk_trailer = (const gchar *)priv->buffer->data + chunk_trailer_offset; if (chunk_trailer[0] != '\r' && chunk_trailer[1] != '\n') { g_warning("Invalid HTTP chunk"); return G_SOURCE_REMOVE; } g_byte_array_append(priv->response_body, priv->buffer->data + chunk_data_offset, chunk_length); offset = chunk_end; // Empty chunk is end of data. if (chunk_length == 0) { is_complete = TRUE; break; } } g_byte_array_remove_range(priv->buffer, 0, offset); break; case SOUP_ENCODING_CONTENT_LENGTH: content_length = soup_message_headers_get_content_length(priv->response_headers); n = content_length - (priv->response_body->len + priv->response_body_used); if (n > priv->buffer->len) { n = priv->buffer->len; } g_byte_array_append(priv->response_body, priv->buffer->data, n); g_byte_array_remove_range(priv->buffer, 0, n); is_complete = (priv->response_body->len + priv->response_body_used) >= content_length; break; default: e = g_error_new(SNAPD_ERROR, SNAPD_ERROR_READ_FAILED, "Unable to determine header encoding"); complete_all_requests(self, e); return G_SOURCE_REMOVE; } /* Match this response to the next uncompleted request */ SnapdRequest *request = get_first_request(self); if (request == NULL) { g_warning("Ignoring unexpected response"); return G_SOURCE_REMOVE; } const gchar *content_type = soup_message_headers_get_content_type(priv->response_headers, NULL); if (g_strcmp0(content_type, "application/json-seq") == 0) { /* Handle each sequence element */ while (priv->response_body->len > 0) { /* Requests start with a record separator */ if (priv->response_body->data[0] != 0x1e) { break; } gsize seq_start = 1, seq_end = 1; while (seq_end < priv->response_body->len && priv->response_body->data[seq_end] != 0x1e) { seq_end++; } gboolean have_end = seq_end < priv->response_body->len && priv->response_body->data[seq_end] == 0x1e; if (!have_end && !is_complete) { break; } g_autoptr(GError) json_error = NULL; if (!parse_seq(self, request, (const gchar *)priv->response_body->data + seq_start, seq_end - seq_start, &json_error)) { g_warning("Ignoring invalid JSON: %s", json_error->message); return G_SOURCE_REMOVE; } g_byte_array_remove_range(priv->response_body, 0, seq_end); priv->response_body_used += seq_end; } if (is_complete) { complete_request(self, request, NULL); } } else if (is_complete) { g_autoptr(GBytes) b = g_bytes_new(priv->response_body->data, priv->response_body->len); parse_response(self, request, priv->response_status_code, content_type, b); } if (is_complete) { #if SOUP_CHECK_VERSION(2, 99, 2) g_clear_pointer(&priv->response_headers, soup_message_headers_unref); #else g_clear_pointer(&priv->response_headers, soup_message_headers_free); #endif g_byte_array_set_size(priv->response_body, 0); priv->response_body_used = 0; } else { return G_SOURCE_CONTINUE; } } } static gboolean cancel_idle_cb(gpointer user_data) { RequestData *data = user_data; g_autoptr(GError) error = NULL; g_cancellable_set_error_if_cancelled( _snapd_request_get_cancellable(data->request), &error); complete_request(data->client, data->request, error); return G_SOURCE_REMOVE; } static void request_cancelled_cb(GCancellable *cancellable, RequestData *data) { /* Asynchronous requests require asking snapd to stop them */ if (SNAPD_IS_REQUEST_ASYNC(data->request)) { SnapdRequestAsync *r = SNAPD_REQUEST_ASYNC(data->request); /* Cancel if we have got a response from snapd */ if (_snapd_request_async_get_change_id(r) != NULL) send_cancel(data->client, r); } else { /* Execute in an idle thread so g_cancellable_disconnect doesn't deadlock */ g_autoptr(GSource) idle_source = g_idle_source_new(); g_source_set_callback(idle_source, cancel_idle_cb, request_data_ref(data), (GDestroyNotify)request_data_unref); g_source_attach(idle_source, _snapd_request_get_context(data->request)); } } static GSocketAddress *create_socket_address(const gchar *socket_path) { if (socket_path[0] == '@') { return g_unix_socket_address_new_with_type(socket_path + 1, -1, G_UNIX_SOCKET_ADDRESS_ABSTRACT); } else { return g_unix_socket_address_new(socket_path); } } static GSocket *open_snapd_socket(const gchar *socket_path, GCancellable *cancellable, GError **error) { g_return_val_if_fail(socket_path != NULL, NULL); g_autoptr(GError) error_local = NULL; g_autoptr(GSocket) socket = g_socket_new(G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error_local); if (socket == NULL) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_CONNECTION_FAILED, "Unable to create snapd socket: %s", error_local->message); return NULL; } g_socket_set_blocking(socket, FALSE); g_autoptr(GSocketAddress) address = create_socket_address(socket_path); if (!g_socket_connect(socket, address, cancellable, &error_local)) { g_set_error(error, SNAPD_ERROR, SNAPD_ERROR_CONNECTION_FAILED, "Unable to connect snapd socket: %s", error_local->message); return NULL; } return g_steal_pointer(&socket); } static GSocket *do_open_snapd_socket(const gchar *socket_path, GCancellable *cancellable, GError **error) { if (socket_path != NULL) { return open_snapd_socket(socket_path, cancellable, error); } if (getenv("SNAP") == NULL) { return open_snapd_socket(SNAPD_SOCKET, cancellable, error); } g_autoptr(GSocket) sock = open_snapd_socket(SNAPD_SNAP_SOCKET, cancellable, error); if (sock == NULL) { sock = open_snapd_socket(SNAPD_SNAP_SOCKET_OLD, cancellable, error); } return g_steal_pointer(&sock); } static GSource *make_read_source(SnapdClient *self, GMainContext *context) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_autoptr(GSource) source = g_socket_create_source(priv->snapd_socket, G_IO_IN, NULL); g_source_set_name(source, "snapd-glib-read-source"); g_source_set_callback(source, (GSourceFunc)read_cb, self, NULL); g_source_attach(source, context); return g_steal_pointer(&source); } static gboolean write_to_snapd(SnapdClient *self, GByteArray *data, GCancellable *cancellable, GError **error) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); guint n_sent = 0; while (n_sent < data->len) { gssize n_written = g_socket_send(priv->snapd_socket, (const gchar *)(data->data + n_sent), data->len - n_sent, cancellable, error); if (n_written < 0) return FALSE; n_sent += n_written; } return TRUE; } static void send_request(SnapdClient *self, SnapdRequest *request) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); // This code can be replaced with support in libsoup3 at some point. // https://gitlab.gnome.org/GNOME/libsoup/-/issues/75 _snapd_request_set_source_object(request, G_OBJECT(self)); g_autoptr(RequestData) data = request_data_new(self, request); { g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&priv->requests_mutex); g_ptr_array_add(priv->requests, request_data_ref(data)); } GCancellable *cancellable = _snapd_request_get_cancellable(request); if (cancellable != NULL) data->cancelled_id = g_cancellable_connect( cancellable, G_CALLBACK(request_cancelled_cb), request_data_new(self, request), (GDestroyNotify)request_data_unref); g_autoptr(GBytes) body = NULL; SoupMessage *message = _snapd_request_get_message(request, &body); #if SOUP_CHECK_VERSION(2, 99, 2) SoupMessageHeaders *request_headers = soup_message_get_request_headers(message); #else SoupMessageHeaders *request_headers = message->request_headers; #endif soup_message_headers_append(request_headers, "Host", ""); soup_message_headers_append(request_headers, "Connection", "keep-alive"); if (priv->user_agent != NULL) soup_message_headers_append(request_headers, "User-Agent", priv->user_agent); if (priv->allow_interaction) soup_message_headers_append(request_headers, "X-Allow-Interaction", "true"); g_autofree gchar *accept_languages = get_accept_languages(); soup_message_headers_append(request_headers, "Accept-Language", accept_languages); if (priv->auth_data != NULL) { g_autoptr(GString) authorization = g_string_new(""); g_string_append_printf(authorization, "Macaroon root=\"%s\"", snapd_auth_data_get_macaroon(priv->auth_data)); GStrv discharges = snapd_auth_data_get_discharges(priv->auth_data); if (discharges != NULL) for (gsize i = 0; discharges[i] != NULL; i++) g_string_append_printf(authorization, ",discharge=\"%s\"", discharges[i]); soup_message_headers_append(request_headers, "Authorization", authorization->str); } if (body != NULL) soup_message_headers_set_content_length(request_headers, g_bytes_get_size(body)); #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_message_get_method(message); #else const gchar *method = message->method; #endif g_autoptr(GByteArray) request_data = g_byte_array_new(); append_string(request_data, method); append_string(request_data, " "); #if SOUP_CHECK_VERSION(2, 99, 2) GUri *uri = soup_message_get_uri(message); const gchar *uri_path = g_uri_get_path(uri); const gchar *uri_query = g_uri_get_query(uri); #else SoupURI *uri = soup_message_get_uri(message); const gchar *uri_path = uri->path; const gchar *uri_query = uri->query; #endif append_string(request_data, uri_path); if (uri_query != NULL) { append_string(request_data, "?"); append_string(request_data, uri_query); } append_string(request_data, " HTTP/1.1\r\n"); SoupMessageHeadersIter iter; soup_message_headers_iter_init(&iter, request_headers); const char *name, *value; while (soup_message_headers_iter_next(&iter, &name, &value)) { append_string(request_data, name); append_string(request_data, ": "); append_string(request_data, value); append_string(request_data, "\r\n"); } append_string(request_data, "\r\n"); if (body != NULL) g_byte_array_append(request_data, g_bytes_get_data(body, NULL), g_bytes_get_size(body)); gboolean new_socket = FALSE; if (priv->snapd_socket == NULL) { g_autoptr(GError) error = NULL; priv->snapd_socket = do_open_snapd_socket(priv->socket_path, cancellable, &error); if (priv->snapd_socket == NULL) { complete_request(self, request, error); return; } new_socket = TRUE; } data->read_source = make_read_source(self, _snapd_request_get_context(request)); /* send HTTP request */ g_autoptr(GError) error = NULL; if (write_to_snapd(self, request_data, cancellable, &error)) return; /* If was re-using closed socket, then reconnect and retry */ if (!new_socket && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE)) { g_clear_error(&error); g_clear_object(&priv->snapd_socket); g_source_destroy(data->read_source); g_clear_pointer(&data->read_source, g_source_unref); priv->snapd_socket = do_open_snapd_socket(priv->socket_path, cancellable, &error); if (priv->snapd_socket == NULL) { complete_request(self, request, error); return; } data->read_source = make_read_source(self, _snapd_request_get_context(request)); if (write_to_snapd(self, request_data, cancellable, &error)) return; } g_autoptr(GError) e = g_error_new(SNAPD_ERROR, SNAPD_ERROR_WRITE_FAILED, "Failed to write to snapd: %s", error->message); complete_request(self, request, e); } typedef struct { SnapdClient *client; SnapdLogCallback callback; gpointer callback_data; } FollowLogsData; static FollowLogsData *follow_logs_data_new(SnapdClient *client, SnapdLogCallback callback, gpointer callback_data) { FollowLogsData *data = g_slice_new0(FollowLogsData); data->client = client; data->callback = callback; data->callback_data = callback_data; return data; } static void follow_logs_data_free(FollowLogsData *data) { g_slice_free(FollowLogsData, data); } static void log_cb(SnapdGetLogs *request, SnapdLog *log, gpointer user_data) { FollowLogsData *data = user_data; data->callback(data->client, log, data->callback_data); } /** * snapd_client_connect_async: * @client: a #SnapdClient * @cancellable: (allow-none): a #GCancellable or %NULL * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * This method is no longer required and does nothing, snapd-glib now connects * on demand. * * Since: 1.3 * Deprecated: 1.24 */ void snapd_client_connect_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(GTask) task = g_task_new(self, cancellable, callback, user_data); g_task_return_boolean(task, TRUE); } /** * snapd_client_connect_finish: * @client: a #SnapdClient * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_connect_async(). * See snapd_client_connect_sync() for more information. * * Returns: %TRUE if successfully connected to snapd. * * Since: 1.3 */ gboolean snapd_client_connect_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(g_task_is_valid(result, self), FALSE); return g_task_propagate_boolean(G_TASK(result), error); } /** * snapd_client_set_socket_path: * @client: a #SnapdClient * @socket_path: (allow-none): a socket path or %NULL to reset to the default. * If the socket name is in the form '@XXXXXXX', it will be * considered an abstract socket with XXXXXXX as its path. * * Set the Unix socket path to connect to snapd with. * Defaults to the system socket, taking into account if the code is running * confined in a Snap or not. * * Since: 1.24 */ void snapd_client_set_socket_path(SnapdClient *self, const gchar *socket_path) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_return_if_fail(SNAPD_IS_CLIENT(self)); g_free(priv->socket_path); if (socket_path != NULL) priv->socket_path = g_strdup(socket_path); else priv->socket_path = NULL; } /** * snapd_client_get_socket_path: * @client: a #SnapdClient * * Get the unix socket path to connect to snapd with. * * Returns: socket path. * * Since: 1.24 */ const gchar *snapd_client_get_socket_path(SnapdClient *self) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); if (priv->socket_path != NULL) { return priv->socket_path; } if (getenv("SNAP") == NULL) { return SNAPD_SOCKET; } else { return SNAPD_SNAP_SOCKET; } } /** * snapd_client_set_user_agent: * @client: a #SnapdClient * @user_agent: (allow-none): a user agent or %NULL. * * Set the HTTP user-agent that is sent with each request to snapd. * Defaults to "snapd-glib/VERSION". * * Since: 1.16 */ void snapd_client_set_user_agent(SnapdClient *self, const gchar *user_agent) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_return_if_fail(SNAPD_IS_CLIENT(self)); g_free(priv->user_agent); priv->user_agent = g_strdup(user_agent); } /** * snapd_client_get_user_agent: * @client: a #SnapdClient * * Get the HTTP user-agent that is sent with each request to snapd. * * Returns: (allow-none): user agent or %NULL if none set. * * Since: 1.16 */ const gchar *snapd_client_get_user_agent(SnapdClient *self) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); return priv->user_agent; } /** * snapd_client_set_allow_interaction: * @client: a #SnapdClient * @allow_interaction: whether to allow interaction. * * Set whether snapd operations are allowed to interact with the user. * This affects operations that use polkit authorisation. * Defaults to TRUE. * * Since: 1.19 */ void snapd_client_set_allow_interaction(SnapdClient *self, gboolean allow_interaction) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_return_if_fail(SNAPD_IS_CLIENT(self)); priv->allow_interaction = allow_interaction; } /** * snapd_client_get_maintenance: * @client: a #SnapdClient * * Get the maintenance information reported by snapd or %NULL if no maintenance * is in progress. This information is updated after every request. * * Returns: (transfer none) (allow-none): a #SnapdMaintenance or %NULL. * * Since: 1.45 */ SnapdMaintenance *snapd_client_get_maintenance(SnapdClient *self) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); return priv->maintenance; } /** * snapd_client_get_allow_interaction: * @client: a #SnapdClient * * Get whether snapd operations are allowed to interact with the user. * * Returns: %TRUE if interaction is allowed. * * Since: 1.19 */ gboolean snapd_client_get_allow_interaction(SnapdClient *self) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); return priv->allow_interaction; } /** * snapd_client_login_async: * @client: a #SnapdClient. * @email: email address to log in with. * @password: password to log in with. * @otp: (allow-none): response to one-time password challenge. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get authorization to install/remove snaps. * See snapd_client_login_sync() for more information. * * Since: 1.0 * Deprecated: 1.26: Use snapd_client_login2_async() */ void snapd_client_login_async(SnapdClient *self, const gchar *email, const gchar *password, const gchar *otp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { snapd_client_login2_async(self, email, password, otp, cancellable, callback, user_data); } /** * snapd_client_login_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_login_async(). * See snapd_client_login_sync() for more information. * * Returns: (transfer full): a #SnapdAuthData or %NULL on error. * * Since: 1.0 * Deprecated: 1.26: Use snapd_client_login2_finish() */ SnapdAuthData *snapd_client_login_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_finish(self, result, error); if (user_information == NULL) return NULL; return g_object_ref(snapd_user_information_get_auth_data(user_information)); } /** * snapd_client_login2_async: * @client: a #SnapdClient. * @email: email address to log in with. * @password: password to log in with. * @otp: (allow-none): response to one-time password challenge. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get authorization to install/remove snaps. * See snapd_client_login2_sync() for more information. * * Since: 1.26 */ void snapd_client_login2_async(SnapdClient *self, const gchar *email, const gchar *password, const gchar *otp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdPostLogin) request = _snapd_post_login_new( email, password, otp, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_login2_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_login2_async(). * See snapd_client_login2_sync() for more information. * * Returns: (transfer full): a #SnapdUserInformation or %NULL on error. * * Since: 1.26 */ SnapdUserInformation *snapd_client_login2_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_POST_LOGIN(result), NULL); SnapdPostLogin *request = SNAPD_POST_LOGIN(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_object_ref(_snapd_post_login_get_user_information(request)); } /** * snapd_client_logout_async: * @client: a #SnapdClient. * @id: login ID to use. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously log out from the snap store. * See snapd_client_logout_sync() for more information. * * Since: 1.55 */ void snapd_client_logout_async(SnapdClient *self, gint64 id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdPostLogout) request = _snapd_post_logout_new(id, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_logout_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_logout_async(). * See snapd_client_logout_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.55 */ gboolean snapd_client_logout_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_LOGOUT(result), FALSE); SnapdPostLogout *request = SNAPD_POST_LOGOUT(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return FALSE; return TRUE; } /** * snapd_client_set_auth_data: * @client: a #SnapdClient. * @auth_data: (allow-none): a #SnapdAuthData or %NULL. * * Set the authorization data to use for requests. Authorization data can be * obtained by: * * - Logging into snapd using snapd_client_login_sync() * * - Using an existing authorization with snapd_auth_data_new(). * * Since: 1.0 */ void snapd_client_set_auth_data(SnapdClient *self, SnapdAuthData *auth_data) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_return_if_fail(SNAPD_IS_CLIENT(self)); g_clear_object(&priv->auth_data); if (auth_data != NULL) priv->auth_data = g_object_ref(auth_data); } /** * snapd_client_get_auth_data: * @client: a #SnapdClient. * * Get the authorization data that is used for requests. * * Returns: (transfer none) (allow-none): a #SnapdAuthData or %NULL. * * Since: 1.0 */ SnapdAuthData *snapd_client_get_auth_data(SnapdClient *self) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); return priv->auth_data; } /** * snapd_client_get_notices_async: * @client: a #SnapdClient. * @since_date_time: send only the notices generated after this moment (NULL for * all). * @timeout: time, in microseconds, to wait for a new notice (zero to return * immediately). * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get notifications that have occurred / are occurring on the * snap daemon. * * The @since_date_time field, being a GDateTime, has a resolution of * microseconds, so, if nanosecond resolution is needed, it is mandatory to call * #snapd_client_notices_set_after_notice before calling this method. * * Since: 1.65 */ void snapd_client_get_notices_async(SnapdClient *self, GDateTime *since_date_time, GTimeSpan timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); snapd_client_get_notices_with_filters_async(self, NULL, NULL, NULL, NULL, since_date_time, timeout, cancellable, callback, user_data); } /** * snapd_client_get_notices_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_notices_async(). * * Returns: (transfer container) (element-type SnapdNotice): a #GPtrArray object * containing the requested notices, or NULL in case of error. * * Since: 1.65 */ GPtrArray *snapd_client_get_notices_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_NOTICES(result), NULL); SnapdGetNotices *request = SNAPD_GET_NOTICES(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_ptr_array_ref(_snapd_get_notices_get_notices(request)); } /** * snapd_client_get_notices_with_filters_async: * @client: a #SnapdClient. * @user_id: filter by this user-id (NULL for no filter). * @users: filter by this comma-separated list of users (NULL for no filter). * @types: filter by this comma-separated list of types (NULL for no filter). * @keys: filter by this comma-separated list of keys (NULL for no filter). * @since_date_time: send only the notices generated after this moment (NULL for * all). * @timeout: time, in microseconds, to wait for a new notice (zero to return * immediately). * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get notifications that have occurred / are occurring on the * snap daemon, allowing to filter the results with several options. * * The @since_date_time field, being a GDateTime, has a resolution of * microseconds, so, if nanosecond resolution is needed, it is mandatory to call * #snapd_client_notices_set_after_notice before calling this method. * * Since: 1.65 */ void snapd_client_get_notices_with_filters_async( SnapdClient *self, gchar *user_id, gchar *users, gchar *types, gchar *keys, GDateTime *since_date_time, GTimeSpan timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); SnapdClientPrivate *priv = snapd_client_get_instance_private(self); g_autoptr(SnapdGetNotices) request = _snapd_get_notices_new(user_id, users, types, keys, since_date_time, priv->since_date_time_nanoseconds, timeout, cancellable, callback, user_data); // reset the nanoseconds value, to ensure that the wrong value isn't used // in subsequent calls. priv->since_date_time_nanoseconds = -1; send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_notices_with_filters_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_notices_with_filters_async(). * * Returns: (transfer container) (element-type SnapdNotice): a #GPtrArray object * containing the requested notices, or NULL in case of error. * * Since: 1.65 */ GPtrArray *snapd_client_get_notices_with_filters_finish(SnapdClient *self, GAsyncResult *result, GError **error) { return snapd_client_get_notices_finish(self, result, error); } /** * snapd_client_notices_set_after_notice: * @client: a #SnapdClient * @notice: the last #SnapdNotice received, to get all the notices after it. * * Allows to set the "since" parameter with nanosecond accuracy when doing a * call to get the notices. This is currently needed because GDateTime has only * an accuracy of 1 microsecond, but to receive notice events correctly, without * loosing any of them, an accuracy of 1 nanosecond is needed in the value * passed on in the @since_date_time parameter. * * The value is "reset" after any call to snapd_client_get_notices_*(), so it * must be set again always before doing any of those calls. * * Passing NULL will reset the value too, in which case the mili- and * micro-seconds defined in the @since_date_time parameter will be used. * * Since: 1.66 */ void snapd_client_notices_set_after_notice(SnapdClient *self, SnapdNotice *notice) { g_return_if_fail(SNAPD_IS_CLIENT(self)); SnapdClientPrivate *priv = snapd_client_get_instance_private(self); priv->since_date_time_nanoseconds = (notice == NULL) ? -1 : snapd_notice_get_last_occurred_nanoseconds(notice); } /** * snapd_client_notices_set_since_nanoseconds: * @client: a #SnapdClient * @nanoseconds: the nanoseconds value to use to combine with the * #since_date_time property to filter notices after it * * Allows to set the "since" parameter with nanosecond accuracy when doing a * call to get the notices. This is currently needed because GDateTime has only * an accuracy of 1 microsecond, but to receive notice events correctly, without * loosing any, it is needed 1 nanosecond accuracy in the value passed on in the * @since_date_time parameter. * * The value is "reset" after any call to snapd_client_get_notices_*(), so it * must be set always before doing any of those calls. * * Passing NULL will reset the value too, in which case the mili- and * micro-seconds defined in the @since_date_time parameter will be used. * * Since: 1.66 */ void snapd_client_notices_set_since_nanoseconds(SnapdClient *self, int nanoseconds) { g_return_if_fail(SNAPD_IS_CLIENT(self)); SnapdClientPrivate *priv = snapd_client_get_instance_private(self); priv->since_date_time_nanoseconds = nanoseconds; } /** * snapd_client_get_changes_async: * @client: a #SnapdClient. * @filter: changes to filter on. * @snap_name: (allow-none): name of snap to filter on or %NULL for changes for * any snap. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get changes that have occurred / are occurring on the snap * daemon. See snapd_client_get_changes_sync() for more information. * * Since: 1.29 */ void snapd_client_get_changes_async(SnapdClient *self, SnapdChangeFilter filter, const gchar *snap_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); const gchar *select = NULL; switch (filter) { case SNAPD_CHANGE_FILTER_ALL: select = "all"; break; case SNAPD_CHANGE_FILTER_IN_PROGRESS: select = "in-progress"; break; case SNAPD_CHANGE_FILTER_READY: select = "ready"; break; } g_autoptr(SnapdGetChanges) request = _snapd_get_changes_new( select, snap_name, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_changes_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_changes_async(). * See snapd_client_get_changes_sync() for more information. * * Returns: (transfer container) (element-type SnapdChange): an array of * #SnapdChange or %NULL on error. * * Since: 1.29 */ GPtrArray *snapd_client_get_changes_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_CHANGES(result), NULL); SnapdGetChanges *request = SNAPD_GET_CHANGES(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_ptr_array_ref(_snapd_get_changes_get_changes(request)); } /** * snapd_client_get_change_async: * @client: a #SnapdClient. * @id: a change ID to get information on. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get information on a change. * See snapd_client_get_change_sync() for more information. * * Since: 1.29 */ void snapd_client_get_change_async(SnapdClient *self, const gchar *id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(id != NULL); g_autoptr(SnapdGetChange) request = _snapd_get_change_new(id, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_change_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_change_async(). * See snapd_client_get_change_sync() for more information. * * Returns: (transfer full): a #SnapdChange or %NULL on error. * * Since: 1.29 */ SnapdChange *snapd_client_get_change_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_CHANGE(result), NULL); SnapdGetChange *request = SNAPD_GET_CHANGE(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; SnapdChange *change = _snapd_get_change_get_change(request); return change == NULL ? NULL : g_object_ref(change); } /** * snapd_client_abort_change_async: * @client: a #SnapdClient. * @id: a change ID to abort. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously abort a change. * See snapd_client_abort_change_sync() for more information. * * Since: 1.30 */ void snapd_client_abort_change_async(SnapdClient *self, const gchar *id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(id != NULL); g_autoptr(SnapdPostChange) request = _snapd_post_change_new(id, "abort", cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_abort_change_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_abort_change_async(). * See snapd_client_abort_change_sync() for more information. * * Returns: (transfer full): a #SnapdChange or %NULL on error. * * Since: 1.30 */ SnapdChange *snapd_client_abort_change_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_POST_CHANGE(result), NULL); SnapdPostChange *request = SNAPD_POST_CHANGE(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_object_ref(_snapd_post_change_get_change(request)); } /** * snapd_client_get_system_information_async: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Request system information asynchronously from snapd. * See snapd_client_get_system_information_sync() for more information. * * Since: 1.0 */ void snapd_client_get_system_information_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetSystemInfo) request = _snapd_get_system_info_new(cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_system_information_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_system_information_async(). * See snapd_client_get_system_information_sync() for more information. * * Returns: (transfer full): a #SnapdSystemInformation or %NULL on error. * * Since: 1.0 */ SnapdSystemInformation *snapd_client_get_system_information_finish( SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_SYSTEM_INFO(result), NULL); SnapdGetSystemInfo *request = SNAPD_GET_SYSTEM_INFO(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_object_ref(_snapd_get_system_info_get_system_information(request)); } /** * snapd_client_list_one_async: * @client: a #SnapdClient. * @name: name of snap to get. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get information of a single installed snap. * See snapd_client_list_one_sync() for more information. * * Since: 1.0 * Deprecated: 1.42: Use snapd_client_get_snap_async() */ void snapd_client_list_one_async(SnapdClient *self, const gchar *name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return snapd_client_get_snap_async(self, name, cancellable, callback, user_data); } /** * snapd_client_list_one_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_list_one_async(). * See snapd_client_list_one_sync() for more information. * * Returns: (transfer full): a #SnapdSnap or %NULL on error. * * Since: 1.0 * Deprecated: 1.42: Use snapd_client_get_snap_finish() */ SnapdSnap *snapd_client_list_one_finish(SnapdClient *self, GAsyncResult *result, GError **error) { return snapd_client_get_snap_finish(self, result, error); } /** * snapd_client_get_snap_async: * @client: a #SnapdClient. * @name: name of snap to get. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get information of a single installed snap. * See snapd_client_get_snap_sync() for more information. * * Since: 1.42 */ void snapd_client_get_snap_async(SnapdClient *self, const gchar *name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetSnap) request = _snapd_get_snap_new(name, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_snap_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_snap_async(). * See snapd_client_get_snap_sync() for more information. * * Returns: (transfer full): a #SnapdSnap or %NULL on error. * * Since: 1.42 */ SnapdSnap *snapd_client_get_snap_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_SNAP(result), NULL); SnapdGetSnap *request = SNAPD_GET_SNAP(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_object_ref(_snapd_get_snap_get_snap(request)); } /** * snapd_client_get_snap_conf_async: * @client: a #SnapdClient. * @name: name of snap to get configuration from. * @keys: (allow-none): keys to returns or %NULL to return all. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get configuration for a snap. * See snapd_client_get_snap_conf_sync() for more information. * * Since: 1.48 */ void snapd_client_get_snap_conf_async(SnapdClient *self, const gchar *name, GStrv keys, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(name != NULL); g_autoptr(SnapdGetSnapConf) request = _snapd_get_snap_conf_new(name, keys, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_snap_conf_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_snap_conf_async(). * See snapd_client_get_snap_conf_sync() for more information. * * Returns: (transfer container) (element-type utf8 GVariant): a table of * configuration values or %NULL on error. * * Since: 1.48 */ GHashTable *snapd_client_get_snap_conf_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_SNAP_CONF(result), NULL); SnapdGetSnapConf *request = SNAPD_GET_SNAP_CONF(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_hash_table_ref(_snapd_get_snap_conf_get_conf(request)); } /** * snapd_client_set_snap_conf_async: * @client: a #SnapdClient. * @name: name of snap to set configuration for. * @key_values: (element-type utf8 GVariant): Keys to set. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously set configuration for a snap. * See snapd_client_set_snap_conf_sync() for more information. * * Since: 1.48 */ void snapd_client_set_snap_conf_async(SnapdClient *self, const gchar *name, GHashTable *key_values, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(name != NULL); g_return_if_fail(key_values != NULL); g_autoptr(SnapdPutSnapConf) request = _snapd_put_snap_conf_new( name, key_values, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_set_snap_conf_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_set_snap_conf_async(). * See snapd_client_set_snap_conf_sync() for more information. * * Returns: %TRUE if configuration successfully applied. * * Since: 1.48 */ gboolean snapd_client_set_snap_conf_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_PUT_SNAP_CONF(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_get_apps_async: * @client: a #SnapdClient. * @flags: a set of #SnapdGetAppsFlags to control what results are returned. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get information on installed apps. * See snapd_client_get_apps_sync() for more information. * * Since: 1.25 * Deprecated: 1.45: Use snapd_client_get_apps2_async() */ void snapd_client_get_apps_async(SnapdClient *self, SnapdGetAppsFlags flags, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return snapd_client_get_apps2_async(self, flags, NULL, cancellable, callback, user_data); } /** * snapd_client_get_apps_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_apps_async(). * See snapd_client_get_apps_sync() for more information. * * Returns: (transfer container) (element-type SnapdApp): an array of #SnapdApp * or %NULL on error. * * Since: 1.25 * Deprecated: 1.45: Use snapd_client_get_apps2_finish() */ GPtrArray *snapd_client_get_apps_finish(SnapdClient *self, GAsyncResult *result, GError **error) { return snapd_client_get_apps2_finish(self, result, error); } /** * snapd_client_get_apps2_async: * @client: a #SnapdClient. * @flags: a set of #SnapdGetAppsFlags to control what results are returned. * @snaps: (allow-none): A list of snap names to return results for. If %NULL or * empty then apps for all installed snaps are returned. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get information on installed apps. * See snapd_client_get_apps2_sync() for more information. * * Since: 1.45 */ void snapd_client_get_apps2_async(SnapdClient *self, SnapdGetAppsFlags flags, GStrv snaps, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetApps) request = _snapd_get_apps_new(snaps, cancellable, callback, user_data); if ((flags & SNAPD_GET_APPS_FLAGS_SELECT_SERVICES) != 0) _snapd_get_apps_set_select(request, "service"); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_apps2_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_apps2_async(). * See snapd_client_get_apps2_sync() for more information. * * Returns: (transfer container) (element-type SnapdApp): an array of #SnapdApp * or %NULL on error. * * Since: 1.45 */ GPtrArray *snapd_client_get_apps2_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_APPS(result), NULL); SnapdGetApps *request = SNAPD_GET_APPS(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_ptr_array_ref(_snapd_get_apps_get_apps(request)); } /** * snapd_client_get_icon_async: * @client: a #SnapdClient. * @name: name of snap to get icon for. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get the icon for an installed snap. * See snapd_client_get_icon_sync() for more information. * * Since: 1.0 */ void snapd_client_get_icon_async(SnapdClient *self, const gchar *name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetIcon) request = _snapd_get_icon_new(name, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_icon_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_icon_async(). * See snapd_client_get_icon_sync() for more information. * * Returns: (transfer full): a #SnapdIcon or %NULL on error. * * Since: 1.0 */ SnapdIcon *snapd_client_get_icon_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_ICON(result), NULL); SnapdGetIcon *request = SNAPD_GET_ICON(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_object_ref(_snapd_get_icon_get_icon(request)); } /** * snapd_client_list_async: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get information on all installed snaps. * See snapd_client_list_sync() for more information. * * Since: 1.0 * Deprecated: 1.42: Use snapd_client_get_snaps_async() */ void snapd_client_list_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return snapd_client_get_snaps_async(self, SNAPD_GET_SNAPS_FLAGS_NONE, NULL, cancellable, callback, user_data); } /** * snapd_client_list_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_list_async(). * See snapd_client_list_sync() for more information. * * Returns: (transfer container) (element-type SnapdSnap): an array of * #SnapdSnap or %NULL on error. * * Since: 1.0 * Deprecated: 1.42: Use snapd_client_get_snaps_finish() */ GPtrArray *snapd_client_list_finish(SnapdClient *self, GAsyncResult *result, GError **error) { return snapd_client_get_snaps_finish(self, result, error); } /** * snapd_client_get_snaps_async: * @client: a #SnapdClient. * @flags: a set of #SnapdGetSnapsFlags to control what results are returned. * @names: (allow-none): A list of snap names to return results for. If %NULL or * empty then all installed snaps are returned. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get information on installed snaps. * See snapd_client_get_snaps_sync() for more information. * * When settings the @flags variable, only one of * SNAPD_GET_SNAPS_FLAGS_INCLUDE_INACTIVE and * SNAPD_GET_SNAPS_FLAGS_REFRESH_INHIBITED can be set. Setting both results in * an error. * * Since: 1.42 */ void snapd_client_get_snaps_async(SnapdClient *self, SnapdGetSnapsFlags flags, GStrv names, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { // SNAPD_GET_SNAPS_FLAGS_INCLUDE_INACTIVE and // SNAPD_GET_SNAPS_FLAGS_REFRESH_INHIBITED are mutually exclusive; only one can // be set. #define SNAPD_GET_SNAPS_FLAGS_EXCLUSIVE \ (SNAPD_GET_SNAPS_FLAGS_INCLUDE_INACTIVE | \ SNAPD_GET_SNAPS_FLAGS_REFRESH_INHIBITED) g_assert((flags & SNAPD_GET_SNAPS_FLAGS_EXCLUSIVE) != SNAPD_GET_SNAPS_FLAGS_EXCLUSIVE); #undef SNAPD_GET_SNAPS_FLAGS_EXCLUSIVE g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetSnaps) request = _snapd_get_snaps_new(cancellable, names, callback, user_data); if ((flags & SNAPD_GET_SNAPS_FLAGS_INCLUDE_INACTIVE) != 0) _snapd_get_snaps_set_select(request, "all"); if ((flags & SNAPD_GET_SNAPS_FLAGS_REFRESH_INHIBITED) != 0) _snapd_get_snaps_set_select(request, "refresh-inhibited"); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_snaps_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_snaps_async(). * See snapd_client_get_snaps_sync() for more information. * * Returns: (transfer container) (element-type SnapdSnap): an array of * #SnapdSnap or %NULL on error. * * Since: 1.42 */ GPtrArray *snapd_client_get_snaps_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_SNAPS(result), NULL); SnapdGetSnaps *request = SNAPD_GET_SNAPS(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_ptr_array_ref(_snapd_get_snaps_get_snaps(request)); } /** * snapd_client_get_assertions_async: * @client: a #SnapdClient. * @type: assertion type to get. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get assertions. * See snapd_client_get_assertions_sync() for more information. * * Since: 1.8 */ void snapd_client_get_assertions_async(SnapdClient *self, const gchar *type, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(type != NULL); g_autoptr(SnapdGetAssertions) request = _snapd_get_assertions_new(type, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_assertions_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_assertions_async(). * See snapd_client_get_assertions_sync() for more information. * * Returns: (transfer full) (array zero-terminated=1): an array of assertions or * %NULL on error. * * Since: 1.8 */ GStrv snapd_client_get_assertions_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_ASSERTIONS(result), NULL); SnapdGetAssertions *request = SNAPD_GET_ASSERTIONS(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_strdupv(_snapd_get_assertions_get_assertions(request)); } /** * snapd_client_add_assertions_async: * @client: a #SnapdClient. * @assertions: assertions to add. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously add an assertion. * See snapd_client_add_assertions_sync() for more information. * * Since: 1.8 */ void snapd_client_add_assertions_async(SnapdClient *self, GStrv assertions, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(assertions != NULL); g_autoptr(SnapdPostAssertions) request = _snapd_post_assertions_new(assertions, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_add_assertions_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_add_assertions_async(). * See snapd_client_add_assertions_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.8 */ gboolean snapd_client_add_assertions_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_ASSERTIONS(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_get_interfaces_async: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get the installed snap interfaces. * See snapd_client_get_interfaces_sync() for more information. * * Since: 1.0 * Deprecated: 1.48: Use snapd_client_get_connections2_async() */ void snapd_client_get_interfaces_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetInterfacesLegacy) request = _snapd_get_interfaces_legacy_new(cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_interfaces_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @plugs: (out) (allow-none) (transfer container) (element-type SnapdPlug): the * location to store the array of #SnapdPlug or %NULL. * @slots: (out) (allow-none) (transfer container) (element-type SnapdSlot): the * location to store the array of #SnapdSlot or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_interfaces_async(). * See snapd_client_get_interfaces_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 * Deprecated: 1.48: Use snapd_client_get_connections2_finish() */ gboolean snapd_client_get_interfaces_finish(SnapdClient *self, GAsyncResult *result, GPtrArray **plugs, GPtrArray **slots, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_GET_INTERFACES_LEGACY(result), FALSE); SnapdGetInterfacesLegacy *request = SNAPD_GET_INTERFACES_LEGACY(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return FALSE; if (plugs) *plugs = g_ptr_array_ref(_snapd_get_interfaces_legacy_get_plugs(request)); if (slots) *slots = g_ptr_array_ref(_snapd_get_interfaces_legacy_get_slots(request)); return TRUE; } /** * snapd_client_get_interfaces2_async: * @client: a #SnapdClient. * @flags: a set of #SnapdGetInterfacesFlags to control what information is * returned about the interfaces. * @names: (allow-none) (array zero-terminated=1): a null-terminated array of * interface names or %NULL. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get the installed snap interfaces. * See snapd_client_get_interfaces2_sync() for more information. * * Since: 1.48 */ void snapd_client_get_interfaces2_async(SnapdClient *self, SnapdGetInterfacesFlags flags, GStrv names, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetInterfaces) request = _snapd_get_interfaces_new(names, cancellable, callback, user_data); if ((flags & SNAPD_GET_INTERFACES_FLAGS_INCLUDE_DOCS) != 0) _snapd_get_interfaces_set_include_docs(request, TRUE); if ((flags & SNAPD_GET_INTERFACES_FLAGS_INCLUDE_PLUGS) != 0) _snapd_get_interfaces_set_include_plugs(request, TRUE); if ((flags & SNAPD_GET_INTERFACES_FLAGS_INCLUDE_SLOTS) != 0) _snapd_get_interfaces_set_include_slots(request, TRUE); if ((flags & SNAPD_GET_INTERFACES_FLAGS_ONLY_CONNECTED) != 0) _snapd_get_interfaces_set_only_connected(request, TRUE); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_interfaces2_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_interfaces2_async(). * See snapd_client_get_interfaces2_sync() for more information. * * Returns: (transfer container) (element-type SnapdInterface): an array of * #SnapdInterface or %NULL on error. * * Since: 1.48 */ GPtrArray *snapd_client_get_interfaces2_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_GET_INTERFACES(result), FALSE); SnapdGetInterfaces *request = SNAPD_GET_INTERFACES(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_ptr_array_ref(_snapd_get_interfaces_get_interfaces(request)); } /** * snapd_client_get_connections_async: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get the installed snap connections. * See snapd_client_get_connections_sync() for more information. * * Since: 1.48 * Deprecated: 1.49: Use snapd_client_get_connections2_async() */ void snapd_client_get_connections_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { snapd_client_get_connections2_async(self, SNAPD_GET_CONNECTIONS_FLAGS_NONE, NULL, NULL, cancellable, callback, user_data); } /** * snapd_client_get_connections_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @established: (out) (allow-none) (transfer container) (element-type SnapdConnection): * the location to store the array of connections or %NULL. * @undesired: (out) (allow-none) (transfer container) (element-type SnapdConnection): * the location to store the array of auto-connected * connections that have been manually disconnected or %NULL. * @plugs: (out) (allow-none) (transfer container) (element-type SnapdPlug): the * location to store the array of #SnapdPlug or %NULL. * @slots: (out) (allow-none) (transfer container) (element-type SnapdSlot): the * location to store the array of #SnapdSlot or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_connections_async(). * See snapd_client_get_connections_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.48 * Deprecated: 1.49: Use snapd_client_get_connections2_finish() */ gboolean snapd_client_get_connections_finish(SnapdClient *self, GAsyncResult *result, GPtrArray **established, GPtrArray **undesired, GPtrArray **plugs, GPtrArray **slots, GError **error) { return snapd_client_get_connections2_finish(self, result, established, undesired, plugs, slots, error); } /** * snapd_client_get_connections2_async: * @client: a #SnapdClient. * @flags: a set of #SnapdGetConnectionsFlags to control what results are * returned. * @snap: (allow-none): the name of the snap to get connections for or %NULL for * all snaps. * @interface: (allow-none): the name of the interface to get connections for or * %NULL for all interfaces. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get the installed snap connections. * See snapd_client_get_connections_sync() for more information. * * Since: 1.49 */ void snapd_client_get_connections2_async( SnapdClient *self, SnapdGetConnectionsFlags flags, const gchar *snap, const gchar *interface, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); const gchar *select = NULL; if ((flags & SNAPD_GET_CONNECTIONS_FLAGS_SELECT_ALL) != 0) select = "all"; g_autoptr(SnapdGetConnections) request = _snapd_get_connections_new( snap, interface, select, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_connections2_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @established: (out) (allow-none) (transfer container) (element-type SnapdConnection): * the location to store the array of connections or %NULL. * @undesired: (out) (allow-none) (transfer container) (element-type SnapdConnection): * the location to store the array of auto-connected * connections that have been manually disconnected or %NULL. * @plugs: (out) (allow-none) (transfer container) (element-type SnapdPlug): the * location to store the array of #SnapdPlug or %NULL. * @slots: (out) (allow-none) (transfer container) (element-type SnapdSlot): the * location to store the array of #SnapdSlot or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_connections_async(). * See snapd_client_get_connections_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.49 */ gboolean snapd_client_get_connections2_finish(SnapdClient *self, GAsyncResult *result, GPtrArray **established, GPtrArray **undesired, GPtrArray **plugs, GPtrArray **slots, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_GET_CONNECTIONS(result), FALSE); SnapdGetConnections *request = SNAPD_GET_CONNECTIONS(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return FALSE; if (established) *established = g_ptr_array_ref(_snapd_get_connections_get_established(request)); if (undesired) *undesired = g_ptr_array_ref(_snapd_get_connections_get_undesired(request)); if (plugs) *plugs = g_ptr_array_ref(_snapd_get_connections_get_plugs(request)); if (slots) *slots = g_ptr_array_ref(_snapd_get_connections_get_slots(request)); return TRUE; } /** * snapd_client_connect_interface_async: * @client: a #SnapdClient. * @plug_snap: name of snap containing plug. * @plug_name: name of plug to connect. * @slot_snap: name of snap containing socket. * @slot_name: name of slot to connect. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously connect two interfaces together. * See snapd_client_connect_interface_sync() for more information. * * Since: 1.0 */ void snapd_client_connect_interface_async( SnapdClient *self, const gchar *plug_snap, const gchar *plug_name, const gchar *slot_snap, const gchar *slot_name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdPostInterfaces) request = _snapd_post_interfaces_new( "connect", plug_snap, plug_name, slot_snap, slot_name, progress_callback, progress_callback_data, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_connect_interface_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_connect_interface_async(). * See snapd_client_connect_interface_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 */ gboolean snapd_client_connect_interface_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_INTERFACES(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_disconnect_interface_async: * @client: a #SnapdClient. * @plug_snap: name of snap containing plug. * @plug_name: name of plug to disconnect. * @slot_snap: name of snap containing socket. * @slot_name: name of slot to disconnect. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously disconnect two interfaces. * See snapd_client_disconnect_interface_sync() for more information. * * Since: 1.0 */ void snapd_client_disconnect_interface_async( SnapdClient *self, const gchar *plug_snap, const gchar *plug_name, const gchar *slot_snap, const gchar *slot_name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdPostInterfaces) request = _snapd_post_interfaces_new( "disconnect", plug_snap, plug_name, slot_snap, slot_name, progress_callback, progress_callback_data, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_disconnect_interface_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_disconnect_interface_async(). * See snapd_client_disconnect_interface_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 */ gboolean snapd_client_disconnect_interface_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_INTERFACES(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_find_async: * @client: a #SnapdClient. * @flags: a set of #SnapdFindFlags to control how the find is performed. * @query: (allow-none): query string to send or %NULL to return featured snaps. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously find snaps in the store. * See snapd_client_find_sync() for more information. * * Since: 1.0 */ void snapd_client_find_async(SnapdClient *self, SnapdFindFlags flags, const gchar *query, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(query != NULL); snapd_client_find_category_async(self, flags, NULL, query, cancellable, callback, user_data); } /** * snapd_client_find_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @suggested_currency: (out) (allow-none): location to store the ISO 4217 * currency that is suggested to purchase with. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_find_async(). * See snapd_client_find_sync() for more information. * * Returns: (transfer container) (element-type SnapdSnap): an array of * #SnapdSnap or %NULL on error. * * Since: 1.0 */ GPtrArray *snapd_client_find_finish(SnapdClient *self, GAsyncResult *result, gchar **suggested_currency, GError **error) { return snapd_client_find_category_finish(self, result, suggested_currency, error); } /** * snapd_client_find_section_async: * @client: a #SnapdClient. * @flags: a set of #SnapdFindFlags to control how the find is performed. * @section: (allow-none): store section to search in or %NULL to search in all * sections. * @query: (allow-none): query string to send or %NULL to get all snaps from the * given section. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously find snaps in the store. * See snapd_client_find_section_sync() for more information. * * Since: 1.7 * Deprecated: 1.64: Use snapd_client_find_category_async() */ void snapd_client_find_section_async(SnapdClient *self, SnapdFindFlags flags, const gchar *section, const gchar *query, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetFind) request = _snapd_get_find_new(cancellable, callback, user_data); if ((flags & SNAPD_FIND_FLAGS_MATCH_NAME) != 0) _snapd_get_find_set_name(request, query); else if ((flags & SNAPD_FIND_FLAGS_MATCH_COMMON_ID) != 0) _snapd_get_find_set_common_id(request, query); else _snapd_get_find_set_query(request, query); if ((flags & SNAPD_FIND_FLAGS_SELECT_PRIVATE) != 0) _snapd_get_find_set_select(request, "private"); else if ((flags & SNAPD_FIND_FLAGS_SELECT_REFRESH) != 0) _snapd_get_find_set_select(request, "refresh"); else if ((flags & SNAPD_FIND_FLAGS_SCOPE_WIDE) != 0) _snapd_get_find_set_scope(request, "wide"); _snapd_get_find_set_section(request, section); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_find_section_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @suggested_currency: (out) (allow-none): location to store the ISO 4217 * currency that is suggested to purchase with. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_find_async(). * See snapd_client_find_sync() for more information. * * Returns: (transfer container) (element-type SnapdSnap): an array of * #SnapdSnap or %NULL on error. * * Since: 1.7 * Deprecated: 1.64: Use snapd_client_find_category_finish() */ GPtrArray *snapd_client_find_section_finish(SnapdClient *self, GAsyncResult *result, gchar **suggested_currency, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_FIND(result), NULL); SnapdGetFind *request = SNAPD_GET_FIND(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; if (suggested_currency != NULL) *suggested_currency = g_strdup(_snapd_get_find_get_suggested_currency(request)); return g_ptr_array_ref(_snapd_get_find_get_snaps(request)); } /** * snapd_client_find_category_async: * @client: a #SnapdClient. * @flags: a set of #SnapdFindFlags to control how the find is performed. * @category: (allow-none): store category to search in or %NULL to search in * all categories. * @query: (allow-none): query string to send or %NULL to get all snaps from the * given category. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously find snaps in the store. * See snapd_client_find_category_sync() for more information. * * Since: 1.64 */ void snapd_client_find_category_async(SnapdClient *self, SnapdFindFlags flags, const gchar *category, const gchar *query, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetFind) request = _snapd_get_find_new(cancellable, callback, user_data); if ((flags & SNAPD_FIND_FLAGS_MATCH_NAME) != 0) _snapd_get_find_set_name(request, query); else if ((flags & SNAPD_FIND_FLAGS_MATCH_COMMON_ID) != 0) _snapd_get_find_set_common_id(request, query); else _snapd_get_find_set_query(request, query); if ((flags & SNAPD_FIND_FLAGS_SELECT_PRIVATE) != 0) _snapd_get_find_set_select(request, "private"); else if ((flags & SNAPD_FIND_FLAGS_SELECT_REFRESH) != 0) _snapd_get_find_set_select(request, "refresh"); else if ((flags & SNAPD_FIND_FLAGS_SCOPE_WIDE) != 0) _snapd_get_find_set_scope(request, "wide"); _snapd_get_find_set_category(request, category); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_find_category_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @suggested_currency: (out) (allow-none): location to store the ISO 4217 * currency that is suggested to purchase with. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_find_async(). * See snapd_client_find_sync() for more information. * * Returns: (transfer container) (element-type SnapdSnap): an array of * #SnapdSnap or %NULL on error. * * Since: 1.64 */ GPtrArray *snapd_client_find_category_finish(SnapdClient *self, GAsyncResult *result, gchar **suggested_currency, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_FIND(result), NULL); SnapdGetFind *request = SNAPD_GET_FIND(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; if (suggested_currency != NULL) *suggested_currency = g_strdup(_snapd_get_find_get_suggested_currency(request)); return g_ptr_array_ref(_snapd_get_find_get_snaps(request)); } /** * snapd_client_find_refreshable_async: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously find snaps in store that are newer revisions than locally * installed versions. See snapd_client_find_refreshable_sync() for more * information. * * Since: 1.8 */ void snapd_client_find_refreshable_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetFind) request = _snapd_get_find_new(cancellable, callback, user_data); _snapd_get_find_set_select(request, "refresh"); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_find_refreshable_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_find_refreshable_async(). * See snapd_client_find_refreshable_sync() for more information. * * Returns: (transfer container) (element-type SnapdSnap): an array of * #SnapdSnap or %NULL on error. * * Since: 1.5 */ GPtrArray *snapd_client_find_refreshable_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_FIND(result), NULL); SnapdGetFind *request = SNAPD_GET_FIND(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_ptr_array_ref(_snapd_get_find_get_snaps(request)); } /** * snapd_client_install_async: * @client: a #SnapdClient. * @name: name of snap to install. * @channel: (allow-none): channel to install from or %NULL for default. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously install a snap from the store. * See snapd_client_install_sync() for more information. * * Since: 1.0 * Deprecated: 1.12: Use snapd_client_install2_async() */ void snapd_client_install_async(SnapdClient *self, const gchar *name, const gchar *channel, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { snapd_client_install2_async(self, SNAPD_INSTALL_FLAGS_NONE, name, channel, NULL, progress_callback, progress_callback_data, cancellable, callback, user_data); } /** * snapd_client_install_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_install_async(). * See snapd_client_install_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 * Deprecated: 1.12: Use snapd_client_install2_finish() */ gboolean snapd_client_install_finish(SnapdClient *self, GAsyncResult *result, GError **error) { return snapd_client_install2_finish(self, result, error); } /** * snapd_client_install2_async: * @client: a #SnapdClient. * @flags: a set of #SnapdInstallFlags to control install options. * @name: name of snap to install. * @channel: (allow-none): channel to install from or %NULL for default. * @revision: (allow-none): revision to install or %NULL for default. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously install a snap from the store. * See snapd_client_install2_sync() for more information. * * Since: 1.12 */ void snapd_client_install2_async(SnapdClient *self, SnapdInstallFlags flags, const gchar *name, const gchar *channel, const gchar *revision, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(name != NULL); g_autoptr(SnapdPostSnap) request = _snapd_post_snap_new( name, "install", progress_callback, progress_callback_data, cancellable, callback, user_data); _snapd_post_snap_set_channel(request, channel); _snapd_post_snap_set_revision(request, revision); if ((flags & SNAPD_INSTALL_FLAGS_CLASSIC) != 0) _snapd_post_snap_set_classic(request, TRUE); if ((flags & SNAPD_INSTALL_FLAGS_DANGEROUS) != 0) _snapd_post_snap_set_dangerous(request, TRUE); if ((flags & SNAPD_INSTALL_FLAGS_DEVMODE) != 0) _snapd_post_snap_set_devmode(request, TRUE); if ((flags & SNAPD_INSTALL_FLAGS_JAILMODE) != 0) _snapd_post_snap_set_jailmode(request, TRUE); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_install2_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_install2_async(). * See snapd_client_install2_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.12 */ gboolean snapd_client_install2_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_SNAP(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } typedef struct { SnapdClient *client; SnapdPostSnapStream *request; GCancellable *cancellable; GInputStream *stream; } InstallStreamData; static InstallStreamData *install_stream_data_new(SnapdClient *client, SnapdPostSnapStream *request, GCancellable *cancellable, GInputStream *stream) { InstallStreamData *data = g_slice_new(InstallStreamData); data->client = g_object_ref(client); data->request = g_object_ref(request); data->cancellable = cancellable != NULL ? g_object_ref(cancellable) : NULL; data->stream = g_object_ref(stream); return data; } static void install_stream_data_free(InstallStreamData *data) { g_object_unref(data->client); g_object_unref(data->request); if (data->cancellable != NULL) g_object_unref(data->cancellable); g_object_unref(data->stream); g_slice_free(InstallStreamData, data); } G_DEFINE_AUTOPTR_CLEANUP_FUNC(InstallStreamData, install_stream_data_free) static void stream_read_cb(GObject *source_object, GAsyncResult *result, gpointer user_data) { g_autoptr(InstallStreamData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GBytes) read_data = g_input_stream_read_bytes_finish(data->stream, result, &error); if (!_snapd_request_propagate_error(SNAPD_REQUEST(data->request), &error)) return; if (g_bytes_get_size(read_data) == 0) send_request(data->client, SNAPD_REQUEST(data->request)); else { _snapd_post_snap_stream_append_data(data->request, g_bytes_get_data(read_data, NULL), g_bytes_get_size(read_data)); InstallStreamData *d = g_steal_pointer(&data); g_input_stream_read_bytes_async(d->stream, 65535, G_PRIORITY_DEFAULT, d->cancellable, stream_read_cb, d); } } /** * snapd_client_install_stream_async: * @client: a #SnapdClient. * @flags: a set of #SnapdInstallFlags to control install options. * @stream: a #GInputStream containing the snap file contents to install. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously install a snap. * See snapd_client_install_stream_sync() for more information. * * Since: 1.9 */ void snapd_client_install_stream_async( SnapdClient *self, SnapdInstallFlags flags, GInputStream *stream, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(G_IS_INPUT_STREAM(stream)); g_autoptr(SnapdPostSnapStream) request = _snapd_post_snap_stream_new(progress_callback, progress_callback_data, cancellable, callback, user_data); if ((flags & SNAPD_INSTALL_FLAGS_CLASSIC) != 0) _snapd_post_snap_stream_set_classic(request, TRUE); if ((flags & SNAPD_INSTALL_FLAGS_DANGEROUS) != 0) _snapd_post_snap_stream_set_dangerous(request, TRUE); if ((flags & SNAPD_INSTALL_FLAGS_DEVMODE) != 0) _snapd_post_snap_stream_set_devmode(request, TRUE); if ((flags & SNAPD_INSTALL_FLAGS_JAILMODE) != 0) _snapd_post_snap_stream_set_jailmode(request, TRUE); g_input_stream_read_bytes_async( stream, 65535, G_PRIORITY_DEFAULT, cancellable, stream_read_cb, install_stream_data_new(self, request, cancellable, stream)); } /** * snapd_client_install_stream_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_install_stream_async(). * See snapd_client_install_stream_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.9 */ gboolean snapd_client_install_stream_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_SNAP_STREAM(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_try_async: * @client: a #SnapdClient. * @path: path to snap directory to try. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously try a snap. * See snapd_client_try_sync() for more information. * * Since: 1.9 */ void snapd_client_try_async(SnapdClient *self, const gchar *path, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(path != NULL); g_autoptr(SnapdPostSnapTry) request = _snapd_post_snap_try_new(path, progress_callback, progress_callback_data, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_try_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_try_async(). * See snapd_client_try_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.9 */ gboolean snapd_client_try_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_SNAP_TRY(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_refresh_async: * @client: a #SnapdClient. * @name: name of snap to refresh. * @channel: (allow-none): channel to refresh from or %NULL for default. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously ensure an installed snap is at the latest version. * See snapd_client_refresh_sync() for more information. * * Since: 1.0 */ void snapd_client_refresh_async(SnapdClient *self, const gchar *name, const gchar *channel, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(name != NULL); g_autoptr(SnapdPostSnap) request = _snapd_post_snap_new( name, "refresh", progress_callback, progress_callback_data, cancellable, callback, user_data); _snapd_post_snap_set_channel(request, channel); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_refresh_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_refresh_async(). * See snapd_client_refresh_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 */ gboolean snapd_client_refresh_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_SNAP(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_refresh_all_async: * @client: a #SnapdClient. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously ensure all snaps are updated to their latest versions. * See snapd_client_refresh_all_sync() for more information. * * Since: 1.5 */ void snapd_client_refresh_all_async(SnapdClient *self, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdPostSnaps) request = _snapd_post_snaps_new( "refresh", progress_callback, progress_callback_data, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_refresh_all_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_refresh_all_async(). * See snapd_client_refresh_all_sync() for more information. * * Returns: (transfer full): a %NULL-terminated array of the snap names * refreshed or %NULL on error. * * Since: 1.5 */ GStrv snapd_client_refresh_all_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_SNAPS(result), FALSE); SnapdPostSnaps *request = SNAPD_POST_SNAPS(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_strdupv(_snapd_post_snaps_get_snap_names(request)); } /** * snapd_client_remove_async: * @client: a #SnapdClient. * @name: name of snap to remove. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously uninstall a snap. * See snapd_client_remove_sync() for more information. * * Since: 1.0 * Deprecated 1.50: Use snapd_client_remove2_async() */ void snapd_client_remove_async(SnapdClient *self, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { snapd_client_remove2_async(self, SNAPD_REMOVE_FLAGS_NONE, name, progress_callback, progress_callback_data, cancellable, callback, user_data); } /** * snapd_client_remove_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_remove_async(). * See snapd_client_remove_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 * Deprecated 1.50: Use snapd_client_remove2_finish() */ gboolean snapd_client_remove_finish(SnapdClient *self, GAsyncResult *result, GError **error) { return snapd_client_remove2_finish(self, result, error); } /** * snapd_client_remove2_async: * @client: a #SnapdClient. * @flags: a set of #SnapdRemoveFlags to control remove options. * @name: name of snap to remove. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously uninstall a snap. * See snapd_client_remove2_sync() for more information. * * Since: 1.50 */ void snapd_client_remove2_async(SnapdClient *self, SnapdRemoveFlags flags, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(name != NULL); g_autoptr(SnapdPostSnap) request = _snapd_post_snap_new( name, "remove", progress_callback, progress_callback_data, cancellable, callback, user_data); if ((flags & SNAPD_REMOVE_FLAGS_PURGE) != 0) _snapd_post_snap_set_purge(request, TRUE); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_remove2_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_remove2_async(). * See snapd_client_remove2_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.50 */ gboolean snapd_client_remove2_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_SNAP(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_enable_async: * @client: a #SnapdClient. * @name: name of snap to enable. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously enable an installed snap. * See snapd_client_enable_sync() for more information. * * Since: 1.0 */ void snapd_client_enable_async(SnapdClient *self, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(name != NULL); g_autoptr(SnapdPostSnap) request = _snapd_post_snap_new( name, "enable", progress_callback, progress_callback_data, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_enable_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_enable_async(). * See snapd_client_enable_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 */ gboolean snapd_client_enable_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_SNAP(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_disable_async: * @client: a #SnapdClient. * @name: name of snap to disable. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously disable an installed snap. * See snapd_client_disable_sync() for more information. * * Since: 1.0 */ void snapd_client_disable_async(SnapdClient *self, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(name != NULL); g_autoptr(SnapdPostSnap) request = _snapd_post_snap_new( name, "disable", progress_callback, progress_callback_data, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_disable_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_disable_async(). * See snapd_client_disable_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.0 */ gboolean snapd_client_disable_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_SNAP(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_switch_async: * @client: a #SnapdClient. * @name: name of snap to switch channel. * @channel: channel to track. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously set the tracking channel on an installed snap. * See snapd_client_switch_sync() for more information. * * Since: 1.26 */ void snapd_client_switch_async(SnapdClient *self, const gchar *name, const gchar *channel, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(name != NULL); g_autoptr(SnapdPostSnap) request = _snapd_post_snap_new( name, "switch", progress_callback, progress_callback_data, cancellable, callback, user_data); _snapd_post_snap_set_channel(request, channel); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_switch_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_switch_async(). * See snapd_client_switch_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.26 */ gboolean snapd_client_switch_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_SNAP(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_check_buy_async: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously check if able to buy snaps. * See snapd_client_check_buy_sync() for more information. * * Since: 1.3 */ void snapd_client_check_buy_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetBuyReady) request = _snapd_get_buy_ready_new(cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_check_buy_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_check_buy_async(). * See snapd_client_check_buy_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.3 */ gboolean snapd_client_check_buy_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_GET_BUY_READY(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_buy_async: * @client: a #SnapdClient. * @id: id of snap to buy. * @amount: amount of currency to spend, e.g. 0.99. * @currency: the currency to buy with as an ISO 4217 currency code, e.g. "NZD". * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously buy a snap from the store. * See snapd_client_buy_sync() for more information. * * Since: 1.3 */ void snapd_client_buy_async(SnapdClient *self, const gchar *id, gdouble amount, const gchar *currency, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(id != NULL); g_return_if_fail(currency != NULL); g_autoptr(SnapdPostBuy) request = _snapd_post_buy_new( id, amount, currency, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_buy_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_buy_async(). * See snapd_client_buy_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.3 */ gboolean snapd_client_buy_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_BUY(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_create_user_async: * @client: a #SnapdClient. * @email: the email of the user to create. * @flags: a set of #SnapdCreateUserFlags to control how the user account is * created. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously create a local user account. * See snapd_client_create_user_sync() for more information. * * Since: 1.3 */ void snapd_client_create_user_async(SnapdClient *self, const gchar *email, SnapdCreateUserFlags flags, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(email != NULL); g_autoptr(SnapdPostCreateUser) request = _snapd_post_create_user_new(email, cancellable, callback, user_data); if ((flags & SNAPD_CREATE_USER_FLAGS_SUDO) != 0) _snapd_post_create_user_set_sudoer(request, TRUE); if ((flags & SNAPD_CREATE_USER_FLAGS_KNOWN) != 0) _snapd_post_create_user_set_known(request, TRUE); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_create_user_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_create_user_async(). * See snapd_client_create_user_sync() for more information. * * Returns: (transfer full): a #SnapdUserInformation or %NULL on error. * * Since: 1.3 */ SnapdUserInformation *snapd_client_create_user_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_POST_CREATE_USER(result), NULL); SnapdPostCreateUser *request = SNAPD_POST_CREATE_USER(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_object_ref(_snapd_post_create_user_get_user_information(request)); } /** * snapd_client_create_users_async: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously create local user accounts using the system-user assertions * that are valid for this device. See snapd_client_create_users_sync() for more * information. * * Since: 1.3 */ void snapd_client_create_users_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdPostCreateUsers) request = _snapd_post_create_users_new(cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_create_users_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_create_users_async(). * See snapd_client_create_users_sync() for more information. * * Returns: (transfer container) (element-type SnapdUserInformation): an array * of #SnapdUserInformation or %NULL on error. * * Since: 1.3 */ GPtrArray *snapd_client_create_users_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_POST_CREATE_USERS(result), NULL); SnapdPostCreateUsers *request = SNAPD_POST_CREATE_USERS(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_ptr_array_ref( _snapd_post_create_users_get_users_information(request)); } /** * snapd_client_get_users_async: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get user accounts that are valid for this device. * See snapd_client_get_users_sync() for more information. * * Since: 1.26 */ void snapd_client_get_users_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetUsers) request = _snapd_get_users_new(cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_users_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_users_async(). * See snapd_client_get_users_sync() for more information. * * Returns: (transfer container) (element-type SnapdUserInformation): an array * of #SnapdUserInformation or %NULL on error. * * Since: 1.26 */ GPtrArray *snapd_client_get_users_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_USERS(result), NULL); SnapdGetUsers *request = SNAPD_GET_USERS(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_ptr_array_ref(_snapd_get_users_get_users_information(request)); } /** * snapd_client_get_sections_async: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get the store sections. * See snapd_client_get_sections_sync() for more information. * * Since: 1.7 * Deprecated: 1.64: Use snapd_client_get_categories_async() */ void snapd_client_get_sections_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetSections) request = _snapd_get_sections_new(cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_sections_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_sections_async(). * See snapd_client_get_sections_sync() for more information. * * Returns: (transfer full) (array zero-terminated=1): an array of section names * or %NULL on error. * * Since: 1.7 * Deprecated: 1.64: Use snapd_client_get_categories_finish() */ GStrv snapd_client_get_sections_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_SECTIONS(result), NULL); SnapdGetSections *request = SNAPD_GET_SECTIONS(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_strdupv(_snapd_get_sections_get_sections(request)); } /** * snapd_client_get_categories_async: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get the store categories. * See snapd_client_get_categories_sync() for more information. * * Since: 1.64 */ void snapd_client_get_categories_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetCategories) request = _snapd_get_categories_new(cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_categories_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_categories_async(). * See snapd_client_get_categories_sync() for more information. * * Returns: (transfer container) (element-type SnapdCategoryDetails): an array * of #SnapdCategoryDetails or %NULL on error. * * Since: 1.64 */ GPtrArray *snapd_client_get_categories_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_CATEGORIES(result), NULL); SnapdGetCategories *request = SNAPD_GET_CATEGORIES(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_ptr_array_ref(_snapd_get_categories_get_categories(request)); } /** * snapd_client_get_aliases_async: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get the available aliases. * See snapd_client_get_aliases_sync() for more information. * * Since: 1.8 */ void snapd_client_get_aliases_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetAliases) request = _snapd_get_aliases_new(cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_aliases_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_aliases_async(). * See snapd_client_get_aliases_sync() for more information. * * Returns: (transfer container) (element-type SnapdAlias): an array of * #SnapdAlias or %NULL on error. * * Since: 1.8 */ GPtrArray *snapd_client_get_aliases_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_ALIASES(result), NULL); SnapdGetAliases *request = SNAPD_GET_ALIASES(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_ptr_array_ref(_snapd_get_aliases_get_aliases(request)); } static void send_change_aliases_request( SnapdClient *self, const gchar *action, const gchar *snap, const gchar *app, const gchar *alias, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_autoptr(SnapdPostAliases) request = _snapd_post_aliases_new( action, snap, app, alias, progress_callback, progress_callback_data, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_alias_async: * @client: a #SnapdClient. * @snap: the name of the snap to modify. * @app: an app in the snap to make the alias to. * @alias: the name of the alias (i.e. the command that will run this app). * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously create an alias to an app. * See snapd_client_alias_sync() for more information. * * Since: 1.25 */ void snapd_client_alias_async(SnapdClient *self, const gchar *snap, const gchar *app, const gchar *alias, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(snap != NULL); g_return_if_fail(app != NULL); g_return_if_fail(alias != NULL); send_change_aliases_request(self, "alias", snap, app, alias, progress_callback, progress_callback_data, cancellable, callback, user_data); } /** * snapd_client_alias_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_alias_async(). * See snapd_client_alias_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.25 */ gboolean snapd_client_alias_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_ALIASES(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_unalias_async: * @client: a #SnapdClient. * @snap: (allow-none): the name of the snap to modify or %NULL. * @alias: (allow-none): the name of the alias to remove or %NULL to remove all * aliases for the given snap. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously remove an alias from an app. * See snapd_client_unalias_sync() for more information. * * Since: 1.25 */ void snapd_client_unalias_async(SnapdClient *self, const gchar *snap, const gchar *alias, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(alias != NULL); send_change_aliases_request(self, "unalias", snap, NULL, alias, progress_callback, progress_callback_data, cancellable, callback, user_data); } /** * snapd_client_unalias_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_unalias_async(). * See snapd_client_unalias_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.25 */ gboolean snapd_client_unalias_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_ALIASES(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_prefer_async: * @client: a #SnapdClient. * @snap: the name of the snap to modify. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously ???. * See snapd_client_prefer_sync() for more information. * * Since: 1.25 */ void snapd_client_prefer_async(SnapdClient *self, const gchar *snap, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(snap != NULL); send_change_aliases_request(self, "prefer", snap, NULL, NULL, progress_callback, progress_callback_data, cancellable, callback, user_data); } /** * snapd_client_prefer_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_prefer_async(). * See snapd_client_prefer_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.25 */ gboolean snapd_client_prefer_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_ALIASES(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_enable_aliases_async: * @client: a #SnapdClient. * @snap: the name of the snap to modify. * @aliases: the aliases to modify. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously change the state of aliases. * See snapd_client_enable_aliases_sync() for more information. * * Since: 1.8 * Deprecated: 1.25: Use snapd_client_alias_async() */ void snapd_client_enable_aliases_async(SnapdClient *self, const gchar *snap, GStrv aliases, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(GTask) task = g_task_new(self, cancellable, callback, user_data); g_task_return_new_error(task, SNAPD_ERROR, SNAPD_ERROR_FAILED, "snapd_client_enable_aliases_async is deprecated"); } /** * snapd_client_enable_aliases_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_enable_aliases_async(). * See snapd_client_enable_aliases_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.8 * Deprecated: 1.25: Use snapd_client_unalias_finish() */ gboolean snapd_client_enable_aliases_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(g_task_is_valid(result, self), FALSE); return g_task_propagate_boolean(G_TASK(result), error); } /** * snapd_client_disable_aliases_async: * @client: a #SnapdClient. * @snap: the name of the snap to modify. * @aliases: the aliases to modify. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously change the state of aliases. * See snapd_client_disable_aliases_sync() for more information. * * Since: 1.8 * Deprecated: 1.25: Use snapd_client_unalias_async() */ void snapd_client_disable_aliases_async(SnapdClient *self, const gchar *snap, GStrv aliases, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(GTask) task = g_task_new(self, cancellable, callback, user_data); g_task_return_new_error(task, SNAPD_ERROR, SNAPD_ERROR_FAILED, "snapd_client_disable_aliases_async is deprecated"); } /** * snapd_client_disable_aliases_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_disable_aliases_async(). * See snapd_client_disable_aliases_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.8 * Deprecated: 1.25: Use snapd_client_unalias_finish() */ gboolean snapd_client_disable_aliases_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(g_task_is_valid(result, self), FALSE); return g_task_propagate_boolean(G_TASK(result), error); } /** * snapd_client_reset_aliases_async: * @client: a #SnapdClient. * @snap: the name of the snap to modify. * @aliases: the aliases to modify. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously change the state of aliases. * See snapd_client_reset_aliases_sync() for more information. * * Since: 1.8 * Deprecated: 1.25: Use snapd_client_disable_aliases_async() */ void snapd_client_reset_aliases_async(SnapdClient *self, const gchar *snap, GStrv aliases, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(GTask) task = g_task_new(self, cancellable, callback, user_data); g_task_return_new_error(task, SNAPD_ERROR, SNAPD_ERROR_FAILED, "snapd_client_reset_aliases_async is deprecated"); } /** * snapd_client_reset_aliases_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_reset_aliases_async(). * See snapd_client_reset_aliases_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.8 * Deprecated: 1.25: Use snapd_client_disable_aliases_finish() */ gboolean snapd_client_reset_aliases_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(g_task_is_valid(result, self), FALSE); return g_task_propagate_boolean(G_TASK(result), error); } /** * snapd_client_run_snapctl_async: * @client: a #SnapdClient. * @context_id: context for this call. * @args: the arguments to pass to snapctl. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously run a snapctl command. * See snapd_client_run_snapctl_sync() for more information. * * Since: 1.8 * Deprecated: 1.59: Use snapd_client_run_snapctl2_async() */ void snapd_client_run_snapctl_async(SnapdClient *self, const gchar *context_id, GStrv args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { return snapd_client_run_snapctl2_async(self, context_id, args, cancellable, callback, user_data); } /** * snapd_client_run_snapctl_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @stdout_output: (out) (allow-none): the location to write the stdout from the * command or %NULL. * @stderr_output: (out) (allow-none): the location to write the stderr from the * command or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_run_snapctl_async(). * See snapd_client_run_snapctl_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.8 * Deprecated: 1.59: Use snapd_client_run_snapctl2_finish() */ gboolean snapd_client_run_snapctl_finish(SnapdClient *self, GAsyncResult *result, gchar **stdout_output, gchar **stderr_output, GError **error) { g_return_val_if_fail(SNAPD_IS_POST_SNAPCTL(result), FALSE); SnapdPostSnapctl *request = SNAPD_POST_SNAPCTL(result); /* We need to return an error for unsuccessful commands to match old API */ if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return FALSE; return snapd_client_run_snapctl2_finish(self, result, stdout_output, stderr_output, NULL, error); } /** * snapd_client_run_snapctl2_async: * @client: a #SnapdClient. * @context_id: context for this call. * @args: the arguments to pass to snapctl. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously run a snapctl command. * See snapd_client_run_snapctl_sync() for more information. * * Since: 1.59 */ void snapd_client_run_snapctl2_async(SnapdClient *self, const gchar *context_id, GStrv args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(context_id != NULL); g_return_if_fail(args != NULL); g_autoptr(SnapdPostSnapctl) request = _snapd_post_snapctl_new( context_id, args, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_run_snapctl2_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @stdout_output: (out) (allow-none): the location to write the stdout from the * command or %NULL. * @stderr_output: (out) (allow-none): the location to write the stderr from the * command or %NULL. * @exit_code: (out) (allow-none): the location to write the exit code of the * command or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_run_snapctl2_async(). * See snapd_client_run_snapctl2_sync() for more information. * * Returns: %TRUE on success or %FALSE on error. * * Since: 1.59 */ gboolean snapd_client_run_snapctl2_finish(SnapdClient *self, GAsyncResult *result, gchar **stdout_output, gchar **stderr_output, int *exit_code, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_SNAPCTL(result), FALSE); SnapdPostSnapctl *request = SNAPD_POST_SNAPCTL(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) { if (g_error_matches(*error, SNAPD_ERROR, SNAPD_ERROR_UNSUCCESSFUL)) { /* Ignore unsuccessful errors */ g_clear_error(error); } else { return FALSE; } } if (stdout_output) *stdout_output = g_strdup(_snapd_post_snapctl_get_stdout_output(request)); if (stderr_output) *stderr_output = g_strdup(_snapd_post_snapctl_get_stderr_output(request)); if (exit_code) *exit_code = _snapd_post_snapctl_get_exit_code(request); return TRUE; } /** * snapd_client_download_async: * @client: a #SnapdClient. * @name: name of snap to download. * @channel: (allow-none): channel to download from. * @revision: (allow-none): revision to download. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously download a snap. * See snapd_client_download_sync() for more information. * * Since: 1.54 */ void snapd_client_download_async(SnapdClient *self, const gchar *name, const gchar *channel, const gchar *revision, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_return_if_fail(name != NULL); g_autoptr(SnapdPostDownload) request = _snapd_post_download_new( name, channel, revision, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_download_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_download_async(). * See snapd_client_download_sync() for more information. * * Returns: the snap contents or %NULL on error. * * Since: 1.54 */ GBytes *snapd_client_download_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_POST_DOWNLOAD(result), NULL); SnapdPostDownload *request = SNAPD_POST_DOWNLOAD(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_bytes_ref(_snapd_post_download_get_data(request)); } /** * snapd_client_check_themes_async: * @client: a #SnapdClient. * @gtk_theme_names: (allow-none): a list of GTK theme names. * @icon_theme_names: (allow-none): a list of icon theme names. * @sound_theme_names: (allow-none): a list of sound theme names. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously check for snaps providing the requested desktop themes. * See snapd_client_check_themes_sync() for more information. * * Since: 1.60 */ void snapd_client_check_themes_async(SnapdClient *self, GStrv gtk_theme_names, GStrv icon_theme_names, GStrv sound_theme_names, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetThemes) request = _snapd_get_themes_new( gtk_theme_names, icon_theme_names, sound_theme_names, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_check_themes_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @gtk_theme_status: (out) (transfer container) (element-type utf8 SnapdThemeStatus): * status of GTK themes. * @icon_theme_status: (out) (transfer container) (element-type utf8 SnapdThemeStatus): * status of icon themes. * @sound_theme_status: (out) (transfer container) (element-type utf8 SnapdThemeStatus): * status of sound themes. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_check_themes_async(). * See snapd_client_check_themes_sync() for more information. * * Returns: %TRUE on success. * * Since: 1.60 */ gboolean snapd_client_check_themes_finish(SnapdClient *self, GAsyncResult *result, GHashTable **gtk_theme_status, GHashTable **icon_theme_status, GHashTable **sound_theme_status, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_GET_THEMES(result), FALSE); SnapdGetThemes *request = SNAPD_GET_THEMES(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return FALSE; if (gtk_theme_status) *gtk_theme_status = g_hash_table_ref(_snapd_get_themes_get_gtk_theme_status(request)); if (icon_theme_status) *icon_theme_status = g_hash_table_ref(_snapd_get_themes_get_icon_theme_status(request)); if (sound_theme_status) *sound_theme_status = g_hash_table_ref(_snapd_get_themes_get_sound_theme_status(request)); return TRUE; } /** * snapd_client_install_themes_async: * @client: a #SnapdClient. * @gtk_theme_names: (allow-none): a list of GTK theme names. * @icon_theme_names: (allow-none): a list of icon theme names. * @sound_theme_names: (allow-none): a list of sound theme names. * @progress_callback: (allow-none) (scope call): function to callback with * progress. * @progress_callback_data: (closure): user data to pass to @progress_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously install snaps that provide the requested desktop themes. * See snapd_client_install_themes_sync() for more information. * * Since: 1.60 */ void snapd_client_install_themes_async( SnapdClient *self, GStrv gtk_theme_names, GStrv icon_theme_names, GStrv sound_theme_names, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdPostThemes) request = _snapd_post_themes_new( gtk_theme_names, icon_theme_names, sound_theme_names, progress_callback, progress_callback_data, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_install_themes_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_install_themes_async(). * See snapd_client_install_themes_sync() for more information. * * Returns: %TRUE on success. * * Since: 1.60 */ gboolean snapd_client_install_themes_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_POST_THEMES(result), FALSE); return _snapd_request_propagate_error(SNAPD_REQUEST(result), error); } /** * snapd_client_get_logs_async: * @client: a #SnapdClient. * @names: (allow-none) (array zero-terminated=1): a null-terminated array of * service names or %NULL. * @n: the number of logs to return or 0 for default. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get logs for snap services. * See snapd_client_get_logs_sync() for more information. * * Since: 1.64 */ void snapd_client_get_logs_async(SnapdClient *self, GStrv names, size_t n, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetLogs) request = _snapd_get_logs_new( names, n, FALSE, NULL, NULL, NULL, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_logs_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_logs_async(). * See snapd_client_get_logs_sync() for more information. * * Returns: (transfer container) (element-type SnapdLog): an array of #SnapdLog * or %NULL on error. * * Since: 1.64 */ GPtrArray *snapd_client_get_logs_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_LOGS(result), NULL); SnapdGetLogs *request = SNAPD_GET_LOGS(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_ptr_array_ref(_snapd_get_logs_get_logs(request)); } /** * snapd_client_follow_logs_async: * @client: a #SnapdClient. * @names: (allow-none) (array zero-terminated=1): a null-terminated array of * service names or %NULL. * @log_callback: (scope async): a #SnapdLogCallback to call when a log is * received. * @log_callback_data: (closure): the data to pass to @log_callback. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Follow logs for snap services. This call will only complete if snapd closes * the connection and will stop any other request on this client from being * sent. * * Since: 1.64 */ void snapd_client_follow_logs_async(SnapdClient *self, GStrv names, SnapdLogCallback log_callback, gpointer log_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetLogs) request = _snapd_get_logs_new( names, 0, TRUE, log_cb, follow_logs_data_new(self, log_callback, log_callback_data), (GDestroyNotify)follow_logs_data_free, cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_follow_logs_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_follow_logs_async(). * See snapd_client_follow_logs_sync() for more information. * * Returns: %TRUE on success. * * Since: 1.64 */ gboolean snapd_client_follow_logs_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), FALSE); g_return_val_if_fail(SNAPD_IS_GET_LOGS(result), FALSE); SnapdGetLogs *request = SNAPD_GET_LOGS(result); return _snapd_request_propagate_error(SNAPD_REQUEST(request), error); } /** * snapd_client_get_model_assertion_async: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Get the active model assertion for this device. * * Since: 1.67 */ void snapd_client_get_model_assertion_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetModel) request = _snapd_get_model_new(cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_model_assertion_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_model_assertion_async(). * See snapd_client_get_model_assertion_sync() for more information. * * Returns: (transfer full): an assertion or %NULL on error. * * Since: 1.67 */ gchar *snapd_client_get_model_assertion_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_MODEL(result), NULL); SnapdGetModel *request = SNAPD_GET_MODEL(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_strdup(_snapd_get_model_get_model_assertion(request)); } /** * snapd_client_get_serial_assertion_async: * @client: a #SnapdClient. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Get the active serial assertion for this device. * * Since: 1.67 */ void snapd_client_get_serial_assertion_async(SnapdClient *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(SNAPD_IS_CLIENT(self)); g_autoptr(SnapdGetModelSerial) request = _snapd_get_model_serial_new(cancellable, callback, user_data); send_request(self, SNAPD_REQUEST(request)); } /** * snapd_client_get_serial_assertion_finish: * @client: a #SnapdClient. * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete request started with snapd_client_get_serial_assertion_async(). * See snapd_client_get_serial_assertion_sync() for more information. * * Returns: (transfer full): an assertion or %NULL on error. * * Since: 1.67 */ gchar *snapd_client_get_serial_assertion_finish(SnapdClient *self, GAsyncResult *result, GError **error) { g_return_val_if_fail(SNAPD_IS_CLIENT(self), NULL); g_return_val_if_fail(SNAPD_IS_GET_MODEL_SERIAL(result), NULL); SnapdGetModelSerial *request = SNAPD_GET_MODEL_SERIAL(result); if (!_snapd_request_propagate_error(SNAPD_REQUEST(request), error)) return NULL; return g_strdup(_snapd_get_model_serial_get_serial_assertion(request)); } /** * snapd_client_new: * * Create a new client to talk to snapd. * * Returns: a new #SnapdClient * * Since: 1.0 **/ SnapdClient *snapd_client_new(void) { return g_object_new(SNAPD_TYPE_CLIENT, NULL); } /** * snapd_client_new_from_socket: * @socket: A #GSocket that is connected to snapd. * * Create a new client to talk on an existing socket. * * Returns: a new #SnapdClient * * Since: 1.5 **/ SnapdClient *snapd_client_new_from_socket(GSocket *socket) { SnapdClient *self = snapd_client_new(); SnapdClientPrivate *priv = snapd_client_get_instance_private(SNAPD_CLIENT(self)); priv->snapd_socket = g_object_ref(socket); g_socket_set_blocking(priv->snapd_socket, FALSE); return self; } static void snapd_client_finalize(GObject *object) { SnapdClientPrivate *priv = snapd_client_get_instance_private(SNAPD_CLIENT(object)); g_mutex_clear(&priv->requests_mutex); g_mutex_clear(&priv->buffer_mutex); g_clear_pointer(&priv->socket_path, g_free); g_clear_pointer(&priv->user_agent, g_free); g_clear_object(&priv->auth_data); g_clear_pointer(&priv->requests, g_ptr_array_unref); if (priv->snapd_socket != NULL) g_socket_close(priv->snapd_socket, NULL); g_clear_object(&priv->snapd_socket); g_clear_pointer(&priv->buffer, g_byte_array_unref); #if SOUP_CHECK_VERSION(2, 99, 2) g_clear_pointer(&priv->response_headers, soup_message_headers_unref); #else g_clear_pointer(&priv->response_headers, soup_message_headers_free); #endif g_clear_pointer(&priv->response_body, g_byte_array_unref); g_clear_object(&priv->maintenance); G_OBJECT_CLASS(snapd_client_parent_class)->finalize(object); } static void snapd_client_class_init(SnapdClientClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->finalize = snapd_client_finalize; } static void snapd_client_init(SnapdClient *self) { SnapdClientPrivate *priv = snapd_client_get_instance_private(self); priv->socket_path = NULL; priv->user_agent = g_strdup("snapd-glib/" VERSION); priv->allow_interaction = TRUE; priv->requests = g_ptr_array_new_with_free_func((GDestroyNotify)request_data_unref); priv->buffer = g_byte_array_new(); priv->response_body = g_byte_array_new(); // nanoseconds, by default, is set to -1 to specify that the value // is not set, and thus the decimal value from GDateTime should be // used when generating the timestamp for the AFTER field in the // /v2/notice method. priv->since_date_time_nanoseconds = -1; g_mutex_init(&priv->requests_mutex); g_mutex_init(&priv->buffer_mutex); } snapd-glib-1.67/snapd-glib/snapd-client.h000066400000000000000000001640421477073115000202550ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_CLIENT_H__ #define __SNAPD_CLIENT_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include #include #include #include #include #include #include #include #include #include #include #include G_BEGIN_DECLS #define SNAPD_TYPE_CLIENT (snapd_client_get_type()) G_DECLARE_DERIVABLE_TYPE(SnapdClient, snapd_client, SNAPD, CLIENT, GObject) struct _SnapdClientClass { /*< private >*/ GObjectClass parent_class; /*< private >*/ /* padding, for future expansion */ void (*_snapd_reserved1)(void); void (*_snapd_reserved2)(void); void (*_snapd_reserved3)(void); void (*_snapd_reserved4)(void); }; /** * SnapdChangeFilter: * @SNAPD_CHANGE_FILTER_ALL: Return all changes. * @SNAPD_CHANGE_FILTER_READY: Return only changes that are ready. * @SNAPD_CHANGE_FILTER_IN_PROGRESS: Return only changes that are in-progress. * * Filter to apply to changes. * * Since: 1.29 */ typedef enum { SNAPD_CHANGE_FILTER_ALL, SNAPD_CHANGE_FILTER_IN_PROGRESS, SNAPD_CHANGE_FILTER_READY } SnapdChangeFilter; /** * SnapdGetSnapsFlags: * @SNAPD_GET_SNAPS_FLAGS_NONE: No flags, default behaviour. * @SNAPD_GET_SNAPS_FLAGS_INCLUDE_INACTIVE: Return snaps that are installed but * not active. * @SNAPD_GET_SNAPS_FLAGS_REFRESH_INHIBITED: Return snaps that are * refresh-inhibited. * * Flag to change which snaps are returned. * * Since: 1.42 */ typedef enum { SNAPD_GET_SNAPS_FLAGS_NONE = 0, SNAPD_GET_SNAPS_FLAGS_INCLUDE_INACTIVE = 1 << 0, SNAPD_GET_SNAPS_FLAGS_REFRESH_INHIBITED = 1 << 1 } SnapdGetSnapsFlags; /** * SnapdGetAppsFlags: * @SNAPD_GET_APPS_FLAGS_NONE: No flags, default behaviour. * @SNAPD_GET_APPS_FLAGS_SELECT_SERVICES: Select services only. * * Flag to change which apps are returned. * * Since: 1.25 */ typedef enum { SNAPD_GET_APPS_FLAGS_NONE = 0, SNAPD_GET_APPS_FLAGS_SELECT_SERVICES = 1 << 0 } SnapdGetAppsFlags; /** * SnapdGetConnectionsFlags: * @SNAPD_GET_CONNECTIONS_FLAGS_NONE: No flags, default behaviour. * @SNAPD_GET_CONNECTIONS_FLAGS_SELECT_ALL: Select all connections, not just * connected ones. * * Flag to change how connections are returned. * * Since: 1.49 */ typedef enum { SNAPD_GET_CONNECTIONS_FLAGS_NONE = 0, SNAPD_GET_CONNECTIONS_FLAGS_SELECT_ALL = 1 << 0, } SnapdGetConnectionsFlags; /** * SnapdFindFlags: * @SNAPD_FIND_FLAGS_NONE: No flags, default behaviour. * @SNAPD_FIND_FLAGS_MATCH_NAME: Search for snaps whose name matches the given * string. The match is exact unless the string ends in *. * @SNAPD_FIND_FLAGS_MATCH_COMMON_ID: Search for snaps whose common ID matches * the given string. * @SNAPD_FIND_FLAGS_SELECT_PRIVATE: Search private snaps. * @SNAPD_FIND_FLAGS_SELECT_REFRESH: Deprecated, do not use. * @SNAPD_FIND_FLAGS_SCOPE_WIDE: Search for snaps from any architecture or * branch. * * Flag to change how a find is performed. * * Since: 1.0 */ typedef enum { SNAPD_FIND_FLAGS_NONE = 0, SNAPD_FIND_FLAGS_MATCH_NAME = 1 << 0, SNAPD_FIND_FLAGS_SELECT_PRIVATE = 1 << 1, SNAPD_FIND_FLAGS_SELECT_REFRESH = 1 << 2, SNAPD_FIND_FLAGS_SCOPE_WIDE = 1 << 3, SNAPD_FIND_FLAGS_MATCH_COMMON_ID = 1 << 4 } SnapdFindFlags; /** * SnapdInstallFlags: * @SNAPD_INSTALL_FLAGS_NONE: No flags, default behaviour. * @SNAPD_INSTALL_FLAGS_CLASSIC: Put snap in classic mode and disable security * confinement. * @SNAPD_INSTALL_FLAGS_DANGEROUS: Install the given snap file even if there are * no pre-acknowledged signatures for it, meaning it was not verified and * could be dangerous (implied by #SNAPD_INSTALL_FLAGS_DEVMODE). * @SNAPD_INSTALL_FLAGS_DEVMODE: Put snap in development mode and disable * security confinement. * @SNAPD_INSTALL_FLAGS_JAILMODE: Put snap in enforced confinement mode. * * Flags to control install options. * * Since: 1.12 */ typedef enum { SNAPD_INSTALL_FLAGS_NONE = 0, SNAPD_INSTALL_FLAGS_CLASSIC = 1 << 0, SNAPD_INSTALL_FLAGS_DANGEROUS = 1 << 1, SNAPD_INSTALL_FLAGS_DEVMODE = 1 << 2, SNAPD_INSTALL_FLAGS_JAILMODE = 1 << 3 } SnapdInstallFlags; /** * SnapdRemoveFlags: * @SNAPD_REMOVE_FLAGS_NONE: No flags, default behaviour. * @SNAPD_REMOVE_FLAGS_PURGE: Don't save a snapshot the snap's data when * removing. * * Flags to control remove options. * * Since: 1.50 */ typedef enum { SNAPD_REMOVE_FLAGS_NONE = 0, SNAPD_REMOVE_FLAGS_PURGE = 1 << 0, } SnapdRemoveFlags; /** * SnapdCreateUserFlags: * @SNAPD_CREATE_USER_FLAGS_NONE: No flags, default behaviour. * @SNAPD_CREATE_USER_FLAGS_SUDO: Gives sudo access to created user. * @SNAPD_CREATE_USER_FLAGS_KNOWN: Use the local system-user assertions to * create the user. * * Flag to control when a user accounts is created. * * Since: 1.3 */ typedef enum { SNAPD_CREATE_USER_FLAGS_NONE = 0, SNAPD_CREATE_USER_FLAGS_SUDO = 1 << 0, SNAPD_CREATE_USER_FLAGS_KNOWN = 1 << 1 } SnapdCreateUserFlags; /** * SnapdGetInterfacesFlags: * @SNAPD_GET_INTERFACES_FLAGS_NONE: No flags, default behaviour. * @SNAPD_GET_INTERFACES_FLAGS_INCLUDE_DOCS: Include interface documentation. * @SNAPD_GET_INTERFACES_FLAGS_INCLUDE_PLUGS: Include associated plugs. * @SNAPD_GET_INTERFACES_FLAGS_INCLUDE_SLOTS: Include associated slots. * @SNAPD_GET_INTERFACES_FLAGS_ONLY_CONNECTED: Only return connected interfaces. * * Flags to control how interface information is returned. * * Since: 1.48 */ typedef enum { SNAPD_GET_INTERFACES_FLAGS_NONE = 0, SNAPD_GET_INTERFACES_FLAGS_INCLUDE_DOCS = 1 << 0, SNAPD_GET_INTERFACES_FLAGS_INCLUDE_PLUGS = 1 << 1, SNAPD_GET_INTERFACES_FLAGS_INCLUDE_SLOTS = 1 << 2, SNAPD_GET_INTERFACES_FLAGS_ONLY_CONNECTED = 1 << 3, } SnapdGetInterfacesFlags; /** * SnapdThemeStatus: * @SNAPD_THEME_STATUS_INSTALLED: the theme is installed. * @SNAPD_THEME_STATUS_AVAILABLE: the theme is not installed but a package is * available. * @SNAPD_THEME_STATUS_UNAVAILABLE: the theme is not available. * * The status of a snap-packaged desktop theme. * * Since: 1.60 */ typedef enum { SNAPD_THEME_STATUS_INSTALLED = 1, SNAPD_THEME_STATUS_AVAILABLE, SNAPD_THEME_STATUS_UNAVAILABLE, } SnapdThemeStatus; /** * SnapdProgressCallback: * @client: a #SnapdClient * @change: a #SnapdChange describing the change in progress * @deprecated: A deprecated field that is no longer used. * @user_data: user data passed to the callback * * Signature for callback function used in * snapd_client_connect_interface_sync(), * snapd_client_disconnect_interface_async(), * snapd_client_install2_sync(), * snapd_client_refresh_sync(), * snapd_client_remove2_sync(), * snapd_client_enable_sync() and * snapd_client_disable_sync(). * * Since: 1.0 */ typedef void (*SnapdProgressCallback)(SnapdClient *client, SnapdChange *change, gpointer deprecated, gpointer user_data); /** * SnapdLogCallback: * @client: a #SnapdClient * @log: a #SnapdLog received * @user_data: user data passed to the callback * * Signature for callback function used in snapd_client_follow_logs_sync(). * * Since: 1.64 */ typedef void (*SnapdLogCallback)(SnapdClient *client, SnapdLog *log, gpointer user_data); SnapdClient *snapd_client_new(void); SnapdClient *snapd_client_new_from_socket(GSocket *socket); gboolean snapd_client_connect_sync(SnapdClient *client, GCancellable *cancellable, GError **error) G_DEPRECATED; void snapd_client_connect_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED; gboolean snapd_client_connect_finish(SnapdClient *client, GAsyncResult *result, GError **error) G_DEPRECATED; void snapd_client_set_socket_path(SnapdClient *client, const gchar *socket_path); const gchar *snapd_client_get_socket_path(SnapdClient *client); void snapd_client_set_user_agent(SnapdClient *client, const gchar *user_agent); const gchar *snapd_client_get_user_agent(SnapdClient *client); void snapd_client_set_allow_interaction(SnapdClient *client, gboolean allow_interaction); gboolean snapd_client_get_allow_interaction(SnapdClient *client); SnapdMaintenance *snapd_client_get_maintenance(SnapdClient *client); SnapdAuthData *snapd_client_login_sync(SnapdClient *client, const gchar *email, const gchar *password, const gchar *otp, GCancellable *cancellable, GError **error) G_DEPRECATED_FOR(snapd_client_login2_sync); void snapd_client_login_async(SnapdClient *client, const gchar *email, const gchar *password, const gchar *otp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED_FOR(snapd_client_login2_async); SnapdAuthData *snapd_client_login_finish(SnapdClient *client, GAsyncResult *result, GError **error) G_DEPRECATED_FOR(snapd_client_login2_finish); SnapdUserInformation * snapd_client_login2_sync(SnapdClient *client, const gchar *email, const gchar *password, const gchar *otp, GCancellable *cancellable, GError **error); void snapd_client_login2_async(SnapdClient *client, const gchar *email, const gchar *password, const gchar *otp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); SnapdUserInformation *snapd_client_login2_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_logout_sync(SnapdClient *client, gint64 id, GCancellable *cancellable, GError **error); void snapd_client_logout_async(SnapdClient *client, gint64 id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_logout_finish(SnapdClient *client, GAsyncResult *result, GError **error); void snapd_client_set_auth_data(SnapdClient *client, SnapdAuthData *auth_data); SnapdAuthData *snapd_client_get_auth_data(SnapdClient *client); GPtrArray *snapd_client_get_changes_sync(SnapdClient *client, SnapdChangeFilter filter, const gchar *snap_name, GCancellable *cancellable, GError **error); void snapd_client_get_changes_async(SnapdClient *client, SnapdChangeFilter filter, const gchar *snap_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_get_changes_finish(SnapdClient *client, GAsyncResult *result, GError **error); SnapdChange *snapd_client_get_change_sync(SnapdClient *client, const gchar *id, GCancellable *cancellable, GError **error); void snapd_client_get_change_async(SnapdClient *client, const gchar *id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); SnapdChange *snapd_client_get_change_finish(SnapdClient *client, GAsyncResult *result, GError **error); SnapdChange *snapd_client_abort_change_sync(SnapdClient *client, const gchar *id, GCancellable *cancellable, GError **error); void snapd_client_abort_change_async(SnapdClient *client, const gchar *id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); SnapdChange *snapd_client_abort_change_finish(SnapdClient *client, GAsyncResult *result, GError **error); SnapdSystemInformation *snapd_client_get_system_information_sync( SnapdClient *client, GCancellable *cancellable, GError **error); void snapd_client_get_system_information_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); SnapdSystemInformation *snapd_client_get_system_information_finish( SnapdClient *client, GAsyncResult *result, GError **error); GPtrArray *snapd_client_list_sync(SnapdClient *client, GCancellable *cancellable, GError **error) G_DEPRECATED_FOR(snapd_client_get_snaps_sync); void snapd_client_list_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED_FOR(snapd_client_get_snaps_async); GPtrArray *snapd_client_list_finish(SnapdClient *client, GAsyncResult *result, GError **error) G_DEPRECATED_FOR(snapd_client_get_snaps_finish); GPtrArray *snapd_client_get_snaps_sync(SnapdClient *client, SnapdGetSnapsFlags flags, GStrv names, GCancellable *cancellable, GError **error); void snapd_client_get_snaps_async(SnapdClient *client, SnapdGetSnapsFlags flags, GStrv names, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_get_snaps_finish(SnapdClient *client, GAsyncResult *result, GError **error); SnapdSnap *snapd_client_list_one_sync(SnapdClient *client, const gchar *name, GCancellable *cancellable, GError **error) G_DEPRECATED_FOR(snapd_client_get_snap_sync); void snapd_client_list_one_async(SnapdClient *client, const gchar *name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED_FOR(snapd_client_get_snap_async); SnapdSnap *snapd_client_list_one_finish(SnapdClient *client, GAsyncResult *result, GError **error) G_DEPRECATED_FOR(snapd_client_get_snap_finish); SnapdSnap *snapd_client_get_snap_sync(SnapdClient *client, const gchar *name, GCancellable *cancellable, GError **error); void snapd_client_get_snap_async(SnapdClient *client, const gchar *name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); SnapdSnap *snapd_client_get_snap_finish(SnapdClient *client, GAsyncResult *result, GError **error); GHashTable *snapd_client_get_snap_conf_sync(SnapdClient *client, const gchar *name, GStrv keys, GCancellable *cancellable, GError **error); void snapd_client_get_snap_conf_async(SnapdClient *client, const gchar *name, GStrv keys, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GHashTable *snapd_client_get_snap_conf_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_set_snap_conf_sync(SnapdClient *client, const gchar *name, GHashTable *key_values, GCancellable *cancellable, GError **error); void snapd_client_set_snap_conf_async(SnapdClient *client, const gchar *name, GHashTable *key_values, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_set_snap_conf_finish(SnapdClient *client, GAsyncResult *result, GError **error); GPtrArray *snapd_client_get_apps_sync(SnapdClient *client, SnapdGetAppsFlags flags, GCancellable *cancellable, GError **error) G_DEPRECATED_FOR(snapd_client_get_apps2_sync); void snapd_client_get_apps_async(SnapdClient *client, SnapdGetAppsFlags flags, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED_FOR(snapd_client_get_apps2_async); GPtrArray *snapd_client_get_apps_finish(SnapdClient *client, GAsyncResult *result, GError **error) G_DEPRECATED_FOR(snapd_client_get_apps2_finish); GPtrArray *snapd_client_get_apps2_sync(SnapdClient *client, SnapdGetAppsFlags flags, GStrv snaps, GCancellable *cancellable, GError **error); void snapd_client_get_apps2_async(SnapdClient *client, SnapdGetAppsFlags flags, GStrv snaps, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_get_apps2_finish(SnapdClient *client, GAsyncResult *result, GError **error); SnapdIcon *snapd_client_get_icon_sync(SnapdClient *client, const gchar *name, GCancellable *cancellable, GError **error); void snapd_client_get_icon_async(SnapdClient *client, const gchar *name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); SnapdIcon *snapd_client_get_icon_finish(SnapdClient *client, GAsyncResult *result, GError **error); GStrv snapd_client_get_assertions_sync(SnapdClient *client, const gchar *type, GCancellable *cancellable, GError **error); void snapd_client_get_assertions_async(SnapdClient *client, const gchar *type, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GStrv snapd_client_get_assertions_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_add_assertions_sync(SnapdClient *client, GStrv assertions, GCancellable *cancellable, GError **error); void snapd_client_add_assertions_async(SnapdClient *client, GStrv assertions, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_add_assertions_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_get_interfaces_sync(SnapdClient *client, GPtrArray **plugs, GPtrArray **slots, GCancellable *cancellable, GError **error) G_DEPRECATED_FOR(snapd_client_get_connections_sync); void snapd_client_get_interfaces_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED_FOR(snapd_client_get_connections_async); gboolean snapd_client_get_interfaces_finish(SnapdClient *client, GAsyncResult *result, GPtrArray **plugs, GPtrArray **slots, GError **error) G_DEPRECATED_FOR(snapd_client_get_connections_finish); GPtrArray *snapd_client_get_interfaces2_sync(SnapdClient *client, SnapdGetInterfacesFlags flags, GStrv names, GCancellable *cancellable, GError **error); void snapd_client_get_interfaces2_async(SnapdClient *client, SnapdGetInterfacesFlags flags, GStrv names, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_get_interfaces2_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_get_connections_sync( SnapdClient *client, GPtrArray **established, GPtrArray **undesired, GPtrArray **plugs, GPtrArray **slots, GCancellable *cancellable, GError **error) G_DEPRECATED_FOR(snapd_client_get_connections2_sync); void snapd_client_get_connections_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED_FOR(snapd_client_get_connections2_async); gboolean snapd_client_get_connections_finish( SnapdClient *client, GAsyncResult *result, GPtrArray **established, GPtrArray **undesired, GPtrArray **plugs, GPtrArray **slots, GError **error) G_DEPRECATED_FOR(snapd_client_get_connections2_finish); gboolean snapd_client_get_connections2_sync( SnapdClient *client, SnapdGetConnectionsFlags flags, const gchar *snap, const gchar *interface, GPtrArray **established, GPtrArray **undesired, GPtrArray **plugs, GPtrArray **slots, GCancellable *cancellable, GError **error); void snapd_client_get_connections2_async( SnapdClient *client, SnapdGetConnectionsFlags flags, const gchar *snap, const gchar *interface, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_get_connections2_finish(SnapdClient *client, GAsyncResult *result, GPtrArray **established, GPtrArray **undesired, GPtrArray **plugs, GPtrArray **slots, GError **error); gboolean snapd_client_connect_interface_sync( SnapdClient *client, const gchar *plug_snap, const gchar *plug_name, const gchar *slot_snap, const gchar *slot_name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_connect_interface_async( SnapdClient *client, const gchar *plug_snap, const gchar *plug_name, const gchar *slot_snap, const gchar *slot_name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_connect_interface_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_disconnect_interface_sync( SnapdClient *client, const gchar *plug_snap, const gchar *plug_name, const gchar *slot_snap, const gchar *slot_name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_disconnect_interface_async( SnapdClient *client, const gchar *plug_snap, const gchar *plug_name, const gchar *slot_snap, const gchar *slot_name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_disconnect_interface_finish(SnapdClient *client, GAsyncResult *result, GError **error); GPtrArray *snapd_client_find_sync(SnapdClient *client, SnapdFindFlags flags, const gchar *query, gchar **suggested_currency, GCancellable *cancellable, GError **error); void snapd_client_find_async(SnapdClient *client, SnapdFindFlags flags, const gchar *query, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_find_finish(SnapdClient *client, GAsyncResult *result, gchar **suggested_currency, GError **error); GPtrArray *snapd_client_find_section_sync( SnapdClient *client, SnapdFindFlags flags, const gchar *section, const gchar *query, gchar **suggested_currency, GCancellable *cancellable, GError **error) G_DEPRECATED_FOR(snapd_client_find_category_sync); void snapd_client_find_section_async(SnapdClient *client, SnapdFindFlags flags, const gchar *section, const gchar *query, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED_FOR(snapd_client_find_category_async); GPtrArray * snapd_client_find_section_finish(SnapdClient *client, GAsyncResult *result, gchar **suggested_currency, GError **error) G_DEPRECATED_FOR(snapd_client_find_category_finish); GPtrArray * snapd_client_find_category_sync(SnapdClient *client, SnapdFindFlags flags, const gchar *category, const gchar *query, gchar **suggested_currency, GCancellable *cancellable, GError **error); void snapd_client_find_category_async(SnapdClient *client, SnapdFindFlags flags, const gchar *category, const gchar *query, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_find_category_finish(SnapdClient *client, GAsyncResult *result, gchar **suggested_currency, GError **error); GPtrArray *snapd_client_find_refreshable_sync(SnapdClient *client, GCancellable *cancellable, GError **error); void snapd_client_find_refreshable_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_find_refreshable_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_install_sync(SnapdClient *client, const gchar *name, const gchar *channel, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) G_DEPRECATED_FOR(snapd_client_install2_sync); void snapd_client_install_async( SnapdClient *client, const gchar *name, const gchar *channel, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED_FOR(snapd_client_install2_async); gboolean snapd_client_install_finish(SnapdClient *client, GAsyncResult *result, GError **error) G_DEPRECATED_FOR(snapd_client_install2_finish); gboolean snapd_client_install2_sync(SnapdClient *client, SnapdInstallFlags flags, const gchar *name, const gchar *channel, const gchar *revision, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_install2_async(SnapdClient *client, SnapdInstallFlags flags, const gchar *name, const gchar *channel, const gchar *revision, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_install2_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_install_stream_sync( SnapdClient *client, SnapdInstallFlags flags, GInputStream *stream, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_install_stream_async( SnapdClient *client, SnapdInstallFlags flags, GInputStream *stream, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_install_stream_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_try_sync(SnapdClient *client, const gchar *path, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_try_async(SnapdClient *client, const gchar *path, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_try_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_refresh_sync(SnapdClient *client, const gchar *name, const gchar *channel, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_refresh_async(SnapdClient *client, const gchar *name, const gchar *channel, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_refresh_finish(SnapdClient *client, GAsyncResult *result, GError **error); GStrv snapd_client_refresh_all_sync(SnapdClient *client, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_refresh_all_async(SnapdClient *client, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GStrv snapd_client_refresh_all_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_remove_sync(SnapdClient *client, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) G_DEPRECATED_FOR(snapd_client_remove2_sync); void snapd_client_remove_async(SnapdClient *client, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED_FOR(snapd_client_remove2_async); gboolean snapd_client_remove_finish(SnapdClient *client, GAsyncResult *result, GError **error) G_DEPRECATED_FOR(snapd_client_remove2_finish); gboolean snapd_client_remove2_sync(SnapdClient *client, SnapdRemoveFlags flags, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_remove2_async(SnapdClient *client, SnapdRemoveFlags flags, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_remove2_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_enable_sync(SnapdClient *client, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_enable_async(SnapdClient *client, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_enable_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_disable_sync(SnapdClient *client, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_disable_async(SnapdClient *client, const gchar *name, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_disable_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_switch_sync(SnapdClient *client, const gchar *name, const gchar *channel, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_switch_async(SnapdClient *client, const gchar *name, const gchar *channel, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_switch_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_check_buy_sync(SnapdClient *client, GCancellable *cancellable, GError **error); void snapd_client_check_buy_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_check_buy_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_buy_sync(SnapdClient *client, const gchar *id, gdouble amount, const gchar *currency, GCancellable *cancellable, GError **error); void snapd_client_buy_async(SnapdClient *client, const gchar *id, gdouble amount, const gchar *currency, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_buy_finish(SnapdClient *client, GAsyncResult *result, GError **error); SnapdUserInformation *snapd_client_create_user_sync(SnapdClient *client, const gchar *email, SnapdCreateUserFlags flags, GCancellable *cancellable, GError **error); void snapd_client_create_user_async(SnapdClient *client, const gchar *email, SnapdCreateUserFlags flags, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); SnapdUserInformation *snapd_client_create_user_finish(SnapdClient *client, GAsyncResult *result, GError **error); GPtrArray *snapd_client_create_users_sync(SnapdClient *client, GCancellable *cancellable, GError **error); void snapd_client_create_users_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_create_users_finish(SnapdClient *client, GAsyncResult *result, GError **error); GPtrArray *snapd_client_get_users_sync(SnapdClient *client, GCancellable *cancellable, GError **error); void snapd_client_get_users_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_get_users_finish(SnapdClient *client, GAsyncResult *result, GError **error); GStrv snapd_client_get_sections_sync(SnapdClient *client, GCancellable *cancellable, GError **error) G_DEPRECATED; void snapd_client_get_sections_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED; GStrv snapd_client_get_sections_finish(SnapdClient *client, GAsyncResult *result, GError **error) G_DEPRECATED; GPtrArray *snapd_client_get_categories_sync(SnapdClient *client, GCancellable *cancellable, GError **error); void snapd_client_get_categories_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_get_categories_finish(SnapdClient *client, GAsyncResult *result, GError **error); GPtrArray *snapd_client_get_aliases_sync(SnapdClient *client, GCancellable *cancellable, GError **error); void snapd_client_get_aliases_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_get_aliases_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_alias_sync(SnapdClient *client, const gchar *snap, const gchar *app, const gchar *alias, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_alias_async(SnapdClient *client, const gchar *snap, const gchar *app, const gchar *alias, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_alias_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_unalias_sync(SnapdClient *client, const gchar *snap, const gchar *alias, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_unalias_async(SnapdClient *client, const gchar *snap, const gchar *alias, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_unalias_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_prefer_sync(SnapdClient *client, const gchar *snap, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_prefer_async(SnapdClient *client, const gchar *snap, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_prefer_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_enable_aliases_sync( SnapdClient *client, const gchar *snap, GStrv aliases, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) G_DEPRECATED; void snapd_client_enable_aliases_async(SnapdClient *client, const gchar *snap, GStrv aliases, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED; gboolean snapd_client_enable_aliases_finish(SnapdClient *client, GAsyncResult *result, GError **error) G_DEPRECATED; gboolean snapd_client_disable_aliases_sync( SnapdClient *client, const gchar *snap, GStrv aliases, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) G_DEPRECATED; void snapd_client_disable_aliases_async(SnapdClient *client, const gchar *snap, GStrv aliases, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED; gboolean snapd_client_disable_aliases_finish(SnapdClient *client, GAsyncResult *result, GError **error) G_DEPRECATED; gboolean snapd_client_reset_aliases_sync( SnapdClient *client, const gchar *snap, GStrv aliases, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error) G_DEPRECATED; void snapd_client_reset_aliases_async(SnapdClient *client, const gchar *snap, GStrv aliases, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED; gboolean snapd_client_reset_aliases_finish(SnapdClient *client, GAsyncResult *result, GError **error) G_DEPRECATED; gboolean snapd_client_run_snapctl_sync( SnapdClient *client, const gchar *context_id, GStrv args, gchar **stdout_output, gchar **stderr_output, GCancellable *cancellable, GError **error) G_DEPRECATED_FOR(snapd_client_run_snapctl2_sync); void snapd_client_run_snapctl_async(SnapdClient *client, const gchar *context_id, GStrv args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) G_DEPRECATED_FOR(snapd_client_run_snapctl2_async); gboolean snapd_client_run_snapctl_finish(SnapdClient *client, GAsyncResult *result, gchar **stdout_output, gchar **stderr_output, GError **error) G_DEPRECATED_FOR(snapd_client_run_snapctl2_finish); gboolean snapd_client_run_snapctl2_sync(SnapdClient *client, const gchar *context_id, GStrv args, gchar **stdout_output, gchar **stderr_output, int *exit_code, GCancellable *cancellable, GError **error); void snapd_client_run_snapctl2_async(SnapdClient *client, const gchar *context_id, GStrv args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_run_snapctl2_finish(SnapdClient *client, GAsyncResult *result, gchar **stdout_output, gchar **stderr_output, int *exit_code, GError **error); GBytes *snapd_client_download_sync(SnapdClient *client, const gchar *name, const gchar *channel, const gchar *revision, GCancellable *cancellable, GError **error); void snapd_client_download_async(SnapdClient *client, const gchar *name, const gchar *channel, const gchar *revision, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GBytes *snapd_client_download_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_check_themes_sync( SnapdClient *client, GStrv gtk_theme_names, GStrv icon_theme_names, GStrv sound_theme_names, GHashTable **gtk_theme_status, GHashTable **icon_theme_status, GHashTable **sound_theme_status, GCancellable *cancellable, GError **error); void snapd_client_check_themes_async(SnapdClient *client, GStrv gtk_theme_names, GStrv icon_theme_names, GStrv sound_theme_names, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_check_themes_finish(SnapdClient *client, GAsyncResult *result, GHashTable **gtk_theme_status, GHashTable **icon_theme_status, GHashTable **sound_theme_status, GError **error); gboolean snapd_client_install_themes_sync( SnapdClient *client, GStrv gtk_theme_names, GStrv icon_theme_names, GStrv sound_theme_names, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GError **error); void snapd_client_install_themes_async( SnapdClient *client, GStrv gtk_theme_names, GStrv icon_theme_names, GStrv sound_theme_names, SnapdProgressCallback progress_callback, gpointer progress_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_install_themes_finish(SnapdClient *client, GAsyncResult *result, GError **error); GPtrArray *snapd_client_get_logs_sync(SnapdClient *client, GStrv names, size_t n, GCancellable *cancellable, GError **error); void snapd_client_get_logs_async(SnapdClient *client, GStrv names, size_t n, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_get_logs_finish(SnapdClient *client, GAsyncResult *result, GError **error); gboolean snapd_client_follow_logs_sync(SnapdClient *client, GStrv names, SnapdLogCallback log_callback, gpointer log_callback_data, GCancellable *cancellable, GError **error); void snapd_client_follow_logs_async(SnapdClient *client, GStrv names, SnapdLogCallback log_callback, gpointer log_callback_data, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean snapd_client_follow_logs_finish(SnapdClient *client, GAsyncResult *result, GError **error); GPtrArray *snapd_client_get_notices_sync(SnapdClient *client, GDateTime *since_date_time, GTimeSpan timeout, GCancellable *cancellable, GError **error); void snapd_client_get_notices_async(SnapdClient *client, GDateTime *since_date_time, GTimeSpan timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_get_notices_finish(SnapdClient *client, GAsyncResult *result, GError **error); GPtrArray *snapd_client_get_notices_with_filters_sync( SnapdClient *client, gchar *user_id, gchar *users, gchar *types, gchar *keys, GDateTime *since_date_time, GTimeSpan timeout, GCancellable *cancellable, GError **error); void snapd_client_get_notices_with_filters_async( SnapdClient *client, gchar *user_id, gchar *users, gchar *types, gchar *keys, GDateTime *since_date_time, GTimeSpan timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GPtrArray *snapd_client_get_notices_with_filters_finish(SnapdClient *client, GAsyncResult *result, GError **error); void snapd_client_notices_set_after_notice(SnapdClient *client, SnapdNotice *notice); void snapd_client_notices_set_since_nanoseconds(SnapdClient *client, gint32 nanoseconds); gchar *snapd_client_get_model_assertion_sync(SnapdClient *client, GCancellable *cancellable, GError **error); void snapd_client_get_model_assertion_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gchar *snapd_client_get_model_assertion_finish(SnapdClient *client, GAsyncResult *result, GError **error); gchar *snapd_client_get_serial_assertion_sync(SnapdClient *client, GCancellable *cancellable, GError **error); void snapd_client_get_serial_assertion_async(SnapdClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gchar *snapd_client_get_serial_assertion_finish(SnapdClient *client, GAsyncResult *result, GError **error); G_END_DECLS #endif /* __SNAPD_CLIENT_H__ */ snapd-glib-1.67/snapd-glib/snapd-connection.c000066400000000000000000000337451477073115000211360ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-connection.h" /** * SECTION: snapd-connection * @short_description: Plug to slot connections * @include: snapd-glib/snapd-glib.h * * A #SnapdConnection contains information about how a #SnapdPlug is connected * to a #SnapdSlot. Connections are queried using * snapd_client_get_connections_sync(). */ /** * SnapdConnection: * * #SnapdConnection contains the state of Snap a interface connection. * * Since: 1.0 */ struct _SnapdConnection { GObject parent_instance; SnapdSlotRef *slot; SnapdPlugRef *plug; gchar *interface; gboolean manual; gboolean gadget; GHashTable *slot_attributes; GHashTable *plug_attributes; /* legacy */ gchar *name; gchar *snap; }; enum { PROP_NAME = 1, PROP_SNAP, PROP_SLOT, PROP_PLUG, PROP_INTERFACE, PROP_MANUAL, PROP_GADGET, PROP_SLOT_ATTRIBUTES, PROP_PLUG_ATTRIBUTES, PROP_LAST }; G_DEFINE_TYPE(SnapdConnection, snapd_connection, G_TYPE_OBJECT) /** * snapd_connection_get_slot: * @connection: a #SnapdConnection. * * Get the slot this connection is made with. * * Returns: (transfer none): a reference to a slot. * * Since: 1.48 */ SnapdSlotRef *snapd_connection_get_slot(SnapdConnection *self) { g_return_val_if_fail(SNAPD_IS_CONNECTION(self), NULL); return self->slot; } /** * snapd_connection_get_plug: * @connection: a #SnapdConnection. * * Get the plug this connection is made with. * * Returns: (transfer none): a reference to a plug. * * Since: 1.48 */ SnapdPlugRef *snapd_connection_get_plug(SnapdConnection *self) { g_return_val_if_fail(SNAPD_IS_CONNECTION(self), NULL); return self->plug; } /** * snapd_connection_get_interface: * @connection: a #SnapdConnection. * * Get the interface this connections uses. * * Returns: an interface name. * * Since: 1.48 */ const gchar *snapd_connection_get_interface(SnapdConnection *self) { g_return_val_if_fail(SNAPD_IS_CONNECTION(self), NULL); return self->interface; } /** * snapd_connection_get_manual: * @connection: a #SnapdConnection. * * Get if this connection was made manually. * * Returns: %TRUE if connection was made manually. * * Since: 1.48 */ gboolean snapd_connection_get_manual(SnapdConnection *self) { g_return_val_if_fail(SNAPD_IS_CONNECTION(self), FALSE); return self->manual; } /** * snapd_connection_get_gadget: * @connection: a #SnapdConnection. * * Get if this connection was made by the gadget snap. * * Returns: %TRUE if connection was made by the gadget snap. * * Since: 1.48 */ gboolean snapd_connection_get_gadget(SnapdConnection *self) { g_return_val_if_fail(SNAPD_IS_CONNECTION(self), FALSE); return self->gadget; } /** * snapd_connection_get_slot_attribute_names: * @connection: a #SnapdConnection. * @length: (out) (allow-none): location to write number of attributes or %NULL * if not required. * * Get the names of the attributes the connected slot has. * * Returns: (transfer full) (array zero-terminated=1): a string array of * attribute names. Free with g_strfreev(). * * Since: 1.48 */ GStrv snapd_connection_get_slot_attribute_names(SnapdConnection *self, guint *length) { g_return_val_if_fail(SNAPD_IS_CONNECTION(self), NULL); GHashTableIter iter; g_hash_table_iter_init(&iter, self->slot_attributes); guint size = g_hash_table_size(self->slot_attributes); GStrv names = g_malloc(sizeof(gchar *) * (size + 1)); guint i; gpointer name; for (i = 0; g_hash_table_iter_next(&iter, &name, NULL); i++) names[i] = g_strdup(name); names[i] = NULL; if (length != NULL) *length = size; return names; } /** * snapd_connection_has_slot_attribute: * @connection: a #SnapdConnection. * @name: an attribute name. * * Check if the connected slot has an attribute. * * Returns: %TRUE if this attribute exists. * * Since: 1.48 */ gboolean snapd_connection_has_slot_attribute(SnapdConnection *self, const gchar *name) { g_return_val_if_fail(SNAPD_IS_CONNECTION(self), FALSE); return g_hash_table_contains(self->slot_attributes, name); } /** * snapd_connection_get_slot_attribute: * @connection: a #SnapdConnection. * @name: an attribute name. * * Get an attribute for connected slot. * * Returns: (transfer none) (allow-none): an attribute value or %NULL if not * set. * * Since: 1.48 */ GVariant *snapd_connection_get_slot_attribute(SnapdConnection *self, const gchar *name) { g_return_val_if_fail(SNAPD_IS_CONNECTION(self), NULL); return g_hash_table_lookup(self->slot_attributes, name); } /** * snapd_connection_get_plug_attribute_names: * @connection: a #SnapdConnection. * @length: (out) (allow-none): location to write number of attributes or %NULL * if not required. * * Get the names of the attributes the connected plug has. * * Returns: (transfer full) (array zero-terminated=1): a string array of * attribute names. Free with g_strfreev(). * * Since: 1.48 */ GStrv snapd_connection_get_plug_attribute_names(SnapdConnection *self, guint *length) { g_return_val_if_fail(SNAPD_IS_CONNECTION(self), NULL); GHashTableIter iter; g_hash_table_iter_init(&iter, self->plug_attributes); guint size = g_hash_table_size(self->plug_attributes); GStrv names = g_malloc(sizeof(gchar *) * (size + 1)); guint i; gpointer name; for (i = 0; g_hash_table_iter_next(&iter, &name, NULL); i++) names[i] = g_strdup(name); names[i] = NULL; if (length != NULL) *length = size; return names; } /** * snapd_connection_has_plug_attribute: * @connection: a #SnapdConnection. * @name: an attribute name. * * Check if the connected plug has an attribute. * * Returns: %TRUE if this attribute exists. * * Since: 1.48 */ gboolean snapd_connection_has_plug_attribute(SnapdConnection *self, const gchar *name) { g_return_val_if_fail(SNAPD_IS_CONNECTION(self), FALSE); return g_hash_table_contains(self->plug_attributes, name); } /** * snapd_connection_get_plug_attribute: * @connection: a #SnapdConnection. * @name: an attribute name. * * Get an attribute for connected plug. * * Returns: (transfer none) (allow-none): an attribute value or %NULL if not * set. * * Since: 1.48 */ GVariant *snapd_connection_get_plug_attribute(SnapdConnection *self, const gchar *name) { g_return_val_if_fail(SNAPD_IS_CONNECTION(self), NULL); return g_hash_table_lookup(self->plug_attributes, name); } /** * snapd_connection_get_name: * @connection: a #SnapdConnection. * * Get the name of this connection (i.e. a slot or plug name). * * Returns: a name. * * Since: 1.0 * Deprecated: 1.48: Use snapd_plug_ref_get_plug() or snapd_slot_ref_get_slot() */ const gchar *snapd_connection_get_name(SnapdConnection *self) { g_return_val_if_fail(SNAPD_IS_CONNECTION(self), NULL); return self->name; } /** * snapd_connection_get_snap: * @connection: a #SnapdConnection. * * Get the snap this connection is on. * * Returns: a snap name. * * Since: 1.0 * Deprecated: 1.48: Use snapd_plug_ref_get_snap() or snapd_slot_ref_get_snap() */ const gchar *snapd_connection_get_snap(SnapdConnection *self) { g_return_val_if_fail(SNAPD_IS_CONNECTION(self), NULL); return self->snap; } static void snapd_connection_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdConnection *self = SNAPD_CONNECTION(object); switch (prop_id) { case PROP_NAME: g_free(self->name); self->name = g_strdup(g_value_get_string(value)); break; case PROP_SNAP: g_free(self->snap); self->snap = g_strdup(g_value_get_string(value)); break; case PROP_PLUG: g_set_object(&self->plug, g_value_get_object(value)); break; case PROP_SLOT: g_set_object(&self->slot, g_value_get_object(value)); break; case PROP_INTERFACE: g_free(self->interface); self->interface = g_strdup(g_value_get_string(value)); break; case PROP_MANUAL: self->manual = g_value_get_boolean(value); break; case PROP_GADGET: self->gadget = g_value_get_boolean(value); break; case PROP_SLOT_ATTRIBUTES: g_clear_pointer(&self->slot_attributes, g_hash_table_unref); if (g_value_get_boxed(value) != NULL) self->slot_attributes = g_hash_table_ref(g_value_get_boxed(value)); break; case PROP_PLUG_ATTRIBUTES: g_clear_pointer(&self->plug_attributes, g_hash_table_unref); if (g_value_get_boxed(value) != NULL) self->plug_attributes = g_hash_table_ref(g_value_get_boxed(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_connection_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdConnection *self = SNAPD_CONNECTION(object); switch (prop_id) { case PROP_NAME: g_value_set_string(value, self->name); break; case PROP_SNAP: g_value_set_string(value, self->snap); break; case PROP_PLUG: g_value_set_object(value, self->plug); break; case PROP_SLOT: g_value_set_object(value, self->slot); break; case PROP_INTERFACE: g_value_set_string(value, self->snap); break; case PROP_MANUAL: g_value_set_boolean(value, self->manual); break; case PROP_GADGET: g_value_set_boolean(value, self->gadget); break; case PROP_SLOT_ATTRIBUTES: g_value_set_boxed(value, self->slot_attributes); break; case PROP_PLUG_ATTRIBUTES: g_value_set_boxed(value, self->plug_attributes); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_connection_finalize(GObject *object) { SnapdConnection *self = SNAPD_CONNECTION(object); g_clear_object(&self->slot); g_clear_object(&self->plug); g_clear_pointer(&self->interface, g_free); g_clear_pointer(&self->slot_attributes, g_hash_table_unref); g_clear_pointer(&self->plug_attributes, g_hash_table_unref); g_clear_pointer(&self->name, g_free); g_clear_pointer(&self->snap, g_free); G_OBJECT_CLASS(snapd_connection_parent_class)->finalize(object); } static void snapd_connection_class_init(SnapdConnectionClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_connection_set_property; gobject_class->get_property = snapd_connection_get_property; gobject_class->finalize = snapd_connection_finalize; g_object_class_install_property( gobject_class, PROP_NAME, g_param_spec_string( "name", "name", "Name of connection/plug on snap", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SNAP, g_param_spec_string( "snap", "snap", "Snap this connection is made to", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SLOT, g_param_spec_object("slot", "slot", "Slot this connection is made with", SNAPD_TYPE_SLOT_REF, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PLUG, g_param_spec_object("plug", "plug", "Plug this connection is made with", SNAPD_TYPE_PLUG_REF, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_INTERFACE, g_param_spec_string( "interface", "interface", "Interface this connection uses", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_MANUAL, g_param_spec_boolean( "manual", "manual", "TRUE if connection was made manually", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_GADGET, g_param_spec_boolean( "gadget", "gadget", "TRUE if connection was made by the gadget snap", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SLOT_ATTRIBUTES, g_param_spec_boxed("slot-attrs", "slot-attrs", "Attributes for connected slot", G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PLUG_ATTRIBUTES, g_param_spec_boxed("plug-attrs", "plug-attrs", "Attributes for connected plug", G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_connection_init(SnapdConnection *self) {} snapd-glib-1.67/snapd-glib/snapd-connection.h000066400000000000000000000043251477073115000211330ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_CONNECTION_H__ #define __SNAPD_CONNECTION_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include #include #include G_BEGIN_DECLS #define SNAPD_TYPE_CONNECTION (snapd_connection_get_type()) G_DECLARE_FINAL_TYPE(SnapdConnection, snapd_connection, SNAPD, CONNECTION, GObject) SnapdSlotRef *snapd_connection_get_slot(SnapdConnection *connection); SnapdPlugRef *snapd_connection_get_plug(SnapdConnection *connection); const gchar *snapd_connection_get_interface(SnapdConnection *connection); gboolean snapd_connection_get_manual(SnapdConnection *connection); gboolean snapd_connection_get_gadget(SnapdConnection *connection); GStrv snapd_connection_get_slot_attribute_names(SnapdConnection *connection, guint *length); gboolean snapd_connection_has_slot_attribute(SnapdConnection *connection, const gchar *name); GVariant *snapd_connection_get_slot_attribute(SnapdConnection *connection, const gchar *name); GStrv snapd_connection_get_plug_attribute_names(SnapdConnection *connection, guint *length); gboolean snapd_connection_has_plug_attribute(SnapdConnection *connection, const gchar *name); GVariant *snapd_connection_get_plug_attribute(SnapdConnection *connection, const gchar *name); const gchar * snapd_connection_get_name(SnapdConnection *connection) G_DEPRECATED; const gchar * snapd_connection_get_snap(SnapdConnection *connection) G_DEPRECATED; G_END_DECLS #endif /* __SNAPD_CONNECTION_H__ */ snapd-glib-1.67/snapd-glib/snapd-enum-types.c.in000066400000000000000000000023371477073115000215030ustar00rootroot00000000000000/*** BEGIN file-header ***/ /* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-enum-types.h" /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@basename@" */ #include "@filename@" /*** END file-production ***/ /*** BEGIN value-header ***/ GType @enum_name@_get_type (void) { static volatile gsize g_enum_type_id__volatile = 0; if (g_once_init_enter (&g_enum_type_id__volatile)) { static const G@Type@Value values[] = { /*** END value-header ***/ /*** BEGIN value-production ***/ { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, /*** END value-production ***/ /*** BEGIN value-tail ***/ { 0, NULL, NULL } }; GType g_enum_type_id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id); } return g_enum_type_id__volatile; } /*** END value-tail ***/ snapd-glib-1.67/snapd-glib/snapd-enum-types.h.in000066400000000000000000000017701477073115000215100ustar00rootroot00000000000000/*** BEGIN file-header ***/ /* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_ENUM_TYPES_H__ #define __SNAPD_ENUM_TYPES_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@basename@" */ /*** END file-production ***/ /*** BEGIN file-tail ***/ G_END_DECLS #endif /* !__SNAPD_ENUM_TYPES_H__ */ /*** END file-tail ***/ /*** BEGIN value-header ***/ GType @enum_name@_get_type (void) G_GNUC_CONST; #define SNAPD_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) /*** END value-header ***/ snapd-glib-1.67/snapd-glib/snapd-error.c000066400000000000000000000013021477073115000201100ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-error.h" /** * SECTION:snapd-error * @short_description: Snap error codes * @include: snapd-glib/snapd-glib.h * * Error code definitions for various snapd operations. */ /** * snapd_error_quark: * * Gets the Snapd Error Quark. * * Returns: a #GQuark. * * Since: 1.0 **/ G_DEFINE_QUARK(snapd - error - quark, snapd_error) snapd-glib-1.67/snapd-glib/snapd-error.h000066400000000000000000000124061477073115000201240ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_ERROR_H__ #define __SNAPD_ERROR_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS /** * SnapdError: * @SNAPD_ERROR_CONNECTION_FAILED: not able to connect to snapd. * @SNAPD_ERROR_WRITE_FAILED: an error occurred while writing to snapd. * @SNAPD_ERROR_READ_FAILED: an error occurred while reading from snapd. * @SNAPD_ERROR_BAD_REQUEST: snapd did not understand the request that was sent. * @SNAPD_ERROR_BAD_RESPONSE: the response received from snapd was not * understood. * @SNAPD_ERROR_AUTH_DATA_REQUIRED: the requested operation requires * authorization data. * @SNAPD_ERROR_AUTH_DATA_INVALID: the provided authorization data is invalid. * @SNAPD_ERROR_TWO_FACTOR_REQUIRED: login requires a two factor code. * @SNAPD_ERROR_TWO_FACTOR_INVALID: the two factor code provided at login is * invalid. * @SNAPD_ERROR_PERMISSION_DENIED: this user account is not permitted to perform * the requested operation. * @SNAPD_ERROR_FAILED: an unspecified error occurred while communicating * with snapd. * @SNAPD_ERROR_TERMS_NOT_ACCEPTED: this user has not accepted the store's terms * of service. * @SNAPD_ERROR_PAYMENT_NOT_SETUP: this user has not configured a payment * method. * @SNAPD_ERROR_PAYMENT_DECLINED: this user has had their payment method * declined by the payment provider. * @SNAPD_ERROR_ALREADY_INSTALLED: the requested snap is already installed. * @SNAPD_ERROR_NOT_INSTALLED: the requested snap is not installed. * @SNAPD_ERROR_NO_UPDATE_AVAILABLE: no update is available for this snap. * @SNAPD_ERROR_PASSWORD_POLICY_ERROR: provided password is not valid. * @SNAPD_ERROR_NEEDS_DEVMODE: this snap needs to be installed using devmode. * @SNAPD_ERROR_NEEDS_CLASSIC: this snap needs to be installed using classic * mode. * @SNAPD_ERROR_NEEDS_CLASSIC_SYSTEM: a classic system is required to install * this snap. * @SNAPD_ERROR_BAD_QUERY: a bad query was provided. * @SNAPD_ERROR_NETWORK_TIMEOUT: A timeout occurred during the request. * @SNAPD_ERROR_NOT_FOUND: the requested snap couldn't be found. * @SNAPD_ERROR_NOT_IN_STORE: the requested snap is not in the store. * @SNAPD_ERROR_AUTH_CANCELLED: authentication was cancelled by the user. * @SNAPD_ERROR_NOT_CLASSIC: snap not compatible with classic mode. * @SNAPD_ERROR_REVISION_NOT_AVAILABLE: requested snap revision not available. * @SNAPD_ERROR_CHANNEL_NOT_AVAILABLE: requested snap channel not available. * @SNAPD_ERROR_NOT_A_SNAP: the given snap or directory does not look like a * snap. * @SNAPD_ERROR_DNS_FAILURE: A hostname failed to resolve during the request. * @SNAPD_ERROR_OPTION_NOT_FOUND: A requested configuration option is not set. * @SNAPD_ERROR_UNSUCCESSFUL: A snapctl command was unsuccessful. * @SNAPD_ERROR_APP_NOT_FOUND: The requested app coundn't be found. * @SNAPD_ERROR_ARCHITECTURE_NOT_AVAILABLE: No snap revision on specified * architecture. * @SNAPD_ERROR_CHANGE_CONFLICT: The requested operation would conflict with * currently ongoing change. * @SNAPD_ERROR_INTERFACES_UNCHANGED: The requested interfaces' operation would * have no effect. * @SNAPD_ERROR_ALREADY_RUNNING: An async process is already running. * @SNAPD_ERROR_NOT_RUNNING: An async process is not running. * * Error codes returned by snapd operations. * * Since: 1.0 */ typedef enum { SNAPD_ERROR_CONNECTION_FAILED, SNAPD_ERROR_WRITE_FAILED, SNAPD_ERROR_READ_FAILED, SNAPD_ERROR_BAD_REQUEST, SNAPD_ERROR_BAD_RESPONSE, SNAPD_ERROR_AUTH_DATA_REQUIRED, SNAPD_ERROR_AUTH_DATA_INVALID, SNAPD_ERROR_TWO_FACTOR_REQUIRED, SNAPD_ERROR_TWO_FACTOR_INVALID, SNAPD_ERROR_PERMISSION_DENIED, SNAPD_ERROR_FAILED, SNAPD_ERROR_TERMS_NOT_ACCEPTED, SNAPD_ERROR_PAYMENT_NOT_SETUP, SNAPD_ERROR_PAYMENT_DECLINED, SNAPD_ERROR_ALREADY_INSTALLED, SNAPD_ERROR_NOT_INSTALLED, SNAPD_ERROR_NO_UPDATE_AVAILABLE, SNAPD_ERROR_PASSWORD_POLICY_ERROR, SNAPD_ERROR_NEEDS_DEVMODE, SNAPD_ERROR_NEEDS_CLASSIC, SNAPD_ERROR_NEEDS_CLASSIC_SYSTEM, SNAPD_ERROR_BAD_QUERY, SNAPD_ERROR_NETWORK_TIMEOUT, SNAPD_ERROR_NOT_FOUND, SNAPD_ERROR_NOT_IN_STORE, SNAPD_ERROR_AUTH_CANCELLED, SNAPD_ERROR_NOT_CLASSIC, SNAPD_ERROR_REVISION_NOT_AVAILABLE, SNAPD_ERROR_CHANNEL_NOT_AVAILABLE, SNAPD_ERROR_NOT_A_SNAP, SNAPD_ERROR_DNS_FAILURE, SNAPD_ERROR_OPTION_NOT_FOUND, SNAPD_ERROR_UNSUCCESSFUL, SNAPD_ERROR_APP_NOT_FOUND, SNAPD_ERROR_ARCHITECTURE_NOT_AVAILABLE, SNAPD_ERROR_CHANGE_CONFLICT, SNAPD_ERROR_INTERFACES_UNCHANGED, SNAPD_ERROR_ALREADY_RUNNING, SNAPD_ERROR_NOT_RUNNING, } SnapdError; /** * SNAPD_ERROR: * * Error domain for errors returned by snapd. Errors in this domain will * be from the #SnapdError enumeration. See #GError for information * on error domains. */ #define SNAPD_ERROR snapd_error_quark() GQuark snapd_error_quark(void) G_GNUC_CONST; G_END_DECLS #endif /* __SNAPD_ERROR_H__ */ snapd-glib-1.67/snapd-glib/snapd-glib.h000066400000000000000000000032611477073115000177070ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_GLIB_H__ #define __SNAPD_GLIB_H__ #define __SNAPD_GLIB_INSIDE__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #undef __SNAPD_GLIB_INSIDE__ #endif /* __SNAPD_GLIB_H__ */ snapd-glib-1.67/snapd-glib/snapd-glib.map000066400000000000000000000000441477073115000202310ustar00rootroot00000000000000{ global: snapd_*; local: *; }; snapd-glib-1.67/snapd-glib/snapd-glib.pc.in000066400000000000000000000004311477073115000204630ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: Snapd GLib Description: Libary for accessing snapd Version: @VERSION@ Libs: -L${libdir} -lsnapd-glib Cflags: -I${includedir}/snapd-glib Requires: gobject-2.0 gio-2.0 libsoup-2.4 json-glib-1.0 snapd-glib-1.67/snapd-glib/snapd-icon.c000066400000000000000000000073121477073115000177160ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-icon.h" /** * SECTION:snapd-icon * @short_description: Snap icon data * @include: snapd-glib/snapd-glib.h * * A #SnapdIcon contains the icon data for a given snap. Icons can be requested * using snapd_client_get_icon_sync(). */ /** * SnapdIcon: * * #SnapdIcon contains icon data. * * Since: 1.0 */ struct _SnapdIcon { GObject parent_instance; gchar *mime_type; GBytes *data; }; enum { PROP_MIME_TYPE = 1, PROP_DATA, PROP_LAST }; G_DEFINE_TYPE(SnapdIcon, snapd_icon, G_TYPE_OBJECT) /** * snapd_icon_get_mime_type: * @icon: a #SnapdIcon. * * Get the mime-type for this icon, e.g. "image/png". * * Returns: a MIME type. * * Since: 1.0 */ const gchar *snapd_icon_get_mime_type(SnapdIcon *self) { g_return_val_if_fail(SNAPD_IS_ICON(self), NULL); return self->mime_type; } /** * snapd_icon_get_data: * @icon: a #SnapdIcon. * * Get the binary data for this icon. * * Returns: (transfer none): the binary data. * * Since: 1.0 */ GBytes *snapd_icon_get_data(SnapdIcon *self) { g_return_val_if_fail(SNAPD_IS_ICON(self), NULL); return self->data; } static void snapd_icon_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdIcon *self = SNAPD_ICON(object); switch (prop_id) { case PROP_MIME_TYPE: g_free(self->mime_type); self->mime_type = g_strdup(g_value_get_string(value)); break; case PROP_DATA: g_clear_pointer(&self->data, g_bytes_unref); if (g_value_get_boxed(value) != NULL) self->data = g_bytes_ref(g_value_get_boxed(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_icon_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdIcon *self = SNAPD_ICON(object); switch (prop_id) { case PROP_MIME_TYPE: g_value_set_string(value, self->mime_type); break; case PROP_DATA: g_value_set_boxed(value, self->data); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_icon_finalize(GObject *object) { SnapdIcon *self = SNAPD_ICON(object); g_clear_pointer(&self->mime_type, g_free); g_clear_pointer(&self->data, g_bytes_unref); G_OBJECT_CLASS(snapd_icon_parent_class)->finalize(object); } static void snapd_icon_class_init(SnapdIconClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_icon_set_property; gobject_class->get_property = snapd_icon_get_property; gobject_class->finalize = snapd_icon_finalize; g_object_class_install_property( gobject_class, PROP_MIME_TYPE, g_param_spec_string("mime-type", "mime-type", "Icon mime type", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_DATA, g_param_spec_boxed("data", "data", "Icon data", G_TYPE_BYTES, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_icon_init(SnapdIcon *self) {} snapd-glib-1.67/snapd-glib/snapd-icon.h000066400000000000000000000015211477073115000177170ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_ICON_H__ #define __SNAPD_ICON_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_ICON (snapd_icon_get_type()) G_DECLARE_FINAL_TYPE(SnapdIcon, snapd_icon, SNAPD, ICON, GObject) const gchar *snapd_icon_get_mime_type(SnapdIcon *icon); GBytes *snapd_icon_get_data(SnapdIcon *icon); G_END_DECLS #endif /* __SNAPD_ICON_H__ */ snapd-glib-1.67/snapd-glib/snapd-interface.c000066400000000000000000000326571477073115000207400ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-interface.h" /** * SECTION: snapd-interface * @short_description: Snap interface info * @include: snapd-glib/snapd-glib.h * * A #SnapdInterface represents information about a particular * interface type and the related plugs and slots provided by snaps on * the system. * * Available interfaces can be queried using * snapd_client_get_interfaces2_sync(). */ /** * SnapdInterface: * * #SnapdInterface contains information about a Snap interface. * * Since: 1.48 */ struct _SnapdInterface { GObject parent_instance; gchar *name; gchar *summary; gchar *doc_url; GPtrArray *plugs; GPtrArray *slots; }; enum { PROP_NAME = 1, PROP_SUMMARY, PROP_DOC_URL, PROP_PLUGS, PROP_SLOTS, }; G_DEFINE_TYPE(SnapdInterface, snapd_interface, G_TYPE_OBJECT); /** * snapd_interface_get_name: * @interface: a #SnapdInterface * * Get the name of this interface. * * Returns: a name. * * Since: 1.48 */ const gchar *snapd_interface_get_name(SnapdInterface *self) { g_return_val_if_fail(SNAPD_IS_INTERFACE(self), NULL); return self->name; } /** * snapd_interface_get_summary: * @interface: a #SnapdInterface * * Get the summary of this interface. * * Returns: a summary. * * Since: 1.48 */ const gchar *snapd_interface_get_summary(SnapdInterface *self) { g_return_val_if_fail(SNAPD_IS_INTERFACE(self), NULL); return self->summary; } /** * snapd_interface_get_doc_url: * @interface: a #SnapdInterface * * Get the documentation URL of this interface. * * Returns: a URL. * * Since: 1.48 */ const gchar *snapd_interface_get_doc_url(SnapdInterface *self) { g_return_val_if_fail(SNAPD_IS_INTERFACE(self), NULL); return self->doc_url; } /** * snapd_interface_get_plugs: * @interface: a #SnapdInterface * * Get the plugs matching this interface type. * * Returns: (transfer none) (element-type SnapdPlug): an array of #SnapdPlug. * * Since: 1.48 */ GPtrArray *snapd_interface_get_plugs(SnapdInterface *self) { g_return_val_if_fail(SNAPD_IS_INTERFACE(self), NULL); return self->plugs; } /** * snapd_interface_get_slots: * @interface: a #SnapdInterface * * Get the slots matching this interface type. * * Returns: (transfer none) (element-type SnapdSlot): an array of #SnapdSlot. * * Since: 1.48 */ GPtrArray *snapd_interface_get_slots(SnapdInterface *self) { g_return_val_if_fail(SNAPD_IS_INTERFACE(self), NULL); return self->slots; } /** * snapd_interface_make_label: * @interface: a #SnapdInterface * * Make a label for this interface suitable for a user interface. * * Returns: a newly allocated label string. * * Since: 1.57 */ gchar *snapd_interface_make_label(SnapdInterface *self) { if (strcmp(self->name, "account-control") == 0) return g_strdup(_("Add user accounts and change passwords")); else if (strcmp(self->name, "alsa") == 0) return g_strdup(_("Play and record sound")); else if (strcmp(self->name, "audio-playback") == 0) return g_strdup(_("Play audio")); else if (strcmp(self->name, "audio-record") == 0) return g_strdup(_("Record audio")); else if (strcmp(self->name, "avahi-observe") == 0) return g_strdup( _("Detect network devices using mDNS/DNS-SD (Bonjour/zeroconf)")); else if (strcmp(self->name, "bluetooth-control") == 0) return g_strdup(_("Access bluetooth hardware directly")); else if (strcmp(self->name, "bluez") == 0) return g_strdup(_("Use bluetooth devices")); else if (strcmp(self->name, "camera") == 0) return g_strdup(_("Use your camera")); else if (strcmp(self->name, "cups-control") == 0) return g_strdup(_("Print documents")); else if (strcmp(self->name, "joystick") == 0) return g_strdup(_("Use any connected joystick")); else if (strcmp(self->name, "docker") == 0) return g_strdup(_("Allow connecting to the Docker service")); else if (strcmp(self->name, "firewall-control") == 0) return g_strdup(_("Configure network firewall")); else if (strcmp(self->name, "fuse-support") == 0) return g_strdup(_("Setup and use privileged FUSE filesystems")); else if (strcmp(self->name, "fwupd") == 0) return g_strdup(_("Update firmware on this device")); else if (strcmp(self->name, "hardware-observe") == 0) return g_strdup(_("Access hardware information")); else if (strcmp(self->name, "hardware-random-control") == 0) return g_strdup(_("Provide entropy to hardware random number generator")); else if (strcmp(self->name, "hardware-random-observe") == 0) return g_strdup(_("Use hardware-generated random numbers")); else if (strcmp(self->name, "home") == 0) return g_strdup(_("Access files in your home folder")); else if (strcmp(self->name, "libvirt") == 0) return g_strdup(_("Access libvirt service")); else if (strcmp(self->name, "locale-control") == 0) return g_strdup(_("Change system language and region settings")); else if (strcmp(self->name, "location-control") == 0) return g_strdup(_("Change location settings and providers")); else if (strcmp(self->name, "location-observe") == 0) return g_strdup(_("Access your location")); else if (strcmp(self->name, "log-observe") == 0) return g_strdup(_("Read system and application logs")); else if (strcmp(self->name, "lxd") == 0) return g_strdup(_("Access LXD service")); else if (strcmp(self->name, "modem-manager") == 0) return g_strdup(_("Use and configure modems")); else if (strcmp(self->name, "mount-observe") == 0) return g_strdup(_("Read system mount information and disk quotas")); else if (strcmp(self->name, "mpris") == 0) return g_strdup(_("Control music and video players")); else if (strcmp(self->name, "network-control") == 0) return g_strdup(_("Change low-level network settings")); else if (strcmp(self->name, "network-manager") == 0) return g_strdup(_("Access the NetworkManager service to read and change " "network settings")); else if (strcmp(self->name, "network-observe") == 0) return g_strdup(_("Read access to network settings")); else if (strcmp(self->name, "network-setup-control") == 0) return g_strdup(_("Change network settings")); else if (strcmp(self->name, "network-setup-observe") == 0) return g_strdup(_("Read network settings")); else if (strcmp(self->name, "ofono") == 0) return g_strdup(_("Access the ofono service to read and change network " "settings for mobile telephony")); else if (strcmp(self->name, "openvswitch") == 0) return g_strdup(_("Control Open vSwitch hardware")); else if (strcmp(self->name, "optical-drive") == 0) return g_strdup(_("Read from CD/DVD")); else if (strcmp(self->name, "password-manager-service") == 0) return g_strdup(_("Read, add, change, or remove saved passwords")); else if (strcmp(self->name, "ppp") == 0) return g_strdup(_("Access pppd and ppp devices for configuring " "Point-to-Point Protocol connections")); else if (strcmp(self->name, "process-control") == 0) return g_strdup(_("Pause or end any process on the system")); else if (strcmp(self->name, "pulseaudio") == 0) return g_strdup(_("Play and record sound")); else if (strcmp(self->name, "raw-usb") == 0) return g_strdup(_("Access USB hardware directly")); else if (strcmp(self->name, "removable-media") == 0) return g_strdup(_("Read/write files on removable storage devices")); else if (strcmp(self->name, "screen-inhibit-control") == 0) return g_strdup(_("Prevent screen sleep/lock")); else if (strcmp(self->name, "serial-port") == 0) return g_strdup(_("Access serial port hardware")); else if (strcmp(self->name, "shutdown") == 0) return g_strdup(_("Restart or power off the device")); else if (strcmp(self->name, "snapd-control") == 0) return g_strdup(_("Install, remove and configure software")); else if (strcmp(self->name, "storage-framework-service") == 0) return g_strdup(_("Access Storage Framework service")); else if (strcmp(self->name, "system-observe") == 0) return g_strdup(_("Read process and system information")); else if (strcmp(self->name, "system-trace") == 0) return g_strdup(_("Monitor and control any running program")); else if (strcmp(self->name, "time-control") == 0) return g_strdup(_("Change the date and time")); else if (strcmp(self->name, "timeserver-control") == 0) return g_strdup(_("Change time server settings")); else if (strcmp(self->name, "timezone-control") == 0) return g_strdup(_("Change the time zone")); else if (strcmp(self->name, "udisks2") == 0) return g_strdup(_("Access the UDisks2 service for configuring disks and " "removable media")); else if (strcmp(self->name, "unity8-calendar") == 0) return g_strdup(_("Read/change shared calendar events in Ubuntu Unity 8")); else if (strcmp(self->name, "unity8-contacts") == 0) return g_strdup(_("Read/change shared contacts in Ubuntu Unity 8")); else if (strcmp(self->name, "upower-observe") == 0) return g_strdup(_("Access energy usage data")); else if (strcmp(self->name, "u2f-devices") == 0) return g_strdup(_("Read/write access to U2F devices exposed")); if (self->summary != NULL) return g_strdup_printf("%s: %s", self->name, self->summary); else return g_strdup(self->name); } static void snapd_interface_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdInterface *self = SNAPD_INTERFACE(object); switch (prop_id) { case PROP_NAME: g_free(self->name); self->name = g_strdup(g_value_get_string(value)); break; case PROP_SUMMARY: g_free(self->summary); self->summary = g_strdup(g_value_get_string(value)); break; case PROP_DOC_URL: g_free(self->doc_url); self->doc_url = g_strdup(g_value_get_string(value)); break; case PROP_PLUGS: g_clear_pointer(&self->plugs, g_ptr_array_unref); self->plugs = g_value_dup_boxed(value); break; case PROP_SLOTS: g_clear_pointer(&self->slots, g_ptr_array_unref); self->slots = g_value_dup_boxed(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_interface_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdInterface *self = SNAPD_INTERFACE(object); switch (prop_id) { case PROP_NAME: g_value_set_string(value, self->name); break; case PROP_SUMMARY: g_value_set_string(value, self->summary); break; case PROP_DOC_URL: g_value_set_string(value, self->doc_url); break; case PROP_PLUGS: g_value_set_boxed(value, self->plugs); break; case PROP_SLOTS: g_value_set_boxed(value, self->slots); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_interface_finalize(GObject *object) { SnapdInterface *self = SNAPD_INTERFACE(object); g_clear_pointer(&self->name, g_free); g_clear_pointer(&self->summary, g_free); g_clear_pointer(&self->doc_url, g_free); g_clear_pointer(&self->plugs, g_ptr_array_unref); g_clear_pointer(&self->slots, g_ptr_array_unref); G_OBJECT_CLASS(snapd_interface_parent_class)->finalize(object); } static void snapd_interface_class_init(SnapdInterfaceClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_interface_set_property; gobject_class->get_property = snapd_interface_get_property; gobject_class->finalize = snapd_interface_finalize; g_object_class_install_property( gobject_class, PROP_NAME, g_param_spec_string("name", "name", "Interface name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SUMMARY, g_param_spec_string("summary", "summary", "Interface summary", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_DOC_URL, g_param_spec_string( "doc-url", "doc-url", "Interface documentation URL", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PLUGS, g_param_spec_boxed( "plugs", "plugs", "Plugs of this interface type", G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SLOTS, g_param_spec_boxed( "slots", "slots", "Slots of this interface type", G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_interface_init(SnapdInterface *self) {} snapd-glib-1.67/snapd-glib/snapd-interface.h000066400000000000000000000022431477073115000207310ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_INTERFACE_H__ #define __SNAPD_INTERFACE_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_INTERFACE (snapd_interface_get_type()) G_DECLARE_FINAL_TYPE(SnapdInterface, snapd_interface, SNAPD, INTERFACE, GObject) const gchar *snapd_interface_get_name(SnapdInterface *interface); const gchar *snapd_interface_get_summary(SnapdInterface *interface); const gchar *snapd_interface_get_doc_url(SnapdInterface *interface); GPtrArray *snapd_interface_get_plugs(SnapdInterface *interface); GPtrArray *snapd_interface_get_slots(SnapdInterface *interface); gchar *snapd_interface_make_label(SnapdInterface *interface); G_END_DECLS #endif /* __SNAPD_INTERFACE_H__ */ snapd-glib-1.67/snapd-glib/snapd-log.c000066400000000000000000000125701477073115000175510ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-log.h" #include "snapd-enum-types.h" /** * SECTION:snapd-log * @short_description: Snap service log entry * @include: snapd-glib/snapd-glib.h * * A #SnapdLog contains a line from a log for a snap service as returned using * snapd_client_get_logs_sync(). */ /** * SnapdLog: * * #SnapdLog is an opaque data structure and can only be accessed * using the provided functions. * * Since: 1.64 */ struct _SnapdLog { GObject parent_instance; GDateTime *timestamp; gchar *message; gchar *sid; gchar *pid; }; enum { PROP_TIMESTAMP = 1, PROP_MESSAGE, PROP_SID, PROP_PID, PROP_LAST }; G_DEFINE_TYPE(SnapdLog, snapd_log, G_TYPE_OBJECT) /** * snapd_log_get_timestamp: * @log: a #SnapdLog. * * Get the time this log was generated. * * Returns: a timestamp. * * Since: 1.64 */ GDateTime *snapd_log_get_timestamp(SnapdLog *self) { g_return_val_if_fail(SNAPD_IS_LOG(self), NULL); return self->timestamp; } /** * snapd_log_get_message: * @log: a #SnapdLog. * * Get the message of this log, e.g. "service started" * * Returns: a log message. * * Since: 1.64 */ const gchar *snapd_log_get_message(SnapdLog *self) { g_return_val_if_fail(SNAPD_IS_LOG(self), NULL); return self->message; } /** * snapd_log_get_sid: * @log: a #SnapdLog. * * Get the syslog id of this log, e.g. "cups.cups-browsed" * * Returns: a syslog id. * * Since: 1.64 */ const gchar *snapd_log_get_sid(SnapdLog *self) { g_return_val_if_fail(SNAPD_IS_LOG(self), NULL); return self->sid; } /** * snapd_log_get_pid: * @log: a #SnapdLog. * * Get the process ID of this log, e.g. "1234" * * Returns: a process id. * * Since: 1.64 */ const gchar *snapd_log_get_pid(SnapdLog *self) { g_return_val_if_fail(SNAPD_IS_LOG(self), NULL); return self->pid; } static void snapd_log_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdLog *self = SNAPD_LOG(object); switch (prop_id) { case PROP_TIMESTAMP: g_clear_pointer(&self->timestamp, g_date_time_unref); if (g_value_get_boxed(value) != NULL) self->timestamp = g_date_time_ref(g_value_get_boxed(value)); break; case PROP_MESSAGE: g_free(self->message); self->message = g_strdup(g_value_get_string(value)); break; case PROP_SID: g_free(self->sid); self->sid = g_strdup(g_value_get_string(value)); break; case PROP_PID: g_free(self->pid); self->pid = g_strdup(g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_log_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdLog *self = SNAPD_LOG(object); switch (prop_id) { case PROP_TIMESTAMP: g_value_set_boxed(value, self->timestamp); break; case PROP_MESSAGE: g_value_set_string(value, self->message); break; case PROP_SID: g_value_set_string(value, self->sid); break; case PROP_PID: g_value_set_string(value, self->pid); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_log_finalize(GObject *object) { SnapdLog *self = SNAPD_LOG(object); g_clear_pointer(&self->timestamp, g_date_time_unref); g_clear_pointer(&self->message, g_free); g_clear_pointer(&self->sid, g_free); g_clear_pointer(&self->pid, g_free); G_OBJECT_CLASS(snapd_log_parent_class)->finalize(object); } static void snapd_log_class_init(SnapdLogClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_log_set_property; gobject_class->get_property = snapd_log_get_property; gobject_class->finalize = snapd_log_finalize; g_object_class_install_property( gobject_class, PROP_TIMESTAMP, g_param_spec_boxed( "timestamp", "timestamp", "Timestamp", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_MESSAGE, g_param_spec_string("message", "message", "Message", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SID, g_param_spec_string("sid", "sid", "Syslog ID", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PID, g_param_spec_string("pid", "pid", "Process ID", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_log_init(SnapdLog *self) {} snapd-glib-1.67/snapd-glib/snapd-log.h000066400000000000000000000016511477073115000175540ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_LOG_H__ #define __SNAPD_LOG_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_LOG (snapd_log_get_type()) G_DECLARE_FINAL_TYPE(SnapdLog, snapd_log, SNAPD, LOG, GObject) GDateTime *snapd_log_get_timestamp(SnapdLog *log); const gchar *snapd_log_get_message(SnapdLog *log); const gchar *snapd_log_get_sid(SnapdLog *log); const gchar *snapd_log_get_pid(SnapdLog *log); G_END_DECLS #endif /* __SNAPD_LOG_H__ */ snapd-glib-1.67/snapd-glib/snapd-login.c000066400000000000000000000076761477073115000201130ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-client.h" #include "snapd-error.h" #include "snapd-login.h" /** * SECTION: snapd-login * @short_description: Client authorization * @include: snapd-glib/snapd-glib.h * * Deprecated methods of authenticating with snapd. */ /** * snapd_login_sync: * @username: username to log in with. * @password: password to log in with. * @otp: (allow-none): response to one-time password challenge. * @cancellable: (allow-none): a #GCancellable or %NULL. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * This call used to contact a D-Bus service to perform snapd authentication * using Polkit. This now just creates a #SnapdClient and does the call * directly. * * Returns: (transfer full): a #SnapdAuthData or %NULL on error. * * Since: 1.0 * Deprecated: 1.34: Use snapd_client_login2_sync() */ SnapdAuthData *snapd_login_sync(const gchar *username, const gchar *password, const gchar *otp, GCancellable *cancellable, GError **error) { g_return_val_if_fail(username != NULL, NULL); g_return_val_if_fail(password != NULL, NULL); g_autoptr(SnapdClient) client = snapd_client_new(); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, username, password, otp, cancellable, error); if (user_information == NULL) return NULL; return g_object_ref(snapd_user_information_get_auth_data(user_information)); } static void login_cb(GObject *object, GAsyncResult *result, gpointer user_data) { GTask *task = user_data; g_autoptr(GError) error = NULL; g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_finish(SNAPD_CLIENT(object), result, &error); if (user_information != NULL) g_task_return_pointer( task, g_object_ref(snapd_user_information_get_auth_data(user_information)), g_object_unref); else g_task_return_error(task, error); } /** * snapd_login_async: * @username: username to log in with. * @password: password to log in with. * @otp: (allow-none): response to one-time password challenge. * @cancellable: (allow-none): a #GCancellable or %NULL. * @callback: (scope async): a #GAsyncReadyCallback to call when the request is * satisfied. * @user_data: (closure): the data to pass to callback function. * * Asynchronously get authorization to install/remove snaps. * See snapd_login_sync() for more information. * * Since: 1.0 * Deprecated: 1.34: Use snapd_client_login2_async() */ void snapd_login_async(const gchar *username, const gchar *password, const gchar *otp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail(username != NULL); g_return_if_fail(password != NULL); g_autoptr(GTask) task = g_task_new(NULL, cancellable, callback, user_data); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_login2_async(client, username, password, otp, cancellable, login_cb, task); } /** * snapd_login_finish: * @result: a #GAsyncResult. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Complete login started with snapd_login_async(). * See snapd_login_sync() for more information. * * Returns: (transfer full): a #SnapdAuthData or %NULL on error. * * Since: 1.0 * Deprecated: 1.34: Use snapd_client_login2_finish() */ SnapdAuthData *snapd_login_finish(GAsyncResult *result, GError **error) { return g_task_propagate_pointer(G_TASK(result), error); } snapd-glib-1.67/snapd-glib/snapd-login.h000066400000000000000000000024431477073115000201030ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_LOGIN_H__ #define __SNAPD_LOGIN_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include #include #include G_BEGIN_DECLS G_DEPRECATED_FOR(snapd_client_login2_sync) SnapdAuthData *snapd_login_sync(const gchar *username, const gchar *password, const gchar *otp, GCancellable *cancellable, GError **error); G_DEPRECATED_FOR(snapd_client_login2_async) void snapd_login_async(const gchar *username, const gchar *password, const gchar *otp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); G_DEPRECATED_FOR(snapd_client_login2_finish) SnapdAuthData *snapd_login_finish(GAsyncResult *result, GError **error); G_END_DECLS #endif /* __SNAPD_LOGIN_H__ */ snapd-glib-1.67/snapd-glib/snapd-maintenance.c000066400000000000000000000101261477073115000212450ustar00rootroot00000000000000/* * Copyright (C) 2018 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-enum-types.h" #include "snapd-maintenance.h" /** * SECTION:snapd-maintenance * @short_description: Snap maintenance information * @include: snapd-glib/snapd-glib.h * * A #SnapdMaintenance contains maintenance information for the snapd daemon. * The current maintenance information can be retrieved using * snapd_client_get_maintenance (). */ /** * SnapdMaintenance: * * #SnapdMaintenance contains maintenance information. * * Since: 1.45 */ struct _SnapdMaintenance { GObject parent_instance; SnapdMaintenanceKind kind; gchar *message; }; enum { PROP_KIND = 1, PROP_MESSAGE, PROP_LAST }; G_DEFINE_TYPE(SnapdMaintenance, snapd_maintenance, G_TYPE_OBJECT) /** * snapd_maintenance_get_kind: * @maintenance: a #SnapdMaintenance. * * Get the kind of maintenance kind, e.g. * %SNAPD_MAINTENANCE_KIND_DAEMON_RESTART. * * Returns: a #SnapdMaintenanceKind. * * Since: 1.45 */ SnapdMaintenanceKind snapd_maintenance_get_kind(SnapdMaintenance *self) { g_return_val_if_fail(SNAPD_IS_MAINTENANCE(self), SNAPD_MAINTENANCE_KIND_UNKNOWN); return self->kind; } /** * snapd_maintenance_get_message: * @maintenance: a #SnapdMaintenance. * * Get the user readable message associate with the maintenance state. * * Returns: message text. * * Since: 1.45 */ const gchar *snapd_maintenance_get_message(SnapdMaintenance *self) { g_return_val_if_fail(SNAPD_IS_MAINTENANCE(self), NULL); return self->message; } static void snapd_maintenance_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdMaintenance *self = SNAPD_MAINTENANCE(object); switch (prop_id) { case PROP_KIND: self->kind = g_value_get_enum(value); break; case PROP_MESSAGE: g_free(self->message); self->message = g_strdup(g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_maintenance_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdMaintenance *self = SNAPD_MAINTENANCE(object); switch (prop_id) { case PROP_KIND: g_value_set_enum(value, self->kind); break; case PROP_MESSAGE: g_value_set_boxed(value, self->message); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_maintenance_finalize(GObject *object) { SnapdMaintenance *self = SNAPD_MAINTENANCE(object); g_clear_pointer(&self->message, g_free); G_OBJECT_CLASS(snapd_maintenance_parent_class)->finalize(object); } static void snapd_maintenance_class_init(SnapdMaintenanceClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_maintenance_set_property; gobject_class->get_property = snapd_maintenance_get_property; gobject_class->finalize = snapd_maintenance_finalize; g_object_class_install_property( gobject_class, PROP_KIND, g_param_spec_enum( "kind", "kind", "Maintenance kind", SNAPD_TYPE_MAINTENANCE_KIND, SNAPD_MAINTENANCE_KIND_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_MESSAGE, g_param_spec_string("message", "message", "User readable message", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_maintenance_init(SnapdMaintenance *self) {} snapd-glib-1.67/snapd-glib/snapd-maintenance.h000066400000000000000000000026151477073115000212560ustar00rootroot00000000000000/* * Copyright (C) 2018 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_MAINTENANCE_H__ #define __SNAPD_MAINTENANCE_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_MAINTENANCE (snapd_maintenance_get_type()) G_DECLARE_FINAL_TYPE(SnapdMaintenance, snapd_maintenance, SNAPD, MAINTENANCE, GObject) /** * SnapdMaintenanceKind: * @SNAPD_MAINTENANCE_KIND_UNKNOWN: an unknown maintenance kind is occurring. * @SNAPD_MAINTENANCE_KIND_DAEMON_RESTART: the daemon is restarting. * @SNAPD_MAINTENANCE_KIND_SYSTEM_RESTART: the system is restarting. * * Type of snap. * * Since: 1.45 */ typedef enum { SNAPD_MAINTENANCE_KIND_UNKNOWN, SNAPD_MAINTENANCE_KIND_DAEMON_RESTART, SNAPD_MAINTENANCE_KIND_SYSTEM_RESTART } SnapdMaintenanceKind; SnapdMaintenanceKind snapd_maintenance_get_kind(SnapdMaintenance *maintenance); const gchar *snapd_maintenance_get_message(SnapdMaintenance *maintenance); G_END_DECLS #endif /* __SNAPD_MAINTENANCE_H__ */ snapd-glib-1.67/snapd-glib/snapd-markdown-node.c000066400000000000000000000122621477073115000215330ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-enum-types.h" #include "snapd-markdown-node.h" /** * SECTION:snapd-markdown-node * @short_description: Snap markdown node * @include: snapd-glib/snapd-glib.h * * A #SnapdMarkdownNode represents a markdown node extracted from text. See * #SnapdMarkdownParser for more information. */ /** * SnapdMarkdownNode: * * #SnapdMarkdownNode is an opaque data structure and can only be accessed * using the provided functions. * * Since: 1.48 */ struct _SnapdMarkdownNode { GObject parent_instance; SnapdMarkdownNodeType node_type; gchar *text; GPtrArray *children; }; enum { PROP_NODE_TYPE = 1, PROP_TEXT, PROP_CHILDREN, PROP_LAST }; G_DEFINE_TYPE(SnapdMarkdownNode, snapd_markdown_node, G_TYPE_OBJECT) static void snapd_markdown_node_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdMarkdownNode *self = SNAPD_MARKDOWN_NODE(object); switch (prop_id) { case PROP_NODE_TYPE: self->node_type = g_value_get_enum(value); break; case PROP_TEXT: g_free(self->text); self->text = g_strdup(g_value_get_string(value)); break; case PROP_CHILDREN: g_clear_pointer(&self->children, g_ptr_array_unref); if (g_value_get_boxed(value) != NULL) self->children = g_ptr_array_ref(g_value_get_boxed(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_markdown_node_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdMarkdownNode *self = SNAPD_MARKDOWN_NODE(object); switch (prop_id) { case PROP_NODE_TYPE: g_value_set_enum(value, self->node_type); break; case PROP_TEXT: g_value_set_string(value, self->text); break; case PROP_CHILDREN: g_value_set_boxed(value, self->children); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_markdown_node_finalize(GObject *object) { SnapdMarkdownNode *self = SNAPD_MARKDOWN_NODE(object); g_clear_pointer(&self->text, g_free); g_clear_pointer(&self->children, g_ptr_array_unref); G_OBJECT_CLASS(snapd_markdown_node_parent_class)->finalize(object); } static void snapd_markdown_node_class_init(SnapdMarkdownNodeClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_markdown_node_set_property; gobject_class->get_property = snapd_markdown_node_get_property; gobject_class->finalize = snapd_markdown_node_finalize; g_object_class_install_property( gobject_class, PROP_NODE_TYPE, g_param_spec_enum("node-type", "node-type", "Type of node", SNAPD_TYPE_MARKDOWN_NODE_TYPE, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_TEXT, g_param_spec_string("text", "text", "Text this node contains", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_CHILDREN, g_param_spec_boxed( "children", "children", "Child nodes", G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_markdown_node_init(SnapdMarkdownNode *self) {} /** * snapd_markdown_node_get_node_type: * @node: a #SnapdMarkdownNode. * * Get the type of node this is. * * Returns: a #SnapdMarkdownNodeType * * Since: 1.48 */ SnapdMarkdownNodeType snapd_markdown_node_get_node_type(SnapdMarkdownNode *self) { g_return_val_if_fail(SNAPD_IS_MARKDOWN_NODE(self), 0); return self->node_type; } /** * snapd_markdown_node_get_text: * @node: a #SnapdMarkdownNode. * * Gets the text associated with this node. This is only present for nodes of * type %SNAPD_MARKDOWN_NODE_TYPE_TEXT. * * Returns: a UTF-8 string or %NULL if none in this node. * * Since: 1.48 */ const gchar *snapd_markdown_node_get_text(SnapdMarkdownNode *self) { g_return_val_if_fail(SNAPD_IS_MARKDOWN_NODE(self), NULL); return self->text; } /** * snapd_markdown_node_get_children: * @node: a #SnapdMarkdownNode. * * Get the child nodes of this node. * * Returns: (transfer none) (element-type SnapdMarkdownNode): child nodes or * %NULL if none. Since: 1.48 */ GPtrArray *snapd_markdown_node_get_children(SnapdMarkdownNode *self) { g_return_val_if_fail(SNAPD_IS_MARKDOWN_NODE(self), NULL); return self->children; } snapd-glib-1.67/snapd-glib/snapd-markdown-node.h000066400000000000000000000037461477073115000215470ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_MARKDOWN_NODE_H__ #define __SNAPD_MARKDOWN_NODE_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_MARKDOWN_NODE (snapd_markdown_node_get_type()) G_DECLARE_FINAL_TYPE(SnapdMarkdownNode, snapd_markdown_node, SNAPD, MARKDOWN_NODE, GObject) /** * SnapdMarkdownNodeType: * @SNAPD_MARKDOWN_NODE_TYPE_TEXT: a piece of text. * @SNAPD_MARKDOWN_NODE_TYPE_PARAGRAPH: a paragraph. * @SNAPD_MARKDOWN_NODE_TYPE_UNORDERED_LIST: an unordered list. * @SNAPD_MARKDOWN_NODE_TYPE_LIST_ITEM: a list item. * @SNAPD_MARKDOWN_NODE_TYPE_CODE_BLOCK: a code block. * @SNAPD_MARKDOWN_NODE_TYPE_CODE_SPAN: a code span. * @SNAPD_MARKDOWN_NODE_TYPE_EMPHASIS: emphasised text. * @SNAPD_MARKDOWN_NODE_TYPE_STRONG_EMPHASIS: strongly emphasised text. * @SNAPD_MARKDOWN_NODE_TYPE_URL: a URL. * * Type of markdown node. * * Since: 1.48 */ typedef enum { SNAPD_MARKDOWN_NODE_TYPE_TEXT, SNAPD_MARKDOWN_NODE_TYPE_PARAGRAPH, SNAPD_MARKDOWN_NODE_TYPE_UNORDERED_LIST, SNAPD_MARKDOWN_NODE_TYPE_LIST_ITEM, SNAPD_MARKDOWN_NODE_TYPE_CODE_BLOCK, SNAPD_MARKDOWN_NODE_TYPE_CODE_SPAN, SNAPD_MARKDOWN_NODE_TYPE_EMPHASIS, SNAPD_MARKDOWN_NODE_TYPE_STRONG_EMPHASIS, SNAPD_MARKDOWN_NODE_TYPE_URL } SnapdMarkdownNodeType; SnapdMarkdownNodeType snapd_markdown_node_get_node_type(SnapdMarkdownNode *node); const gchar *snapd_markdown_node_get_text(SnapdMarkdownNode *node); GPtrArray *snapd_markdown_node_get_children(SnapdMarkdownNode *node); G_END_DECLS #endif /* __SNAPD_MARKDOWN_NODE_H__ */ snapd-glib-1.67/snapd-glib/snapd-markdown-parser.c000066400000000000000000000632301477073115000221030ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include #include "snapd-markdown-node.h" #include "snapd-markdown-parser.h" /** * SECTION:snapd-markdown-parser * @short_description: Snap markdown text parser * @include: snapd-glib/snapd-glib.h * * A #SnapdMarkdownParser parses text formatted in markdown; for example the * text returned by snapd_snap_get_description (). * * Snap supports the following subset of CommonMark (https://commonmark.org): * - Indented Code Blocks * - Paragraphs * - Blank Lines * - Unordered Lists * - Backslash escapes * - Code spans * * In addition text that contains URLs are converted into links. * * Use snapd_markdown_parser_parse () to convert text into a tree of * #SnapdMarkdownNode that you can then process to display in your client. */ /** * SnapdMarkdownParser: * * #SnapdMarkdownParser is an opaque data structure and can only be accessed * using the provided functions. * * Since: 1.48 */ struct _SnapdMarkdownParser { GObject parent_instance; gboolean preserve_whitespace; }; G_DEFINE_TYPE(SnapdMarkdownParser, snapd_markdown_parser, G_TYPE_OBJECT) static gboolean parse_empty_line(const gchar *line) { for (int i = 0; line[i] != '\0'; i++) if (!isspace(line[i])) return FALSE; return TRUE; } static gboolean parse_paragraph(const gchar *line, gchar **text) { int i = 0; while (isspace(line[i])) i++; if (text != NULL) *text = g_strdup(line + i); return TRUE; } static gboolean parse_bullet_list_item(const gchar *line, int *offset, gchar *symbol, gchar **bullet_text) { int i = 0; while (isspace(line[i])) i++; gchar symbol_ = line[i]; if (symbol_ != '-' && symbol_ != '+' && symbol_ != '*') return FALSE; int marker_offset = i; i++; if (line[i] == '\0') return FALSE; if (!isspace(line[i])) return FALSE; i++; int offset_ = i; while (isspace(line[offset_])) offset_++; /* Blank lines start one place after marker */ if (line[offset_] == '\0') offset_ = marker_offset + 1; if (offset != NULL) *offset = offset_; if (symbol != NULL) *symbol = symbol_; if (bullet_text != NULL) *bullet_text = g_strdup(line + i); return TRUE; } static gboolean parse_list_item_line(const gchar *line, int offset, gchar **text) { for (int i = 0; i < offset; i++) { if (!isspace(line[i])) return FALSE; } if (text != NULL) *text = g_strdup(line + offset); return TRUE; } static gboolean parse_indented_code_block(const gchar *line, gchar **text) { int space_count = 0; while (line[space_count] == ' ') space_count++; if (space_count < 4) return FALSE; if (text != NULL) *text = g_strdup(line + 4); return TRUE; } static gboolean is_punctuation_character(gchar c) { return strchr("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", c) != NULL; // FIXME: Also support unicode categories Pc, Pd, Pe, Pf, Pi, Po, and Ps. } static gboolean is_left_flanking_delimiter_run(const gchar *text, int index) { if (text[index] != '*' && text[index] != '_') return FALSE; int run_length = 1; while (text[index + run_length] == text[index]) run_length++; /* 1) Must not be followed by whitespace */ if (text[index + run_length] == '\0') return FALSE; if (isspace(text[index + run_length])) return FALSE; /* 2a) Is not followed by punctuation */ if (!is_punctuation_character(text[index + run_length])) return TRUE; /* 2b) Followed by punctuation and preceeded by whitespace or punctuation */ if (index == 0 || isspace(text[index - 1])) return TRUE; if (is_punctuation_character(text[index - 1])) return TRUE; return FALSE; } static gboolean is_right_flanking_delimiter_run(const gchar *text, int index) { if (text[index] != '*' && text[index] != '_') return FALSE; int run_length = 1; while (text[index + run_length] == text[index]) run_length++; /* 1) Not preceeded by whitespace */ if (index == 0 || isspace(text[index - 1])) return FALSE; /* 2a) No preceeded by punctuation */ if (!is_punctuation_character(text[index - 1])) return TRUE; /* 2b) Preceeded by punctuation and followed by whitespace or punctuation */ if (text[index + run_length] == '\0' || isspace(text[index + run_length])) return TRUE; if (is_punctuation_character(text[index + run_length])) return TRUE; return FALSE; } static gchar *strip_text(const gchar *text) { g_autoptr(GString) stripped_text = g_string_new(""); /* Strip leading whitespace */ int i = 0; while (isspace(text[i])) i++; gboolean in_whitespace = FALSE; while (text[i] != '\0') { if (isspace(text[i])) in_whitespace = TRUE; else { if (in_whitespace) g_string_append_c(stripped_text, ' '); in_whitespace = FALSE; g_string_append_c(stripped_text, text[i]); } i++; } return g_steal_pointer(&stripped_text->str); } typedef struct { gchar character; int length; gboolean can_open_emphasis; gboolean can_close_emphasis; } EmphasisInfo; static EmphasisInfo *emphasis_info_new(void) { return g_new0(EmphasisInfo, 1); } static void emphasis_info_free(EmphasisInfo *info) { g_free(info); } G_DEFINE_AUTOPTR_CLEANUP_FUNC(EmphasisInfo, emphasis_info_free) SnapdMarkdownNode *make_text_node(const gchar *text, int length) { if (length > 0) { g_autofree gchar *subtext = g_strndup(text, length); return g_object_new(SNAPD_TYPE_MARKDOWN_NODE, "node-type", SNAPD_MARKDOWN_NODE_TYPE_TEXT, "text", subtext, NULL); } else return g_object_new(SNAPD_TYPE_MARKDOWN_NODE, "node-type", SNAPD_MARKDOWN_NODE_TYPE_TEXT, "text", text, NULL); } SnapdMarkdownNode *make_paragraph_text_node(SnapdMarkdownParser *self, const gchar *text, int length) { if (self->preserve_whitespace) return make_text_node(text, length); g_autoptr(GString) result = g_string_new(""); gchar last_c = '\0'; for (int i = 0; text[i] != '\0' && (length == -1 || i < length); i++) { gchar c = text[i]; if (isspace(c)) { if (!isspace(last_c)) g_string_append_c(result, ' '); } else g_string_append_c(result, c); last_c = c; } return make_text_node(result->str, -1); } SnapdMarkdownNode *make_delimiter_node(EmphasisInfo *info) { g_autofree gchar *text = g_malloc(info->length + 1); for (int i = 0; i < info->length; i++) text[i] = info->character; text[info->length] = '\0'; return g_object_new(SNAPD_TYPE_MARKDOWN_NODE, "node-type", SNAPD_MARKDOWN_NODE_TYPE_TEXT, "text", text, NULL); } SnapdMarkdownNode *make_code_node(SnapdMarkdownNodeType type, const gchar *text) { g_autoptr(GPtrArray) children = g_ptr_array_new_with_free_func(g_object_unref); g_ptr_array_add(children, make_text_node(text, -1)); return g_object_new(SNAPD_TYPE_MARKDOWN_NODE, "node-type", type, "children", children, NULL); } static void find_emphasis(GPtrArray *nodes, GHashTable *emphasis_info) { for (int end_index = 0; end_index < nodes->len; end_index++) { SnapdMarkdownNode *end_node = g_ptr_array_index(nodes, end_index); EmphasisInfo *end_info = g_hash_table_lookup(emphasis_info, end_node); if (end_info == NULL || !end_info->can_close_emphasis) continue; /* Find a start emphasis that matches this end */ int start_index; SnapdMarkdownNode *start_node; EmphasisInfo *start_info; for (start_index = end_index - 1; start_index >= 0; start_index--) { start_node = g_ptr_array_index(nodes, start_index); start_info = g_hash_table_lookup(emphasis_info, start_node); if (start_info != NULL && start_info->can_open_emphasis && start_info->character == end_info->character) break; } if (start_index < 0) continue; // FIXME: Can do if both a multiple of three if ((start_info->can_open_emphasis && start_info->can_close_emphasis) || (end_info->can_open_emphasis && end_info->can_close_emphasis)) { if ((start_info->length + end_info->length) % 3 == 0) continue; } g_assert(start_info->length > 0); g_assert(end_info->length > 0); SnapdMarkdownNodeType node_type; if (start_info->length > 1 && end_info->length > 1) { node_type = SNAPD_MARKDOWN_NODE_TYPE_STRONG_EMPHASIS; start_info->length -= 2; end_info->length -= 2; } else { node_type = SNAPD_MARKDOWN_NODE_TYPE_EMPHASIS; start_info->length--; end_info->length--; } /* Replace nodes */ g_autoptr(GPtrArray) children = g_ptr_array_new_with_free_func(g_object_unref); for (int i = start_index + 1; i < end_index; i++) { SnapdMarkdownNode *node = g_ptr_array_index(nodes, i); g_ptr_array_add(children, g_object_ref(node)); } g_ptr_array_remove_range(nodes, start_index, end_index - start_index + 1); g_ptr_array_insert(nodes, start_index, g_object_new(SNAPD_TYPE_MARKDOWN_NODE, "node-type", node_type, "children", children, NULL)); g_hash_table_steal(emphasis_info, start_node); g_hash_table_steal(emphasis_info, end_node); if (end_info->length > 0) { SnapdMarkdownNode *node = make_delimiter_node(end_info); g_hash_table_insert(emphasis_info, node, end_info); g_ptr_array_insert(nodes, start_index + 1, node); } else emphasis_info_free(end_info); if (start_info->length > 0) { SnapdMarkdownNode *node = make_delimiter_node(start_info); g_hash_table_insert(emphasis_info, node, start_info); g_ptr_array_insert(nodes, start_index, node); } else emphasis_info_free(start_info); end_index = start_index; } } static int backtick_count(const gchar *text) { int count = 0; while (text[count] == '`') count++; return count; } static void combine_text_nodes(GPtrArray *nodes) { for (int i = 0; i < nodes->len; i++) { SnapdMarkdownNode *node = g_ptr_array_index(nodes, i); GPtrArray *children = snapd_markdown_node_get_children(node); if (children != NULL) combine_text_nodes(children); if (snapd_markdown_node_get_node_type(node) != SNAPD_MARKDOWN_NODE_TYPE_TEXT) continue; int node_count = 1; g_autoptr(GString) text = NULL; while (i + node_count < nodes->len) { SnapdMarkdownNode *n = g_ptr_array_index(nodes, i + node_count); if (snapd_markdown_node_get_node_type(n) != SNAPD_MARKDOWN_NODE_TYPE_TEXT) break; if (text == NULL) text = g_string_new(snapd_markdown_node_get_text(node)); g_string_append(text, snapd_markdown_node_get_text(n)); node_count++; } if (node_count > 1) { g_ptr_array_remove_range(nodes, i, node_count); g_ptr_array_insert(nodes, i, make_text_node(text->str, -1)); } } } static gboolean is_valid_url_char(gchar c) { if ((c & 0x80) != 0) return TRUE; if (c >= 'a' && c <= 'z') return TRUE; if (c >= 'A' && c <= 'Z') return TRUE; if (c >= '0' && c <= '9') return TRUE; /* "Safe" characters */ if (strchr("$-_.+", c) != NULL) return TRUE; /* "Reserved" characters */ if (strchr(";/?:@&=", c) != NULL) return TRUE; if (strchr("~#[]!'()*,%", c) != NULL) return TRUE; return FALSE; } static gboolean is_url(const gchar *text, int *length) { int prefix_length; if (g_str_has_prefix(text, "http://")) prefix_length = 7; else if (g_str_has_prefix(text, "https://")) prefix_length = 8; else if (g_str_has_prefix(text, "mailto:")) prefix_length = 7; else return FALSE; int _length = prefix_length; int bracket_count = 0; while (text[_length] != '\0' && is_valid_url_char(text[_length])) { if (text[_length] == '(') bracket_count++; else if (text[_length] == ')') { bracket_count--; if (bracket_count < 0) break; } _length++; } /* Can't end in punctuation */ while (_length > prefix_length && strchr(",.", text[_length - 1]) != NULL) _length--; if (_length == prefix_length) return FALSE; if (length != NULL) *length = _length; return TRUE; } static int find_url(const gchar *text, int *url_length) { for (int offset = 0; text[offset] != '\0'; offset++) if (is_url(text + offset, url_length)) return offset; return -1; } SnapdMarkdownNode *make_url_node(const gchar *text, int length) { g_autoptr(GPtrArray) children = g_ptr_array_new_with_free_func(g_object_unref); g_ptr_array_add(children, make_text_node(text, length)); return g_object_new(SNAPD_TYPE_MARKDOWN_NODE, "node-type", SNAPD_MARKDOWN_NODE_TYPE_URL, "children", children, NULL); } static void extract_urls(GPtrArray *nodes) { for (int i = 0; i < nodes->len; i++) { SnapdMarkdownNode *node = g_ptr_array_index(nodes, i); GPtrArray *children; const gchar *text; int url_offset, url_length; children = snapd_markdown_node_get_children(node); if (snapd_markdown_node_get_node_type(node) != SNAPD_MARKDOWN_NODE_TYPE_URL && children != NULL) extract_urls(children); if (snapd_markdown_node_get_node_type(node) != SNAPD_MARKDOWN_NODE_TYPE_TEXT) continue; text = snapd_markdown_node_get_text(node); url_offset = find_url(text, &url_length); if (url_offset >= 0) { if (text[url_offset + url_length] != '\0') g_ptr_array_insert(nodes, i + 1, make_text_node(text + url_offset + url_length, -1)); g_ptr_array_insert(nodes, i + 1, make_url_node(text + url_offset, url_length)); if (url_offset > 0) g_ptr_array_insert(nodes, i + 1, make_text_node(text, url_offset)); g_ptr_array_remove_index(nodes, i); } } } static GPtrArray *markup_inline(SnapdMarkdownParser *self, const gchar *text) { /* Split into nodes */ g_autoptr(GPtrArray) nodes = g_ptr_array_new_with_free_func(g_object_unref); g_autoptr(GHashTable) emphasis_info = g_hash_table_new_full( g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)emphasis_info_free); for (int i = 0; text[i] != '\0';) { int start = i; /* Extract code spans */ if (text[start] == '`') { int size = backtick_count(text + start); int end = start + size; while (text[end] != '\0') { int s = backtick_count(text + end); if (s == size) break; else if (s == 0) end++; else end += s; } if (text[end] != '\0') { g_autofree gchar *code_text = g_strndup(text + start + size, end - start - size); g_autofree gchar *stripped_code_text = strip_text(code_text); g_ptr_array_add(nodes, make_code_node(SNAPD_MARKDOWN_NODE_TYPE_CODE_SPAN, stripped_code_text)); i = end + size; } else { g_ptr_array_add(nodes, make_paragraph_text_node(self, text + start, size)); i = start + size; } continue; } /* Escaped characters */ if (text[start] == '\\' && is_punctuation_character(text[start + 1])) { g_ptr_array_add(nodes, make_text_node(text + start + 1, 1)); i = start + 2; continue; } /* Extract emphasis delimiters (we determine later if they are used) */ if (text[start] == '*' || text[start] == '_') { while (text[i] == text[start]) i++; gboolean is_left_flanking = is_left_flanking_delimiter_run(text, start); gboolean is_right_flanking = is_right_flanking_delimiter_run(text, start); g_autoptr(EmphasisInfo) info = emphasis_info_new(); info->character = text[start]; info->length = i - start; if (text[start] == '_') { info->can_open_emphasis = is_left_flanking && (!is_right_flanking || (start > 0 && is_punctuation_character(text[start - 1]))); info->can_close_emphasis = is_right_flanking && (!is_left_flanking || is_punctuation_character(text[i])); } else if (text[start] == '*') { info->can_open_emphasis = is_left_flanking; info->can_close_emphasis = is_right_flanking; } SnapdMarkdownNode *node = make_paragraph_text_node(self, text + start, i - start); g_ptr_array_add(nodes, node); g_hash_table_insert(emphasis_info, node, g_steal_pointer(&info)); continue; } /* Extract text until next potential emphasis or code span */ while (text[i] != '\0') { if (text[i] == '*' || text[i] == '_' || text[i] == '`') break; if (text[i] == '\\' && is_punctuation_character(text[i + 1])) break; i++; } g_ptr_array_add(nodes, make_paragraph_text_node(self, text + start, i - start)); } /* Convert nodes into emphasis */ find_emphasis(nodes, emphasis_info); /* Combine sequential text nodes */ combine_text_nodes(nodes); /* Extract URLs */ extract_urls(nodes); return g_steal_pointer(&nodes); } static GPtrArray *markdown_to_markup(SnapdMarkdownParser *self, const gchar *text) { /* Snap supports the following subset of CommonMark (https://commonmark.org/): * * Indented code blocks * Paragraphs * Blank lines * Lists * Backslash escapes * Code spans * Emphasis and strong emphasis * Textual content * * In addition, links are automatically converted to hyperlinks. */ /* 1. Split into lines */ g_autoptr(GPtrArray) line_array = g_ptr_array_new_with_free_func(g_free); int line_start = 0; for (int i = 0; text[i] != '\0'; i++) { if (text[i] == '\n' || text[i] == '\r') { if (text[i] == '\r' && text[i + 1] == '\n') i++; g_ptr_array_add(line_array, g_strndup(text + line_start, i - line_start + 1)); line_start = i + 1; } } if (text[line_start] != '\0') g_ptr_array_add(line_array, g_strdup(text + line_start)); g_ptr_array_add(line_array, NULL); GStrv lines = (GStrv)line_array->pdata; /* 2. Split lines into blocks (paragraphs, lists, code) */ int line_number = 0; g_autoptr(GPtrArray) nodes = g_ptr_array_new_with_free_func(g_object_unref); while (lines[line_number] != NULL) { /* Skip empty lines */ if (parse_empty_line(lines[line_number])) { line_number++; continue; } g_autofree gchar *block_text = NULL; int bullet_offset = 0; gchar bullet_symbol; g_autofree gchar *bullet_text = NULL; /* Indented code blocks */ if (parse_indented_code_block(lines[line_number], &block_text)) { g_autoptr(GString) code_text = g_string_new(""); g_string_append(code_text, block_text); while (TRUE) { line_number++; if (lines[line_number] == NULL) break; g_autofree gchar *text = NULL; if (parse_indented_code_block(lines[line_number], &text)) { g_string_append(code_text, text); } else if (parse_empty_line(lines[line_number])) g_string_append_c(code_text, '\n'); else break; } /* Remove trailing empty lines */ while (g_str_has_suffix(code_text->str, "\n\n")) g_string_truncate(code_text, code_text->len - 1); g_ptr_array_add(nodes, make_code_node(SNAPD_MARKDOWN_NODE_TYPE_CODE_BLOCK, code_text->str)); } /* Bullet lists */ else if (parse_bullet_list_item(lines[line_number], &bullet_offset, &bullet_symbol, &bullet_text)) { g_autoptr(GPtrArray) list_items = g_ptr_array_new_with_free_func(g_object_unref); g_autoptr(GString) list_data = g_string_new(bullet_text); gboolean starts_with_empty_line = bullet_text[0] == '\0'; gboolean have_item = TRUE; while (TRUE) { line_number++; if (lines[line_number] == NULL) break; if (parse_empty_line(lines[line_number])) { if (starts_with_empty_line) break; g_string_append(list_data, lines[line_number]); have_item = TRUE; continue; } starts_with_empty_line = FALSE; g_autofree gchar *line_text = NULL; if (parse_list_item_line(lines[line_number], bullet_offset, &line_text)) { g_string_append(list_data, line_text); have_item = TRUE; continue; } if (have_item) { g_autoptr(GPtrArray) children = markdown_to_markup(self, list_data->str); g_ptr_array_add(list_items, g_object_new(SNAPD_TYPE_MARKDOWN_NODE, "node-type", SNAPD_MARKDOWN_NODE_TYPE_LIST_ITEM, "children", children, NULL)); g_string_assign(list_data, ""); have_item = FALSE; } // FIXME: Check matching offset g_autofree gchar *text = NULL; gchar symbol; if (!parse_bullet_list_item(lines[line_number], &bullet_offset, &symbol, &text)) break; if (symbol != bullet_symbol) break; g_string_assign(list_data, text); have_item = TRUE; } if (have_item) { g_autoptr(GPtrArray) children = markdown_to_markup(self, list_data->str); g_ptr_array_add(list_items, g_object_new(SNAPD_TYPE_MARKDOWN_NODE, "node-type", SNAPD_MARKDOWN_NODE_TYPE_LIST_ITEM, "children", children, NULL)); } g_ptr_array_add(nodes, g_object_new(SNAPD_TYPE_MARKDOWN_NODE, "node-type", SNAPD_MARKDOWN_NODE_TYPE_UNORDERED_LIST, "children", list_items, NULL)); } /* Paragraphs */ else { g_autoptr(GString) paragraph_text = g_string_new(""); while (TRUE) { g_autofree gchar *text = NULL; parse_paragraph(lines[line_number], &text); g_string_append(paragraph_text, text); line_number++; /* Out of data */ if (lines[line_number] == NULL) break; /* Break on empty line */ if (parse_empty_line(lines[line_number])) break; /* Break on non-empty list items */ g_autofree gchar *bullet_text = NULL; if (parse_bullet_list_item(lines[line_number], NULL, NULL, &bullet_text)) { if (bullet_text[0] != '\0') break; } } /* Strip leading and trailing whitespace */ int offset = 0; while (isspace(paragraph_text->str[offset])) offset++; int length = paragraph_text->len; while (length > 0 && isspace(paragraph_text->str[length - 1])) length--; if (offset + length > paragraph_text->len) length = 0; g_autofree gchar *stripped_text = g_strndup(paragraph_text->str + offset, length); g_autoptr(GPtrArray) children = markup_inline(self, stripped_text); g_ptr_array_add(nodes, g_object_new(SNAPD_TYPE_MARKDOWN_NODE, "node-type", SNAPD_MARKDOWN_NODE_TYPE_PARAGRAPH, "children", children, NULL)); } } return g_steal_pointer(&nodes); } /** * snapd_markdown_parser_new: * @version: version supported by the client. * * Create an object to parse markdown text. * * Returns: a new #SnapdMarkdownParser * * Since: 1.48 */ SnapdMarkdownParser *snapd_markdown_parser_new(SnapdMarkdownVersion version) { return g_object_new(SNAPD_TYPE_MARKDOWN_PARSER, NULL); } /** * snapd_markdown_parser_set_preserve_whitespace: * @parser: a #SnapdMarkdownParser. * @preserve_whitespace: %TRUE if the parse should keep paragraph whitespace * intact. * * Consecutive paragraph whitespace (space, tabs, newlines) is automatically * combined into a single space character. This renders the paragraphs in the * form that HTML uses. If you need the original whitespace that the markdown * author wrote then set this to %FALSE. * * Since: 1.48 */ void snapd_markdown_parser_set_preserve_whitespace( SnapdMarkdownParser *self, gboolean preserve_whitespace) { g_return_if_fail(SNAPD_IS_MARKDOWN_PARSER(self)); self->preserve_whitespace = preserve_whitespace; } /** * snapd_markdown_parser_get_preserve_whitespace: * @parser: a #SnapdMarkdownParser. * * Check if paragraph whitespace will be kept intact. * * Returns: %TRUE if paragraph whitespace is preserved. * * Since: 1.48 */ gboolean snapd_markdown_parser_get_preserve_whitespace(SnapdMarkdownParser *self) { g_return_val_if_fail(SNAPD_IS_MARKDOWN_PARSER(self), FALSE); return self->preserve_whitespace; } /** * snapd_markdown_parser_parse: * @parser: a #SnapdMarkdownParser. * @text: text to parse. * * Convert text in snapd markdown format to markup. * * Returns: (transfer container) (element-type SnapdMarkdownNode): Text split * into blocks. * * Since: 1.48 */ GPtrArray *snapd_markdown_parser_parse(SnapdMarkdownParser *self, const gchar *text) { g_return_val_if_fail(SNAPD_IS_MARKDOWN_PARSER(self), NULL); g_return_val_if_fail(text != NULL, NULL); return markdown_to_markup(self, text); } static void snapd_markdown_parser_class_init(SnapdMarkdownParserClass *klass) {} static void snapd_markdown_parser_init(SnapdMarkdownParser *self) {} snapd-glib-1.67/snapd-glib/snapd-markdown-parser.h000066400000000000000000000030311477073115000221010ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_MARKDOWN_PARSER_H__ #define __SNAPD_MARKDOWN_PARSER_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_MARKDOWN_PARSER (snapd_markdown_parser_get_type()) /** * SnapdMarkdownVersion: * @SNAPD_MARKDOWN_VERSION_0: the initial version of Snap markdown. * * Version of markdown to parse. Picking a version will ensure only nodes of the * expected type are decoded. * * Since: 1.48 */ typedef enum { SNAPD_MARKDOWN_VERSION_0 } SnapdMarkdownVersion; G_DECLARE_FINAL_TYPE(SnapdMarkdownParser, snapd_markdown_parser, SNAPD, MARKDOWN_PARSER, GObject) SnapdMarkdownParser *snapd_markdown_parser_new(SnapdMarkdownVersion version); void snapd_markdown_parser_set_preserve_whitespace( SnapdMarkdownParser *parser, gboolean preserve_whitespace); gboolean snapd_markdown_parser_get_preserve_whitespace(SnapdMarkdownParser *parser); GPtrArray *snapd_markdown_parser_parse(SnapdMarkdownParser *parser, const gchar *text); G_END_DECLS #endif /* __SNAPD_MARKDOWN_PARSER_H__ */ snapd-glib-1.67/snapd-glib/snapd-media.c000066400000000000000000000123311477073115000200420ustar00rootroot00000000000000/* * Copyright (C) 2018 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-media.h" /** * SECTION: snapd-media * @short_description: Media information * @include: snapd-glib/snapd-glib.h * * A #SnapdMedia represents media (icons, screenshots etc) that are associated * with a snap. Snap media can be queried using snapd_snap_get_media(). */ /** * SnapdMedia: * * #SnapdMedia contains media information. * * Since: 1.45 */ struct _SnapdMedia { GObject parent_instance; gchar *type; gchar *url; guint width; guint height; }; enum { PROP_TYPE = 1, PROP_URL, PROP_WIDTH, PROP_HEIGHT, PROP_LAST }; G_DEFINE_TYPE(SnapdMedia, snapd_media, G_TYPE_OBJECT) SnapdMedia *snapd_media_new(void) { return g_object_new(SNAPD_TYPE_MEDIA, NULL); } /** * snapd_media_get_media_type: * @media: a #SnapdMedia. * * Get the type for this media, e.g. "icon" or "screenshot". * * Returns: a type name * * Since: 1.45 */ const gchar *snapd_media_get_media_type(SnapdMedia *self) { g_return_val_if_fail(SNAPD_IS_MEDIA(self), NULL); return self->type; } /** * snapd_media_get_url: * @media: a #SnapdMedia. * * Get the URL for this media, e.g. "http://example.com/media.png" * * Returns: a URL * * Since: 1.45 */ const gchar *snapd_media_get_url(SnapdMedia *self) { g_return_val_if_fail(SNAPD_IS_MEDIA(self), NULL); return self->url; } /** * snapd_media_get_width: * @media: a #SnapdMedia. * * Get the width of the media in pixels or 0 if unknown. * * Return: a width * * Since: 1.45 */ guint snapd_media_get_width(SnapdMedia *self) { g_return_val_if_fail(SNAPD_IS_MEDIA(self), 0); return self->width; } /** * snapd_media_get_height: * @media: a #SnapdMedia. * * Get the height of the media in pixels or 0 if unknown. * * Return: a height * * Since: 1.45 */ guint snapd_media_get_height(SnapdMedia *self) { g_return_val_if_fail(SNAPD_IS_MEDIA(self), 0); return self->height; } static void snapd_media_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdMedia *self = SNAPD_MEDIA(object); switch (prop_id) { case PROP_TYPE: g_free(self->type); self->type = g_strdup(g_value_get_string(value)); break; case PROP_URL: g_free(self->url); self->url = g_strdup(g_value_get_string(value)); break; case PROP_WIDTH: self->width = g_value_get_uint(value); break; case PROP_HEIGHT: self->height = g_value_get_uint(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_media_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdMedia *self = SNAPD_MEDIA(object); switch (prop_id) { case PROP_TYPE: g_value_set_string(value, self->type); break; case PROP_URL: g_value_set_string(value, self->url); break; case PROP_WIDTH: g_value_set_uint(value, self->width); break; case PROP_HEIGHT: g_value_set_uint(value, self->height); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_media_finalize(GObject *object) { SnapdMedia *self = SNAPD_MEDIA(object); g_clear_pointer(&self->type, g_free); g_clear_pointer(&self->url, g_free); G_OBJECT_CLASS(snapd_media_parent_class)->finalize(object); } static void snapd_media_class_init(SnapdMediaClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_media_set_property; gobject_class->get_property = snapd_media_get_property; gobject_class->finalize = snapd_media_finalize; g_object_class_install_property( gobject_class, PROP_TYPE, g_param_spec_string("type", "type", "Type for this media", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_URL, g_param_spec_string("url", "url", "URL for this media", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_WIDTH, g_param_spec_uint( "width", "width", "Width of media in pixels", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_HEIGHT, g_param_spec_uint( "height", "height", "Height of media in pixels", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_media_init(SnapdMedia *self) {} snapd-glib-1.67/snapd-glib/snapd-media.h000066400000000000000000000017071477073115000200540ustar00rootroot00000000000000/* * Copyright (C) 2018 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_MEDIA_H__ #define __SNAPD_MEDIA_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_MEDIA (snapd_media_get_type()) G_DECLARE_FINAL_TYPE(SnapdMedia, snapd_media, SNAPD, MEDIA, GObject) const gchar *snapd_media_get_media_type(SnapdMedia *media); const gchar *snapd_media_get_url(SnapdMedia *media); guint snapd_media_get_width(SnapdMedia *media); guint snapd_media_get_height(SnapdMedia *media); G_END_DECLS #endif /* __SNAPD_MEDIA_H__ */ snapd-glib-1.67/snapd-glib/snapd-notice.c000066400000000000000000000444011477073115000202470ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-notice.h" /** * SECTION: snapd-notice * @short_description: Notices element * @include: snapd-glib/snapd-glib.h * * A #SnapdNotice contains information about a notice that is notified. */ /** * SnapdNotice: * * #SnapdNotice contains information on a notification element. * * Since: 1.65 */ enum { PROP_ID = 1, PROP_USER_ID, PROP_TYPE, PROP_KEY, PROP_FIRST_OCCURRED, PROP_LAST_OCCURRED, PROP_LAST_OCCURRED_NANO, PROP_LAST_REPEATED, PROP_OCCURRENCES, PROP_LAST_DATA, PROP_REPEAT_AFTER, PROP_EXPIRE_AFTER, PROP_LAST }; struct _SnapdNotice { GObject parent_instance; gchar *id; gchar *userid; SnapdNoticeType type; gchar *key; GDateTime *first_occurred; GDateTime *last_occurred; // last_ocurred_internal contains the same date/time, but without // microseconds. Useful to speedup comparisons. GDateTime *last_occurred_internal; int last_occurred_nanosecond; GDateTime *last_repeated; GHashTable *data; gint64 occurrences; GTimeSpan repeat_after; GTimeSpan expire_after; }; G_DEFINE_TYPE(SnapdNotice, snapd_notice, G_TYPE_OBJECT) /** * snapd_notice_get_id: * @notice: a #SnapdNotice. * * Get the unique ID for this notice. * * Returns: an ID. * * Since: 1.65 */ const gchar *snapd_notice_get_id(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), NULL); return self->id; } /** * snapd_notice_get_user_id: * @notice: a #SnapdNotice. * * Get the user ID for this notice, or NULL if no user is defined * * Returns: an user ID. * * Since: 1.65 */ const gchar *snapd_notice_get_user_id(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), NULL); return self->userid; } /** * snapd_notice_get_notice_type: * @notice: a #SnapdNotice. * * Gets the type of notice this is. * * Returns: the type of notice. * * Since: 1.65 */ SnapdNoticeType snapd_notice_get_notice_type(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), SNAPD_NOTICE_TYPE_UNKNOWN); return self->type; } /** * snapd_notice_get_key: * @notice: a #SnapdNotice. * * Get the notice-id or the instance-name, depending on the type. * * Returns: a string with the key. * * Since: 1.65 */ const gchar *snapd_notice_get_key(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), NULL); return self->key; } /** * snapd_notice_get_last_data: * @notice: a #SnapdNotice. * * Get the data of the notice. * * Returns: (transfer container): a HashTable with the data elements. * * Since: 1.65 * Deprecated: 1.66: Use snapd_notice_get_last_data2() */ GHashTable *snapd_notice_get_last_data(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), NULL); return g_hash_table_ref(self->data); } /** * snapd_notice_get_last_data2: (rename-to snapd_notice_get_last_data) * @notice: a #SnapdNotice. * * Get the data of the notice. * * Returns: (transfer none): a HashTable with the data elements. * * Since: 1.66 */ GHashTable *snapd_notice_get_last_data2(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), NULL); return self->data; } /** * snapd_notice_get_first_occurred: * @notice: a #SnapdNotice. * * Get the time this notification first occurred. * * Returns: (transfer full): a #GDateTime. * * Since: 1.65 * Deprecated: 1.66: Use snapd_notice_get_first_occurred2() */ GDateTime *snapd_notice_get_first_occurred(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), NULL); if (self->first_occurred == NULL) return NULL; return g_date_time_ref(self->first_occurred); } /** * snapd_notice_get_first_occurred2: (rename-to snapd_notice_get_first_occurred) * @notice: a #SnapdNotice. * * Get the time this notification first occurred. * * Returns: (transfer none): a #GDateTime. * * Since: 1.66 */ GDateTime *snapd_notice_get_first_occurred2(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), NULL); return self->first_occurred; } /** * snapd_notice_get_last_occurred: * @notice: a #SnapdNotice. * * Get the time this notification last occurred. * * Returns: (transfer full): a #GDateTime. * * Since: 1.65 * Deprecated: 1.66: Use snapd_notice_get_last_occurred2() */ GDateTime *snapd_notice_get_last_occurred(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), NULL); if (self->last_occurred == NULL) return NULL; return g_date_time_ref(self->last_occurred); } /** * snapd_notice_get_last_occurred2: (rename-to snapd_notice_get_last_occurred) * @notice: a #SnapdNotice. * * Get the time this notification last occurred. * * Returns: (transfer none): a #GDateTime. * * Since: 1.66 */ GDateTime *snapd_notice_get_last_occurred2(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), NULL); return self->last_occurred; } /** * snapd_notice_get_last_occurred_nanoseconds: * @notice: a #SnapdNotice. * * Get the nanoseconds value of *last-occurred*, exactly as sent by * snapd. Useful when combined with #snapd_client_notices_set_since_nanoseconds, * and used internally by snapd_client_notices_set_after_notice, to ensure the * maximum possible precission when dealing with timestamps. * * Returns: the nanosecond value between 0 and 999999999, or -1 if no * nanosecond value was set. * * Since: 1.66 */ int snapd_notice_get_last_occurred_nanoseconds(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), 0); return self->last_occurred_nanosecond; } /** * snapd_notice_get_last_repeated: * @notice: a #SnapdNotice. * * Get the time this notification last repeated. * * Returns: (transfer full): a #GDateTime. * * Since: 1.65 * Deprecated: 1.66: Use snapd_notice_get_last_repeated2() */ GDateTime *snapd_notice_get_last_repeated(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), NULL); if (self->last_repeated == NULL) return NULL; return g_date_time_ref(self->last_repeated); } /** * snapd_notice_get_last_repeated2: (rename-to snapd_notice_get_last_repeated) * @notice: a #SnapdNotice. * * Get the time this notification last repeated. * * Returns: (transfer none): a #GDateTime. * * Since: 1.66 */ GDateTime *snapd_notice_get_last_repeated2(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), NULL); return self->last_repeated; } /** * snapd_notice_get_occurrences: * @notice: a #SnapdNotice. * * Get the number of times that this notification has been triggered. * * Returns: a count. * * Since: 1.65 */ gint64 snapd_notice_get_occurrences(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), 0); return self->occurrences; } /** * snapd_notice_get_repeat_after: * @notice: a #SnapdNotice. * * Get the time interval after this notification can be repeated. * * Returns: a #GTimeSpan. * * Since: 1.65 */ GTimeSpan snapd_notice_get_repeat_after(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), 0); return self->repeat_after; } /** * snapd_notice_get_expire_after: * @notice: a #SnapdNotice. * * Get the time interval after this notification can expire. * * Returns: a #GTimeSpan. * * Since: 1.65 */ GTimeSpan snapd_notice_get_expire_after(SnapdNotice *self) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), 0); return self->expire_after; } /** * snapd_notice_compare_last_occurred: * @notice: a #SnapdNotice. * @notice_to_compare: another #SnapdNotice. * * Compare the last_occurred fields (and the last_occurred_nanosecond if * available) of both notices, and returns whether the first one is before, same * or after the second one. * * Returns: -1 if the first one is before the second one; 0 if both are the same * time instant, and 1 if the first one is after the second one. * * Since: 1.66 */ gint snapd_notice_compare_last_occurred(SnapdNotice *self, SnapdNotice *notice_to_compare) { g_return_val_if_fail(SNAPD_IS_NOTICE(self), 0); g_return_val_if_fail(SNAPD_IS_NOTICE(notice_to_compare), 0); // first, compare without micro/nanoseconds. This is a must to avoid errors // due to rounding, because the g_date_time objects are created using a // gdouble. gint c = g_date_time_compare(self->last_occurred_internal, notice_to_compare->last_occurred_internal); if (c != 0) return c; // now take into account the nanoseconds if available int self_nano = self->last_occurred_nanosecond; if (self_nano == -1) self_nano = 1000 * g_date_time_get_microsecond(self->last_occurred); int notice_nano = notice_to_compare->last_occurred_nanosecond; if (notice_nano == -1) notice_nano = 1000 * g_date_time_get_microsecond(notice_to_compare->last_occurred); if (self_nano < notice_nano) return -1; if (self_nano == notice_nano) return 0; return 1; } static void snapd_notice_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdNotice *self = SNAPD_NOTICE(object); GDateTime *tmpdate; switch (prop_id) { case PROP_ID: g_free(self->id); self->id = g_strdup(g_value_get_string(value)); break; case PROP_USER_ID: g_free(self->userid); self->userid = g_strdup(g_value_get_string(value)); break; case PROP_TYPE: self->type = g_value_get_uint(value); break; case PROP_KEY: g_free(self->key); self->key = g_strdup(g_value_get_string(value)); break; case PROP_FIRST_OCCURRED: g_clear_pointer(&self->first_occurred, g_date_time_unref); tmpdate = g_value_get_boxed(value); self->first_occurred = tmpdate == NULL ? NULL : g_date_time_ref(tmpdate); break; case PROP_LAST_OCCURRED: g_clear_pointer(&self->last_occurred, g_date_time_unref); g_clear_pointer(&self->last_occurred_internal, g_date_time_unref); if (g_value_get_boxed(value) != NULL) { self->last_occurred = g_date_time_ref(g_value_get_boxed(value)); // store the same date/time, but without microseconds self->last_occurred_internal = g_date_time_add(self->last_occurred, -g_date_time_get_microsecond(self->last_occurred)); } break; case PROP_LAST_OCCURRED_NANO: self->last_occurred_nanosecond = g_value_get_int(value); break; case PROP_LAST_REPEATED: g_clear_pointer(&self->last_repeated, g_date_time_unref); if (g_value_get_boxed(value) != NULL) self->last_repeated = g_date_time_ref(g_value_get_boxed(value)); break; case PROP_OCCURRENCES: self->occurrences = g_value_get_int64(value); break; case PROP_LAST_DATA: g_clear_pointer(&self->data, g_hash_table_unref); if (g_value_get_boxed(value) != NULL) self->data = g_hash_table_ref(g_value_get_boxed(value)); else self->data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); break; case PROP_EXPIRE_AFTER: self->expire_after = g_value_get_int64(value); break; case PROP_REPEAT_AFTER: self->repeat_after = g_value_get_int64(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_notice_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdNotice *self = SNAPD_NOTICE(object); switch (prop_id) { case PROP_ID: g_value_set_string(value, self->id); break; case PROP_USER_ID: g_value_set_string(value, self->userid); break; case PROP_TYPE: g_value_set_uint(value, self->type); break; case PROP_KEY: g_value_set_string(value, self->key); break; case PROP_FIRST_OCCURRED: g_value_set_boxed(value, self->first_occurred); break; case PROP_LAST_OCCURRED: g_value_set_boxed(value, self->last_occurred); break; case PROP_LAST_OCCURRED_NANO: g_value_set_int(value, self->last_occurred_nanosecond); break; case PROP_LAST_REPEATED: g_value_set_boxed(value, self->last_repeated); break; case PROP_OCCURRENCES: g_value_set_int(value, self->occurrences); break; case PROP_LAST_DATA: g_value_set_boxed(value, self->data); break; case PROP_EXPIRE_AFTER: g_value_set_int64(value, self->expire_after); break; case PROP_REPEAT_AFTER: g_value_set_int64(value, self->repeat_after); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_notice_finalize(GObject *object) { SnapdNotice *self = SNAPD_NOTICE(object); g_clear_pointer(&self->id, g_free); g_clear_pointer(&self->userid, g_free); g_clear_pointer(&self->key, g_free); g_clear_pointer(&self->first_occurred, g_date_time_unref); g_clear_pointer(&self->last_occurred, g_date_time_unref); g_clear_pointer(&self->last_occurred_internal, g_date_time_unref); g_clear_pointer(&self->last_repeated, g_date_time_unref); g_clear_pointer(&self->data, g_hash_table_unref); G_OBJECT_CLASS(snapd_notice_parent_class)->finalize(object); } static void snapd_notice_class_init(SnapdNoticeClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_notice_set_property; gobject_class->get_property = snapd_notice_get_property; gobject_class->finalize = snapd_notice_finalize; g_object_class_install_property( gobject_class, PROP_ID, g_param_spec_string("id", "id", "ID of notice", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_USER_ID, g_param_spec_string( "user-id", "user-id", "UserID of the user who may view this notice (NULL means all users)", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_TYPE, g_param_spec_uint( "notice-type", "notice-type", "Type of notice", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_KEY, g_param_spec_string("key", "key", "Key of notice", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_FIRST_OCCURRED, g_param_spec_boxed("first-occurred", "first-occurred", "Time this notice first occurred", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_LAST_OCCURRED, g_param_spec_boxed("last-occurred", "last-occurred", "Time this notice last occurred", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_LAST_OCCURRED_NANO, g_param_spec_int("last-occurred-nanoseconds", "last-occurred-nanoseconds", "Time this notice last ocurred, in string format and " "with nanosecond accuracy", -1, 999999999, -1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_LAST_REPEATED, g_param_spec_boxed("last-repeated", "last-repeated", "Time this notice was last repeated", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_OCCURRENCES, g_param_spec_int64("occurrences", "occurrences", "Number of time one of these notices has occurred", G_MININT, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_LAST_DATA, g_param_spec_boxed( "last-data", "last-data", "Data for this notice", G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_REPEAT_AFTER, g_param_spec_int64("repeat-after", "repeat-after", "Time (in ms) after one of these was last repeated " "should we allow it to repeat", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_EXPIRE_AFTER, g_param_spec_int64("expire-after", "expire-after", "Time (in ms) since one of these last occurred until " "we should drop the notice", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_notice_init(SnapdNotice *self) { self->data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); } snapd-glib-1.67/snapd-glib/snapd-notice.h000066400000000000000000000041361477073115000202550ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_NOTICE_H__ #define __SNAPD_NOTICE_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include typedef enum { SNAPD_NOTICE_TYPE_UNKNOWN = 0, SNAPD_NOTICE_TYPE_CHANGE_UPDATE, SNAPD_NOTICE_TYPE_REFRESH_INHIBIT, SNAPD_NOTICE_TYPE_SNAP_RUN_INHIBIT } SnapdNoticeType; G_BEGIN_DECLS #define SNAPD_TYPE_NOTICE (snapd_notice_get_type()) G_DECLARE_FINAL_TYPE(SnapdNotice, snapd_notice, SNAPD, NOTICE, GObject) const gchar *snapd_notice_get_id(SnapdNotice *notice); const gchar *snapd_notice_get_user_id(SnapdNotice *notice); SnapdNoticeType snapd_notice_get_notice_type(SnapdNotice *notice); const gchar *snapd_notice_get_key(SnapdNotice *notice); GDateTime *snapd_notice_get_first_occurred(SnapdNotice *notice) G_DEPRECATED; GDateTime *snapd_notice_get_first_occurred2(SnapdNotice *notice); GDateTime *snapd_notice_get_last_occurred(SnapdNotice *notice) G_DEPRECATED; GDateTime *snapd_notice_get_last_occurred2(SnapdNotice *notice); int snapd_notice_get_last_occurred_nanoseconds(SnapdNotice *notice); GDateTime *snapd_notice_get_last_repeated(SnapdNotice *notice) G_DEPRECATED; GDateTime *snapd_notice_get_last_repeated2(SnapdNotice *notice); gint64 snapd_notice_get_occurrences(SnapdNotice *notice); GHashTable *snapd_notice_get_last_data(SnapdNotice *notice) G_DEPRECATED; GHashTable *snapd_notice_get_last_data2(SnapdNotice *notice); GTimeSpan snapd_notice_get_repeat_after(SnapdNotice *notice); GTimeSpan snapd_notice_get_expire_after(SnapdNotice *notice); gint snapd_notice_compare_last_occurred(SnapdNotice *notice, SnapdNotice *notice_to_compare); G_END_DECLS #endif /* __SNAPD_NOTICE_H__ */ snapd-glib-1.67/snapd-glib/snapd-notices-monitor.c000066400000000000000000000173001477073115000221150ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "snapd-notices-monitor.h" /** * SECTION: snapd-notices-monitor * @short_description: Allows to receive events from snapd. * @include: snapd-glib/snapd-glib.h * * #SnapdNoticesMonitor allows to receive in real time events from * snapd, like status changes in an ongoing refresh, inhibited refreshes * due to the snap being active, or inhibited launches due to an ongoing * refresh. */ /** * SnapdNoticesMonitor: * * #SnapdNoticesMonitor allows to receive in real time events from * snapd, like status changes in an ongoing refresh, inhibited refreshes * due to the snap being active, or inhibited launches due to an ongoing * refresh. * * Since: 1.66 */ struct _SnapdNoticesMonitor { GObject parent_instance; SnapdClient *client; GCancellable *cancellable; SnapdNotice *last_notice; gboolean running; }; enum { PROP_CLIENT = 1, PROP_LAST }; G_DEFINE_TYPE(SnapdNoticesMonitor, snapd_notices_monitor, G_TYPE_OBJECT) static void begin_monitor(SnapdNoticesMonitor *self); static void monitor_cb(SnapdClient *source, GAsyncResult *res, SnapdNoticesMonitor *self) { g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) notices = snapd_client_get_notices_finish(source, res, &error); if (error != NULL) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_signal_emit_by_name(self, "error-event", error); self->running = FALSE; g_clear_object(&self->cancellable); self->cancellable = g_cancellable_new(); g_object_unref(self); return; } if (notices != NULL) { gboolean first_run = self->last_notice == NULL; for (int i = 0; i < notices->len; i++) { g_autoptr(SnapdNotice) notice = g_object_ref(notices->pdata[i]); if (self->last_notice == NULL || snapd_notice_compare_last_occurred(self->last_notice, notice) <= 0) { g_clear_object(&self->last_notice); self->last_notice = g_object_ref(notice); } g_signal_emit_by_name(self, "notice-event", notice, first_run); } } begin_monitor(self); // continue waiting for new notifications } static void begin_monitor(SnapdNoticesMonitor *self) { snapd_client_notices_set_after_notice(self->client, self->last_notice); GDateTime *last_date_time = self->last_notice == NULL ? NULL : (GDateTime *)snapd_notice_get_last_occurred2(self->last_notice); snapd_client_get_notices_async( self->client, last_date_time, 2000000000000000, // "infinity" (there is a limit in snapd, around 9 // billion seconds) self->cancellable, (GAsyncReadyCallback)monitor_cb, self); } /** * snapd_notices_monitor_start: * @monitor: a #SnapdNoticesMonitor * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Starts the asynchronous listening proccess, that will wait for new * notices and emit a "notice-event" signal with the new notice as * parameter. * * Returns: FALSE if there was an error, TRUE if everything worked fine * and the object is listening for events. * * Since: 1.66 */ gboolean snapd_notices_monitor_start(SnapdNoticesMonitor *self, GError **error) { g_return_val_if_fail((error == NULL) || (*error == NULL), FALSE); g_return_val_if_fail(SNAPD_IS_NOTICES_MONITOR(self), FALSE); if (self->running) { *error = g_error_new(SNAPD_ERROR, SNAPD_ERROR_ALREADY_RUNNING, "The notices monitor is already running."); return FALSE; } self->running = TRUE; begin_monitor(g_object_ref(self)); return TRUE; } /** * snapd_notices_monitor_stop: * @monitor: a #SnapdNoticesMonitor * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * * Stops the asynchronous listening proccess started with * #snapd_notices_monitor_start. * * Returns: FALSE if there was an error, TRUE if everything worked fine. * * Since: 1.66 */ gboolean snapd_notices_monitor_stop(SnapdNoticesMonitor *self, GError **error) { g_return_val_if_fail((error == NULL) || (*error == NULL), FALSE); g_return_val_if_fail(SNAPD_IS_NOTICES_MONITOR(self), FALSE); if (!self->running) { *error = g_error_new(SNAPD_ERROR, SNAPD_ERROR_NOT_RUNNING, "The notices monitor isn't running."); return FALSE; } g_cancellable_cancel(self->cancellable); return TRUE; } static void snapd_notices_monitor_dispose(GObject *object) { SnapdNoticesMonitor *self = SNAPD_NOTICES_MONITOR(object); if (self->cancellable != NULL) g_cancellable_cancel(self->cancellable); g_clear_object(&self->client); g_clear_object(&self->cancellable); g_clear_object(&self->last_notice); G_OBJECT_CLASS(snapd_notices_monitor_parent_class)->dispose(object); } static void snapd_notices_monitor_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdNoticesMonitor *self = SNAPD_NOTICES_MONITOR(object); switch (prop_id) { case PROP_CLIENT: g_clear_object(&self->client); if (g_value_get_object(value) != NULL) self->client = g_object_ref(g_value_get_object(value)); break; } } static void snapd_notices_monitor_init(SnapdNoticesMonitor *self) { self->cancellable = g_cancellable_new(); } static void snapd_notices_monitor_class_init(SnapdNoticesMonitorClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_notices_monitor_set_property; gobject_class->dispose = snapd_notices_monitor_dispose; g_object_class_install_property( gobject_class, PROP_CLIENT, g_param_spec_object( "client", "client", "SnapdClient to use to communicate", SNAPD_TYPE_CLIENT, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_signal_new("notice-event", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 2, SNAPD_TYPE_NOTICE, G_TYPE_BOOLEAN); g_signal_new("error-event", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_ERROR); } /** * snapd_notices_monitor_new: * * Creates a new #SnapdNoticesMonitor to receive events. * * Returns: (transfer full): a new #SnapdNoticesMonitor * * Since: 1.66 */ SnapdNoticesMonitor *snapd_notices_monitor_new(void) { g_autoptr(SnapdClient) client = snapd_client_new(); SnapdNoticesMonitor *self = g_object_new(snapd_notices_monitor_get_type(), "client", client, NULL); return self; } /** * snapd_notices_monitor_new_with_client: * @client: a #SnapdClient object * * Creates a new #SnapdNoticesMonitor to receive events, using the * specified #SnapdClient object to ask info about each task. * * Returns: (transfer full): a new #SnapdNoticesMonitor * * Since: 1.66 */ SnapdNoticesMonitor * snapd_notices_monitor_new_with_client(SnapdClient *client) { SnapdNoticesMonitor *self = g_object_new(snapd_notices_monitor_get_type(), "client", client, NULL); return self; } snapd-glib-1.67/snapd-glib/snapd-notices-monitor.h000066400000000000000000000022671477073115000221300ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #pragma once #include G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(SnapdNoticesMonitor, snapd_notices_monitor, SNAPD, NOTICES_MONITOR, GObject) SnapdNoticesMonitor *snapd_notices_monitor_new(void); SnapdNoticesMonitor *snapd_notices_monitor_new_with_client(SnapdClient *client); gboolean snapd_notices_monitor_start(SnapdNoticesMonitor *monitor, GError **error); gboolean snapd_notices_monitor_stop(SnapdNoticesMonitor *monitor, GError **error); G_END_DECLS snapd-glib-1.67/snapd-glib/snapd-plug-ref.c000066400000000000000000000072341477073115000205120ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-plug-ref.h" /** * SECTION: snapd-plug-ref * @short_description: Reference to a plug * @include: snapd-glib/snapd-glib.h * * A #SnapdPlugRef contains a reference to a plug. */ /** * SnapdPlugRef: * * #SnapdPlugRef contains the state of Snap a interface plug_ref. * * Since: 1.0 */ struct _SnapdPlugRef { GObject parent_instance; gchar *plug; gchar *snap; }; enum { PROP_PLUG = 1, PROP_SNAP, PROP_LAST }; G_DEFINE_TYPE(SnapdPlugRef, snapd_plug_ref, G_TYPE_OBJECT) /** * snapd_plug_ref_get_plug: * @plug_ref: a #SnapdPlugRef. * * Get the name of the plug. * * Returns: a name. * * Since: 1.48 */ const gchar *snapd_plug_ref_get_plug(SnapdPlugRef *self) { g_return_val_if_fail(SNAPD_IS_PLUG_REF(self), NULL); return self->plug; } /** * snapd_plug_ref_get_snap: * @plug_ref: a #SnapdPlugRef. * * Get the snap this plug is on. * * Returns: a snap name. * * Since: 1.48 */ const gchar *snapd_plug_ref_get_snap(SnapdPlugRef *self) { g_return_val_if_fail(SNAPD_IS_PLUG_REF(self), NULL); return self->snap; } static void snapd_plug_ref_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdPlugRef *self = SNAPD_PLUG_REF(object); switch (prop_id) { case PROP_PLUG: g_free(self->plug); self->plug = g_strdup(g_value_get_string(value)); break; case PROP_SNAP: g_free(self->snap); self->snap = g_strdup(g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_plug_ref_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdPlugRef *self = SNAPD_PLUG_REF(object); switch (prop_id) { case PROP_PLUG: g_value_set_string(value, self->plug); break; case PROP_SNAP: g_value_set_string(value, self->snap); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_plug_ref_finalize(GObject *object) { SnapdPlugRef *self = SNAPD_PLUG_REF(object); g_clear_pointer(&self->plug, g_free); g_clear_pointer(&self->snap, g_free); G_OBJECT_CLASS(snapd_plug_ref_parent_class)->finalize(object); } static void snapd_plug_ref_class_init(SnapdPlugRefClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_plug_ref_set_property; gobject_class->get_property = snapd_plug_ref_get_property; gobject_class->finalize = snapd_plug_ref_finalize; g_object_class_install_property( gobject_class, PROP_PLUG, g_param_spec_string("plug", "plug", "Name of plug", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SNAP, g_param_spec_string("snap", "snap", "Snap this plug is on", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_plug_ref_init(SnapdPlugRef *self) {} snapd-glib-1.67/snapd-glib/snapd-plug-ref.h000066400000000000000000000016061477073115000205140ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_PLUG_REF_H__ #define __SNAPD_PLUG_REF_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_PLUG_REF (snapd_plug_ref_get_type()) G_DECLARE_FINAL_TYPE(SnapdPlugRef, snapd_plug_ref, SNAPD, PLUG_REF, GObject) const gchar *snapd_plug_ref_get_plug(SnapdPlugRef *plug_ref); const gchar *snapd_plug_ref_get_snap(SnapdPlugRef *plug_ref); G_END_DECLS #endif /* __SNAPD_PLUG_REF_H__ */ snapd-glib-1.67/snapd-glib/snapd-plug.c000066400000000000000000000242541477073115000177410ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-connection.h" #include "snapd-plug.h" #include "snapd-slot-ref.h" /** * SECTION: snapd-plug * @short_description: Snap plugs * @include: snapd-glib/snapd-glib.h * * A #SnapdPlug represents a part of a snap that can be connected to a * #SnapdSlot on another snap. Available plugs can be queried using * snapd_client_get_interfaces_sync(). Plugs can be connected / disconnected * using snapd_client_connect_interface_sync() and * snapd_client_disconnect_interface_sync(). */ /** * SnapdPlug: * * #SnapdPlug contains information about a Snap plug. * * Since: 1.0 */ struct _SnapdPlug { GObject parent_instance; gchar *name; gchar *snap; gchar *interface; GHashTable *attributes; gchar *label; GPtrArray *connections; GPtrArray *legacy_connections; }; enum { PROP_NAME = 1, PROP_SNAP, PROP_INTERFACE, PROP_LABEL, PROP_CONNECTIONS, PROP_ATTRIBUTES, PROP_LAST }; G_DEFINE_TYPE(SnapdPlug, snapd_plug, G_TYPE_OBJECT) /** * snapd_plug_get_name: * @plug: a #SnapdPlug. * * Get the name of this plug. * * Returns: a name. * * Since: 1.0 */ const gchar *snapd_plug_get_name(SnapdPlug *self) { g_return_val_if_fail(SNAPD_IS_PLUG(self), NULL); return self->name; } /** * snapd_plug_get_snap: * @plug: a #SnapdPlug. * * Get the snap this plug is on. * * Returns: a snap name. * * Since: 1.0 */ const gchar *snapd_plug_get_snap(SnapdPlug *self) { g_return_val_if_fail(SNAPD_IS_PLUG(self), NULL); return self->snap; } /** * snapd_plug_get_interface: * @plug: a #SnapdPlug. * * Get the name of the interface this plug provides. * * Returns: an interface name. * * Since: 1.0 */ const gchar *snapd_plug_get_interface(SnapdPlug *self) { g_return_val_if_fail(SNAPD_IS_PLUG(self), NULL); return self->interface; } /** * snapd_plug_get_attribute_names: * @plug: a #SnapdPlug. * @length: (out) (allow-none): location to write number of attributes or %NULL * if not required. * * Get the names of the attributes this plug has. * * Returns: (transfer full) (array zero-terminated=1): a string array of * attribute names. Free with g_strfreev(). * * Since: 1.3 */ GStrv snapd_plug_get_attribute_names(SnapdPlug *self, guint *length) { g_return_val_if_fail(SNAPD_IS_PLUG(self), NULL); guint size = g_hash_table_size(self->attributes); GStrv names = g_malloc(sizeof(gchar *) * (size + 1)); GHashTableIter iter; g_hash_table_iter_init(&iter, self->attributes); guint i; gpointer name; for (i = 0; g_hash_table_iter_next(&iter, &name, NULL); i++) names[i] = g_strdup(name); names[i] = NULL; if (length != NULL) *length = size; return names; } /** * snapd_plug_has_attribute: * @plug: a #SnapdPlug. * @name: an attribute name. * * Check if this plug has an attribute. * * Returns: %TRUE if this attribute exists. * * Since: 1.3 */ gboolean snapd_plug_has_attribute(SnapdPlug *self, const gchar *name) { g_return_val_if_fail(SNAPD_IS_PLUG(self), FALSE); return g_hash_table_contains(self->attributes, name); } /** * snapd_plug_get_attribute: * @plug: a #SnapdPlug. * @name: an attribute name. * * Get an attribute for this interface. * * Returns: (transfer none) (allow-none): an attribute value or %NULL if not * set. * * Since: 1.3 */ GVariant *snapd_plug_get_attribute(SnapdPlug *self, const gchar *name) { g_return_val_if_fail(SNAPD_IS_PLUG(self), NULL); return g_hash_table_lookup(self->attributes, name); } /** * snapd_plug_get_label: * @plug: a #SnapdPlug. * * Get a human readable label for this plug. * * Returns: a label. * * Since: 1.0 */ const gchar *snapd_plug_get_label(SnapdPlug *self) { g_return_val_if_fail(SNAPD_IS_PLUG(self), NULL); return self->label; } /** * snapd_plug_get_connections: * @plug: a #SnapdPlug. * * Get the connections being made with this plug. * * Returns: (transfer none) (element-type SnapdConnection): an array of * #SnapdConnection. * * Since: 1.0 * Deprecated: 1.48: Use snapd_plug_get_connected_slots() */ GPtrArray *snapd_plug_get_connections(SnapdPlug *self) { g_return_val_if_fail(SNAPD_IS_PLUG(self), NULL); if (self->legacy_connections != NULL) return self->legacy_connections; self->legacy_connections = g_ptr_array_new_with_free_func(g_object_unref); for (int i = 0; i < self->connections->len; i++) { SnapdSlotRef *slot_ref = g_ptr_array_index(self->connections, i); SnapdConnection *connection = g_object_new( SNAPD_TYPE_CONNECTION, "name", snapd_slot_ref_get_slot(slot_ref), "snap", snapd_slot_ref_get_snap(slot_ref), NULL); g_ptr_array_add(self->legacy_connections, connection); } return self->legacy_connections; } /** * snapd_plug_get_connected_slots: * @plug: a #SnapdPlug. * * Get the slots connected to this plug. * * Returns: (transfer none) (element-type SnapdSlotRef): an array of * #SnapdSlotRef. * * Since: 1.48 */ GPtrArray *snapd_plug_get_connected_slots(SnapdPlug *self) { g_return_val_if_fail(SNAPD_IS_PLUG(self), NULL); return self->connections; } static void snapd_plug_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdPlug *self = SNAPD_PLUG(object); switch (prop_id) { case PROP_NAME: g_free(self->name); self->name = g_strdup(g_value_get_string(value)); break; case PROP_SNAP: g_free(self->snap); self->snap = g_strdup(g_value_get_string(value)); break; case PROP_INTERFACE: g_free(self->interface); self->interface = g_strdup(g_value_get_string(value)); break; case PROP_LABEL: g_free(self->label); self->label = g_strdup(g_value_get_string(value)); break; case PROP_CONNECTIONS: g_clear_pointer(&self->connections, g_ptr_array_unref); if (g_value_get_boxed(value) != NULL) self->connections = g_ptr_array_ref(g_value_get_boxed(value)); break; case PROP_ATTRIBUTES: g_clear_pointer(&self->attributes, g_hash_table_unref); if (g_value_get_boxed(value) != NULL) self->attributes = g_hash_table_ref(g_value_get_boxed(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_plug_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdPlug *self = SNAPD_PLUG(object); switch (prop_id) { case PROP_NAME: g_value_set_string(value, self->name); break; case PROP_SNAP: g_value_set_string(value, self->snap); break; case PROP_INTERFACE: g_value_set_string(value, self->interface); break; case PROP_LABEL: g_value_set_string(value, self->label); break; case PROP_CONNECTIONS: g_value_set_boxed(value, self->connections); break; case PROP_ATTRIBUTES: g_value_set_boxed(value, self->attributes); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_plug_finalize(GObject *object) { SnapdPlug *self = SNAPD_PLUG(object); g_clear_pointer(&self->name, g_free); g_clear_pointer(&self->snap, g_free); g_clear_pointer(&self->interface, g_free); g_clear_pointer(&self->attributes, g_hash_table_unref); g_clear_pointer(&self->label, g_free); g_clear_pointer(&self->connections, g_ptr_array_unref); g_clear_pointer(&self->legacy_connections, g_ptr_array_unref); G_OBJECT_CLASS(snapd_plug_parent_class)->finalize(object); } static void snapd_plug_class_init(SnapdPlugClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_plug_set_property; gobject_class->get_property = snapd_plug_get_property; gobject_class->finalize = snapd_plug_finalize; g_object_class_install_property( gobject_class, PROP_NAME, g_param_spec_string("name", "name", "Plug name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SNAP, g_param_spec_string("snap", "snap", "Snap this plug is on", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_INTERFACE, g_param_spec_string( "interface", "interface", "Interface this plug provides", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_LABEL, g_param_spec_string( "label", "label", "Short description of this plug", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_CONNECTIONS, g_param_spec_boxed("connections", "connections", "Connections with this plug", G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_ATTRIBUTES, g_param_spec_boxed("attributes", "attributes", "Attributes for this plug", G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_plug_init(SnapdPlug *self) { self->attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref); } snapd-glib-1.67/snapd-glib/snapd-plug.h000066400000000000000000000025021477073115000177360ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_PLUG_H__ #define __SNAPD_PLUG_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_PLUG (snapd_plug_get_type()) G_DECLARE_FINAL_TYPE(SnapdPlug, snapd_plug, SNAPD, PLUG, GObject) const gchar *snapd_plug_get_name(SnapdPlug *plug); const gchar *snapd_plug_get_snap(SnapdPlug *plug); const gchar *snapd_plug_get_interface(SnapdPlug *plug); GStrv snapd_plug_get_attribute_names(SnapdPlug *plug, guint *length); gboolean snapd_plug_has_attribute(SnapdPlug *plug, const gchar *name); GVariant *snapd_plug_get_attribute(SnapdPlug *plug, const gchar *name); const gchar *snapd_plug_get_label(SnapdPlug *plug); GPtrArray *snapd_plug_get_connections(SnapdPlug *plug) G_DEPRECATED_FOR(snapd_plug_get_connected_slots); GPtrArray *snapd_plug_get_connected_slots(SnapdPlug *plug); G_END_DECLS #endif /* __SNAPD_PLUG_H__ */ snapd-glib-1.67/snapd-glib/snapd-price.c000066400000000000000000000072061477073115000200720ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-price.h" /** * SECTION: snapd-price * @short_description: Pricing information * @include: snapd-glib/snapd-glib.h * * A #SnapdPrice represents an amount of money required to purchase a snap. * Prices can be queried using snapd_snap_get_prices() and are used in * snapd_client_buy_sync(). */ /** * SnapdPrice: * * #SnapdPrice contains pricing information. * * Since: 1.0 */ struct _SnapdPrice { GObject parent_instance; gdouble amount; gchar *currency; }; enum { PROP_AMOUNT = 1, PROP_CURRENCY, PROP_LAST }; G_DEFINE_TYPE(SnapdPrice, snapd_price, G_TYPE_OBJECT) /** * snapd_price_get_amount: * @price: a #SnapdPrice. * * Get the currency amount for this price, e.g. 0.99. * * Return: a currency amount. * * Since: 1.0 */ gdouble snapd_price_get_amount(SnapdPrice *self) { g_return_val_if_fail(SNAPD_IS_PRICE(self), 0.0); return self->amount; } /** * snapd_price_get_currency: * @price: a #SnapdPrice. * * Get the currency this price is in, e.g. "NZD". * * Returns: an ISO 4217 currency code. * * Since: 1.0 */ const gchar *snapd_price_get_currency(SnapdPrice *self) { g_return_val_if_fail(SNAPD_IS_PRICE(self), NULL); return self->currency; } static void snapd_price_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdPrice *self = SNAPD_PRICE(object); switch (prop_id) { case PROP_AMOUNT: self->amount = g_value_get_double(value); break; case PROP_CURRENCY: g_free(self->currency); self->currency = g_strdup(g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_price_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdPrice *self = SNAPD_PRICE(object); switch (prop_id) { case PROP_AMOUNT: g_value_set_double(value, self->amount); break; case PROP_CURRENCY: g_value_set_string(value, self->currency); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_price_finalize(GObject *object) { SnapdPrice *self = SNAPD_PRICE(object); g_clear_pointer(&self->currency, g_free); G_OBJECT_CLASS(snapd_price_parent_class)->finalize(object); } static void snapd_price_class_init(SnapdPriceClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_price_set_property; gobject_class->get_property = snapd_price_get_property; gobject_class->finalize = snapd_price_finalize; g_object_class_install_property( gobject_class, PROP_AMOUNT, g_param_spec_double( "amount", "amount", "Amount of price", 0.0, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_CURRENCY, g_param_spec_string("currency", "currency", "Currency amount is in", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_price_init(SnapdPrice *self) {} snapd-glib-1.67/snapd-glib/snapd-price.h000066400000000000000000000015401477073115000200720ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_PRICE_H__ #define __SNAPD_PRICE_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_PRICE (snapd_price_get_type()) G_DECLARE_FINAL_TYPE(SnapdPrice, snapd_price, SNAPD, PRICE, GObject) gdouble snapd_price_get_amount(SnapdPrice *price); const gchar *snapd_price_get_currency(SnapdPrice *price); G_END_DECLS #endif /* __SNAPD_PRICE_H__ */ snapd-glib-1.67/snapd-glib/snapd-screenshot.c000066400000000000000000000112071477073115000211410ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-screenshot.h" /** * SECTION: snapd-screenshot * @short_description: Screenshot information * @include: snapd-glib/snapd-glib.h * * A #SnapdScreenshot represents a screenshot that shows a snap. * Screenshots can be queried using snapd_snap_get_screenshots(). */ /** * SnapdScreenshot: * * #SnapdScreenshot contains screenshot information. * * Since: 1.0 */ struct _SnapdScreenshot { GObject parent_instance; gchar *url; guint width; guint height; }; enum { PROP_URL = 1, PROP_WIDTH, PROP_HEIGHT, PROP_LAST }; G_DEFINE_TYPE(SnapdScreenshot, snapd_screenshot, G_TYPE_OBJECT) SnapdScreenshot *snapd_screenshot_new(void) { return g_object_new(SNAPD_TYPE_SCREENSHOT, NULL); } /** * snapd_screenshot_get_url: * @screenshot: a #SnapdScreenshot. * * Get the URL for this screenshot, e.g. "http://example.com/screenshot.png" * * Returns: a URL * * Since: 1.0 */ const gchar *snapd_screenshot_get_url(SnapdScreenshot *self) { g_return_val_if_fail(SNAPD_IS_SCREENSHOT(self), NULL); return self->url; } /** * snapd_screenshot_get_width: * @screenshot: a #SnapdScreenshot. * * Get the width of the screenshot in pixels or 0 if unknown. * * Return: a width * * Since: 1.0 */ guint snapd_screenshot_get_width(SnapdScreenshot *self) { g_return_val_if_fail(SNAPD_IS_SCREENSHOT(self), 0); return self->width; } /** * snapd_screenshot_get_height: * @screenshot: a #SnapdScreenshot. * * Get the height of the screenshot in pixels or 0 if unknown. * * Return: a height * * Since: 1.0 */ guint snapd_screenshot_get_height(SnapdScreenshot *self) { g_return_val_if_fail(SNAPD_IS_SCREENSHOT(self), 0); return self->height; } static void snapd_screenshot_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdScreenshot *self = SNAPD_SCREENSHOT(object); switch (prop_id) { case PROP_URL: g_free(self->url); self->url = g_strdup(g_value_get_string(value)); break; case PROP_WIDTH: self->width = g_value_get_uint(value); break; case PROP_HEIGHT: self->height = g_value_get_uint(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_screenshot_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdScreenshot *self = SNAPD_SCREENSHOT(object); switch (prop_id) { case PROP_URL: g_value_set_string(value, self->url); break; case PROP_WIDTH: g_value_set_uint(value, self->width); break; case PROP_HEIGHT: g_value_set_uint(value, self->height); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_screenshot_finalize(GObject *object) { SnapdScreenshot *self = SNAPD_SCREENSHOT(object); g_clear_pointer(&self->url, g_free); G_OBJECT_CLASS(snapd_screenshot_parent_class)->finalize(object); } static void snapd_screenshot_class_init(SnapdScreenshotClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_screenshot_set_property; gobject_class->get_property = snapd_screenshot_get_property; gobject_class->finalize = snapd_screenshot_finalize; g_object_class_install_property( gobject_class, PROP_URL, g_param_spec_string("url", "url", "URL for this screenshot", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_WIDTH, g_param_spec_uint( "width", "width", "Width of screenshot in pixels", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_HEIGHT, g_param_spec_uint( "height", "height", "Height of screenshot in pixels", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_screenshot_init(SnapdScreenshot *self) {} snapd-glib-1.67/snapd-glib/snapd-screenshot.h000066400000000000000000000017641477073115000211550ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_SCREENSHOT_H__ #define __SNAPD_SCREENSHOT_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_SCREENSHOT (snapd_screenshot_get_type()) G_DECLARE_FINAL_TYPE(SnapdScreenshot, snapd_screenshot, SNAPD, SCREENSHOT, GObject) const gchar *snapd_screenshot_get_url(SnapdScreenshot *screenshot); guint snapd_screenshot_get_width(SnapdScreenshot *screenshot); guint snapd_screenshot_get_height(SnapdScreenshot *screenshot); G_END_DECLS #endif /* __SNAPD_SCREENSHOT_H__ */ snapd-glib-1.67/snapd-glib/snapd-slot-ref.c000066400000000000000000000072341477073115000205240ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-slot-ref.h" /** * SECTION: snapd-slot-ref * @short_description: Reference to a slot * @include: snapd-glib/snapd-glib.h * * A #SnapdSlotRef contains a reference to a slot. */ /** * SnapdSlotRef: * * #SnapdSlotRef contains the state of Snap a interface slot_ref. * * Since: 1.0 */ struct _SnapdSlotRef { GObject parent_instance; gchar *slot; gchar *snap; }; enum { PROP_SLOT = 1, PROP_SNAP, PROP_LAST }; G_DEFINE_TYPE(SnapdSlotRef, snapd_slot_ref, G_TYPE_OBJECT) /** * snapd_slot_ref_get_slot: * @slot_ref: a #SnapdSlotRef. * * Get the name of the slot. * * Returns: a name. * * Since: 1.48 */ const gchar *snapd_slot_ref_get_slot(SnapdSlotRef *self) { g_return_val_if_fail(SNAPD_IS_SLOT_REF(self), NULL); return self->slot; } /** * snapd_slot_ref_get_snap: * @slot_ref: a #SnapdSlotRef. * * Get the snap this slot is on. * * Returns: a snap name. * * Since: 1.48 */ const gchar *snapd_slot_ref_get_snap(SnapdSlotRef *self) { g_return_val_if_fail(SNAPD_IS_SLOT_REF(self), NULL); return self->snap; } static void snapd_slot_ref_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdSlotRef *self = SNAPD_SLOT_REF(object); switch (prop_id) { case PROP_SLOT: g_free(self->slot); self->slot = g_strdup(g_value_get_string(value)); break; case PROP_SNAP: g_free(self->snap); self->snap = g_strdup(g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_slot_ref_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdSlotRef *self = SNAPD_SLOT_REF(object); switch (prop_id) { case PROP_SLOT: g_value_set_string(value, self->slot); break; case PROP_SNAP: g_value_set_string(value, self->snap); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_slot_ref_finalize(GObject *object) { SnapdSlotRef *self = SNAPD_SLOT_REF(object); g_clear_pointer(&self->slot, g_free); g_clear_pointer(&self->snap, g_free); G_OBJECT_CLASS(snapd_slot_ref_parent_class)->finalize(object); } static void snapd_slot_ref_class_init(SnapdSlotRefClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_slot_ref_set_property; gobject_class->get_property = snapd_slot_ref_get_property; gobject_class->finalize = snapd_slot_ref_finalize; g_object_class_install_property( gobject_class, PROP_SLOT, g_param_spec_string("slot", "slot", "Name of slot", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SNAP, g_param_spec_string("snap", "snap", "Snap this slot is on", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_slot_ref_init(SnapdSlotRef *self) {} snapd-glib-1.67/snapd-glib/snapd-slot-ref.h000066400000000000000000000016061477073115000205260ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_SLOT_REF_H__ #define __SNAPD_SLOT_REF_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_SLOT_REF (snapd_slot_ref_get_type()) G_DECLARE_FINAL_TYPE(SnapdSlotRef, snapd_slot_ref, SNAPD, SLOT_REF, GObject) const gchar *snapd_slot_ref_get_slot(SnapdSlotRef *slot_ref); const gchar *snapd_slot_ref_get_snap(SnapdSlotRef *slot_ref); G_END_DECLS #endif /* __SNAPD_SLOT_REF_H__ */ snapd-glib-1.67/snapd-glib/snapd-slot.c000066400000000000000000000242701477073115000177510ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-connection.h" #include "snapd-plug-ref.h" #include "snapd-slot.h" /** * SECTION: snapd-slot * @short_description: Snap slots * @include: snapd-glib/snapd-glib.h * * A #SnapdSlot represents a part of a snap that can be connected to by one or * more #SnapdPlug from other snaps. Available slots can be queried using * snapd_client_get_interfaces_sync(). Plugs can be connected / disconnected * using snapd_client_connect_interface_sync() and * snapd_client_disconnect_interface_sync(). */ /** * SnapdSlot: * * #SnapdSlot contains information about a Snap slot. * * Since: 1.0 */ struct _SnapdSlot { GObject parent_instance; gchar *name; gchar *snap; gchar *interface; GHashTable *attributes; gchar *label; GPtrArray *connections; GPtrArray *legacy_connections; }; enum { PROP_NAME = 1, PROP_SNAP, PROP_INTERFACE, PROP_LABEL, PROP_CONNECTIONS, PROP_ATTRIBUTES, PROP_LAST }; G_DEFINE_TYPE(SnapdSlot, snapd_slot, G_TYPE_OBJECT) /** * snapd_slot_get_name: * @slot: a #SnapdSlot. * * Get the name of this slot. * * Returns: a name * * Since: 1.0 */ const gchar *snapd_slot_get_name(SnapdSlot *self) { g_return_val_if_fail(SNAPD_IS_SLOT(self), NULL); return self->name; } /** * snapd_slot_get_snap: * @slot: a #SnapdSlot. * * Get the snap this slot is on. * * Returns: a snap name. * * Since: 1.0 */ const gchar *snapd_slot_get_snap(SnapdSlot *self) { g_return_val_if_fail(SNAPD_IS_SLOT(self), NULL); return self->snap; } /** * snapd_slot_get_interface: * @slot: a #SnapdSlot. * * Get the name of the interface this slot accepts. * * Returns: an interface name. * * Since: 1.0 */ const gchar *snapd_slot_get_interface(SnapdSlot *self) { g_return_val_if_fail(SNAPD_IS_SLOT(self), NULL); return self->interface; } /** * snapd_slot_get_attribute_names: * @slot: a #SnapdSlot. * @length: (out) (allow-none): location to write number of attributes or %NULL * if not required. * * Get the names of the attributes this slot has. * * Returns: (transfer full) (array zero-terminated=1): a string array of * attribute names. Free with g_strfreev(). * * Since: 1.3 */ GStrv snapd_slot_get_attribute_names(SnapdSlot *self, guint *length) { g_return_val_if_fail(SNAPD_IS_SLOT(self), NULL); guint size = g_hash_table_size(self->attributes); GStrv names = g_malloc(sizeof(gchar *) * (size + 1)); GHashTableIter iter; g_hash_table_iter_init(&iter, self->attributes); guint i; gpointer name; for (i = 0; g_hash_table_iter_next(&iter, &name, NULL); i++) names[i] = g_strdup(name); names[i] = NULL; if (length != NULL) *length = size; return names; } /** * snapd_slot_has_attribute: * @slot: a #SnapdSlot. * @name: an attribute name. * * Check if this slot has an attribute. * * Returns: %TRUE if this attribute exists. * * Since: 1.3 */ gboolean snapd_slot_has_attribute(SnapdSlot *self, const gchar *name) { g_return_val_if_fail(SNAPD_IS_SLOT(self), FALSE); return g_hash_table_contains(self->attributes, name); } /** * snapd_slot_get_attribute: * @slot: a #SnapdSlot. * @name: an attribute name. * * Get an attribute for this interface. * * Returns: (transfer none) (allow-none): an attribute value or %NULL if not * set. * * Since: 1.3 */ GVariant *snapd_slot_get_attribute(SnapdSlot *self, const gchar *name) { g_return_val_if_fail(SNAPD_IS_SLOT(self), NULL); return g_hash_table_lookup(self->attributes, name); } /** * snapd_slot_get_label: * @slot: a #SnapdSlot. * * Get a human readable label for this slot. * * Returns: a label. * * Since: 1.0 */ const gchar *snapd_slot_get_label(SnapdSlot *self) { g_return_val_if_fail(SNAPD_IS_SLOT(self), NULL); return self->label; } /** * snapd_slot_get_connections: * @slot: a #SnapdSlot. * * Get the connections being made with this slot. * * Returns: (transfer none) (element-type SnapdConnection): an array of * #SnapdConnection. * * Since: 1.0 * Deprecated: 1.48: Use snapd_slot_get_connected_plugs() */ GPtrArray *snapd_slot_get_connections(SnapdSlot *self) { g_return_val_if_fail(SNAPD_IS_SLOT(self), NULL); if (self->legacy_connections != NULL) return self->legacy_connections; self->legacy_connections = g_ptr_array_new_with_free_func(g_object_unref); for (int i = 0; i < self->connections->len; i++) { SnapdPlugRef *plug_ref = g_ptr_array_index(self->connections, i); SnapdConnection *connection = g_object_new( SNAPD_TYPE_CONNECTION, "name", snapd_plug_ref_get_plug(plug_ref), "snap", snapd_plug_ref_get_snap(plug_ref), NULL); g_ptr_array_add(self->legacy_connections, connection); } return self->legacy_connections; } /** * snapd_slot_get_connected_plugs: * @slot: a #SnapdSlot. * * Get the plugs connected to this slot. * * Returns: (transfer none) (element-type SnapdPlugRef): an array of * #SnapdPlugRef. * * Since: 1.48 */ GPtrArray *snapd_slot_get_connected_plugs(SnapdSlot *self) { g_return_val_if_fail(SNAPD_IS_SLOT(self), NULL); return self->connections; } static void snapd_slot_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdSlot *self = SNAPD_SLOT(object); switch (prop_id) { case PROP_NAME: g_free(self->name); self->name = g_strdup(g_value_get_string(value)); break; case PROP_SNAP: g_free(self->snap); self->snap = g_strdup(g_value_get_string(value)); break; case PROP_INTERFACE: g_free(self->interface); self->interface = g_strdup(g_value_get_string(value)); break; case PROP_LABEL: g_free(self->label); self->label = g_strdup(g_value_get_string(value)); break; case PROP_CONNECTIONS: g_clear_pointer(&self->connections, g_ptr_array_unref); if (g_value_get_boxed(value) != NULL) self->connections = g_ptr_array_ref(g_value_get_boxed(value)); break; case PROP_ATTRIBUTES: g_clear_pointer(&self->attributes, g_hash_table_unref); if (g_value_get_boxed(value) != NULL) self->attributes = g_hash_table_ref(g_value_get_boxed(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_slot_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdSlot *self = SNAPD_SLOT(object); switch (prop_id) { case PROP_NAME: g_value_set_string(value, self->name); break; case PROP_SNAP: g_value_set_string(value, self->snap); break; case PROP_INTERFACE: g_value_set_string(value, self->interface); break; case PROP_LABEL: g_value_set_string(value, self->label); break; case PROP_CONNECTIONS: g_value_set_boxed(value, self->connections); break; case PROP_ATTRIBUTES: g_value_set_boxed(value, self->attributes); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_slot_finalize(GObject *object) { SnapdSlot *self = SNAPD_SLOT(object); g_clear_pointer(&self->name, g_free); g_clear_pointer(&self->snap, g_free); g_clear_pointer(&self->interface, g_free); g_clear_pointer(&self->attributes, g_hash_table_unref); g_clear_pointer(&self->label, g_free); g_clear_pointer(&self->connections, g_ptr_array_unref); g_clear_pointer(&self->legacy_connections, g_ptr_array_unref); G_OBJECT_CLASS(snapd_slot_parent_class)->finalize(object); } static void snapd_slot_class_init(SnapdSlotClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_slot_set_property; gobject_class->get_property = snapd_slot_get_property; gobject_class->finalize = snapd_slot_finalize; g_object_class_install_property( gobject_class, PROP_NAME, g_param_spec_string("name", "name", "Slot name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SNAP, g_param_spec_string("snap", "snap", "Snap this slot is on", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_INTERFACE, g_param_spec_string( "interface", "interface", "Interface this slot consumes", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_LABEL, g_param_spec_string( "label", "label", "Short description of this slot", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_CONNECTIONS, g_param_spec_boxed("connections", "connections", "Connections with this slot", G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_ATTRIBUTES, g_param_spec_boxed("attributes", "attributes", "Attributes for this slot", G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_slot_init(SnapdSlot *self) { self->attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref); } snapd-glib-1.67/snapd-glib/snapd-slot.h000066400000000000000000000025021477073115000177500ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_SLOT_H__ #define __SNAPD_SLOT_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_SLOT (snapd_slot_get_type()) G_DECLARE_FINAL_TYPE(SnapdSlot, snapd_slot, SNAPD, SLOT, GObject) const gchar *snapd_slot_get_name(SnapdSlot *slot); const gchar *snapd_slot_get_snap(SnapdSlot *slot); const gchar *snapd_slot_get_interface(SnapdSlot *slot); GStrv snapd_slot_get_attribute_names(SnapdSlot *slot, guint *length); gboolean snapd_slot_has_attribute(SnapdSlot *slot, const gchar *name); GVariant *snapd_slot_get_attribute(SnapdSlot *slot, const gchar *name); const gchar *snapd_slot_get_label(SnapdSlot *slot); GPtrArray *snapd_slot_get_connections(SnapdSlot *slot) G_DEPRECATED_FOR(snapd_slot_get_connected_plugs); GPtrArray *snapd_slot_get_connected_plugs(SnapdSlot *slot); G_END_DECLS #endif /* __SNAPD_SLOT_H__ */ snapd-glib-1.67/snapd-glib/snapd-snap.c000066400000000000000000001301331477073115000177250ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-snap.h" #include "snapd-enum-types.h" /** * SECTION:snapd-snap * @short_description: Snap metadata * @include: snapd-glib/snapd-glib.h * * A #SnapdSnap contains the metadata for a given snap. Snap metadata can be * retrieved using snapd_client_list_sync(), snapd_client_list_one_sync() or * snapd_client_find_sync(). */ /** * SnapdSnap: * * #SnapdSnap contains Snap metadata. * * Since: 1.0 */ struct _SnapdSnap { GObject parent_instance; GPtrArray *apps; gchar *base; gchar *broken; GPtrArray *categories; gchar *channel; GPtrArray *channels; GStrv common_ids; SnapdConfinement confinement; gchar *contact; gchar *description; gboolean devmode; gint64 download_size; GDateTime *hold; gchar *icon; gchar *id; GDateTime *install_date; gint64 installed_size; gboolean jailmode; gchar *license; GPtrArray *media; gchar *mounted_from; gchar *name; GPtrArray *prices; gboolean private; gchar *publisher_display_name; gchar *publisher_id; gchar *publisher_username; SnapdPublisherValidation publisher_validation; gchar *revision; GPtrArray *screenshots; SnapdSnapStatus status; gchar *store_url; gchar *summary; gchar *title; gchar *tracking_channel; GStrv tracks; gboolean trymode; SnapdSnapType snap_type; gchar *version; gchar *website; GDateTime *proceed_time; }; enum { PROP_APPS = 1, PROP_CATEGORIES, PROP_CHANNEL, PROP_CONFINEMENT, PROP_CONTACT, PROP_DESCRIPTION, PROP_DEVELOPER, PROP_DEVMODE, PROP_DOWNLOAD_SIZE, PROP_ICON, PROP_ID, PROP_INSTALL_DATE, PROP_INSTALLED_SIZE, PROP_JAILMODE, PROP_NAME, PROP_PRICES, PROP_PRIVATE, PROP_REVISION, PROP_SCREENSHOTS, PROP_STATUS, PROP_STORE_URL, PROP_SUMMARY, PROP_TRYMODE, PROP_SNAP_TYPE, PROP_VERSION, PROP_TRACKING_CHANNEL, PROP_TITLE, PROP_LICENSE, PROP_CHANNELS, PROP_TRACKS, PROP_BROKEN, PROP_COMMON_IDS, PROP_PUBLISHER_DISPLAY_NAME, PROP_PUBLISHER_ID, PROP_PUBLISHER_USERNAME, PROP_PUBLISHER_VALIDATION, PROP_BASE, PROP_MOUNTED_FROM, PROP_MEDIA, PROP_WEBSITE, PROP_HOLD, PROP_PROCEED_TIME, PROP_LAST }; G_DEFINE_TYPE(SnapdSnap, snapd_snap, G_TYPE_OBJECT) /** * snapd_snap_get_apps: * @snap: a #SnapdSnap. * * Get the apps this snap provides. * * Returns: (transfer none) (element-type SnapdApp): an array of #SnapdApp. * * Since: 1.0 */ GPtrArray *snapd_snap_get_apps(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->apps; } /** * snapd_snap_get_base: * @snap: a #SnapdSnap. * * Get the base snap this snap uses. * * Returns: (allow-none): a snap name or %NULL if not set. * * Since: 1.45 */ const gchar *snapd_snap_get_base(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->base; } /** * snapd_snap_get_broken: * @snap: a #SnapdSnap. * * Get the reason this snap is broken. * * Returns: (allow-none): an error string or %NULL if not broken. * * Since: 1.25 */ const gchar *snapd_snap_get_broken(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->broken; } /** * snapd_snap_get_categories: * @snap: a #SnapdSnap. * * Gets the categories this snap belongs to. * * Returns: (transfer none) (element-type SnapdCategory): an array of * #SnapdCategory. * * Since: 1.64 */ GPtrArray *snapd_snap_get_categories(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->categories; } /** * snapd_snap_get_channel: * @snap: a #SnapdSnap. * * Get the channel this snap is from, e.g. "stable". * * Returns: a channel name. * * Since: 1.0 */ const gchar *snapd_snap_get_channel(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->channel; } /** * snapd_snap_get_channels: * @snap: a #SnapdSnap. * * Gets the available channels for this snap. * * Returns: (transfer none) (element-type SnapdChannel): an array of * #SnapdChannel. * * Since: 1.22 */ GPtrArray *snapd_snap_get_channels(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->channels; } static int parse_risk(const gchar *risk) { if (g_strcmp0(risk, "stable") == 0) return 0; else if (g_strcmp0(risk, "candidate") == 0) return 1; else if (g_strcmp0(risk, "beta") == 0) return 2; else if (g_strcmp0(risk, "edge") == 0) return 3; else return -1; } /** * snapd_snap_match_channel: * @snap: a #SnapdSnap. * @name: a channel name. * * Finds the available channel that best matches the given name. * If none matches %NULL is returned. * * Returns: (transfer none) (allow-none): an #SnapdChannel or %NULL. * * Since: 1.22 */ SnapdChannel *snapd_snap_match_channel(SnapdSnap *self, const gchar *name) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); g_return_val_if_fail(name != NULL, NULL); g_autoptr(SnapdChannel) c = g_object_new(SNAPD_TYPE_CHANNEL, "name", name, NULL); SnapdChannel *matched_channel = NULL; int matched_risk = -1; for (guint i = 0; i < self->channels->len; i++) { SnapdChannel *channel = self->channels->pdata[i]; /* Must be same track and branch */ if (g_strcmp0(snapd_channel_get_track(channel), snapd_channel_get_track(c)) != 0 || g_strcmp0(snapd_channel_get_branch(channel), snapd_channel_get_branch(c)) != 0) continue; /* Must be no riskier than requested */ int r = parse_risk(snapd_channel_get_risk(channel)); if (r > parse_risk(snapd_channel_get_risk(c))) continue; /* Use this if unmatched or a better risk match */ if (matched_channel == NULL || r > matched_risk) { matched_channel = channel; matched_risk = r; } } return matched_channel; } /** * snapd_snap_get_common_ids: * @snap: a #SnapdSnap. * * Get common IDs associated with this snap. * * Returns: (transfer none) (array zero-terminated=1): an array of common ids. * * Since: 1.41 */ GStrv snapd_snap_get_common_ids(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->common_ids; } /** * snapd_snap_get_confinement: * @snap: a #SnapdSnap. * * Get the confinement this snap is using, e.g. %SNAPD_CONFINEMENT_STRICT. * * Returns: a #SnapdConfinement. * * Since: 1.0 */ SnapdConfinement snapd_snap_get_confinement(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), SNAPD_CONFINEMENT_UNKNOWN); return self->confinement; } /** * snapd_snap_get_contact: * @snap: a #SnapdSnap. * * Get the means of contacting the snap developer, e.g. * "mailto:developer@example.com". * * Returns: a contact URL. * * Since: 1.13 */ const gchar *snapd_snap_get_contact(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->contact; } /** * snapd_snap_get_description: * @snap: a #SnapdSnap. * * Get a multi-line description of this snap. The description is formatted using * a subset of Markdown. To parse this use a #SnapdMarkdownParser. * * Returns: description text. * * Since: 1.0 */ const gchar *snapd_snap_get_description(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->description; } /** * snapd_snap_get_developer: * @snap: a #SnapdSnap. * * Get the developer who created this snap. * * Returns: a developer name. * * Since: 1.0 * Deprecated: 1.42: Use snapd_snap_get_publisher_username() */ const gchar *snapd_snap_get_developer(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->publisher_username; } /** * snapd_snap_get_devmode: * @snap: a #SnapdSnap. * * Get if this snap is running in developer mode. * * Returns: %TRUE if this snap is running in devmode. * * Since: 1.0 */ gboolean snapd_snap_get_devmode(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), FALSE); return self->devmode; } /** * snapd_snap_get_download_size: * @snap: a #SnapdSnap. * * Get the download size of this snap or 0 if unknown. * * Returns: a byte count. * * Since: 1.0 */ gint64 snapd_snap_get_download_size(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), 0); return self->download_size; } /** * snapd_snap_get_hold: * @snap: a #SnapdSnap. * * Get the date this snap will re-enable automatic refreshing or %NULL if no * hold is present. * * Returns: (transfer none) (allow-none): a #GDateTime or %NULL. * * Since: 1.64 */ GDateTime *snapd_snap_get_hold(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->hold; } /** * snapd_snap_get_proceed_time: * @snap: a @SnapdSnap * * Returns the date and time after which a refresh is forced for this running * snap in the next auto-refresh. By substracting the current date and time it's * possible to know how many time remains before the snap is forced to be * refreshed. * * Returns: (transfer none) (allow-none): a #GDateTime or %NULL. * * Since: 1.65 */ GDateTime *snapd_snap_get_proceed_time(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->proceed_time; } /** * snapd_snap_get_icon: * @snap: a #SnapdSnap. * * Get the icon for this Snap, either a URL or an absolute path to retrieve it * from snapd directly. * * Returns: a URL or path. * * Since: 1.0 */ const gchar *snapd_snap_get_icon(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->icon; } /** * snapd_snap_get_id: * @snap: a #SnapdSnap. * * Gets the unique ID for this snap. * * Returns: an ID. * * Since: 1.0 */ const gchar *snapd_snap_get_id(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->id; } /** * snapd_snap_get_install_date: * @snap: a #SnapdSnap. * * Get the date this snap was installed or %NULL if unknown. * * Returns: (transfer none) (allow-none): a #GDateTime or %NULL. * * Since: 1.0 */ GDateTime *snapd_snap_get_install_date(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->install_date; } /** * snapd_snap_get_installed_size: * @snap: a #SnapdSnap. * * Get the installed size of this snap or 0 if unknown. * * Returns: a byte count. * * Since: 1.0 */ gint64 snapd_snap_get_installed_size(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), 0); return self->installed_size; } /** * snapd_snap_get_jailmode: * @snap: a #SnapdSnap. * * Get if this snap is running in enforced confinement (jail) mode. * * Returns: %TRUE if this snap is running in jailmode. * * Since: 1.8 */ gboolean snapd_snap_get_jailmode(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), FALSE); return self->jailmode; } /** * snapd_snap_get_license: * @snap: a #SnapdSnap. * * Gets the SPDX license expression for this snap, e.g. "GPL-3.0+". * * Returns: (allow-none): an SPDX license expression or %NULL. * * Since: 1.19 */ const gchar *snapd_snap_get_license(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->license; } /** * snapd_snap_get_media: * @snap: a #SnapdSnap. * * Get media that is associated with this snap. * * Returns: (transfer none) (element-type SnapdMedia): an array of #SnapdMedia. * * Since: 1.45 */ GPtrArray *snapd_snap_get_media(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->media; } /** * snapd_snap_get_mounted_from: * @snap: a #SnapdSnap. * * Gets the path this snap is mounted from, which is a .snap file for installed * snaps and a directory for snaps in try mode. * * Returns: (allow-none): a file path or %NULL. * * Since: 1.45 */ const gchar *snapd_snap_get_mounted_from(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->mounted_from; } /** * snapd_snap_get_title: * @snap: a #SnapdSnap. * * Get the title for this snap. If not available use the snap name instead. * * Returns: (allow-none): a title or %NULL. * * Since: 1.14 */ const gchar *snapd_snap_get_title(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->title; } /** * snapd_snap_get_name: * @snap: a #SnapdSnap. * * Get the name of this snap. This is used to reference this snap, e.g. for * installing / removing. * * Returns: a name. * * Since: 1.0 */ const gchar *snapd_snap_get_name(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->name; } /** * snapd_snap_get_prices: * @snap: a #SnapdSnap. * * Get the prices that this snap can be purchased at. * * Returns: (transfer none) (element-type SnapdPrice): an array of #SnapdPrice. * * Since: 1.0 */ GPtrArray *snapd_snap_get_prices(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->prices; } /** * snapd_snap_get_private: * @snap: a #SnapdSnap. * * Get if this snap is only available to the developer. * * Returns: %TRUE if this is a private snap. * * Since: 1.0 */ gboolean snapd_snap_get_private(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), FALSE); return self->private; } /** * snapd_snap_get_publisher_display_name: * @snap: a #SnapdSnap. * * Get the display name of the publisher who created this snap. * * Returns: a publisher display name. * * Since: 1.42 */ const gchar *snapd_snap_get_publisher_display_name(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->publisher_display_name; } /** * snapd_snap_get_publisher_id: * @snap: a #SnapdSnap. * * Get the ID of the publisher who created this snap. * * Returns: a publisher ID. * * Since: 1.42 */ const gchar *snapd_snap_get_publisher_id(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->publisher_id; } /** * snapd_snap_get_publisher_username: * @snap: a #SnapdSnap. * * Get the username of the publisher who created this snap. * * Returns: a publisher username. * * Since: 1.42 */ const gchar *snapd_snap_get_publisher_username(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->publisher_username; } /** * snapd_snap_get_publisher_validation: * @snap: a #SnapdSnap. * * Get the validation for the snap publisher, e.g. * %SNAPD_PUBLISHER_VALIDATION_VERIFIED * * Returns: a #SnapdPublisherValidation. * * Since: 1.42 */ SnapdPublisherValidation snapd_snap_get_publisher_validation(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), SNAPD_PUBLISHER_VALIDATION_UNKNOWN); return self->publisher_validation; } /** * snapd_snap_get_revision: * @snap: a #SnapdSnap. * * Get the revision for this snap. The format of the string is undefined. * See also snapd_snap_get_version(). * * Returns: a revision string. * * Since: 1.0 */ const gchar *snapd_snap_get_revision(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->revision; } /** * snapd_snap_get_screenshots: * @snap: a #SnapdSnap. * * Get the screenshots that are available for this snap. * * Returns: (transfer none) (element-type SnapdScreenshot): an array of * #SnapdScreenshot. * * Since: 1.0 * Deprecated: 1.45: Use snapd_snap_get_media() */ GPtrArray *snapd_snap_get_screenshots(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->screenshots; } /** * snapd_snap_get_snap_type: * @snap: a #SnapdSnap. * * Get the type of snap, e.g. %SNAPD_SNAP_TYPE_APP * * Returns: a #SnapdSnapType. * * Since: 1.0 */ SnapdSnapType snapd_snap_get_snap_type(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), SNAPD_SNAP_TYPE_UNKNOWN); return self->snap_type; } /** * snapd_snap_get_status: * @snap: a #SnapdSnap. * * Get the current status of this snap, e.g. SNAPD_SNAP_STATUS_INSTALLED. * * Returns: a #SnapdSnapStatus. * * Since: 1.0 */ SnapdSnapStatus snapd_snap_get_status(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), SNAPD_SNAP_STATUS_UNKNOWN); return self->status; } /** * snapd_snap_get_store_url: * @snap: a #SnapdSnap. * * Get a URL to the web snap store, e.g. "https://snapcraft.io/example" * * Returns: (allow-none): a URL or %NULL. * * Since: 1.60 */ const gchar *snapd_snap_get_store_url(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->store_url; } /** * snapd_snap_get_summary: * @snap: a #SnapdSnap. * * Get a single line summary for this snap, e.g. "Best app ever!". * * Returns: a summary string. * * Since: 1.0 */ const gchar *snapd_snap_get_summary(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->summary; } /** * snapd_snap_get_tracking_channel: * @snap: a #SnapdSnap. * * Get the channel that updates will be installed from, e.g. "stable". * * Returns: a channel name. * * Since: 1.7 */ const gchar *snapd_snap_get_tracking_channel(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->tracking_channel; } /** * snapd_snap_get_tracks: * @snap: a #SnapdSnap. * * Get the tracks that are available. * * Returns: (transfer none) (array zero-terminated=1): an ordered array of track * names. * * Since: 1.22 */ GStrv snapd_snap_get_tracks(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->tracks; } /** * snapd_snap_get_trymode: * @snap: a #SnapdSnap. * * Get if this snap is running in try mode (installed locally and able to be * directly modified). * * Returns: %TRUE if using trymode. * * Since: 1.0 */ gboolean snapd_snap_get_trymode(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), FALSE); return self->trymode; } /** * snapd_snap_get_version: * @snap: a #SnapdSnap. * * Get the version for this snap. The format of the string is undefined. * See also snapd_snap_get_revision(). * * Returns: a version string. * * Since: 1.0 */ const gchar *snapd_snap_get_version(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->version; } /** * snapd_snap_get_website: * @snap: a #SnapdSnap. * * Get the website of the snap developer, e.g. "http://example.com". * * Returns: a website URL. * * Since: 1.50 */ const gchar *snapd_snap_get_website(SnapdSnap *self) { g_return_val_if_fail(SNAPD_IS_SNAP(self), NULL); return self->website; } static void snapd_snap_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdSnap *self = SNAPD_SNAP(object); switch (prop_id) { case PROP_APPS: g_clear_pointer(&self->apps, g_ptr_array_unref); if (g_value_get_boxed(value) != NULL) self->apps = g_ptr_array_ref(g_value_get_boxed(value)); break; case PROP_BASE: g_free(self->base); self->base = g_strdup(g_value_get_string(value)); break; case PROP_BROKEN: g_free(self->broken); self->broken = g_strdup(g_value_get_string(value)); break; case PROP_CATEGORIES: g_clear_pointer(&self->categories, g_ptr_array_unref); if (g_value_get_boxed(value) != NULL) self->categories = g_ptr_array_ref(g_value_get_boxed(value)); break; case PROP_CHANNEL: g_free(self->channel); self->channel = g_strdup(g_value_get_string(value)); break; case PROP_CHANNELS: g_clear_pointer(&self->channels, g_ptr_array_unref); if (g_value_get_boxed(value) != NULL) self->channels = g_ptr_array_ref(g_value_get_boxed(value)); break; case PROP_CONFINEMENT: self->confinement = g_value_get_enum(value); break; case PROP_CONTACT: g_free(self->contact); self->contact = g_strdup(g_value_get_string(value)); break; case PROP_DESCRIPTION: g_free(self->description); self->description = g_strdup(g_value_get_string(value)); break; case PROP_DEVMODE: self->devmode = g_value_get_boolean(value); break; case PROP_DOWNLOAD_SIZE: self->download_size = g_value_get_int64(value); break; case PROP_HOLD: g_clear_pointer(&self->hold, g_date_time_unref); if (g_value_get_boxed(value) != NULL) self->hold = g_date_time_ref(g_value_get_boxed(value)); break; case PROP_PROCEED_TIME: g_clear_pointer(&self->proceed_time, g_date_time_unref); if (g_value_get_boxed(value) != NULL) self->proceed_time = g_date_time_ref(g_value_get_boxed(value)); break; case PROP_ICON: g_free(self->icon); self->icon = g_strdup(g_value_get_string(value)); break; case PROP_ID: g_free(self->id); self->id = g_strdup(g_value_get_string(value)); break; case PROP_INSTALL_DATE: g_clear_pointer(&self->install_date, g_date_time_unref); if (g_value_get_boxed(value) != NULL) self->install_date = g_date_time_ref(g_value_get_boxed(value)); break; case PROP_INSTALLED_SIZE: self->installed_size = g_value_get_int64(value); break; case PROP_JAILMODE: self->jailmode = g_value_get_boolean(value); break; case PROP_MOUNTED_FROM: g_free(self->mounted_from); self->mounted_from = g_strdup(g_value_get_string(value)); break; case PROP_MEDIA: g_clear_pointer(&self->media, g_ptr_array_unref); if (g_value_get_boxed(value) != NULL) self->media = g_ptr_array_ref(g_value_get_boxed(value)); break; case PROP_NAME: g_free(self->name); self->name = g_strdup(g_value_get_string(value)); break; case PROP_PRICES: g_clear_pointer(&self->prices, g_ptr_array_unref); if (g_value_get_boxed(value) != NULL) self->prices = g_ptr_array_ref(g_value_get_boxed(value)); break; case PROP_PRIVATE: self->private = g_value_get_boolean(value); break; case PROP_PUBLISHER_DISPLAY_NAME: g_free(self->publisher_display_name); self->publisher_display_name = g_strdup(g_value_get_string(value)); break; case PROP_PUBLISHER_ID: g_free(self->publisher_id); self->publisher_id = g_strdup(g_value_get_string(value)); break; case PROP_PUBLISHER_USERNAME: case PROP_DEVELOPER: g_free(self->publisher_username); self->publisher_username = g_strdup(g_value_get_string(value)); break; case PROP_PUBLISHER_VALIDATION: self->publisher_validation = g_value_get_enum(value); break; case PROP_REVISION: g_free(self->revision); self->revision = g_strdup(g_value_get_string(value)); break; case PROP_SCREENSHOTS: g_clear_pointer(&self->screenshots, g_ptr_array_unref); if (g_value_get_boxed(value) != NULL) self->screenshots = g_ptr_array_ref(g_value_get_boxed(value)); break; case PROP_SNAP_TYPE: self->snap_type = g_value_get_enum(value); break; case PROP_STATUS: self->status = g_value_get_enum(value); break; case PROP_STORE_URL: g_free(self->store_url); self->store_url = g_strdup(g_value_get_string(value)); break; case PROP_SUMMARY: g_free(self->summary); self->summary = g_strdup(g_value_get_string(value)); break; case PROP_TITLE: g_free(self->title); self->title = g_strdup(g_value_get_string(value)); break; case PROP_TRACKING_CHANNEL: g_free(self->tracking_channel); self->tracking_channel = g_strdup(g_value_get_string(value)); break; case PROP_TRACKS: g_strfreev(self->tracks); self->tracks = g_strdupv(g_value_get_boxed(value)); break; case PROP_TRYMODE: self->trymode = g_value_get_boolean(value); break; case PROP_VERSION: g_free(self->version); self->version = g_strdup(g_value_get_string(value)); break; case PROP_LICENSE: g_free(self->license); self->license = g_strdup(g_value_get_string(value)); break; case PROP_COMMON_IDS: g_strfreev(self->common_ids); self->common_ids = g_strdupv(g_value_get_boxed(value)); break; case PROP_WEBSITE: g_free(self->website); self->website = g_strdup(g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_snap_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdSnap *self = SNAPD_SNAP(object); switch (prop_id) { case PROP_APPS: g_value_set_boxed(value, self->apps); break; case PROP_BASE: g_value_set_string(value, self->base); break; case PROP_BROKEN: g_value_set_string(value, self->broken); break; case PROP_CATEGORIES: g_value_set_boxed(value, self->categories); break; case PROP_CHANNEL: g_value_set_string(value, self->channel); break; case PROP_CHANNELS: g_value_set_boxed(value, self->channels); break; case PROP_CONFINEMENT: g_value_set_enum(value, self->confinement); break; case PROP_CONTACT: g_value_set_string(value, self->contact); break; case PROP_DESCRIPTION: g_value_set_string(value, self->description); break; case PROP_DEVMODE: g_value_set_boolean(value, self->devmode); break; case PROP_DOWNLOAD_SIZE: g_value_set_int64(value, self->download_size); break; case PROP_HOLD: g_value_set_boxed(value, self->hold); break; case PROP_PROCEED_TIME: g_value_set_boxed(value, self->proceed_time); break; case PROP_ICON: g_value_set_string(value, self->icon); break; case PROP_ID: g_value_set_string(value, self->id); break; case PROP_INSTALL_DATE: g_value_set_boxed(value, self->install_date); break; case PROP_INSTALLED_SIZE: g_value_set_int64(value, self->installed_size); break; case PROP_JAILMODE: g_value_set_boolean(value, self->jailmode); break; case PROP_MEDIA: g_value_set_boxed(value, self->media); break; case PROP_MOUNTED_FROM: g_value_set_string(value, self->mounted_from); break; case PROP_NAME: g_value_set_string(value, self->name); break; case PROP_PRICES: g_value_set_boxed(value, self->prices); break; case PROP_PRIVATE: g_value_set_boolean(value, self->private); break; case PROP_PUBLISHER_DISPLAY_NAME: g_value_set_string(value, self->publisher_display_name); break; case PROP_PUBLISHER_ID: g_value_set_string(value, self->publisher_id); break; case PROP_PUBLISHER_USERNAME: case PROP_DEVELOPER: g_value_set_string(value, self->publisher_username); break; case PROP_PUBLISHER_VALIDATION: g_value_set_enum(value, self->publisher_validation); break; case PROP_REVISION: g_value_set_string(value, self->revision); break; case PROP_SCREENSHOTS: g_value_set_boxed(value, self->screenshots); break; case PROP_SNAP_TYPE: g_value_set_enum(value, self->snap_type); break; case PROP_STATUS: g_value_set_enum(value, self->status); break; case PROP_STORE_URL: g_value_set_string(value, self->store_url); break; case PROP_SUMMARY: g_value_set_string(value, self->summary); break; case PROP_TITLE: g_value_set_string(value, self->title); break; case PROP_TRACKING_CHANNEL: g_value_set_string(value, self->tracking_channel); break; case PROP_TRACKS: g_value_set_boxed(value, self->tracks); break; case PROP_TRYMODE: g_value_set_boolean(value, self->trymode); break; case PROP_VERSION: g_value_set_string(value, self->version); break; case PROP_LICENSE: g_value_set_string(value, self->license); break; case PROP_COMMON_IDS: g_value_set_boxed(value, self->common_ids); break; case PROP_WEBSITE: g_value_set_string(value, self->website); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_snap_finalize(GObject *object) { SnapdSnap *self = SNAPD_SNAP(object); g_clear_pointer(&self->apps, g_ptr_array_unref); g_clear_pointer(&self->base, g_free); g_clear_pointer(&self->broken, g_free); g_clear_pointer(&self->categories, g_ptr_array_unref); g_clear_pointer(&self->channel, g_free); g_clear_pointer(&self->channels, g_ptr_array_unref); g_clear_pointer(&self->common_ids, g_strfreev); g_clear_pointer(&self->contact, g_free); g_clear_pointer(&self->description, g_free); g_clear_pointer(&self->hold, g_date_time_unref); g_clear_pointer(&self->proceed_time, g_date_time_unref); g_clear_pointer(&self->icon, g_free); g_clear_pointer(&self->id, g_free); g_clear_pointer(&self->install_date, g_date_time_unref); g_clear_pointer(&self->name, g_free); g_clear_pointer(&self->license, g_free); g_clear_pointer(&self->media, g_ptr_array_unref); g_clear_pointer(&self->mounted_from, g_free); g_clear_pointer(&self->prices, g_ptr_array_unref); g_clear_pointer(&self->publisher_display_name, g_free); g_clear_pointer(&self->publisher_id, g_free); g_clear_pointer(&self->publisher_username, g_free); g_clear_pointer(&self->revision, g_free); g_clear_pointer(&self->screenshots, g_ptr_array_unref); g_clear_pointer(&self->store_url, g_free); g_clear_pointer(&self->summary, g_free); g_clear_pointer(&self->title, g_free); g_clear_pointer(&self->tracking_channel, g_free); g_clear_pointer(&self->tracks, g_strfreev); g_clear_pointer(&self->version, g_free); g_clear_pointer(&self->website, g_free); G_OBJECT_CLASS(snapd_snap_parent_class)->finalize(object); } static void snapd_snap_class_init(SnapdSnapClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_snap_set_property; gobject_class->get_property = snapd_snap_get_property; gobject_class->finalize = snapd_snap_finalize; g_object_class_install_property( gobject_class, PROP_APPS, g_param_spec_boxed( "apps", "apps", "Apps this snap contains", G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_CATEGORIES, g_param_spec_boxed("categories", "categories", "Categories this snap belongs to", G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_BASE, g_param_spec_string("base", "base", "Base snap this snap uses", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_BROKEN, g_param_spec_string( "broken", "broken", "Error string if snap is broken", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_CHANNEL, g_param_spec_string( "channel", "channel", "Channel the snap is from", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_CHANNELS, g_param_spec_boxed("channels", "channels", "Channels this snap is available on", G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_COMMON_IDS, g_param_spec_boxed("common-ids", "common-ids", "Common IDs", G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_CONFINEMENT, g_param_spec_enum( "confinement", "confinement", "Confinement requested by the snap", SNAPD_TYPE_CONFINEMENT, SNAPD_CONFINEMENT_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_CONTACT, g_param_spec_string( "contact", "contact", "Method of contacting developer", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_DESCRIPTION, g_param_spec_string( "description", "description", "Description of the snap", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_DEVELOPER, g_param_spec_string("developer", "developer", "Developer who created the snap", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_DEPRECATED | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_DEVMODE, g_param_spec_boolean( "devmode", "devmode", "TRUE if the snap is currently installed in devmode", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_DOWNLOAD_SIZE, g_param_spec_int64("download-size", "download-size", "Download size in bytes", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_HOLD, g_param_spec_boxed( "hold", "hold", "Date this snap will re-enable automatic refreshing", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PROCEED_TIME, g_param_spec_boxed("proceed-time", "proceed-time", "Describes time after which a refresh is forced for a " "running snap in the next auto-refresh.", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_ICON, g_param_spec_string("icon", "icon", "URL to the snap icon", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_ID, g_param_spec_string("id", "id", "Unique ID for this snap", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_INSTALL_DATE, g_param_spec_boxed("install-date", "install-date", "Date this snap was installed", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_INSTALLED_SIZE, g_param_spec_int64("installed-size", "installed-size", "Installed size in bytes", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_JAILMODE, g_param_spec_boolean( "jailmode", "jailmode", "TRUE if the snap is currently installed in jailmode", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_LICENSE, g_param_spec_string( "license", "license", "The snap license as an SPDX expression", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_MEDIA, g_param_spec_boxed( "media", "media", "Media associated with this snap", G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_MOUNTED_FROM, g_param_spec_string( "mounted-from", "mounted-from", "Path snap is mounted from", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_NAME, g_param_spec_string("name", "name", "The snap name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PRICES, g_param_spec_boxed( "prices", "prices", "Prices this snap can be purchased for", G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PRIVATE, g_param_spec_boolean( "private", "private", "TRUE if this snap is only available to its author", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PUBLISHER_DISPLAY_NAME, g_param_spec_string("publisher-display-name", "publisher-display-name", "Display name for snap publisher", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PUBLISHER_ID, g_param_spec_string( "publisher-id", "publisher-id", "ID for snap publisher", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PUBLISHER_USERNAME, g_param_spec_string("publisher-username", "publisher-username", "Username for snap publisher", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PUBLISHER_VALIDATION, g_param_spec_enum( "publisher-validation", "publisher-validation", "Validation for snap publisher", SNAPD_TYPE_PUBLISHER_VALIDATION, SNAPD_PUBLISHER_VALIDATION_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_REVISION, g_param_spec_string("revision", "revision", "Revision of this snap", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SCREENSHOTS, g_param_spec_boxed("screenshots", "screenshots", "Screenshots of this snap", G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_STATUS, g_param_spec_enum("status", "status", "State of this snap", SNAPD_TYPE_SNAP_STATUS, SNAPD_SNAP_STATUS_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SUMMARY, g_param_spec_string("summary", "summary", "One line description", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_STORE_URL, g_param_spec_string("store-url", "store-url", "Web store URL", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_TITLE, g_param_spec_string("title", "title", "The snap title", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_TRACKING_CHANNEL, g_param_spec_string("tracking-channel", "tracking-channel", "Channel the snap is currently tracking", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_TRACKS, g_param_spec_boxed("tracks", "tracks", "Track names", G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_TRYMODE, g_param_spec_boolean("trymode", "trymode", "TRUE if this snap is installed in try mode", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SNAP_TYPE, g_param_spec_enum("snap-type", "snap-type", "Snap type", SNAPD_TYPE_SNAP_TYPE, SNAPD_SNAP_TYPE_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_VERSION, g_param_spec_string("version", "version", "Snap version", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_WEBSITE, g_param_spec_string("website", "website", "Website of developer", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_snap_init(SnapdSnap *self) {} snapd-glib-1.67/snapd-glib/snapd-snap.h000066400000000000000000000122641477073115000177360ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_SNAP_H__ #define __SNAPD_SNAP_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include #include #include G_BEGIN_DECLS #define SNAPD_TYPE_SNAP (snapd_snap_get_type()) G_DECLARE_FINAL_TYPE(SnapdSnap, snapd_snap, SNAPD, SNAP, GObject) /** * SnapdSnapType: * @SNAPD_SNAP_TYPE_UNKNOWN: the type of snap is unknown. * @SNAPD_SNAP_TYPE_APP: the snap is an application. * @SNAPD_SNAP_TYPE_KERNEL: the snap is a kernel. * @SNAPD_SNAP_TYPE_GADGET: the snapd is a gadget. * @SNAPD_SNAP_TYPE_OS: the snap is an operating system. * @SNAPD_SNAP_TYPE_CORE: the snap is a core snap. * @SNAPD_SNAP_TYPE_BASE: the snap is a base snap. * @SNAPD_SNAP_TYPE_SNAPD: the snap is the snap daemon. * * Type of snap. * * Since: 1.0 */ typedef enum { SNAPD_SNAP_TYPE_UNKNOWN, SNAPD_SNAP_TYPE_APP, SNAPD_SNAP_TYPE_KERNEL, SNAPD_SNAP_TYPE_GADGET, SNAPD_SNAP_TYPE_OS, SNAPD_SNAP_TYPE_CORE, SNAPD_SNAP_TYPE_BASE, SNAPD_SNAP_TYPE_SNAPD } SnapdSnapType; /** * SnapdSnapStatus: * @SNAPD_SNAP_STATUS_UNKNOWN: the snap state is unknown. * @SNAPD_SNAP_STATUS_AVAILABLE: the snap is available for installation. * @SNAPD_SNAP_STATUS_PRICED: the snap is available for purchase. * @SNAPD_SNAP_STATUS_INSTALLED: the snap is installed but not active. * @SNAPD_SNAP_STATUS_ACTIVE: the snap is installed and active. * * The current state of a snap. * * Since: 1.0 */ typedef enum { SNAPD_SNAP_STATUS_UNKNOWN, SNAPD_SNAP_STATUS_AVAILABLE, SNAPD_SNAP_STATUS_PRICED, SNAPD_SNAP_STATUS_INSTALLED, SNAPD_SNAP_STATUS_ACTIVE } SnapdSnapStatus; /** * SnapdPublisherValidation: * @SNAPD_PUBLISHER_VALIDATION_UNKNOWN: the validation state of the publisher is * unknown. * @SNAPD_PUBLISHER_VALIDATION_UNPROVEN: the publisher has not proven their * identity. * @SNAPD_PUBLISHER_VALIDATION_VERIFIED: the publisher is a star developer. * @SNAPD_PUBLISHER_VALIDATION_STARRED: the publisher has had their identity * verified. * * State of validation for a publisher. * * Since: 1.42 */ typedef enum { SNAPD_PUBLISHER_VALIDATION_UNKNOWN, SNAPD_PUBLISHER_VALIDATION_UNPROVEN, SNAPD_PUBLISHER_VALIDATION_VERIFIED, SNAPD_PUBLISHER_VALIDATION_STARRED } SnapdPublisherValidation; GPtrArray *snapd_snap_get_apps(SnapdSnap *snap); const gchar *snapd_snap_get_base(SnapdSnap *snap); const gchar *snapd_snap_get_broken(SnapdSnap *snap); GPtrArray *snapd_snap_get_categories(SnapdSnap *snap); const gchar *snapd_snap_get_channel(SnapdSnap *snap); GPtrArray *snapd_snap_get_channels(SnapdSnap *snap); SnapdChannel *snapd_snap_match_channel(SnapdSnap *snap, const gchar *name); GStrv snapd_snap_get_common_ids(SnapdSnap *snap); SnapdConfinement snapd_snap_get_confinement(SnapdSnap *snap); const gchar *snapd_snap_get_contact(SnapdSnap *snap); const gchar *snapd_snap_get_description(SnapdSnap *snap); const gchar *snapd_snap_get_developer(SnapdSnap *snap) G_DEPRECATED_FOR(snapd_snap_get_publisher_username); gboolean snapd_snap_get_devmode(SnapdSnap *snap); gint64 snapd_snap_get_download_size(SnapdSnap *snap); GDateTime *snapd_snap_get_hold(SnapdSnap *snap); const gchar *snapd_snap_get_icon(SnapdSnap *snap); const gchar *snapd_snap_get_id(SnapdSnap *snap); GDateTime *snapd_snap_get_install_date(SnapdSnap *snap); gint64 snapd_snap_get_installed_size(SnapdSnap *snap); gboolean snapd_snap_get_jailmode(SnapdSnap *snap); const gchar *snapd_snap_get_license(SnapdSnap *snap); GPtrArray *snapd_snap_get_media(SnapdSnap *snap); const gchar *snapd_snap_get_mounted_from(SnapdSnap *snap); const gchar *snapd_snap_get_name(SnapdSnap *snap); GPtrArray *snapd_snap_get_prices(SnapdSnap *snap); gboolean snapd_snap_get_private(SnapdSnap *snap); const gchar *snapd_snap_get_publisher_display_name(SnapdSnap *snap); const gchar *snapd_snap_get_publisher_id(SnapdSnap *snap); const gchar *snapd_snap_get_publisher_username(SnapdSnap *snap); SnapdPublisherValidation snapd_snap_get_publisher_validation(SnapdSnap *snap); const gchar *snapd_snap_get_revision(SnapdSnap *snap); GPtrArray *snapd_snap_get_screenshots(SnapdSnap *snap) G_DEPRECATED_FOR(snapd_snap_get_media); SnapdSnapType snapd_snap_get_snap_type(SnapdSnap *snap); SnapdSnapStatus snapd_snap_get_status(SnapdSnap *snap); const gchar *snapd_snap_get_store_url(SnapdSnap *snap); const gchar *snapd_snap_get_summary(SnapdSnap *snap); const gchar *snapd_snap_get_title(SnapdSnap *snap); const gchar *snapd_snap_get_tracking_channel(SnapdSnap *snap); GStrv snapd_snap_get_tracks(SnapdSnap *snap); gboolean snapd_snap_get_trymode(SnapdSnap *snap); const gchar *snapd_snap_get_version(SnapdSnap *snap); const gchar *snapd_snap_get_website(SnapdSnap *snap); GDateTime *snapd_snap_get_proceed_time(SnapdSnap *snap); G_END_DECLS #endif /* __SNAPD_SNAP_H__ */ snapd-glib-1.67/snapd-glib/snapd-system-information.c000066400000000000000000000553261477073115000226450ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-system-information.h" #include "snapd-enum-types.h" /** * SECTION:snapd-system-information * @short_description: System information class * @include: snapd-glib/snapd-glib.h * * A #SnapdSystemInformation object contains the system information returned * from snapd. It is requested using snapd_client_get_system_information_sync(). */ /** * SnapdSystemInformation: * * #SnapdSystemInformation contains information about the system snapd is * running on. * * Since: 1.0 */ struct _SnapdSystemInformation { GObject parent_instance; gchar *architecture; gchar *binaries_directory; gchar *build_id; SnapdSystemConfinement confinement; gchar *kernel_version; gboolean on_classic; gboolean managed; gchar *mount_directory; gchar *os_id; gchar *os_version; GDateTime *refresh_hold; GDateTime *refresh_last; GDateTime *refresh_next; gchar *refresh_schedule; gchar *refresh_timer; GHashTable *sandbox_features; gchar *series; gchar *store; gchar *version; }; enum { PROP_ON_CLASSIC = 1, PROP_OS_ID, PROP_OS_VERSION, PROP_SERIES, PROP_STORE, PROP_VERSION, PROP_MANAGED, PROP_KERNEL_VERSION, PROP_BINARIES_DIRECTORY, PROP_MOUNT_DIRECTORY, PROP_CONFINEMENT, PROP_BUILD_ID, PROP_SANDBOX_FEATURES, PROP_REFRESH_HOLD, PROP_REFRESH_LAST, PROP_REFRESH_NEXT, PROP_REFRESH_SCHEDULE, PROP_REFRESH_TIMER, PROP_ARCHITECTURE, PROP_LAST }; G_DEFINE_TYPE(SnapdSystemInformation, snapd_system_information, G_TYPE_OBJECT) /** * snapd_system_information_get_architecture: * @system_information: a #SnapdSystemInformation. * * Get the architecture this system is using, e.g. "amd64". * * Returns: an architecture. * * Since: 1.64 */ const gchar * snapd_system_information_get_architecture(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->architecture; } /** * snapd_system_information_get_binaries_directory: * @system_information: a #SnapdSystemInformation. * * Get the directory snap binaries are stored, e.g. "/snap/bin". * * Returns: a directory. * * Since: 1.11 */ const gchar * snapd_system_information_get_binaries_directory(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->binaries_directory; } /** * snapd_system_information_get_build_id: * @system_information: a #SnapdSystemInformation. * * Gets the unique build ID for the snap build, e.g. * "efdd0b5e69b0742fa5e5bad0771df4d1df2459d1" * * Returns: a build ID. * * Since: 1.40 */ const gchar * snapd_system_information_get_build_id(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->build_id; } /** * snapd_system_information_get_confinement: * @system_information: a #SnapdSystemInformation. * * Get the level of confinement the system supports, e.g. * %SNAPD_SYSTEM_CONFINEMENT_STRICT. * * Returns: a #SnapdSystemConfinement. * * Since: 1.15 */ SnapdSystemConfinement snapd_system_information_get_confinement(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), SNAPD_SYSTEM_CONFINEMENT_UNKNOWN); return self->confinement; } /** * snapd_system_information_get_kernel_version: * @system_information: a #SnapdSystemInformation. * * Get the version of the kernel snapd is running on, e.g. "4.10.0-15-generic". * * Returns: a version string. * * Since: 1.11 */ const gchar * snapd_system_information_get_kernel_version(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->kernel_version; } /** * snapd_system_information_get_managed: * @system_information: a #SnapdSystemInformation. * * Get if snapd is running on a managed system. * * Returns: %TRUE if running on a managed system. * * Since: 1.7 */ gboolean snapd_system_information_get_managed(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), FALSE); return self->managed; } /** * snapd_system_information_get_mount_directory: * @system_information: a #SnapdSystemInformation. * * Get the directory snaps are mounted, e.g. "/snap". * * Returns: a directory. * * Since: 1.11 */ const gchar * snapd_system_information_get_mount_directory(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->mount_directory; } /** * snapd_system_information_get_on_classic: * @system_information: a #SnapdSystemInformation. * * Get if this system is a classic system. * * Returns: %TRUE if running on a classic system. * * Since: 1.0 */ gboolean snapd_system_information_get_on_classic(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), FALSE); return self->on_classic; } /** * snapd_system_information_get_os_id: * @system_information: a #SnapdSystemInformation. * * Get the operating system ID, e.g. "ubuntu". * * Returns: an operating system ID. * * Since: 1.0 */ const gchar *snapd_system_information_get_os_id(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->os_id; } /** * snapd_system_information_get_os_version: * @system_information: a #SnapdSystemInformation. * * Get the operating system version, e.g. "16.04". * * Returns: a version string. * * Since: 1.0 */ const gchar * snapd_system_information_get_os_version(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->os_version; } /** * snapd_system_information_get_refresh_hold: * @system_information: a #SnapdSystemInformation. * * Get the time refreshes will be applied at, or %NULL if they are applied * immediately. * * Returns: (transfer none) (allow-none): a #GDateTime. * * Since: 1.42 */ GDateTime * snapd_system_information_get_refresh_hold(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->refresh_hold; } /** * snapd_system_information_get_refresh_last: * @system_information: a #SnapdSystemInformation. * * Get the time the last refresh occurred, or %NULL if has not occurred. * * Returns: (transfer none) (allow-none): a #GDateTime. * * Since: 1.42 */ GDateTime * snapd_system_information_get_refresh_last(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->refresh_last; } /** * snapd_system_information_get_refresh_next: * @system_information: a #SnapdSystemInformation. * * Get the time the next refresh is scheduled for, or %NULL if none has been * scheduled. * * Returns: (transfer none) (allow-none): a #GDateTime. * * Since: 1.42 */ GDateTime * snapd_system_information_get_refresh_next(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->refresh_next; } /** * snapd_system_information_get_refresh_schedule: * @system_information: a #SnapdSystemInformation. * * Get the schedule when snap refreshes will occur. * * Returns: (allow-none): a Snap refresh schedule string. * * Since: 1.42 */ const gchar * snapd_system_information_get_refresh_schedule(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->refresh_schedule; } /** * snapd_system_information_get_refresh_timer: * @system_information: a #SnapdSystemInformation. * * Get the timer that refreshes are running to. * * Returns: (allow-none): a Snap refresh timer string. * * Since: 1.42 */ const gchar * snapd_system_information_get_refresh_timer(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->refresh_timer; } /** * snapd_system_information_get_sandbox_features: * @system_information: a #SnapdSystemInformation. * * Gets the sandbox features that snapd provides. Each backend in snapd provides * a list of features that it supports. For example, the "confinement-options" * backend may provide "classic", "devmode" and "strict". * * Returns: (transfer none) (element-type utf8 GStrv): a hash table of string * arrays keyed by backend name. * * Since: 1.42 */ GHashTable * snapd_system_information_get_sandbox_features(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->sandbox_features; } /** * snapd_system_information_get_series: * @system_information: a #SnapdSystemInformation. * * Get the series of snapd running, e.g. "16". * * Returns: a series string. * * Since: 1.0 */ const gchar *snapd_system_information_get_series(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->series; } /** * snapd_system_information_get_store: * @system_information: a #SnapdSystemInformation. * * Get the store being used by snapd, e.g. "Ubuntu" * * Returns: (allow-none): a store id or %NULL. * * Since: 1.7 */ const gchar *snapd_system_information_get_store(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->store; } /** * snapd_system_information_get_version: * @system_information: a #SnapdSystemInformation. * * Get the version of snapd running, e.g. "2.11+ppa174-1". * * Returns: a version string. * * Since: 1.0 */ const gchar * snapd_system_information_get_version(SnapdSystemInformation *self) { g_return_val_if_fail(SNAPD_IS_SYSTEM_INFORMATION(self), NULL); return self->version; } static void snapd_system_information_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdSystemInformation *self = SNAPD_SYSTEM_INFORMATION(object); switch (prop_id) { case PROP_ARCHITECTURE: g_free(self->architecture); self->architecture = g_strdup(g_value_get_string(value)); break; case PROP_BINARIES_DIRECTORY: g_free(self->binaries_directory); self->binaries_directory = g_strdup(g_value_get_string(value)); break; case PROP_BUILD_ID: g_free(self->build_id); self->build_id = g_strdup(g_value_get_string(value)); break; case PROP_CONFINEMENT: self->confinement = g_value_get_enum(value); break; case PROP_KERNEL_VERSION: g_free(self->kernel_version); self->kernel_version = g_strdup(g_value_get_string(value)); break; case PROP_MANAGED: self->managed = g_value_get_boolean(value); break; case PROP_MOUNT_DIRECTORY: g_free(self->mount_directory); self->mount_directory = g_strdup(g_value_get_string(value)); break; case PROP_ON_CLASSIC: self->on_classic = g_value_get_boolean(value); break; case PROP_OS_ID: g_free(self->os_id); self->os_id = g_strdup(g_value_get_string(value)); break; case PROP_OS_VERSION: g_free(self->os_version); self->os_version = g_strdup(g_value_get_string(value)); break; case PROP_REFRESH_HOLD: g_clear_pointer(&self->refresh_hold, g_date_time_unref); if (g_value_get_boxed(value) != NULL) self->refresh_hold = g_date_time_ref(g_value_get_boxed(value)); break; case PROP_REFRESH_LAST: g_clear_pointer(&self->refresh_last, g_date_time_unref); if (g_value_get_boxed(value) != NULL) self->refresh_last = g_date_time_ref(g_value_get_boxed(value)); break; case PROP_REFRESH_NEXT: g_clear_pointer(&self->refresh_next, g_date_time_unref); if (g_value_get_boxed(value) != NULL) self->refresh_next = g_date_time_ref(g_value_get_boxed(value)); break; case PROP_REFRESH_SCHEDULE: g_free(self->refresh_schedule); self->refresh_schedule = g_strdup(g_value_get_string(value)); break; case PROP_REFRESH_TIMER: g_free(self->refresh_timer); self->refresh_timer = g_strdup(g_value_get_string(value)); break; case PROP_SANDBOX_FEATURES: g_hash_table_unref(self->sandbox_features); self->sandbox_features = g_hash_table_ref(g_value_get_pointer(value)); break; case PROP_SERIES: g_free(self->series); self->series = g_strdup(g_value_get_string(value)); break; case PROP_STORE: g_free(self->store); self->store = g_strdup(g_value_get_string(value)); break; case PROP_VERSION: g_free(self->version); self->version = g_strdup(g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_system_information_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdSystemInformation *self = SNAPD_SYSTEM_INFORMATION(object); switch (prop_id) { case PROP_ARCHITECTURE: g_value_set_string(value, self->architecture); break; case PROP_BINARIES_DIRECTORY: g_value_set_string(value, self->binaries_directory); break; case PROP_BUILD_ID: g_value_set_string(value, self->build_id); break; case PROP_CONFINEMENT: g_value_set_enum(value, self->confinement); break; case PROP_KERNEL_VERSION: g_value_set_string(value, self->kernel_version); break; case PROP_MANAGED: g_value_set_boolean(value, self->managed); break; case PROP_MOUNT_DIRECTORY: g_value_set_string(value, self->mount_directory); break; case PROP_ON_CLASSIC: g_value_set_boolean(value, self->on_classic); break; case PROP_OS_ID: g_value_set_string(value, self->os_id); break; case PROP_OS_VERSION: g_value_set_string(value, self->os_version); break; case PROP_REFRESH_HOLD: g_value_set_boxed(value, self->refresh_hold); break; case PROP_REFRESH_LAST: g_value_set_boxed(value, self->refresh_last); break; case PROP_REFRESH_NEXT: g_value_set_boxed(value, self->refresh_next); break; case PROP_REFRESH_SCHEDULE: g_value_set_string(value, self->refresh_schedule); break; case PROP_REFRESH_TIMER: g_value_set_string(value, self->refresh_timer); break; case PROP_SANDBOX_FEATURES: g_value_set_pointer(value, self->sandbox_features); break; case PROP_SERIES: g_value_set_string(value, self->series); break; case PROP_STORE: g_value_set_string(value, self->store); break; case PROP_VERSION: g_value_set_string(value, self->version); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_system_information_finalize(GObject *object) { SnapdSystemInformation *self = SNAPD_SYSTEM_INFORMATION(object); g_clear_pointer(&self->architecture, g_free); g_clear_pointer(&self->binaries_directory, g_free); g_clear_pointer(&self->build_id, g_free); g_clear_pointer(&self->kernel_version, g_free); g_clear_pointer(&self->mount_directory, g_free); g_clear_pointer(&self->os_id, g_free); g_clear_pointer(&self->os_version, g_free); g_clear_pointer(&self->refresh_hold, g_date_time_unref); g_clear_pointer(&self->refresh_last, g_date_time_unref); g_clear_pointer(&self->refresh_next, g_date_time_unref); g_clear_pointer(&self->refresh_schedule, g_free); g_clear_pointer(&self->refresh_timer, g_free); g_clear_pointer(&self->sandbox_features, g_hash_table_unref); g_clear_pointer(&self->series, g_free); g_clear_pointer(&self->store, g_free); g_clear_pointer(&self->version, g_free); G_OBJECT_CLASS(snapd_system_information_parent_class)->finalize(object); } static void snapd_system_information_class_init(SnapdSystemInformationClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_system_information_set_property; gobject_class->get_property = snapd_system_information_get_property; gobject_class->finalize = snapd_system_information_finalize; g_object_class_install_property( gobject_class, PROP_ARCHITECTURE, g_param_spec_string( "architecture", "architecture", "System architecture", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_BINARIES_DIRECTORY, g_param_spec_string("binaries-directory", "binaries-directory", "Directory with snap binaries", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_BUILD_ID, g_param_spec_string( "build-id", "build-id", "Unique build ID for snap build", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_CONFINEMENT, g_param_spec_enum( "confinement", "confinement", "Confinement level supported by system", SNAPD_TYPE_SYSTEM_CONFINEMENT, SNAPD_SYSTEM_CONFINEMENT_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_KERNEL_VERSION, g_param_spec_string( "kernel-version", "kernel-version", "Kernel version", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_MANAGED, g_param_spec_boolean( "managed", "managed", "TRUE if snapd managing the system", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_MOUNT_DIRECTORY, g_param_spec_string("mount-directory", "mount-directory", "Directory snaps are mounted in", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_ON_CLASSIC, g_param_spec_boolean("on-classic", "on-classic", "TRUE if running in a classic system", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_OS_ID, g_param_spec_string("os-id", "os-id", "Operating system ID", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_OS_VERSION, g_param_spec_string( "os-version", "os-version", "Operating system version", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_REFRESH_HOLD, g_param_spec_boxed("refresh-hold", "refresh-hold", "Time refreshes will be applied", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_REFRESH_LAST, g_param_spec_boxed("refresh-last", "refresh-last", "Last time a refresh occurred", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_REFRESH_NEXT, g_param_spec_boxed( "refresh-next", "refresh-next", "Next time a refresh is scheduled for", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_REFRESH_SCHEDULE, g_param_spec_string( "refresh-schedule", "refresh-schedule", "Refresh schedule", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_REFRESH_TIMER, g_param_spec_string( "refresh-timer", "refresh-timer", "Refresh timer", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SANDBOX_FEATURES, g_param_spec_pointer( "sandbox-features", "sandbox-features", "Sandbox features", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SERIES, g_param_spec_string("series", "series", "Snappy release series", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_STORE, g_param_spec_string("store", "store", "Snap store", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_VERSION, g_param_spec_string("version", "version", "Snappy version", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_system_information_init(SnapdSystemInformation *self) { self->sandbox_features = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_strfreev); } snapd-glib-1.67/snapd-glib/snapd-system-information.h000066400000000000000000000063761477073115000226530ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_SYSTEM_INFORMATION_H__ #define __SNAPD_SYSTEM_INFORMATION_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_SYSTEM_INFORMATION (snapd_system_information_get_type()) G_DECLARE_FINAL_TYPE(SnapdSystemInformation, snapd_system_information, SNAPD, SYSTEM_INFORMATION, GObject) /** * SnapdSystemConfinement: * @SNAPD_SYSTEM_CONFINEMENT_UNKNOWN: the confinement of the system is unknown. * @SNAPD_SYSTEM_CONFINEMENT_STRICT: the system supports strict confinement. * @SNAPD_SYSTEM_CONFINEMENT_PARTIAL: the system supports partial confinement. * * Confinement used by a snap. * * Since: 1.15 */ typedef enum { SNAPD_SYSTEM_CONFINEMENT_UNKNOWN, SNAPD_SYSTEM_CONFINEMENT_STRICT, SNAPD_SYSTEM_CONFINEMENT_PARTIAL } SnapdSystemConfinement; const gchar *snapd_system_information_get_architecture( SnapdSystemInformation *system_information); const gchar *snapd_system_information_get_binaries_directory( SnapdSystemInformation *system_information); const gchar *snapd_system_information_get_build_id( SnapdSystemInformation *system_information); SnapdSystemConfinement snapd_system_information_get_confinement( SnapdSystemInformation *system_information); const gchar *snapd_system_information_get_kernel_version( SnapdSystemInformation *system_information); gboolean snapd_system_information_get_managed( SnapdSystemInformation *system_information); const gchar *snapd_system_information_get_mount_directory( SnapdSystemInformation *system_information); gboolean snapd_system_information_get_on_classic( SnapdSystemInformation *system_information); const gchar * snapd_system_information_get_os_id(SnapdSystemInformation *system_information); const gchar *snapd_system_information_get_os_version( SnapdSystemInformation *system_information); GDateTime *snapd_system_information_get_refresh_hold( SnapdSystemInformation *system_information); GDateTime *snapd_system_information_get_refresh_last( SnapdSystemInformation *system_information); GDateTime *snapd_system_information_get_refresh_next( SnapdSystemInformation *system_information); const gchar *snapd_system_information_get_refresh_schedule( SnapdSystemInformation *system_information); const gchar *snapd_system_information_get_refresh_timer( SnapdSystemInformation *system_information); GHashTable *snapd_system_information_get_sandbox_features( SnapdSystemInformation *system_information); const gchar * snapd_system_information_get_series(SnapdSystemInformation *system_information); const gchar * snapd_system_information_get_store(SnapdSystemInformation *system_information); const gchar *snapd_system_information_get_version( SnapdSystemInformation *system_information); G_END_DECLS #endif /* __SNAPD_SYSTEM_INFORMATION_H__ */ snapd-glib-1.67/snapd-glib/snapd-task-data.c000066400000000000000000000062721477073115000206430ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-task-data.h" /** * SECTION: snapd-task-data * @short_description: Task extra data * @include: snapd-glib/snapd-glib.h * * A #SnapdTaskData contains extra information on a task in a #SnapdChange. */ /** * SnapdTaskData: * * #SnapdTaskData contains extra information for a task in a Snap transaction. * * Since: 1.66 */ struct _SnapdTaskData { GObject parent_instance; GStrv affected_snaps; }; enum { PROP_ID = 1, PROP_AFFECTED_SNAPS, PROP_LAST }; G_DEFINE_TYPE(SnapdTaskData, snapd_task_data, G_TYPE_OBJECT) /** * snapd_task_data_get_affected_snaps: * @task_data: a #SnapdTaskData. * * Get the list of snaps that are affected by this task, or %NULL if snapd * doesn't send this data. * * Returns: (transfer none) (allow-none): a #GStrv or %NULL. * * Since: 1.66 */ GStrv snapd_task_data_get_affected_snaps(SnapdTaskData *self) { g_return_val_if_fail(SNAPD_IS_TASK_DATA(self), NULL); return self->affected_snaps; } static void snapd_task_data_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdTaskData *self = SNAPD_TASK_DATA(object); switch (prop_id) { case PROP_AFFECTED_SNAPS: g_clear_pointer(&self->affected_snaps, g_strfreev); self->affected_snaps = g_strdupv(g_value_get_boxed(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_task_data_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdTaskData *self = SNAPD_TASK_DATA(object); switch (prop_id) { case PROP_AFFECTED_SNAPS: g_value_set_boxed(value, self->affected_snaps); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_task_data_finalize(GObject *object) { SnapdTaskData *self = SNAPD_TASK_DATA(object); g_clear_pointer(&self->affected_snaps, g_strfreev); G_OBJECT_CLASS(snapd_task_data_parent_class)->finalize(object); } static void snapd_task_data_class_init(SnapdTaskDataClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_task_data_set_property; gobject_class->get_property = snapd_task_data_get_property; gobject_class->finalize = snapd_task_data_finalize; g_object_class_install_property( gobject_class, PROP_AFFECTED_SNAPS, g_param_spec_boxed("affected-snaps", "affected-snaps", "Snaps affected by this task", G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_task_data_init(SnapdTaskData *self) {} snapd-glib-1.67/snapd-glib/snapd-task-data.h000066400000000000000000000015251477073115000206440ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_TASK_DATA_H__ #define __SNAPD_TASK_DATA_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS #define SNAPD_TYPE_TASK_DATA (snapd_task_data_get_type()) G_DECLARE_FINAL_TYPE(SnapdTaskData, snapd_task_data, SNAPD, TASK_DATA, GObject) GStrv snapd_task_data_get_affected_snaps(SnapdTaskData *task_data); G_END_DECLS #endif /* __SNAPD_TASK_DATA_H__ */ snapd-glib-1.67/snapd-glib/snapd-task.c000066400000000000000000000323041477073115000177270ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "snapd-change.h" #include "snapd-task.h" /** * SECTION: snapd-task * @short_description: Task progress * @include: snapd-glib/snapd-glib.h * * A #SnapdTask contains information on a task in a #SnapdChange. */ /** * SnapdTask: * * #SnapdTask contains progress information for a task in a Snap transaction. * * Since: 1.0 */ struct _SnapdTask { GObject parent_instance; gchar *id; gchar *kind; gchar *summary; gchar *status; gchar *progress_label; gint64 progress_done; gint64 progress_total; GDateTime *spawn_time; GDateTime *ready_time; SnapdTaskData *data; }; enum { PROP_ID = 1, PROP_KIND, PROP_SUMMARY, PROP_STATUS, PROP_READY, PROP_PROGRESS_DONE, PROP_PROGRESS_TOTAL, PROP_SPAWN_TIME, PROP_READY_TIME, PROP_PROGRESS_LABEL, PROP_DATA, PROP_LAST }; G_DEFINE_TYPE(SnapdTask, snapd_task, G_TYPE_OBJECT) /** * snapd_task_get_id: * @task: a #SnapdTask. * * Get the unique ID for this task. * * Returns: an ID. * * Since: 1.0 */ const gchar *snapd_task_get_id(SnapdTask *self) { /* Workaround to handle API change in SnapdProgressCallback */ if (SNAPD_IS_CHANGE(self)) return snapd_change_get_id(SNAPD_CHANGE(self)); g_return_val_if_fail(SNAPD_IS_TASK(self), NULL); return self->id; } /** * snapd_task_get_kind: * @task: a #SnapdTask. * * Gets the kind of task this is. * * Returns: the kind of task. * * Since: 1.0 */ const gchar *snapd_task_get_kind(SnapdTask *self) { /* Workaround to handle API change in SnapdProgressCallback */ if (SNAPD_IS_CHANGE(self)) return snapd_change_get_kind(SNAPD_CHANGE(self)); g_return_val_if_fail(SNAPD_IS_TASK(self), NULL); return self->kind; } /** * snapd_task_get_summary: * @task: a #SnapdTask. * * Get a human readable description of the task. * * Returns: a string describing the task. * * Since: 1.0 */ const gchar *snapd_task_get_summary(SnapdTask *self) { /* Workaround to handle API change in SnapdProgressCallback */ if (SNAPD_IS_CHANGE(self)) return snapd_change_get_summary(SNAPD_CHANGE(self)); g_return_val_if_fail(SNAPD_IS_TASK(self), NULL); return self->summary; } /** * snapd_task_get_status: * @task: a #SnapdTask. * * Get the status of the task. * * Returns: a status string. * * Since: 1.0 */ const gchar *snapd_task_get_status(SnapdTask *self) { /* Workaround to handle API change in SnapdProgressCallback */ if (SNAPD_IS_CHANGE(self)) return snapd_change_get_status(SNAPD_CHANGE(self)); g_return_val_if_fail(SNAPD_IS_TASK(self), NULL); return self->status; } /** * snapd_task_get_ready: * @task: a #SnapdTask. * * Get if this task is completed. * * Deprecated: 1.5: Use snapd_change_get_ready() instead. * * Returns: %TRUE if this task is complete. * * Since: 1.0 */ gboolean snapd_task_get_ready(SnapdTask *self) { /* Workaround to handle API change in SnapdProgressCallback */ if (SNAPD_IS_CHANGE(self)) return snapd_change_get_ready(SNAPD_CHANGE(self)); return FALSE; } /** * snapd_task_get_progress_label: * @task: a #SnapdTask. * * Get the the label associated with the progress. * * Returns: a label string. * * Since: 1.5 */ const gchar *snapd_task_get_progress_label(SnapdTask *self) { /* Workaround to handle API change in SnapdProgressCallback */ if (SNAPD_IS_CHANGE(self)) return NULL; g_return_val_if_fail(SNAPD_IS_TASK(self), NULL); return self->progress_label; } /** * snapd_task_get_progress_done: * @task: a #SnapdTask. * * Get the the number of items completed in this task. * * Returns: a count. * * Since: 1.0 */ gint64 snapd_task_get_progress_done(SnapdTask *self) { /* Workaround to handle API change in SnapdProgressCallback */ if (SNAPD_IS_CHANGE(self)) return 0; g_return_val_if_fail(SNAPD_IS_TASK(self), 0); return self->progress_done; } /** * snapd_task_get_progress_total: * @task: a #SnapdTask. * * Get the the total number of items to be completed in this task. * * Returns: a count. * * Since: 1.0 */ gint64 snapd_task_get_progress_total(SnapdTask *self) { /* Workaround to handle API change in SnapdProgressCallback */ if (SNAPD_IS_CHANGE(self)) return 0; g_return_val_if_fail(SNAPD_IS_TASK(self), 0); return self->progress_total; } /** * snapd_task_get_spawn_time: * @task: a #SnapdTask. * * Get the time this task started. * * Returns: (transfer none): a #GDateTime. * * Since: 1.0 */ GDateTime *snapd_task_get_spawn_time(SnapdTask *self) { /* Workaround to handle API change in SnapdProgressCallback */ if (SNAPD_IS_CHANGE(self)) return snapd_change_get_spawn_time(SNAPD_CHANGE(self)); g_return_val_if_fail(SNAPD_IS_TASK(self), NULL); return self->spawn_time; } /** * snapd_task_get_ready_time: * @task: a #SnapdTask. * * Get the time this task completed or %NULL if not yet completed. * * Returns: (transfer none) (allow-none): a #GDateTime or %NULL. * * Since: 1.0 */ GDateTime *snapd_task_get_ready_time(SnapdTask *self) { /* Workaround to handle API change in SnapdProgressCallback */ if (SNAPD_IS_CHANGE(self)) return snapd_change_get_ready_time(SNAPD_CHANGE(self)); g_return_val_if_fail(SNAPD_IS_TASK(self), NULL); return self->ready_time; } /** * snapd_task_get_data: * @task: a #SnapdTask. * * Get the extra data associated with the progress. * * Returns: (transfer none) (allow-none): a #SnapdTaskData or NULL. * * Since: 1.66 */ SnapdTaskData *snapd_task_get_data(SnapdTask *self) { g_return_val_if_fail(SNAPD_IS_TASK(self), NULL); return self->data; } static void snapd_task_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdTask *self = SNAPD_TASK(object); switch (prop_id) { case PROP_ID: g_free(self->id); self->id = g_strdup(g_value_get_string(value)); break; case PROP_KIND: g_free(self->kind); self->kind = g_strdup(g_value_get_string(value)); break; case PROP_SUMMARY: g_free(self->summary); self->summary = g_strdup(g_value_get_string(value)); break; case PROP_STATUS: g_free(self->status); self->status = g_strdup(g_value_get_string(value)); break; case PROP_READY: // Deprecated break; case PROP_PROGRESS_LABEL: g_free(self->progress_label); self->progress_label = g_strdup(g_value_get_string(value)); break; case PROP_PROGRESS_DONE: self->progress_done = g_value_get_int64(value); break; case PROP_PROGRESS_TOTAL: self->progress_total = g_value_get_int64(value); break; case PROP_SPAWN_TIME: g_clear_pointer(&self->spawn_time, g_date_time_unref); if (g_value_get_boxed(value) != NULL) self->spawn_time = g_date_time_ref(g_value_get_boxed(value)); break; case PROP_READY_TIME: g_clear_pointer(&self->ready_time, g_date_time_unref); if (g_value_get_boxed(value) != NULL) self->ready_time = g_date_time_ref(g_value_get_boxed(value)); break; case PROP_DATA: g_clear_object(&self->data); if (g_value_get_object(value) != NULL) self->data = g_object_ref(g_value_get_object(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_task_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdTask *self = SNAPD_TASK(object); switch (prop_id) { case PROP_ID: g_value_set_string(value, self->id); break; case PROP_KIND: g_value_set_string(value, self->kind); break; case PROP_SUMMARY: g_value_set_string(value, self->summary); break; case PROP_STATUS: g_value_set_string(value, self->status); break; case PROP_PROGRESS_LABEL: g_value_set_string(value, self->progress_label); break; case PROP_PROGRESS_DONE: g_value_set_int64(value, self->progress_done); break; case PROP_PROGRESS_TOTAL: g_value_set_int64(value, self->progress_total); break; case PROP_READY: g_value_set_boolean(value, FALSE); break; case PROP_SPAWN_TIME: g_value_set_boxed(value, self->spawn_time); break; case PROP_READY_TIME: g_value_set_boxed(value, self->ready_time); break; case PROP_DATA: g_value_set_object(value, self->data); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_task_finalize(GObject *object) { SnapdTask *self = SNAPD_TASK(object); g_clear_pointer(&self->id, g_free); g_clear_pointer(&self->kind, g_free); g_clear_pointer(&self->summary, g_free); g_clear_pointer(&self->status, g_free); g_clear_pointer(&self->progress_label, g_free); g_clear_pointer(&self->spawn_time, g_date_time_unref); g_clear_pointer(&self->ready_time, g_date_time_unref); g_clear_object(&self->data); G_OBJECT_CLASS(snapd_task_parent_class)->finalize(object); } static void snapd_task_class_init(SnapdTaskClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_task_set_property; gobject_class->get_property = snapd_task_get_property; gobject_class->finalize = snapd_task_finalize; g_object_class_install_property( gobject_class, PROP_ID, g_param_spec_string("id", "id", "ID of task", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_KIND, g_param_spec_string("kind", "kind", "Kind of task", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SUMMARY, g_param_spec_string("summary", "summary", "Summary of task", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_STATUS, g_param_spec_string("status", "status", "Status of task", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PROGRESS_LABEL, g_param_spec_string( "progress-label", "progress-label", "Label for progress", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PROGRESS_DONE, g_param_spec_int64("progress-done", "progress-done", "Number of items done in this task", 0, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_PROGRESS_TOTAL, g_param_spec_int64( "progress-total", "progress-total", "Total number of items to be done in this task", 0, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_READY, g_param_spec_boolean("ready", "ready", "TRUE when task complete", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_DEPRECATED | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SPAWN_TIME, g_param_spec_boxed("spawn-time", "spawn-time", "Time this task started", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_READY_TIME, g_param_spec_boxed("ready-time", "ready-time", "Time this task completed", G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_DATA, g_param_spec_object( "data", "data", "Extra data of task", SNAPD_TYPE_TASK_DATA, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_task_init(SnapdTask *self) {} snapd-glib-1.67/snapd-glib/snapd-task.h000066400000000000000000000026061477073115000177360ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_TASK_H__ #define __SNAPD_TASK_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include "snapd-task-data.h" #include G_BEGIN_DECLS #define SNAPD_TYPE_TASK (snapd_task_get_type()) G_DECLARE_FINAL_TYPE(SnapdTask, snapd_task, SNAPD, TASK, GObject) const gchar *snapd_task_get_id(SnapdTask *task); const gchar *snapd_task_get_kind(SnapdTask *task); const gchar *snapd_task_get_summary(SnapdTask *task); const gchar *snapd_task_get_status(SnapdTask *task); G_DEPRECATED_FOR(snapd_change_get_ready) gboolean snapd_task_get_ready(SnapdTask *task); const gchar *snapd_task_get_progress_label(SnapdTask *task); gint64 snapd_task_get_progress_done(SnapdTask *task); gint64 snapd_task_get_progress_total(SnapdTask *task); GDateTime *snapd_task_get_spawn_time(SnapdTask *task); GDateTime *snapd_task_get_ready_time(SnapdTask *task); SnapdTaskData *snapd_task_get_data(SnapdTask *task); G_END_DECLS #endif /* __SNAPD_TASK_H__ */ snapd-glib-1.67/snapd-glib/snapd-user-information.c000066400000000000000000000160631477073115000222720ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "snapd-user-information.h" /** * SECTION:snapd-user-information * @short_description: User information class * @include: snapd-glib/snapd-glib.h * * A #SnapdUserInformation object contains the information about local users * created using snapd_client_create_user_sync() and * snapd_client_create_users_sync(). */ /** * SnapdUserInformation: * * #SnapdUserInformation contains information about a user account on the system * snapd is running on. * * Since: 1.3 */ struct _SnapdUserInformation { GObject parent_instance; gint64 id; gchar *username; gchar *email; GStrv ssh_keys; SnapdAuthData *auth_data; }; enum { PROP_ID = 1, PROP_USERNAME, PROP_EMAIL, PROP_SSH_KEYS, PROP_AUTH_DATA, PROP_LAST }; G_DEFINE_TYPE(SnapdUserInformation, snapd_user_information, G_TYPE_OBJECT) /** * snapd_user_information_get_id: * @user_information: a #SnapdUserInformation. * * Get the id for this account. * * Returns: a user id. * * Since: 1.26 */ gint64 snapd_user_information_get_id(SnapdUserInformation *self) { g_return_val_if_fail(SNAPD_IS_USER_INFORMATION(self), -1); return self->id; } /** * snapd_user_information_get_username: * @user_information: a #SnapdUserInformation. * * Get the local username for this account. * * Returns: a username. * * Since: 1.3 */ const gchar *snapd_user_information_get_username(SnapdUserInformation *self) { g_return_val_if_fail(SNAPD_IS_USER_INFORMATION(self), NULL); return self->username; } /** * snapd_user_information_get_email: * @user_information: a #SnapdUserInformation. * * Get the email address for this account. * * Returns: a email address. * * Since: 1.26 */ const gchar *snapd_user_information_get_email(SnapdUserInformation *self) { g_return_val_if_fail(SNAPD_IS_USER_INFORMATION(self), NULL); return self->email; } /** * snapd_user_information_get_ssh_keys: * @user_information: a #SnapdUserInformation. * * Get the SSH keys added to this account. * * Returns: (transfer none) (array zero-terminated=1): the names of the SSH * keys. * * Since: 1.3 */ GStrv snapd_user_information_get_ssh_keys(SnapdUserInformation *self) { g_return_val_if_fail(SNAPD_IS_USER_INFORMATION(self), NULL); return self->ssh_keys; } /** * snapd_user_information_get_auth_data: * @user_information: a #SnapdUserInformation. * * Get the email address for this account. * * Returns: (transfer none) (allow-none): a #SnapdAuthData or %NULL if not set. * * Since: 1.26 */ SnapdAuthData * snapd_user_information_get_auth_data(SnapdUserInformation *self) { g_return_val_if_fail(SNAPD_IS_USER_INFORMATION(self), NULL); return self->auth_data; } static void snapd_user_information_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SnapdUserInformation *self = SNAPD_USER_INFORMATION(object); switch (prop_id) { case PROP_ID: self->id = g_value_get_int64(value); break; case PROP_USERNAME: g_free(self->username); self->username = g_strdup(g_value_get_string(value)); break; case PROP_EMAIL: g_free(self->email); self->email = g_strdup(g_value_get_string(value)); break; case PROP_SSH_KEYS: g_strfreev(self->ssh_keys); self->ssh_keys = g_strdupv(g_value_get_boxed(value)); break; case PROP_AUTH_DATA: g_clear_object(&self->auth_data); self->auth_data = g_value_dup_object(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_user_information_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SnapdUserInformation *self = SNAPD_USER_INFORMATION(object); switch (prop_id) { case PROP_ID: g_value_set_int64(value, self->id); break; case PROP_USERNAME: g_value_set_string(value, self->username); break; case PROP_EMAIL: g_value_set_string(value, self->email); break; case PROP_SSH_KEYS: g_value_set_boxed(value, self->ssh_keys); break; case PROP_AUTH_DATA: g_value_set_object(value, self->auth_data); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void snapd_user_information_finalize(GObject *object) { SnapdUserInformation *self = SNAPD_USER_INFORMATION(object); g_clear_pointer(&self->username, g_free); g_clear_pointer(&self->email, g_free); g_clear_pointer(&self->ssh_keys, g_strfreev); g_clear_object(&self->auth_data); G_OBJECT_CLASS(snapd_user_information_parent_class)->finalize(object); } static void snapd_user_information_class_init(SnapdUserInformationClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = snapd_user_information_set_property; gobject_class->get_property = snapd_user_information_get_property; gobject_class->finalize = snapd_user_information_finalize; g_object_class_install_property( gobject_class, PROP_ID, g_param_spec_int64("id", "id", "Account id", G_MININT64, G_MAXINT64, -1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_USERNAME, g_param_spec_string("username", "username", "Unix username", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_EMAIL, g_param_spec_string("email", "email", "Email address", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_SSH_KEYS, g_param_spec_boxed("ssh-keys", "ssh-keys", "SSH keys", G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property( gobject_class, PROP_AUTH_DATA, g_param_spec_object( "auth-data", "auth-data", "Authorization data", SNAPD_TYPE_AUTH_DATA, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void snapd_user_information_init(SnapdUserInformation *self) { self->id = -1; } snapd-glib-1.67/snapd-glib/snapd-user-information.h000066400000000000000000000024671477073115000223020ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_USER_INFORMATION_H__ #define __SNAPD_USER_INFORMATION_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif #include #include "snapd-auth-data.h" G_BEGIN_DECLS #define SNAPD_TYPE_USER_INFORMATION (snapd_user_information_get_type()) G_DECLARE_FINAL_TYPE(SnapdUserInformation, snapd_user_information, SNAPD, USER_INFORMATION, GObject) gint64 snapd_user_information_get_id(SnapdUserInformation *user_information); const gchar * snapd_user_information_get_username(SnapdUserInformation *user_information); const gchar * snapd_user_information_get_email(SnapdUserInformation *user_information); GStrv snapd_user_information_get_ssh_keys( SnapdUserInformation *user_information); SnapdAuthData * snapd_user_information_get_auth_data(SnapdUserInformation *user_information); G_END_DECLS #endif /* __SNAPD_USER_INFORMATION_H__ */ snapd-glib-1.67/snapd-glib/snapd-version.h000066400000000000000000000302271477073115000204610ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __SNAPD_GLIB_VERSION_H__ #define __SNAPD_GLIB_VERSION_H__ #if !defined(__SNAPD_GLIB_INSIDE__) && !defined(SNAPD_COMPILATION) #error "Only can be included directly." #endif /** * SNAPD_GLIB_VERSION_1_0: * * A define that can be used by the C pre-processor to check for features in 1.0 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_0 /** * SNAPD_GLIB_VERSION_1_1: * * A define that can be used by the C pre-processor to check for features in 1.1 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_1 /** * SNAPD_GLIB_VERSION_1_2: * * A define that can be used by the C pre-processor to check for features in 1.2 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_2 /** * SNAPD_GLIB_VERSION_1_3: * * A define that can be used by the C pre-processor to check for features in 1.3 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_3 /** * SNAPD_GLIB_VERSION_1_4: * * A define that can be used by the C pre-processor to check for features in 1.4 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_4 /** * SNAPD_GLIB_VERSION_1_5: * * A define that can be used by the C pre-processor to check for features in 1.5 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_5 /** * SNAPD_GLIB_VERSION_1_6: * * A define that can be used by the C pre-processor to check for features in 1.6 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_6 /** * SNAPD_GLIB_VERSION_1_7: * * A define that can be used by the C pre-processor to check for features in 1.7 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_7 /** * SNAPD_GLIB_VERSION_1_8: * * A define that can be used by the C pre-processor to check for features in 1.8 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_8 /** * SNAPD_GLIB_VERSION_1_9: * * A define that can be used by the C pre-processor to check for features in 1.9 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_9 /** * SNAPD_GLIB_VERSION_1_10: * * A define that can be used by the C pre-processor to check for features * in 1.10 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_10 /** * SNAPD_GLIB_VERSION_1_11: * * A define that can be used by the C pre-processor to check for features * in 1.11 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_11 /** * SNAPD_GLIB_VERSION_1_12: * * A define that can be used by the C pre-processor to check for features * in 1.12 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_12 /** * SNAPD_GLIB_VERSION_1_13: * * A define that can be used by the C pre-processor to check for features * in 1.13 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_13 /** * SNAPD_GLIB_VERSION_1_14: * * A define that can be used by the C pre-processor to check for features * in 1.14 * * Since: 1.14 */ #define SNAPD_GLIB_VERSION_1_14 /** * SNAPD_GLIB_VERSION_1_15: * * A define that can be used by the C pre-processor to check for features * in 1.15 * * Since: 1.15 */ #define SNAPD_GLIB_VERSION_1_15 /** * SNAPD_GLIB_VERSION_1_16: * * A define that can be used by the C pre-processor to check for features * in 1.16 * * Since: 1.16 */ #define SNAPD_GLIB_VERSION_1_16 /** * SNAPD_GLIB_VERSION_1_17: * * A define that can be used by the C pre-processor to check for features * in 1.17 * * Since: 1.17 */ #define SNAPD_GLIB_VERSION_1_17 /** * SNAPD_GLIB_VERSION_1_18: * * A define that can be used by the C pre-processor to check for features * in 1.18 * * Since: 1.18 */ #define SNAPD_GLIB_VERSION_1_18 /** * SNAPD_GLIB_VERSION_1_19: * * A define that can be used by the C pre-processor to check for features * in 1.19 * * Since: 1.19 */ #define SNAPD_GLIB_VERSION_1_19 /** * SNAPD_GLIB_VERSION_1_20: * * A define that can be used by the C pre-processor to check for features * in 1.20 * * Since: 1.20 */ #define SNAPD_GLIB_VERSION_1_20 /** * SNAPD_GLIB_VERSION_1_21: * * A define that can be used by the C pre-processor to check for features * in 1.21 * * Since: 1.21 */ #define SNAPD_GLIB_VERSION_1_21 /** * SNAPD_GLIB_VERSION_1_22: * * A define that can be used by the C pre-processor to check for features * in 1.22 * * Since: 1.22 */ #define SNAPD_GLIB_VERSION_1_22 /** * SNAPD_GLIB_VERSION_1_23: * * A define that can be used by the C pre-processor to check for features * in 1.23 * * Since: 1.23 */ #define SNAPD_GLIB_VERSION_1_23 /** * SNAPD_GLIB_VERSION_1_24: * * A define that can be used by the C pre-processor to check for features * in 1.24 * * Since: 1.24 */ #define SNAPD_GLIB_VERSION_1_24 /** * SNAPD_GLIB_VERSION_1_25: * * A define that can be used by the C pre-processor to check for features * in 1.25 * * Since: 1.25 */ #define SNAPD_GLIB_VERSION_1_25 /** * SNAPD_GLIB_VERSION_1_26: * * A define that can be used by the C pre-processor to check for features * in 1.26 * * Since: 1.26 */ #define SNAPD_GLIB_VERSION_1_26 /** * SNAPD_GLIB_VERSION_1_27: * * A define that can be used by the C pre-processor to check for features * in 1.27 * * Since: 1.27 */ #define SNAPD_GLIB_VERSION_1_27 /** * SNAPD_GLIB_VERSION_1_28: * * A define that can be used by the C pre-processor to check for features * in 1.28 * * Since: 1.28 */ #define SNAPD_GLIB_VERSION_1_28 /** * SNAPD_GLIB_VERSION_1_29: * * A define that can be used by the C pre-processor to check for features * in 1.29 * * Since: 1.29 */ #define SNAPD_GLIB_VERSION_1_29 /** * SNAPD_GLIB_VERSION_1_30: * * A define that can be used by the C pre-processor to check for features * in 1.30 * * Since: 1.30 */ #define SNAPD_GLIB_VERSION_1_30 /** * SNAPD_GLIB_VERSION_1_31: * * A define that can be used by the C pre-processor to check for features * in 1.31 * * Since: 1.31 */ #define SNAPD_GLIB_VERSION_1_31 /** * SNAPD_GLIB_VERSION_1_32: * * A define that can be used by the C pre-processor to check for features * in 1.32 * * Since: 1.32 */ #define SNAPD_GLIB_VERSION_1_32 /** * SNAPD_GLIB_VERSION_1_33: * * A define that can be used by the C pre-processor to check for features * in 1.33 * * Since: 1.33 */ #define SNAPD_GLIB_VERSION_1_33 /** * SNAPD_GLIB_VERSION_1_34: * * A define that can be used by the C pre-processor to check for features * in 1.34 * * Since: 1.34 */ #define SNAPD_GLIB_VERSION_1_34 /** * SNAPD_GLIB_VERSION_1_35: * * A define that can be used by the C pre-processor to check for features * in 1.35 * * Since: 1.35 */ #define SNAPD_GLIB_VERSION_1_35 /** * SNAPD_GLIB_VERSION_1_36: * * A define that can be used by the C pre-processor to check for features * in 1.36 * * Since: 1.36 */ #define SNAPD_GLIB_VERSION_1_36 /** * SNAPD_GLIB_VERSION_1_37: * * A define that can be used by the C pre-processor to check for features * in 1.37 * * Since: 1.37 */ #define SNAPD_GLIB_VERSION_1_37 /** * SNAPD_GLIB_VERSION_1_38: * * A define that can be used by the C pre-processor to check for features * in 1.38 * * Since: 1.38 */ #define SNAPD_GLIB_VERSION_1_38 /** * SNAPD_GLIB_VERSION_1_39: * * A define that can be used by the C pre-processor to check for features * in 1.39 * * Since: 1.39 */ #define SNAPD_GLIB_VERSION_1_39 /** * SNAPD_GLIB_VERSION_1_40: * * A define that can be used by the C pre-processor to check for features * in 1.40 * * Since: 1.40 */ #define SNAPD_GLIB_VERSION_1_40 /** * SNAPD_GLIB_VERSION_1_41: * * A define that can be used by the C pre-processor to check for features * in 1.41 * * Since: 1.41 */ #define SNAPD_GLIB_VERSION_1_41 /** * SNAPD_GLIB_VERSION_1_42: * * A define that can be used by the C pre-processor to check for features * in 1.42 * * Since: 1.42 */ #define SNAPD_GLIB_VERSION_1_42 /** * SNAPD_GLIB_VERSION_1_43: * * A define that can be used by the C pre-processor to check for features * in 1.43 * * Since: 1.43 */ #define SNAPD_GLIB_VERSION_1_43 /** * SNAPD_GLIB_VERSION_1_44: * * A define that can be used by the C pre-processor to check for features * in 1.44 * * Since: 1.44 */ #define SNAPD_GLIB_VERSION_1_44 /** * SNAPD_GLIB_VERSION_1_45: * * A define that can be used by the C pre-processor to check for features * in 1.45 * * Since: 1.45 */ #define SNAPD_GLIB_VERSION_1_45 /** * SNAPD_GLIB_VERSION_1_46: * * A define that can be used by the C pre-processor to check for features * in 1.46 * * Since: 1.46 */ #define SNAPD_GLIB_VERSION_1_46 /** * SNAPD_GLIB_VERSION_1_47: * * A define that can be used by the C pre-processor to check for features * in 1.47 * * Since: 1.47 */ #define SNAPD_GLIB_VERSION_1_47 /** * SNAPD_GLIB_VERSION_1_48: * * A define that can be used by the C pre-processor to check for features * in 1.48 * * Since: 1.48 */ #define SNAPD_GLIB_VERSION_1_48 /** * SNAPD_GLIB_VERSION_1_49: * * A define that can be used by the C pre-processor to check for features * in 1.49 * * Since: 1.49 */ #define SNAPD_GLIB_VERSION_1_49 /** * SNAPD_GLIB_VERSION_1_50: * * A define that can be used by the C pre-processor to check for features * in 1.50 * * Since: 1.50 */ #define SNAPD_GLIB_VERSION_1_50 /** * SNAPD_GLIB_VERSION_1_51: * * A define that can be used by the C pre-processor to check for features * in 1.51 * * Since: 1.51 */ #define SNAPD_GLIB_VERSION_1_51 /** * SNAPD_GLIB_VERSION_1_52: * * A define that can be used by the C pre-processor to check for features * in 1.52 * * Since: 1.52 */ #define SNAPD_GLIB_VERSION_1_52 /** * SNAPD_GLIB_VERSION_1_53: * * A define that can be used by the C pre-processor to check for features * in 1.53 * * Since: 1.53 */ #define SNAPD_GLIB_VERSION_1_53 /** * SNAPD_GLIB_VERSION_1_54: * * A define that can be used by the C pre-processor to check for features * in 1.54 * * Since: 1.54 */ #define SNAPD_GLIB_VERSION_1_54 /** * SNAPD_GLIB_VERSION_1_55: * * A define that can be used by the C pre-processor to check for features * in 1.55 * * Since: 1.55 */ #define SNAPD_GLIB_VERSION_1_55 /** * SNAPD_GLIB_VERSION_1_56: * * A define that can be used by the C pre-processor to check for features * in 1.56 * * Since: 1.56 */ #define SNAPD_GLIB_VERSION_1_56 /** * SNAPD_GLIB_VERSION_1_57: * * A define that can be used by the C pre-processor to check for features * in 1.57 * * Since: 1.57 */ #define SNAPD_GLIB_VERSION_1_57 /** * SNAPD_GLIB_VERSION_1_58: * * A define that can be used by the C pre-processor to check for features * in 1.58 * * Since: 1.58 */ #define SNAPD_GLIB_VERSION_1_58 /** * SNAPD_GLIB_VERSION_1_59: * * A define that can be used by the C pre-processor to check for features * in 1.59 * * Since: 1.59 */ #define SNAPD_GLIB_VERSION_1_59 /** * SNAPD_GLIB_VERSION_1_60: * * A define that can be used by the C pre-processor to check for features * in 1.60 * * Since: 1.60 */ #define SNAPD_GLIB_VERSION_1_60 /** * SNAPD_GLIB_VERSION_1_61: * * A define that can be used by the C pre-processor to check for features * in 1.61 * * Since: 1.61 */ #define SNAPD_GLIB_VERSION_1_61 /** * SNAPD_GLIB_VERSION_1_62: * * A define that can be used by the C pre-processor to check for features * in 1.62 * * Since: 1.62 */ #define SNAPD_GLIB_VERSION_1_62 /** * SNAPD_GLIB_VERSION_1_63: * * A define that can be used by the C pre-processor to check for features * in 1.63 * * Since: 1.63 */ #define SNAPD_GLIB_VERSION_1_63 /** * SNAPD_GLIB_VERSION_1_64: * * A define that can be used by the C pre-processor to check for features * in 1.64 * * Since: 1.64 */ #define SNAPD_GLIB_VERSION_1_64 /** * SNAPD_GLIB_VERSION_1_65: * * A define that can be used by the C pre-processor to check for features * in 1.65 * * Since: 1.65 */ #define SNAPD_GLIB_VERSION_1_65 /** * SNAPD_GLIB_VERSION_1_66: * * A define that can be used by the C pre-processor to check for features * in 1.66 * * Since: 1.66 */ #define SNAPD_GLIB_VERSION_1_66 /** * SNAPD_GLIB_VERSION_1_67: * * A define that can be used by the C pre-processor to check for features * in 1.67 * * Since: 1.67 */ #define SNAPD_GLIB_VERSION_1_67 #endif /* __SNAPD_GLIB_VERSION_H__ */ snapd-glib-1.67/snapd-qt/000077500000000000000000000000001477073115000152235ustar00rootroot00000000000000snapd-glib-1.67/snapd-qt/Snapd/000077500000000000000000000000001477073115000162705ustar00rootroot00000000000000snapd-glib-1.67/snapd-qt/Snapd/Alias000066400000000000000000000000311477073115000172360ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/App000066400000000000000000000000271477073115000167320ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Assertion000066400000000000000000000000351477073115000201600ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/AuthData000066400000000000000000000000351477073115000177040ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Category000066400000000000000000000014451477073115000177740ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_CATEGORY_H #define SNAPD_CATEGORY_H #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdCategory : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString name READ name) Q_PROPERTY(bool featured READ featured) public: explicit QSnapdCategory (void* snapd_object, QObject* parent = 0); QString name () const; bool featured () const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/CategoryDetails000066400000000000000000000000441477073115000212740ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Change000066400000000000000000000000321477073115000173730ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Channel000066400000000000000000000000331477073115000175570ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Client000066400000000000000000000000321477073115000174240ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Connection000066400000000000000000000000361477073115000203110ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Enums000066400000000000000000000000311477073115000172740ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Icon000066400000000000000000000000301477073115000170740ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Interface000066400000000000000000000000351477073115000201110ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Maintenance000066400000000000000000000000371477073115000204350ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/MarkdownNode000066400000000000000000000000411477073115000205760ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/MarkdownParser000066400000000000000000000000431477073115000211470ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Media000066400000000000000000000000311477073115000172240ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Notice000066400000000000000000000000321477073115000174270ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Plug000066400000000000000000000000301477073115000171130ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/PlugRef000066400000000000000000000000341477073115000175540ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Price000066400000000000000000000000311477073115000172470ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Request000066400000000000000000000000331477073115000176370ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Screenshot000066400000000000000000000000361477073115000203270ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Slot000066400000000000000000000000301477073115000171250ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/SlotRef000066400000000000000000000000341477073115000175660ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Snap000066400000000000000000000000301477073115000171050ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/SystemInformation000066400000000000000000000000461477073115000217050ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/Task000066400000000000000000000000301477073115000171060ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/TaskData000066400000000000000000000000351477073115000177050ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/UserInformation000066400000000000000000000000441477073115000213350ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/WrappedObject000066400000000000000000000000421477073115000207400ustar00rootroot00000000000000#include snapd-glib-1.67/snapd-qt/Snapd/alias.h000066400000000000000000000022441477073115000175340ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_ALIAS_H #define SNAPD_ALIAS_H #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdAlias : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString app READ app) Q_PROPERTY(QString appAuto READ appAuto) Q_PROPERTY(QString command READ command) Q_PROPERTY(QString appManual READ appManual) Q_PROPERTY(QString name READ name) Q_PROPERTY(QString snap READ snap) Q_PROPERTY(QSnapdEnums::AliasStatus status READ status) public: explicit QSnapdAlias(void *snapd_object, QObject *parent = 0); Q_DECL_DEPRECATED QString app() const; QString appAuto() const; QString command() const; QString appManual() const; QString name() const; QString snap() const; QSnapdEnums::AliasStatus status() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/app.h000066400000000000000000000023721477073115000172250ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_APP_H #define SNAPD_APP_H #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdApp : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString name READ name) Q_PROPERTY(bool active READ active) Q_PROPERTY(QStringList aliases READ aliases) Q_PROPERTY(QString commonId READ commonId) Q_PROPERTY(QSnapdEnums::DaemonType daemonType READ daemonType) Q_PROPERTY(QString desktopFile READ desktopFile) Q_PROPERTY(bool enabled READ enabled) Q_PROPERTY(QString snap READ snap) public: explicit QSnapdApp(void *snapd_object, QObject *parent = 0); QString name() const; bool active() const; Q_DECL_DEPRECATED QStringList aliases() const; QString commonId() const; QSnapdEnums::DaemonType daemonType() const; QString desktopFile() const; bool enabled() const; QString snap() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/assertion.h000066400000000000000000000016561477073115000204600ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_ASSERTION_H #define SNAPD_ASSERTION_H #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdAssertion : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QStringList headers READ headers) Q_PROPERTY(QString body READ body) Q_PROPERTY(QString signature READ signature) public: explicit QSnapdAssertion(const QString &content, QObject *parent = 0); Q_INVOKABLE QString header(const QString &name) const; QStringList headers() const; QString body() const; QString signature() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/auth-data.h000066400000000000000000000020001477073115000203010ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_AUTH_DATA_H #define SNAPD_AUTH_DATA_H #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdAuthData : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString macaroon READ macaroon) Q_PROPERTY(QStringList discharges READ discharges) public: explicit QSnapdAuthData(void *snapd_object, QObject *parent = 0); explicit QSnapdAuthData(const QString &macaroon, const QStringList &discharges, QObject *parent = 0); explicit QSnapdAuthData(QObject *parent = 0); QString macaroon() const; QStringList discharges() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/category-details.h000066400000000000000000000013611477073115000217020ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_CATEGORY_DETAILS_H #define SNAPD_CATEGORY_DETAILS_H #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdCategoryDetails : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString name READ name) public: explicit QSnapdCategoryDetails(void *snapd_object, QObject *parent = 0); QString name() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/category.h000066400000000000000000000014261477073115000202610ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_CATEGORY_H #define SNAPD_CATEGORY_H #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdCategory : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString name READ name) Q_PROPERTY(bool featured READ featured) public: explicit QSnapdCategory(void *snapd_object, QObject *parent = 0); QString name() const; bool featured() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/change-autorefresh-data.h000066400000000000000000000016661477073115000231330ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_AUTOREFRESH_CHANGE_DATA_H #define SNAPD_AUTOREFRESH_CHANGE_DATA_H #include "change-data.h" #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdAutorefreshChangeData : public QSnapdChangeData { Q_OBJECT Q_PROPERTY(QStringList snapNames READ snapNames) Q_PROPERTY(QStringList refreshForced READ refreshForced) public: explicit QSnapdAutorefreshChangeData(void *snapd_object, QObject *parent = 0); QStringList snapNames() const; QStringList refreshForced() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/change-data.h000066400000000000000000000012741477073115000206010ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_CHANGE_DATA_H #define SNAPD_CHANGE_DATA_H #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdChangeData : public QSnapdWrappedObject { Q_OBJECT public: explicit QSnapdChangeData(void *snapd_object, QObject *parent = 0); }; #endif snapd-glib-1.67/snapd-qt/Snapd/change.h000066400000000000000000000027411477073115000176720ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_CHANGE_H #define SNAPD_CHANGE_H #include #include #include #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdChange : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString id READ id) Q_PROPERTY(QString kind READ kind) Q_PROPERTY(QString summary READ summary) Q_PROPERTY(QString status READ status) Q_PROPERTY(bool ready READ ready) Q_PROPERTY(int taskCount READ taskCount) Q_PROPERTY(QDateTime spawnTime READ spawnTime) Q_PROPERTY(QDateTime readyTime READ readyTime) Q_PROPERTY(QString error READ error) Q_PROPERTY(QSnapdChangeData *data READ data) public: explicit QSnapdChange(void *snapd_object, QObject *parent = 0); QString id() const; QString kind() const; QString summary() const; QString status() const; bool ready() const; int taskCount() const; Q_INVOKABLE QSnapdTask *task(int) const; QDateTime spawnTime() const; QDateTime readyTime() const; QString error() const; QSnapdChangeData *data() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/channel.h000066400000000000000000000027651477073115000200630ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_CHANNEL_H #define SNAPD_CHANNEL_H #include #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdChannel : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString branch READ branch CONSTANT) Q_PROPERTY(QSnapdEnums::SnapConfinement confinement READ confinement CONSTANT) Q_PROPERTY(QString epoch READ epoch CONSTANT) Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(QDateTime releasedAt READ releasedAt CONSTANT) Q_PROPERTY(QString revision READ revision CONSTANT) Q_PROPERTY(QString risk READ risk CONSTANT) Q_PROPERTY(qint64 size READ size CONSTANT) Q_PROPERTY(QString track READ track CONSTANT) Q_PROPERTY(QString version READ version CONSTANT) public: explicit QSnapdChannel(void *snapd_object, QObject *parent = 0); QString branch() const; QSnapdEnums::SnapConfinement confinement() const; QString epoch() const; QString name() const; QDateTime releasedAt() const; QString revision() const; QString risk() const; qint64 size() const; QString track() const; QString version() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/client.h000066400000000000000000001305211477073115000177210ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_CLIENT_H #define SNAPD_CLIENT_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class QSnapdConnectRequestPrivate; #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdConnectRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdConnectRequest(void *snapd_client, QObject *parent = 0); ~QSnapdConnectRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdConnectRequest) }; class QSnapdLoginRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdLoginRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(QSnapdUserInformation *userInformation READ userInformation) Q_PROPERTY(QSnapdAuthData *authData READ authData) public: explicit QSnapdLoginRequest(void *snapd_client, const QString &email, const QString &password, const QString &otp, QObject *parent = 0); ~QSnapdLoginRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QSnapdUserInformation *userInformation(); Q_INVOKABLE QSnapdAuthData *authData(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdLoginRequest) }; class QSnapdLogoutRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdLogoutRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdLogoutRequest(void *snapd_client, qint64 id, QObject *parent = 0); ~QSnapdLogoutRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdLogoutRequest) }; class QSnapdGetChangesRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetChangesRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(int changeCount READ changeCount) public: explicit QSnapdGetChangesRequest(int filter, const QString &snapName, void *snapd_client, QObject *parent = 0); ~QSnapdGetChangesRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE int changeCount() const; Q_INVOKABLE QSnapdChange *change(int) const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetChangesRequest) }; class QSnapdGetChangeRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetChangeRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdGetChangeRequest(const QString &id, void *snapd_client, QObject *parent = 0); ~QSnapdGetChangeRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QSnapdChange *change() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetChangeRequest) }; class QSnapdAbortChangeRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdAbortChangeRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdAbortChangeRequest(const QString &id, void *snapd_client, QObject *parent = 0); ~QSnapdAbortChangeRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QSnapdChange *change() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdAbortChangeRequest) }; class QSnapdGetSystemInformationRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetSystemInformationRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(QSnapdSystemInformation *systemInformation READ systemInformation) public: explicit QSnapdGetSystemInformationRequest(void *snapd_client, QObject *parent = 0); ~QSnapdGetSystemInformationRequest(); virtual void runSync(); virtual void runAsync(); QSnapdSystemInformation *systemInformation(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetSystemInformationRequest) }; class QSnapdListRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdListRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(int snapCount READ snapCount) public: explicit QSnapdListRequest(void *snapd_client, QObject *parent = 0); ~QSnapdListRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE int snapCount() const; Q_INVOKABLE QSnapdSnap *snap(int) const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdListRequest) }; class QSnapdGetSnapsRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetSnapsRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(int snapCount READ snapCount) public: explicit QSnapdGetSnapsRequest(int flags, const QStringList &snaps, void *snapd_client, QObject *parent = 0); ~QSnapdGetSnapsRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE int snapCount() const; Q_INVOKABLE QSnapdSnap *snap(int) const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetSnapsRequest) }; class QSnapdListOneRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdListOneRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdListOneRequest(const QString &name, void *snapd_client, QObject *parent = 0); ~QSnapdListOneRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QSnapdSnap *snap() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdListOneRequest) }; class QSnapdGetSnapRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetSnapRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdGetSnapRequest(const QString &name, void *snapd_client, QObject *parent = 0); ~QSnapdGetSnapRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QSnapdSnap *snap() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetSnapRequest) }; class QSnapdGetSnapConfRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetSnapConfRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdGetSnapConfRequest(const QString &name, const QStringList &keys, void *snapd_client, QObject *parent = 0); ~QSnapdGetSnapConfRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QHash *configuration() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetSnapConfRequest) }; class QSnapdSetSnapConfRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdSetSnapConfRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdSetSnapConfRequest( const QString &name, const QHash &configuration, void *snapd_client, QObject *parent = 0); ~QSnapdSetSnapConfRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdSetSnapConfRequest) }; class QSnapdGetAppsRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetAppsRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(int appCount READ appCount) public: explicit QSnapdGetAppsRequest(int flags, void *snapd_client, QObject *parent = 0); explicit QSnapdGetAppsRequest(int flags, const QStringList &snaps, void *snapd_client, QObject *parent = 0); ~QSnapdGetAppsRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE int appCount() const; Q_INVOKABLE QSnapdApp *app(int) const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetAppsRequest) }; class QSnapdGetIconRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetIconRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdGetIconRequest(const QString &name, void *snapd_client, QObject *parent = 0); ~QSnapdGetIconRequest(); virtual void runSync(); virtual void runAsync(); QSnapdIcon *icon() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetIconRequest) }; class QSnapdGetAssertionsRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetAssertionsRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(QStringList assertions READ assertions) public: explicit QSnapdGetAssertionsRequest(const QString &type, void *snapd_client, QObject *parent = 0); ~QSnapdGetAssertionsRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QStringList assertions() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetAssertionsRequest) }; class QSnapdAddAssertionsRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdAddAssertionsRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdAddAssertionsRequest(const QStringList &assertions, void *snapd_client, QObject *parent = 0); ~QSnapdAddAssertionsRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdAddAssertionsRequest) }; class QSnapdGetConnectionsRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetConnectionsRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(int plugCount READ plugCount) Q_PROPERTY(int slotCount READ slotCount) public: explicit QSnapdGetConnectionsRequest(int flags, const QString &snap, const QString &interface, void *snapd_client, QObject *parent = 0); ~QSnapdGetConnectionsRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE int establishedCount() const; Q_INVOKABLE QSnapdConnection *established(int) const; Q_INVOKABLE int undesiredCount() const; Q_INVOKABLE QSnapdConnection *undesired(int) const; Q_INVOKABLE int plugCount() const; Q_INVOKABLE QSnapdPlug *plug(int) const; Q_INVOKABLE int slotCount() const; Q_INVOKABLE QSnapdSlot *slot(int) const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetConnectionsRequest) }; class QSnapdGetInterfacesRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetInterfacesRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(int plugCount READ plugCount) Q_PROPERTY(int slotCount READ slotCount) public: explicit QSnapdGetInterfacesRequest(void *snapd_client, QObject *parent = 0); ~QSnapdGetInterfacesRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE int plugCount() const; Q_INVOKABLE QSnapdPlug *plug(int) const; Q_INVOKABLE int slotCount() const; Q_INVOKABLE QSnapdSlot *slot(int) const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetInterfacesRequest) }; class QSnapdGetInterfaces2RequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetInterfaces2Request : public QSnapdRequest { Q_OBJECT Q_PROPERTY(int interfaceCount READ interfaceCount) public: explicit QSnapdGetInterfaces2Request(int flags, const QStringList &names, void *snapd_client, QObject *parent = 0); ~QSnapdGetInterfaces2Request(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE int interfaceCount() const; Q_INVOKABLE QSnapdInterface *interface(int) const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetInterfaces2Request) }; class QSnapdConnectInterfaceRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdConnectInterfaceRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdConnectInterfaceRequest(const QString &plug_snap, const QString &plug_name, const QString &slot_snap, const QString &slot_name, void *snapd_client, QObject *parent = 0); ~QSnapdConnectInterfaceRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdConnectInterfaceRequest) }; class QSnapdDisconnectInterfaceRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdDisconnectInterfaceRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdDisconnectInterfaceRequest(const QString &plug_snap, const QString &plug_name, const QString &slot_snap, const QString &slot_name, void *snapd_client, QObject *parent = 0); ~QSnapdDisconnectInterfaceRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdDisconnectInterfaceRequest) }; class QSnapdFindRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdFindRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(int snapCount READ snapCount) Q_PROPERTY(QString suggestedCurrency READ suggestedCurrency) public: explicit QSnapdFindRequest(int flags, const QString §ion, const QString &category, const QString &name, void *snapd_client, QObject *parent = 0); ~QSnapdFindRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE int snapCount() const; Q_INVOKABLE QSnapdSnap *snap(int) const; const QString suggestedCurrency() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdFindRequest) }; class QSnapdFindRefreshableRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdFindRefreshableRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(int snapCount READ snapCount) public: explicit QSnapdFindRefreshableRequest(void *snapd_client, QObject *parent = 0); ~QSnapdFindRefreshableRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE int snapCount() const; Q_INVOKABLE QSnapdSnap *snap(int) const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdFindRefreshableRequest) }; class QSnapdInstallRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdInstallRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdInstallRequest(int flags, const QString &name, const QString &channel, const QString &revision, QIODevice *ioDevice, void *snapd_client, QObject *parent = 0); ~QSnapdInstallRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdInstallRequest) }; class QSnapdTryRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdTryRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdTryRequest(const QString &path, void *snapd_client, QObject *parent = 0); ~QSnapdTryRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdTryRequest) }; class QSnapdRefreshRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdRefreshRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdRefreshRequest(const QString &name, const QString &channel, void *snapd_client, QObject *parent = 0); ~QSnapdRefreshRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdRefreshRequest) }; class QSnapdRefreshAllRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdRefreshAllRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(QStringList snapNames READ snapNames) public: explicit QSnapdRefreshAllRequest(void *snapd_client, QObject *parent = 0); ~QSnapdRefreshAllRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QStringList snapNames() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdRefreshAllRequest) }; class QSnapdRemoveRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdRemoveRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdRemoveRequest(int flags, const QString &name, void *snapd_client, QObject *parent = 0); ~QSnapdRemoveRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdRemoveRequest) }; class QSnapdEnableRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdEnableRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdEnableRequest(const QString &name, void *snapd_client, QObject *parent = 0); ~QSnapdEnableRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdEnableRequest) }; class QSnapdDisableRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdDisableRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdDisableRequest(const QString &name, void *snapd_client, QObject *parent = 0); ~QSnapdDisableRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdDisableRequest) }; class QSnapdSwitchChannelRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdSwitchChannelRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdSwitchChannelRequest(const QString &name, const QString &channel, void *snapd_client, QObject *parent = 0); ~QSnapdSwitchChannelRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdSwitchChannelRequest) }; class QSnapdCheckBuyRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdCheckBuyRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(bool canBuy READ canBuy) public: explicit QSnapdCheckBuyRequest(void *snapd_client, QObject *parent = 0); ~QSnapdCheckBuyRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE bool canBuy() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdCheckBuyRequest) }; class QSnapdBuyRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdBuyRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdBuyRequest(const QString &id, double amount, const QString ¤cy, void *snapd_client, QObject *parent = 0); ~QSnapdBuyRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdBuyRequest) }; class QSnapdCreateUserRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdCreateUserRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdCreateUserRequest(const QString &email, int flags, void *snapd_client, QObject *parent = 0); ~QSnapdCreateUserRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QSnapdUserInformation *userInformation() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdCreateUserRequest) }; class QSnapdCreateUsersRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdCreateUsersRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(int userInformationCount READ userInformationCount) public: explicit QSnapdCreateUsersRequest(void *snapd_client, QObject *parent = 0); ~QSnapdCreateUsersRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE int userInformationCount() const; Q_INVOKABLE QSnapdUserInformation *userInformation(int) const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdCreateUsersRequest) }; class QSnapdGetUsersRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetUsersRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(int userInformationCount READ userInformationCount) public: explicit QSnapdGetUsersRequest(void *snapd_client, QObject *parent = 0); ~QSnapdGetUsersRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE int userInformationCount() const; Q_INVOKABLE QSnapdUserInformation *userInformation(int) const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetUsersRequest) }; class QSnapdGetSectionsRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetSectionsRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdGetSectionsRequest(void *snapd_client, QObject *parent = 0); ~QSnapdGetSectionsRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QStringList sections() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetSectionsRequest) }; class QSnapdGetCategoriesRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetCategoriesRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdGetCategoriesRequest(void *snapd_client, QObject *parent = 0); ~QSnapdGetCategoriesRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE int categoryCount() const; Q_INVOKABLE QSnapdCategoryDetails *category(int) const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetCategoriesRequest) }; class QSnapdGetAliasesRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetAliasesRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(int aliasCount READ aliasCount) public: explicit QSnapdGetAliasesRequest(void *snapd_client, QObject *parent = 0); ~QSnapdGetAliasesRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE int aliasCount() const; Q_INVOKABLE QSnapdAlias *alias(int) const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetAliasesRequest) }; class QSnapdAliasRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdAliasRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdAliasRequest(const QString &snap, const QString &app, const QString &alias, void *snapd_client, QObject *parent = 0); ~QSnapdAliasRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdAliasRequest) }; class QSnapdUnaliasRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdUnaliasRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdUnaliasRequest(const QString &snap, const QString &alias, void *snapd_client, QObject *parent = 0); ~QSnapdUnaliasRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdUnaliasRequest) }; class QSnapdPreferRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdPreferRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdPreferRequest(const QString &snap, void *snapd_client, QObject *parent = 0); ~QSnapdPreferRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdPreferRequest) }; class QSnapdEnableAliasesRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdEnableAliasesRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdEnableAliasesRequest(const QString &snap, const QStringList &aliases, void *snapd_client, QObject *parent = 0); ~QSnapdEnableAliasesRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdEnableAliasesRequest) }; class QSnapdDisableAliasesRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdDisableAliasesRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdDisableAliasesRequest(const QString &snap, const QStringList &aliases, void *snapd_client, QObject *parent = 0); ~QSnapdDisableAliasesRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdDisableAliasesRequest) }; class QSnapdResetAliasesRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdResetAliasesRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdResetAliasesRequest(const QString &snap, const QStringList &aliases, void *snapd_client, QObject *parent = 0); ~QSnapdResetAliasesRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdResetAliasesRequest) }; class QSnapdRunSnapCtlRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdRunSnapCtlRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdRunSnapCtlRequest(const QString &contextId, const QStringList &args, void *snapd_client, QObject *parent = 0); ~QSnapdRunSnapCtlRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QString stdout() const; Q_INVOKABLE QString stderr() const; Q_INVOKABLE int exitCode() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdRunSnapCtlRequest) }; class QSnapdDownloadRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdDownloadRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdDownloadRequest(const QString &name, const QString &channel, const QString &revision, void *snapd_client, QObject *parent = 0); ~QSnapdDownloadRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QByteArray data() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdDownloadRequest) }; class QSnapdCheckThemesRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdCheckThemesRequest : public QSnapdRequest { Q_OBJECT public: enum ThemeStatus { ThemeInstalled, ThemeAvailable, ThemeUnavailable }; Q_ENUM(ThemeStatus) explicit QSnapdCheckThemesRequest(const QStringList >kThemeNames, const QStringList &iconThemeNames, const QStringList &soundThemeNames, void *snapd_client, QObject *parent = 0); ~QSnapdCheckThemesRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE ThemeStatus gtkThemeStatus(const QString &name) const; Q_INVOKABLE ThemeStatus iconThemeStatus(const QString &name) const; Q_INVOKABLE ThemeStatus soundThemeStatus(const QString &name) const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdCheckThemesRequest) }; class QSnapdInstallThemesRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdInstallThemesRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdInstallThemesRequest(const QStringList >kThemeNames, const QStringList &iconThemeNames, const QStringList &soundThemeNames, void *snapd_client, QObject *parent = 0); ~QSnapdInstallThemesRequest(); virtual void runSync(); virtual void runAsync(); void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdInstallThemesRequest) }; class QSnapdNoticesRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdNoticesRequest : public QSnapdRequest { Q_OBJECT Q_PROPERTY(qint64 timeout MEMBER timeout) Q_PROPERTY(bool sinceFilterSet MEMBER sinceFilterSet) Q_PROPERTY(QDateTime sinceFilter MEMBER sinceFilter) Q_PROPERTY(QString userIdFilter MEMBER userIdFilter) Q_PROPERTY(QString usersFilter MEMBER usersFilter) Q_PROPERTY(QString keysFilter MEMBER keysFilter) Q_PROPERTY(QString typesFilter MEMBER typesFilter) Q_PROPERTY(qint32 sinceNanosecondsFilter MEMBER sinceNanosecondsFilter) public: explicit QSnapdNoticesRequest(void *snapd_client, QObject *parent = 0); ~QSnapdNoticesRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE uint noticesCount() const; Q_INVOKABLE QSnapdNotice *getNotice(quint64) const; void handleResult(void *, void *); void resetFilters(); void setSinceDateFilterFromNotice(QSnapdNotice *); void setSinceDateFilterFromDateNanoseconds(QDateTime, qint32); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdNoticesRequest) qint64 timeout; bool sinceFilterSet; QDateTime sinceFilter; QString userIdFilter; QString usersFilter; QString keysFilter; QString typesFilter; qint32 sinceNanosecondsFilter; }; class QSnapdGetModelAssertionRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetModelAssertionRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdGetModelAssertionRequest(void *snapd_client, QObject *parent = 0); ~QSnapdGetModelAssertionRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QString modelAssertion() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetModelAssertionRequest) }; class QSnapdGetSerialAssertionRequestPrivate; class LIBSNAPDQT_EXPORT QSnapdGetSerialAssertionRequest : public QSnapdRequest { Q_OBJECT public: explicit QSnapdGetSerialAssertionRequest(void *snapd_client, QObject *parent = 0); ~QSnapdGetSerialAssertionRequest(); virtual void runSync(); virtual void runAsync(); Q_INVOKABLE QString serialAssertion() const; void handleResult(void *, void *); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdGetSerialAssertionRequest) }; Q_INVOKABLE Q_DECL_DEPRECATED QSnapdLoginRequest * login(const QString &email, const QString &password); Q_INVOKABLE Q_DECL_DEPRECATED QSnapdLoginRequest * login(const QString &email, const QString &password, const QString &otp); class QSnapdClientPrivate; class LIBSNAPDQT_EXPORT QSnapdClient : public QObject { Q_OBJECT Q_PROPERTY(QString socketPath READ socketPath WRITE setSocketPath) Q_PROPERTY(QString userAgent READ userAgent WRITE setUserAgent) Q_PROPERTY( bool allowInteraction READ allowInteraction WRITE setAllowInteraction) Q_FLAGS(GetConnectionsFlags) Q_FLAGS(FindFlags) public: enum ChangeFilter { FilterAll, FilterInProgress, FilterReady }; Q_ENUM(ChangeFilter) enum GetSnapsFlag { IncludeInactive = 1 << 0, RefreshInhibited = 1 << 1 }; Q_DECLARE_FLAGS(GetSnapsFlags, GetSnapsFlag); enum GetAppsFlag { SelectServices = 1 << 0 }; Q_DECLARE_FLAGS(GetAppsFlags, GetAppsFlag); enum GetConnectionsFlag { SelectAll = 1 << 0 }; Q_DECLARE_FLAGS(GetConnectionsFlags, GetConnectionsFlag); enum FindFlag { None = 0, MatchName = 1 << 0, SelectPrivate = 1 << 1, ScopeWide = 1 << 2, MatchCommonId = 1 << 3, }; Q_DECLARE_FLAGS(FindFlags, FindFlag); enum InstallFlag { Classic = 1 << 0, Dangerous = 1 << 1, Devmode = 1 << 2, Jailmode = 1 << 3 }; Q_DECLARE_FLAGS(InstallFlags, InstallFlag); enum RemoveFlag { Purge = 1 << 0, }; Q_DECLARE_FLAGS(RemoveFlags, RemoveFlag); enum CreateUserFlag { Sudo = 1 << 0, Known = 1 << 1 }; Q_DECLARE_FLAGS(CreateUserFlags, CreateUserFlag); enum InterfaceFlag { IncludeDocs = 1 << 1, IncludePlugs = 1 << 2, IncludeSlots = 1 << 3, OnlyConnected = 1 << 4 }; Q_DECLARE_FLAGS(InterfaceFlags, InterfaceFlag); explicit QSnapdClient(QObject *parent = 0); explicit QSnapdClient(int fd, QObject *parent = 0); virtual ~QSnapdClient(); Q_INVOKABLE Q_DECL_DEPRECATED QSnapdConnectRequest *connect(); Q_INVOKABLE QSnapdLoginRequest *login(const QString &email, const QString &password); Q_INVOKABLE QSnapdLoginRequest * login(const QString &email, const QString &password, const QString &otp); Q_INVOKABLE QSnapdLogoutRequest *logout(qint64 id); Q_INVOKABLE void setSocketPath(const QString &socketPath); Q_INVOKABLE QString socketPath() const; Q_INVOKABLE void setUserAgent(const QString &userAgent); Q_INVOKABLE QString userAgent() const; Q_INVOKABLE void setAllowInteraction(bool allowInteraction); Q_INVOKABLE bool allowInteraction() const; Q_INVOKABLE QSnapdMaintenance *maintenance() const; Q_INVOKABLE void setAuthData(QSnapdAuthData *authData); Q_INVOKABLE QSnapdAuthData *authData(); Q_INVOKABLE QSnapdGetChangesRequest *getChanges(); Q_INVOKABLE QSnapdGetChangesRequest *getChanges(ChangeFilter filter); Q_INVOKABLE QSnapdGetChangesRequest *getChanges(const QString &snapName); Q_INVOKABLE QSnapdGetChangesRequest *getChanges(ChangeFilter filter, const QString &snapName); Q_INVOKABLE QSnapdGetChangeRequest *getChange(const QString &id); Q_INVOKABLE QSnapdAbortChangeRequest *abortChange(const QString &id); Q_INVOKABLE QSnapdGetSystemInformationRequest *getSystemInformation(); Q_INVOKABLE Q_DECL_DEPRECATED_X("Use getSnaps()") QSnapdListRequest *list(); Q_INVOKABLE QSnapdGetSnapsRequest *getSnaps(GetSnapsFlags flags, const QStringList &snaps); Q_INVOKABLE QSnapdGetSnapsRequest *getSnaps(GetSnapsFlags flags, const QString &snap); Q_INVOKABLE QSnapdGetSnapsRequest *getSnaps(const QStringList &snaps); Q_INVOKABLE QSnapdGetSnapsRequest *getSnaps(const QString &snap); Q_INVOKABLE QSnapdGetSnapsRequest *getSnaps(); Q_INVOKABLE Q_DECL_DEPRECATED_X("Use getSnap()") QSnapdListOneRequest *listOne(const QString &name); Q_INVOKABLE QSnapdGetSnapRequest *getSnap(const QString &name); Q_INVOKABLE QSnapdGetSnapConfRequest *getSnapConf(const QString &name); Q_INVOKABLE QSnapdGetSnapConfRequest *getSnapConf(const QString &name, const QStringList &keys); Q_INVOKABLE QSnapdSetSnapConfRequest * setSnapConf(const QString &name, const QHash &configuration); Q_INVOKABLE QSnapdGetAppsRequest *getApps(); Q_INVOKABLE QSnapdGetAppsRequest *getApps(GetAppsFlags flags); Q_INVOKABLE QSnapdGetAppsRequest *getApps(GetAppsFlags flags, const QStringList &snaps); Q_INVOKABLE QSnapdGetAppsRequest *getApps(GetAppsFlags flags, const QString &snap); Q_INVOKABLE QSnapdGetAppsRequest *getApps(const QStringList &snaps); Q_INVOKABLE QSnapdGetAppsRequest *getApps(const QString &snap); Q_INVOKABLE QSnapdGetIconRequest *getIcon(const QString &name); Q_INVOKABLE QSnapdGetAssertionsRequest *getAssertions(const QString &type); Q_INVOKABLE QSnapdAddAssertionsRequest * addAssertions(const QStringList &assertions); Q_INVOKABLE QSnapdGetConnectionsRequest *getConnections(); Q_INVOKABLE QSnapdGetConnectionsRequest * getConnections(GetConnectionsFlags flags); Q_INVOKABLE QSnapdGetConnectionsRequest * getConnections(const QString &snap, const QString &interface); Q_INVOKABLE QSnapdGetConnectionsRequest * getConnections(GetConnectionsFlags flags, const QString &snap, const QString &interface); Q_INVOKABLE QSnapdGetInterfacesRequest *getInterfaces(); Q_INVOKABLE QSnapdGetInterfaces2Request *getInterfaces2(); Q_INVOKABLE QSnapdGetInterfaces2Request *getInterfaces2(InterfaceFlags flags); Q_INVOKABLE QSnapdGetInterfaces2Request * getInterfaces2(const QStringList &names); Q_INVOKABLE QSnapdGetInterfaces2Request * getInterfaces2(InterfaceFlags flags, const QStringList &names); Q_INVOKABLE QSnapdConnectInterfaceRequest * connectInterface(const QString &plug_snap, const QString &plug_name, const QString &slot_snap, const QString &slot_name); Q_INVOKABLE QSnapdDisconnectInterfaceRequest * disconnectInterface(const QString &plug_snap, const QString &plug_name, const QString &slot_snap, const QString &slot_name); Q_INVOKABLE QSnapdFindRequest *find(const QString &query); Q_INVOKABLE QSnapdFindRequest *find(FindFlags flags); Q_INVOKABLE QSnapdFindRequest *find(FindFlags flags, const QString &query); Q_INVOKABLE Q_DECL_DEPRECATED_X("Use findCategory()") QSnapdFindRequest *findSection(const QString §ion, const QString &query); Q_INVOKABLE Q_DECL_DEPRECATED_X("Use findCategory()") QSnapdFindRequest *findSection(FindFlags flags, const QString §ion, const QString &query); Q_INVOKABLE QSnapdFindRequest *findCategory(const QString &category, const QString &query); Q_INVOKABLE QSnapdFindRequest * findCategory(FindFlags flags, const QString &category, const QString &query); Q_INVOKABLE QSnapdFindRefreshableRequest *findRefreshable(); Q_INVOKABLE QSnapdInstallRequest *install(const QString &name); Q_INVOKABLE QSnapdInstallRequest *install(const QString &name, const QString &channel); Q_INVOKABLE QSnapdInstallRequest * install(const QString &name, const QString &channel, const QString &revision); Q_INVOKABLE QSnapdInstallRequest *install(InstallFlags flags, const QString &name); Q_INVOKABLE QSnapdInstallRequest * install(InstallFlags flags, const QString &name, const QString &channel); Q_INVOKABLE QSnapdInstallRequest *install(InstallFlags flags, const QString &name, const QString &channel, const QString &revision); Q_INVOKABLE QSnapdInstallRequest *install(QIODevice *ioDevice); Q_INVOKABLE QSnapdInstallRequest *install(InstallFlags flags, QIODevice *ioDevice); Q_INVOKABLE QSnapdTryRequest *trySnap(const QString &path); Q_INVOKABLE QSnapdRefreshRequest *refresh(const QString &name); Q_INVOKABLE QSnapdRefreshRequest *refresh(const QString &name, const QString &channel); Q_INVOKABLE QSnapdRefreshAllRequest *refreshAll(); Q_INVOKABLE QSnapdRemoveRequest *remove(const QString &name); Q_INVOKABLE QSnapdRemoveRequest *remove(RemoveFlags flags, const QString &name); Q_INVOKABLE QSnapdEnableRequest *enable(const QString &name); Q_INVOKABLE QSnapdDisableRequest *disable(const QString &name); Q_INVOKABLE QSnapdSwitchChannelRequest *switchChannel(const QString &name, const QString &channel); Q_INVOKABLE QSnapdCheckBuyRequest *checkBuy(); Q_INVOKABLE QSnapdBuyRequest *buy(const QString &id, double amount, const QString ¤cy); Q_INVOKABLE QSnapdCreateUserRequest *createUser(const QString &email); Q_INVOKABLE QSnapdCreateUserRequest *createUser(const QString &email, CreateUserFlags flags); Q_INVOKABLE QSnapdCreateUsersRequest *createUsers(); Q_INVOKABLE QSnapdGetUsersRequest *getUsers(); Q_INVOKABLE Q_DECL_DEPRECATED_X("Use getCategories()") QSnapdGetSectionsRequest *getSections(); Q_INVOKABLE QSnapdGetCategoriesRequest *getCategories(); Q_INVOKABLE QSnapdGetAliasesRequest *getAliases(); Q_INVOKABLE QSnapdAliasRequest *alias(const QString &snap, const QString &app, const QString &alias); Q_INVOKABLE QSnapdUnaliasRequest *unalias(const QString &snap, const QString &alias); Q_INVOKABLE QSnapdUnaliasRequest *unalias(const QString &alias); Q_INVOKABLE QSnapdPreferRequest *prefer(const QString &snap); Q_INVOKABLE Q_DECL_DEPRECATED QSnapdEnableAliasesRequest * enableAliases(const QString snap, const QStringList &aliases); Q_INVOKABLE Q_DECL_DEPRECATED QSnapdDisableAliasesRequest * disableAliases(const QString snap, const QStringList &aliases); Q_INVOKABLE Q_DECL_DEPRECATED QSnapdResetAliasesRequest * resetAliases(const QString snap, const QStringList &aliases); Q_INVOKABLE QSnapdRunSnapCtlRequest *runSnapCtl(const QString contextId, const QStringList &args); Q_INVOKABLE QSnapdDownloadRequest *download(const QString &name); Q_INVOKABLE QSnapdDownloadRequest *download(const QString &name, const QString &channel, const QString &revision); Q_INVOKABLE QSnapdCheckThemesRequest * checkThemes(const QStringList >kThemeNames, const QStringList &iconThemeNames, const QStringList &soundThemeNames); Q_INVOKABLE QSnapdInstallThemesRequest * installThemes(const QStringList >kThemeNames, const QStringList &iconThemeNames, const QStringList &soundThemeNames); Q_INVOKABLE QSnapdNoticesRequest *getNotices(); Q_INVOKABLE QSnapdGetModelAssertionRequest *getModelAssertion(); Q_INVOKABLE QSnapdGetSerialAssertionRequest *getSerialAssertion(); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdClient) }; Q_DECLARE_OPERATORS_FOR_FLAGS(QSnapdClient::GetAppsFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(QSnapdClient::FindFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(QSnapdClient::InstallFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(QSnapdClient::RemoveFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(QSnapdClient::CreateUserFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(QSnapdClient::InterfaceFlags) #endif snapd-glib-1.67/snapd-qt/Snapd/connection.h000066400000000000000000000030551477073115000206030ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_CONNECTION_H #define SNAPD_CONNECTION_H #include #include #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdConnection : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QSnapdSlotRef slot READ slot) Q_PROPERTY(QSnapdPlugRef plug READ plug) Q_PROPERTY(QString interface READ interface) Q_PROPERTY(bool manual READ manual) Q_PROPERTY(bool gadget READ gadget) Q_PROPERTY(QString name READ name) Q_PROPERTY(QString snap READ snap) public: explicit QSnapdConnection(void *snapd_object, QObject *parent = 0); QSnapdSlotRef *slot() const; QSnapdPlugRef *plug() const; QString interface() const; bool manual() const; bool gadget() const; Q_INVOKABLE QStringList slotAttributeNames() const; Q_INVOKABLE bool hasSlotAttribute(const QString &name) const; Q_INVOKABLE QVariant slotAttribute(const QString &name) const; Q_INVOKABLE QStringList plugAttributeNames() const; Q_INVOKABLE bool hasPlugAttribute(const QString &name) const; Q_INVOKABLE QVariant plugAttribute(const QString &name) const; QString name() const; QString snap() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/enums.h000066400000000000000000000041311477073115000175670ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_ENUMS_H #define SNAPD_ENUMS_H #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdEnums : public QObject { Q_OBJECT public: enum AliasStatus { AliasStatusUnknown, AliasStatusDefault, AliasStatusEnabled, AliasStatusDisabled, AliasStatusAuto, AliasStatusManual }; Q_ENUM(AliasStatus) enum DaemonType { DaemonTypeNone, DaemonTypeUnknown, DaemonTypeSimple, DaemonTypeForking, DaemonTypeOneshot, DaemonTypeDbus, DaemonTypeNotify }; Q_ENUM(DaemonType) enum SnapConfinement { SnapConfinementUnknown, SnapConfinementStrict, SnapConfinementDevmode, SnapConfinementClassic }; Q_ENUM(SnapConfinement) enum SnapType { SnapTypeUnknown, SnapTypeApp, SnapTypeKernel, SnapTypeGadget, SnapTypeOperatingSystem, SnapTypeCore, SnapTypeBase, SnapTypeSnapd }; Q_ENUM(SnapType) enum SnapStatus { SnapStatusUnknown, SnapStatusAvailable, SnapStatusPriced, SnapStatusInstalled, SnapStatusActive }; Q_ENUM(SnapStatus) enum SystemConfinement { SystemConfinementUnknown, SystemConfinementStrict, SystemConfinementPartial }; Q_ENUM(SystemConfinement) enum PublisherValidation { PublisherValidationUnknown, PublisherValidationUnproven, PublisherValidationVerified, PublisherValidationStarred }; Q_ENUM(PublisherValidation) enum MaintenanceKind { MaintenanceKindUnknown, MaintenanceKindDaemonRestart, MaintenanceKindSystemRestart }; Q_ENUM(MaintenanceKind) enum SnapNoticeType { SnapNoticeTypeUnknown, SnapNoticeTypeChangeUpdate, SnapNoticeTypeRefreshInhibit, SnapNoticeTypeSnapRunInhibit }; Q_ENUM(SnapNoticeType) }; #endif snapd-glib-1.67/snapd-qt/Snapd/icon.h000066400000000000000000000014221477073115000173700ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_ICON_H #define SNAPD_ICON_H #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdIcon : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString mimeType READ mimeType) Q_PROPERTY(QByteArray data READ data) public: explicit QSnapdIcon(void *snapd_object, QObject *parent = 0); QString mimeType() const; QByteArray data() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/interface.h000066400000000000000000000022231477073115000204000ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_INTERFACE_H #define SNAPD_INTERFACE_H #include #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdInterface : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString name READ name) Q_PROPERTY(QString summary READ summary) Q_PROPERTY(QString docUrl READ docUrl) Q_PROPERTY(int plugCount READ plugCount) Q_PROPERTY(int slotCount READ slotCount) public: explicit QSnapdInterface(void *snapd_object, QObject *parent = 0); QString name() const; QString summary() const; QString docUrl() const; int plugCount() const; Q_INVOKABLE QSnapdPlug *plug(int) const; int slotCount() const; Q_INVOKABLE QSnapdSlot *slot(int) const; Q_INVOKABLE QString makeLabel() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/maintenance.h000066400000000000000000000015461477073115000207310ustar00rootroot00000000000000/* * Copyright (C) 2018 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_MAINTENANCE_H #define SNAPD_MAINTENANCE_H #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdMaintenance : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QSnapdEnums::MaintenanceKind kind READ kind) Q_PROPERTY(QString message READ message) public: explicit QSnapdMaintenance(void *snapd_object, QObject *parent = 0); QSnapdEnums::MaintenanceKind kind() const; QString message() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/markdown-node.h000066400000000000000000000023621477073115000212110ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_MARKDOWN_NODE_H #define SNAPD_MARKDOWN_NODE_H #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdMarkdownNode : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(NodeType type READ type) Q_PROPERTY(QString text READ text) public: enum NodeType { NodeTypeText, NodeTypeParagraph, NodeTypeUnorderedList, NodeTypeListItem, NodeTypeCodeBlock, NodeTypeCodeSpan, NodeTypeEmphasis, NodeTypeStrongEmphasis, NodeTypeUrl, }; Q_ENUM(NodeType) explicit QSnapdMarkdownNode(void *snapd_object, QObject *parent = 0); explicit QSnapdMarkdownNode(const QSnapdMarkdownNode &node); QSnapdMarkdownNode &operator=(const QSnapdMarkdownNode &node); NodeType type() const; QString text() const; Q_INVOKABLE int childCount() const; Q_INVOKABLE QSnapdMarkdownNode *child(int) const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/markdown-parser.h000066400000000000000000000023071477073115000215570ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_MARKDOWN_PARSER_H #define SNAPD_MARKDOWN_PARSER_H #include #include #include class QSnapdMarkdownParserPrivate; #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdMarkdownParser : public QObject { Q_OBJECT Q_PROPERTY(bool preserveWhitespace READ preserveWhitespace WRITE setPreserveWhitespace) public: enum MarkdownVersion { MarkdownVersion0, }; Q_ENUM(MarkdownVersion) explicit QSnapdMarkdownParser(MarkdownVersion version, QObject *parent = 0); ~QSnapdMarkdownParser(); void setPreserveWhitespace(bool preserveWhitespace) const; bool preserveWhitespace() const; QList parse(const QString &text) const; private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdMarkdownParser) }; #endif snapd-glib-1.67/snapd-qt/Snapd/media.h000066400000000000000000000016061477073115000175230ustar00rootroot00000000000000/* * Copyright (C) 2018 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_MEDIA_H #define SNAPD_MEDIA_H #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdMedia : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString type READ type) Q_PROPERTY(QString url READ url) Q_PROPERTY(quint64 width READ width); Q_PROPERTY(quint64 height READ height); public: explicit QSnapdMedia(void *snapd_object, QObject *parent = 0); QString type() const; QString url() const; quint64 width() const; quint64 height() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/notice.h000066400000000000000000000034721477073115000177300ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_NOTICE_H #define SNAPD_NOTICE_H #include #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdNotice : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString id READ id CONSTANT) Q_PROPERTY(QString userId READ userId CONSTANT) Q_PROPERTY(QSnapdEnums::SnapNoticeType noticeType READ noticeType CONSTANT) Q_PROPERTY(QString key READ key CONSTANT) Q_PROPERTY(QDateTime firstOccurred READ firstOccurred CONSTANT) Q_PROPERTY(QDateTime lastOccurred READ lastOccurred CONSTANT) Q_PROPERTY(QDateTime lastRepeated READ lastRepeated CONSTANT) Q_PROPERTY(qint32 occurrences READ occurrences CONSTANT) Q_PROPERTY(qint64 repeatAfter READ repeatAfter CONSTANT) Q_PROPERTY(qint64 expireAfter READ expireAfter CONSTANT) Q_PROPERTY(QHash lastData READ lastData CONSTANT) Q_PROPERTY( qint32 lastOccurredNanoseconds READ lastOccurredNanoseconds CONSTANT) public: explicit QSnapdNotice(void *snapd_object, QObject *parent = 0); QString id() const; QString userId() const; QSnapdEnums::SnapNoticeType noticeType() const; QString key() const; QDateTime firstOccurred() const; QDateTime lastOccurred() const; QDateTime lastRepeated() const; qint32 occurrences() const; qint64 repeatAfter() const; qint64 expireAfter() const; QHash lastData() const; qint32 lastOccurredNanoseconds() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/plug-ref.h000066400000000000000000000014161477073115000201640ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_PLUG_REF_H #define SNAPD_PLUG_REF_H #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdPlugRef : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString plug READ plug) Q_PROPERTY(QString snap READ snap) public: explicit QSnapdPlugRef(void *snapd_object, QObject *parent = 0); QString plug() const; QString snap() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/plug.h000066400000000000000000000027601477073115000174150ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_PLUG_H #define SNAPD_PLUG_H #include #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdPlug : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString name READ name) Q_PROPERTY(QString snap READ snap) Q_PROPERTY(QString interface READ interface) Q_PROPERTY(QString label READ label) Q_PROPERTY(int connectionCount READ connectionCount) Q_PROPERTY(int connectedSlotCount READ connectedSlotCount) public: explicit QSnapdPlug(void *snapd_object, QObject *parent = 0); QString name() const; QString snap() const; QString interface() const; Q_INVOKABLE QStringList attributeNames() const; Q_INVOKABLE bool hasAttribute(const QString &name) const; Q_INVOKABLE QVariant attribute(const QString &name) const; QString label() const; Q_DECL_DEPRECATED_X("Use connectedSlotCount()") int connectionCount() const; Q_INVOKABLE Q_DECL_DEPRECATED_X("Use connectedSlot()") QSnapdConnection *connection(int) const; int connectedSlotCount() const; Q_INVOKABLE QSnapdSlotRef *connectedSlot(int) const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/price.h000066400000000000000000000014241477073115000175440ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_PRICE_H #define SNAPD_PRICE_H #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdPrice : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(double amount READ amount) Q_PROPERTY(QString currency READ currency) public: explicit QSnapdPrice(void *snapd_object, QObject *parent = 0); double amount() const; QString currency() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/request.h000066400000000000000000000042671477073115000201420ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_REQUEST_H #define SNAPD_REQUEST_H #include #include #include class QSnapdRequestPrivate; #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdRequest : public QObject { Q_OBJECT Q_PROPERTY(bool isFinished READ isFinished) Q_PROPERTY(QSnapdError error READ error) Q_PROPERTY(QString errorString READ errorString) Q_PROPERTY(QSnapdChange change READ change) public: enum QSnapdError { NoError, UnknownError, ConnectionFailed, WriteFailed, ReadFailed, BadRequest, BadResponse, AuthDataRequired, AuthDataInvalid, TwoFactorRequired, TwoFactorInvalid, PermissionDenied, Failed, TermsNotAccepted, PaymentNotSetup, PaymentDeclined, AlreadyInstalled, NotInstalled, NoUpdateAvailable, PasswordPolicyError, NeedsDevmode, NeedsClassic, NeedsClassicSystem, Cancelled, BadQuery, NetworkTimeout, NotFound, NotInStore, AuthCancelled, NotClassic, RevisionNotAvailable, ChannelNotAvailable, NotASnap, DNSFailure, OptionNotFound, AppNotFound, ArchitectureNotAvailable, ChangeConflict, InterfacesUnchanged }; Q_ENUM(QSnapdError) explicit QSnapdRequest(void *snapd_client, QObject *parent = 0); ~QSnapdRequest(); bool isFinished() const; QSnapdError error() const; QString errorString() const; Q_INVOKABLE virtual void runSync() = 0; Q_INVOKABLE virtual void runAsync() = 0; Q_INVOKABLE void cancel(); Q_INVOKABLE QSnapdChange *change() const; void handleProgress(void *); protected: void *getClient() const; void *getCancellable() const; void finish(void *error); Q_SIGNALS: void progress(); void complete(); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QSnapdRequest); }; #endif snapd-glib-1.67/snapd-qt/Snapd/screenshot.h000066400000000000000000000015351477073115000206220ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_SCREENSHOT_H #define SNAPD_SCREENSHOT_H #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdScreenshot : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString url READ url) Q_PROPERTY(quint64 width READ width); Q_PROPERTY(quint64 height READ height); public: explicit QSnapdScreenshot(void *snapd_object, QObject *parent = 0); QString url() const; quint64 width() const; quint64 height() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/slot-ref.h000066400000000000000000000014161477073115000201760ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_SLOT_REF_H #define SNAPD_SLOT_REF_H #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdSlotRef : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString slot READ slot) Q_PROPERTY(QString snap READ snap) public: explicit QSnapdSlotRef(void *snapd_object, QObject *parent = 0); QString slot() const; QString snap() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/slot.h000066400000000000000000000027601477073115000174270ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_SLOT_H #define SNAPD_SLOT_H #include #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdSlot : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString name READ name) Q_PROPERTY(QString snap READ snap) Q_PROPERTY(QString interface READ interface) Q_PROPERTY(QString label READ label) Q_PROPERTY(int connectionCount READ connectionCount) Q_PROPERTY(int connectedPlugCount READ connectedPlugCount) public: explicit QSnapdSlot(void *snapd_object, QObject *parent = 0); QString name() const; QString snap() const; QString interface() const; Q_INVOKABLE QStringList attributeNames() const; Q_INVOKABLE bool hasAttribute(const QString &name) const; Q_INVOKABLE QVariant attribute(const QString &name) const; QString label() const; Q_DECL_DEPRECATED_X("Use connectedPlugCount()") int connectionCount() const; Q_INVOKABLE Q_DECL_DEPRECATED_X("Use connectedPlug()") QSnapdConnection *connection(int) const; int connectedPlugCount() const; Q_INVOKABLE QSnapdPlugRef *connectedPlug(int) const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/snap.h000066400000000000000000000106711477073115000174070ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_SNAP_H #define SNAPD_SNAP_H #include #include #include #include #include #include #include #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdSnap : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(int appCount READ appCount) Q_PROPERTY(QString base READ base) Q_PROPERTY(QString broken READ broken) Q_PROPERTY(int categoryCount READ categoryCount) Q_PROPERTY(QString channel READ channel) Q_PROPERTY(int channelCount READ channelCount) Q_PROPERTY(QStringList commonIds READ commonIds) Q_PROPERTY(QSnapdEnums::SnapConfinement confinement READ confinement) Q_PROPERTY(QString contact READ contact) Q_PROPERTY(QString description READ description) Q_PROPERTY(QString developer READ developer) Q_PROPERTY(bool devmode READ devmode) Q_PROPERTY(qint64 downloadSize READ downloadSize) Q_PROPERTY(QDateTime hold READ hold) Q_PROPERTY(QDateTime proceedTime READ proceedTime) Q_PROPERTY(QString icon READ icon) Q_PROPERTY(QString id READ id) Q_PROPERTY(QDateTime installDate READ installDate) Q_PROPERTY(qint64 installedSize READ installedSize) Q_PROPERTY(bool jailmode READ jailmode) Q_PROPERTY(QString license READ license) Q_PROPERTY(QString mountedFrom READ mountedFrom) Q_PROPERTY(QString name READ name) Q_PROPERTY(int priceCount READ priceCount) Q_PROPERTY(bool isPrivate READ isPrivate) Q_PROPERTY(QString publisherDisplayName READ publisherDisplayName) Q_PROPERTY(QString publisherId READ publisherId) Q_PROPERTY(QString publisherUsername READ publisherUsername) Q_PROPERTY(QSnapdEnums::PublisherValidation publisherValidation READ publisherValidation) Q_PROPERTY(QString revision READ revision) Q_PROPERTY(QSnapdEnums::SnapType snapType READ snapType) Q_PROPERTY(QSnapdEnums::SnapStatus status READ status) Q_PROPERTY(QString storeUrl READ summary) Q_PROPERTY(QString summary READ summary) Q_PROPERTY(QString title READ title) Q_PROPERTY(QString trackingChannel READ trackingChannel) Q_PROPERTY(QStringList tracks READ tracks) Q_PROPERTY(bool trymode READ trymode) Q_PROPERTY(QString version READ version) Q_PROPERTY(QString website READ website) public: explicit QSnapdSnap(void *snapd_object, QObject *parent = 0); int appCount() const; Q_INVOKABLE QSnapdApp *app(int) const; QString base() const; QString broken() const; int categoryCount() const; Q_INVOKABLE QSnapdCategory *category(int) const; QString channel() const; int channelCount() const; Q_INVOKABLE QSnapdChannel *channel(int) const; Q_INVOKABLE QSnapdChannel *matchChannel(const QString &) const; QStringList commonIds() const; QSnapdEnums::SnapConfinement confinement() const; QString contact() const; QString description() const; Q_DECL_DEPRECATED_X("Use publisherUsername()") QString developer() const; bool devmode() const; qint64 downloadSize() const; QDateTime hold() const; QDateTime proceedTime() const; QString icon() const; QString id() const; QDateTime installDate() const; qint64 installedSize() const; bool jailmode() const; QString license() const; int mediaCount() const; Q_INVOKABLE QSnapdMedia *media(int) const; QString mountedFrom() const; QString name() const; int priceCount() const; Q_INVOKABLE QSnapdPrice *price(int) const; bool isPrivate() const; QString publisherDisplayName() const; QString publisherId() const; QString publisherUsername() const; QSnapdEnums::PublisherValidation publisherValidation() const; QString revision() const; Q_DECL_DEPRECATED_X("Use mediaCount()") int screenshotCount() const; Q_DECL_DEPRECATED_X("Use media()") QSnapdScreenshot *screenshot(int) const; QSnapdEnums::SnapType snapType() const; QSnapdEnums::SnapStatus status() const; QString storeUrl() const; QString summary() const; QString title() const; QString trackingChannel() const; QStringList tracks() const; bool trymode() const; QString version() const; QString website() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/snapdqt_global.h000066400000000000000000000010131477073115000214260ustar00rootroot00000000000000/* * Copyright (C) 2025 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #if defined(LIBSNAPDQT) #define LIBSNAPDQT_EXPORT __attribute__((visibility("default"))) #else #define LIBSNAPDQT_EXPORT Q_DECL_IMPORT #endif snapd-glib-1.67/snapd-qt/Snapd/system-information.h000066400000000000000000000043601477073115000223130ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_SYSTEM_INFORMATION_H #define SNAPD_SYSTEM_INFORMATION_H #include #include #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdSystemInformation : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString binariesDirectory READ binariesDirectory) Q_PROPERTY(QString buildId READ buildId) Q_PROPERTY(QSnapdEnums::SystemConfinement confinement READ confinement) Q_PROPERTY(QString kernelVersion READ kernelVersion) Q_PROPERTY(bool managed READ managed) Q_PROPERTY(QString mountDirectory READ mountDirectory) Q_PROPERTY(bool onClassic READ onClassic) Q_PROPERTY(QString osId READ osId) Q_PROPERTY(QString osVersion READ osVersion) Q_PROPERTY(QDateTime refreshHold READ refreshHold) Q_PROPERTY(QDateTime refreshLast READ refreshLast) Q_PROPERTY(QDateTime refreshNext READ refreshNext) Q_PROPERTY(QString refreshSchedule READ refreshSchedule) Q_PROPERTY(QString refreshTimer READ refreshTimer) Q_PROPERTY(QHash sandboxFeatures READ sandboxFeatures) Q_PROPERTY(QString series READ series) Q_PROPERTY(QString store READ store) Q_PROPERTY(QString version READ version) public: explicit QSnapdSystemInformation(void *snapd_object, QObject *parent = 0); QString binariesDirectory() const; QString buildId() const; QSnapdEnums::SystemConfinement confinement() const; QString kernelVersion() const; bool managed() const; QString mountDirectory() const; bool onClassic() const; QString osId() const; QString osVersion() const; QDateTime refreshHold() const; QDateTime refreshLast() const; QDateTime refreshNext() const; QString refreshSchedule() const; QString refreshTimer() const; QHash sandboxFeatures() const; QString series() const; QString store() const; QString version() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/task-data.h000066400000000000000000000014421477073115000203130ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_TASK_DATA_H #define SNAPD_TASK_DATA_H #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdTaskData : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QStringList affectedSnaps READ affectedSnaps) public: explicit QSnapdTaskData(void *snapd_object, QObject *parent = 0); Q_INVOKABLE QStringList affectedSnaps() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/task.h000066400000000000000000000030551477073115000174060ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_TASK_H #define SNAPD_TASK_H #include #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdTask : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(QString id READ id) Q_PROPERTY(QString kind READ kind) Q_PROPERTY(QString summary READ summary) Q_PROPERTY(QString status READ status) Q_PROPERTY(QString progressLabel READ progressLabel) Q_PROPERTY(qint64 progressDone READ progressDone) Q_PROPERTY(qint64 progressTotal READ progressTotal) Q_PROPERTY(QDateTime spawnTime READ spawnTime) Q_PROPERTY(QDateTime readyTime READ readyTime) Q_PROPERTY(QSnapdTaskData taskData READ taskData) public: explicit QSnapdTask(void *snapd_object, QObject *parent = 0); Q_INVOKABLE QString id() const; Q_INVOKABLE QString kind() const; Q_INVOKABLE QString summary() const; Q_INVOKABLE QString status() const; Q_INVOKABLE QString progressLabel() const; Q_INVOKABLE qint64 progressDone() const; Q_INVOKABLE qint64 progressTotal() const; Q_INVOKABLE QDateTime spawnTime() const; Q_INVOKABLE QDateTime readyTime() const; Q_INVOKABLE QSnapdTaskData *taskData() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/user-information.h000066400000000000000000000020551477073115000217440ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_USER_INFORMATION_H #define SNAPD_USER_INFORMATION_H #include #include #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdUserInformation : public QSnapdWrappedObject { Q_OBJECT Q_PROPERTY(int id READ id) Q_PROPERTY(QString username READ username) Q_PROPERTY(QString email READ email) Q_PROPERTY(QStringList sshKeys READ sshKeys) Q_PROPERTY(QSnapdAuthData *authData READ authData) public: explicit QSnapdUserInformation(void *snapd_object, QObject *parent = 0); int id() const; QString username() const; QString email() const; QStringList sshKeys() const; QSnapdAuthData *authData() const; }; #endif snapd-glib-1.67/snapd-qt/Snapd/wrapped-object.h000066400000000000000000000016671477073115000213610ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_WRAPPED_OBJECT_H #define SNAPD_WRAPPED_OBJECT_H #include #include "snapdqt_global.h" class LIBSNAPDQT_EXPORT QSnapdWrappedObject : public QObject { Q_OBJECT public: explicit QSnapdWrappedObject(void *object, void (*unref_func)(void *), QObject *parent = 0) : QObject(parent), wrapped_object(object), unref_func(unref_func) {} ~QSnapdWrappedObject() { unref_func(wrapped_object); } void *wrappedObject() { return wrapped_object; } protected: void *wrapped_object; private: void (*unref_func)(void *); }; #endif snapd-glib-1.67/snapd-qt/SnapdQt5Config.cmake.in000066400000000000000000000010261477073115000214160ustar00rootroot00000000000000# SNAPD_INCLUDE_DIRS - The snapd-qt include directories # SNAPD_LIBRARIES - The libraries needed to use snapd-qt set(SNAPD_LIBRARIES @libdir@/lib@library_name@.so) set(SNAPD_INCLUDE_DIRS @includedir@/@library_name@/) add_library(Snapd::Core SHARED IMPORTED) set_target_properties(Snapd::Core PROPERTIES IMPORTED_LINK_DEPENDENT_LIBRARIES "Qt5::Core" IMPORTED_LOCATION "${SNAPD_LIBRARIES}" IMPORTED_SONAME "lib@library_name@.so" ) set_property(TARGET Snapd::Core PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${SNAPD_INCLUDE_DIRS}) snapd-glib-1.67/snapd-qt/SnapdQt5ConfigVersion.cmake.in000066400000000000000000000007341477073115000227710ustar00rootroot00000000000000set(PACKAGE_VERSION @version@) if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) set(PACKAGE_VERSION_COMPATIBLE FALSE) else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) set(PACKAGE_VERSION_COMPATIBLE TRUE) if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") set(PACKAGE_VERSION_EXACT TRUE) endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) snapd-glib-1.67/snapd-qt/SnapdQt6Config.cmake.in000066400000000000000000000010261477073115000214170ustar00rootroot00000000000000# SNAPD_INCLUDE_DIRS - The snapd-qt include directories # SNAPD_LIBRARIES - The libraries needed to use snapd-qt set(SNAPD_LIBRARIES @libdir@/lib@library_name@.so) set(SNAPD_INCLUDE_DIRS @includedir@/@library_name@/) add_library(Snapd::Core SHARED IMPORTED) set_target_properties(Snapd::Core PROPERTIES IMPORTED_LINK_DEPENDENT_LIBRARIES "Qt6::Core" IMPORTED_LOCATION "${SNAPD_LIBRARIES}" IMPORTED_SONAME "lib@library_name@.so" ) set_property(TARGET Snapd::Core PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${SNAPD_INCLUDE_DIRS}) snapd-glib-1.67/snapd-qt/SnapdQt6ConfigVersion.cmake.in000066400000000000000000000007341477073115000227720ustar00rootroot00000000000000set(PACKAGE_VERSION @version@) if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) set(PACKAGE_VERSION_COMPATIBLE FALSE) else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) set(PACKAGE_VERSION_COMPATIBLE TRUE) if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") set(PACKAGE_VERSION_EXACT TRUE) endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) snapd-glib-1.67/snapd-qt/alias.cpp000066400000000000000000000034721477073115000170260ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/alias.h" QSnapdAlias::QSnapdAlias(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdAlias::app() const { G_GNUC_BEGIN_IGNORE_DEPRECATIONS return snapd_alias_get_app(SNAPD_ALIAS(wrapped_object)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS } QString QSnapdAlias::appAuto() const { return snapd_alias_get_app_auto(SNAPD_ALIAS(wrapped_object)); } QString QSnapdAlias::command() const { return snapd_alias_get_command(SNAPD_ALIAS(wrapped_object)); } QString QSnapdAlias::appManual() const { return snapd_alias_get_app_manual(SNAPD_ALIAS(wrapped_object)); } QString QSnapdAlias::name() const { return snapd_alias_get_name(SNAPD_ALIAS(wrapped_object)); } QString QSnapdAlias::snap() const { return snapd_alias_get_snap(SNAPD_ALIAS(wrapped_object)); } QSnapdEnums::AliasStatus QSnapdAlias::status() const { switch (snapd_alias_get_status(SNAPD_ALIAS(wrapped_object))) { default: case SNAPD_ALIAS_STATUS_UNKNOWN: return QSnapdEnums::AliasStatusUnknown; case SNAPD_ALIAS_STATUS_DEFAULT: return QSnapdEnums::AliasStatusDefault; case SNAPD_ALIAS_STATUS_ENABLED: return QSnapdEnums::AliasStatusEnabled; case SNAPD_ALIAS_STATUS_DISABLED: return QSnapdEnums::AliasStatusDisabled; case SNAPD_ALIAS_STATUS_AUTO: return QSnapdEnums::AliasStatusAuto; case SNAPD_ALIAS_STATUS_MANUAL: return QSnapdEnums::AliasStatusManual; } } snapd-glib-1.67/snapd-qt/app.cpp000066400000000000000000000035131477073115000165110ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/app.h" QSnapdApp::QSnapdApp(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdApp::name() const { return snapd_app_get_name(SNAPD_APP(wrapped_object)); } bool QSnapdApp::active() const { return snapd_app_get_active(SNAPD_APP(wrapped_object)); } QStringList QSnapdApp::aliases() const { return QStringList(); } QString QSnapdApp::commonId() const { return snapd_app_get_common_id(SNAPD_APP(wrapped_object)); } QSnapdEnums::DaemonType QSnapdApp::daemonType() const { switch (snapd_app_get_daemon_type(SNAPD_APP(wrapped_object))) { case SNAPD_DAEMON_TYPE_NONE: return QSnapdEnums::DaemonTypeNone; default: case SNAPD_DAEMON_TYPE_UNKNOWN: return QSnapdEnums::DaemonTypeUnknown; case SNAPD_DAEMON_TYPE_SIMPLE: return QSnapdEnums::DaemonTypeSimple; case SNAPD_DAEMON_TYPE_FORKING: return QSnapdEnums::DaemonTypeForking; case SNAPD_DAEMON_TYPE_ONESHOT: return QSnapdEnums::DaemonTypeOneshot; case SNAPD_DAEMON_TYPE_DBUS: return QSnapdEnums::DaemonTypeDbus; case SNAPD_DAEMON_TYPE_NOTIFY: return QSnapdEnums::DaemonTypeNotify; } } QString QSnapdApp::desktopFile() const { return snapd_app_get_desktop_file(SNAPD_APP(wrapped_object)); } bool QSnapdApp::enabled() const { return snapd_app_get_enabled(SNAPD_APP(wrapped_object)); } QString QSnapdApp::snap() const { return snapd_app_get_snap(SNAPD_APP(wrapped_object)); } snapd-glib-1.67/snapd-qt/assertion.cpp000066400000000000000000000026161477073115000177430ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/assertion.h" QSnapdAssertion::QSnapdAssertion(const QString &contents, QObject *parent) : QSnapdWrappedObject(NULL, g_object_unref, parent) { wrapped_object = snapd_assertion_new(contents.toStdString().c_str()); } QStringList QSnapdAssertion::headers() const { g_auto(GStrv) headers = NULL; QStringList result; headers = snapd_assertion_get_headers(SNAPD_ASSERTION(wrapped_object)); for (int i = 0; headers[i] != NULL; i++) result.append(headers[i]); return result; } QString QSnapdAssertion::header(const QString &name) const { g_autofree gchar *header = snapd_assertion_get_header( SNAPD_ASSERTION(wrapped_object), name.toStdString().c_str()); return header; } QString QSnapdAssertion::body() const { g_autofree gchar *body = snapd_assertion_get_body(SNAPD_ASSERTION(wrapped_object)); return body; } QString QSnapdAssertion::signature() const { g_autofree gchar *signature = snapd_assertion_get_signature(SNAPD_ASSERTION(wrapped_object)); return signature; } snapd-glib-1.67/snapd-qt/auth-data.cpp000066400000000000000000000030611477073115000175770ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/auth-data.h" QSnapdAuthData::QSnapdAuthData(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QSnapdAuthData::QSnapdAuthData(QObject *parent) : QSnapdWrappedObject(snapd_auth_data_new("", NULL), g_object_unref, parent) {} QSnapdAuthData::QSnapdAuthData(const QString &macaroon, const QStringList &discharges, QObject *parent) : QSnapdWrappedObject(NULL, g_object_unref, parent) { g_auto(GStrv) strv = g_new(gchar *, discharges.size() + 1); int i; for (i = 0; i < discharges.size(); i++) strv[i] = g_strdup((char *)discharges.at(i).toStdString().c_str()); strv[i] = NULL; wrapped_object = snapd_auth_data_new(macaroon.toStdString().c_str(), strv); } QString QSnapdAuthData::macaroon() const { return snapd_auth_data_get_macaroon(SNAPD_AUTH_DATA(wrapped_object)); } QStringList QSnapdAuthData::discharges() const { GStrv discharges = snapd_auth_data_get_discharges(SNAPD_AUTH_DATA(wrapped_object)); QStringList result; for (int i = 0; discharges[i] != NULL; i++) result.append(discharges[i]); return result; } snapd-glib-1.67/snapd-qt/category-details.cpp000066400000000000000000000014041477073115000211660ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/category-details.h" QSnapdCategoryDetails::QSnapdCategoryDetails(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdCategoryDetails::name() const { return snapd_category_details_get_name( SNAPD_CATEGORY_DETAILS(wrapped_object)); } snapd-glib-1.67/snapd-qt/category.cpp000066400000000000000000000014241477073115000175450ustar00rootroot00000000000000/* * Copyright (C) 2023 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/category.h" QSnapdCategory::QSnapdCategory(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdCategory::name() const { return snapd_category_get_name(SNAPD_CATEGORY(wrapped_object)); } bool QSnapdCategory::featured() const { return snapd_category_get_featured(SNAPD_CATEGORY(wrapped_object)); } snapd-glib-1.67/snapd-qt/change-autorefresh-data.cpp000066400000000000000000000024471477073115000224170ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/change-autorefresh-data.h" QSnapdAutorefreshChangeData::QSnapdAutorefreshChangeData(void *snapd_object, QObject *parent) : QSnapdChangeData(snapd_object, parent) {} static QStringList gstrv_to_qstringlist(GStrv data) { QStringList retval; if (data != NULL) for (gchar **element = data; *element != NULL; element++) retval << *element; return retval; } QStringList QSnapdAutorefreshChangeData::snapNames() const { QStringList list; GStrv data = snapd_autorefresh_change_data_get_snap_names( SNAPD_AUTOREFRESH_CHANGE_DATA(wrapped_object)); return gstrv_to_qstringlist(data); } QStringList QSnapdAutorefreshChangeData::refreshForced() const { QStringList list; GStrv data = snapd_autorefresh_change_data_get_refresh_forced( SNAPD_AUTOREFRESH_CHANGE_DATA(wrapped_object)); return gstrv_to_qstringlist(data); } snapd-glib-1.67/snapd-qt/change-data.cpp000066400000000000000000000010761477073115000200670ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/change-data.h" QSnapdChangeData::QSnapdChangeData(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} snapd-glib-1.67/snapd-qt/change.cpp000066400000000000000000000052211477073115000171540ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/change.h" QSnapdChange::QSnapdChange(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdChange::id() const { return snapd_change_get_id(SNAPD_CHANGE(wrapped_object)); } QString QSnapdChange::kind() const { return snapd_change_get_kind(SNAPD_CHANGE(wrapped_object)); } QString QSnapdChange::summary() const { return snapd_change_get_summary(SNAPD_CHANGE(wrapped_object)); } QString QSnapdChange::status() const { return snapd_change_get_status(SNAPD_CHANGE(wrapped_object)); } bool QSnapdChange::ready() const { return snapd_change_get_ready(SNAPD_CHANGE(wrapped_object)); } int QSnapdChange::taskCount() const { GPtrArray *tasks; tasks = snapd_change_get_tasks(SNAPD_CHANGE(wrapped_object)); return tasks != NULL ? tasks->len : 0; } QSnapdTask *QSnapdChange::task(int n) const { GPtrArray *tasks; tasks = snapd_change_get_tasks(SNAPD_CHANGE(wrapped_object)); if (tasks == NULL || n < 0 || (guint)n >= tasks->len) return NULL; return new QSnapdTask(tasks->pdata[n]); } static QDateTime convertDateTime(GDateTime *datetime) { if (datetime == NULL) return QDateTime(); QDate date(g_date_time_get_year(datetime), g_date_time_get_month(datetime), g_date_time_get_day_of_month(datetime)); QTime time(g_date_time_get_hour(datetime), g_date_time_get_minute(datetime), g_date_time_get_second(datetime), g_date_time_get_microsecond(datetime) / 1000); return QDateTime(date, time, Qt::OffsetFromUTC, g_date_time_get_utc_offset(datetime) / 1000000); } QDateTime QSnapdChange::spawnTime() const { return convertDateTime( snapd_change_get_spawn_time(SNAPD_CHANGE(wrapped_object))); } QDateTime QSnapdChange::readyTime() const { return convertDateTime( snapd_change_get_ready_time(SNAPD_CHANGE(wrapped_object))); } QString QSnapdChange::error() const { return snapd_change_get_error(SNAPD_CHANGE(wrapped_object)); } QSnapdChangeData *QSnapdChange::data() const { SnapdAutorefreshChangeData *data = SNAPD_AUTOREFRESH_CHANGE_DATA( snapd_change_get_data(SNAPD_CHANGE(wrapped_object))); if (data == NULL) return NULL; return new QSnapdAutorefreshChangeData(SNAPD_CHANGE_DATA(data), NULL); }snapd-glib-1.67/snapd-qt/channel.cpp000066400000000000000000000050451477073115000173430ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/channel.h" QSnapdChannel::QSnapdChannel(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdChannel::branch() const { return snapd_channel_get_branch(SNAPD_CHANNEL(wrapped_object)); } QSnapdEnums::SnapConfinement QSnapdChannel::confinement() const { switch (snapd_channel_get_confinement(SNAPD_CHANNEL(wrapped_object))) { case SNAPD_CONFINEMENT_STRICT: return QSnapdEnums::SnapConfinementStrict; case SNAPD_CONFINEMENT_CLASSIC: return QSnapdEnums::SnapConfinementClassic; case SNAPD_CONFINEMENT_DEVMODE: return QSnapdEnums::SnapConfinementDevmode; case SNAPD_CONFINEMENT_UNKNOWN: default: return QSnapdEnums::SnapConfinementUnknown; } } QString QSnapdChannel::epoch() const { return snapd_channel_get_epoch(SNAPD_CHANNEL(wrapped_object)); } QString QSnapdChannel::name() const { return snapd_channel_get_name(SNAPD_CHANNEL(wrapped_object)); } static QDateTime convertDateTime(GDateTime *datetime) { if (datetime == NULL) return QDateTime(); QDate date(g_date_time_get_year(datetime), g_date_time_get_month(datetime), g_date_time_get_day_of_month(datetime)); QTime time(g_date_time_get_hour(datetime), g_date_time_get_minute(datetime), g_date_time_get_second(datetime), g_date_time_get_microsecond(datetime) / 1000); return QDateTime(date, time, Qt::OffsetFromUTC, g_date_time_get_utc_offset(datetime) / 1000000); } QDateTime QSnapdChannel::releasedAt() const { return convertDateTime( snapd_channel_get_released_at(SNAPD_CHANNEL(wrapped_object))); } QString QSnapdChannel::revision() const { return snapd_channel_get_revision(SNAPD_CHANNEL(wrapped_object)); } QString QSnapdChannel::risk() const { return snapd_channel_get_risk(SNAPD_CHANNEL(wrapped_object)); } qint64 QSnapdChannel::size() const { return snapd_channel_get_size(SNAPD_CHANNEL(wrapped_object)); } QString QSnapdChannel::track() const { return snapd_channel_get_track(SNAPD_CHANNEL(wrapped_object)); } QString QSnapdChannel::version() const { return snapd_channel_get_version(SNAPD_CHANNEL(wrapped_object)); } snapd-glib-1.67/snapd-qt/client-private.h000066400000000000000000000643271477073115000203360ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef SNAPD_CLIENT_PRIVATE_H #define SNAPD_CLIENT_PRIVATE_H #include #include "stream-wrapper.h" #include #include #include G_DECLARE_FINAL_TYPE(CallbackData, callback_data, SNAPD, CALLBACK_DATA, GObject) struct _CallbackData { GObject parent_instance; gpointer request; }; CallbackData *callback_data_new(gpointer request); class QSnapdConnectRequestPrivate { public: QSnapdConnectRequestPrivate(gpointer request) { callback_data = callback_data_new(request); } ~QSnapdConnectRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } CallbackData *callback_data; }; class QSnapdLoginRequestPrivate { public: QSnapdLoginRequestPrivate(gpointer request, const QString &email, const QString &password, const QString &otp) : email(email), password(password), otp(otp) { callback_data = callback_data_new(request); } ~QSnapdLoginRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (user_information != NULL) g_object_unref(user_information); if (auth_data != NULL) g_object_unref(auth_data); } QString email; QString password; QString otp; CallbackData *callback_data; SnapdUserInformation *user_information = NULL; SnapdAuthData *auth_data = NULL; }; class QSnapdLogoutRequestPrivate { public: QSnapdLogoutRequestPrivate(gpointer request, qint64 id) : id(id) { callback_data = callback_data_new(request); } ~QSnapdLogoutRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } qint64 id; CallbackData *callback_data; }; class QSnapdGetChangesRequestPrivate { public: QSnapdGetChangesRequestPrivate(gpointer request, int filter, const QString &snapName) : filter(filter), snapName(snapName) { callback_data = callback_data_new(request); } ~QSnapdGetChangesRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (changes != NULL) g_ptr_array_unref(changes); } int filter; QString snapName; CallbackData *callback_data; GPtrArray *changes = NULL; }; class QSnapdGetChangeRequestPrivate { public: QSnapdGetChangeRequestPrivate(gpointer request, const QString &id) : id(id) { callback_data = callback_data_new(request); } ~QSnapdGetChangeRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (change != NULL) g_object_unref(change); } QString id; CallbackData *callback_data; SnapdChange *change = NULL; }; class QSnapdAbortChangeRequestPrivate { public: QSnapdAbortChangeRequestPrivate(gpointer request, const QString &id) : id(id) { callback_data = callback_data_new(request); } ~QSnapdAbortChangeRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (change != NULL) g_object_unref(change); } QString id; CallbackData *callback_data; SnapdChange *change = NULL; }; class QSnapdGetSystemInformationRequestPrivate { public: QSnapdGetSystemInformationRequestPrivate(gpointer request) { callback_data = callback_data_new(request); } ~QSnapdGetSystemInformationRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (info != NULL) g_object_unref(info); } CallbackData *callback_data; SnapdSystemInformation *info = NULL; }; class QSnapdListRequestPrivate { public: QSnapdListRequestPrivate(gpointer request) { callback_data = callback_data_new(request); } ~QSnapdListRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (snaps != NULL) g_ptr_array_unref(snaps); } CallbackData *callback_data; GPtrArray *snaps = NULL; }; class QSnapdGetSnapsRequestPrivate { public: QSnapdGetSnapsRequestPrivate(gpointer request, int flags, const QStringList &snaps) : flags(flags), filter_snaps(snaps) { callback_data = callback_data_new(request); } ~QSnapdGetSnapsRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (snaps != NULL) g_ptr_array_unref(snaps); } int flags; QStringList filter_snaps; CallbackData *callback_data; GPtrArray *snaps = NULL; }; class QSnapdListOneRequestPrivate { public: QSnapdListOneRequestPrivate(gpointer request, const QString &name) : name(name) { callback_data = callback_data_new(request); } ~QSnapdListOneRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (snap != NULL) g_object_unref(snap); } QString name; CallbackData *callback_data; SnapdSnap *snap = NULL; }; class QSnapdGetSnapRequestPrivate { public: QSnapdGetSnapRequestPrivate(gpointer request, const QString &name) : name(name) { callback_data = callback_data_new(request); } ~QSnapdGetSnapRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (snap != NULL) g_object_unref(snap); } QString name; CallbackData *callback_data; SnapdSnap *snap = NULL; }; class QSnapdGetSnapConfRequestPrivate { public: QSnapdGetSnapConfRequestPrivate(gpointer request, const QString &name, const QStringList &keys) : name(name), keys(keys) { callback_data = callback_data_new(request); } ~QSnapdGetSnapConfRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (configuration != NULL) g_hash_table_unref(configuration); } QString name; QStringList keys; CallbackData *callback_data; GHashTable *configuration = NULL; }; class QSnapdSetSnapConfRequestPrivate { public: QSnapdSetSnapConfRequestPrivate(gpointer request, const QString &name, const QHash &configuration) : name(name), configuration(configuration) { callback_data = callback_data_new(request); } ~QSnapdSetSnapConfRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString name; QHash configuration; CallbackData *callback_data; }; class QSnapdGetAppsRequestPrivate { public: QSnapdGetAppsRequestPrivate(gpointer request, int flags, const QStringList &snaps) : flags(flags), filter_snaps(snaps) { callback_data = callback_data_new(request); } ~QSnapdGetAppsRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (apps != NULL) g_ptr_array_unref(apps); } int flags; QStringList filter_snaps; CallbackData *callback_data; GPtrArray *apps = NULL; }; class QSnapdGetIconRequestPrivate { public: QSnapdGetIconRequestPrivate(gpointer request, const QString &name) : name(name) { callback_data = callback_data_new(request); } ~QSnapdGetIconRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (icon != NULL) g_object_unref(icon); } QString name; CallbackData *callback_data; SnapdIcon *icon = NULL; }; class QSnapdGetAssertionsRequestPrivate { public: QSnapdGetAssertionsRequestPrivate(gpointer request, const QString &type) : type(type) { callback_data = callback_data_new(request); } ~QSnapdGetAssertionsRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (assertions != NULL) g_strfreev(assertions); } QString type; CallbackData *callback_data; GStrv assertions = NULL; }; class QSnapdAddAssertionsRequestPrivate { public: QSnapdAddAssertionsRequestPrivate(gpointer request, const QStringList &assertions) : assertions(assertions) { callback_data = callback_data_new(request); } ~QSnapdAddAssertionsRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QStringList assertions; CallbackData *callback_data; }; class QSnapdGetConnectionsRequestPrivate { public: QSnapdGetConnectionsRequestPrivate(gpointer request, int flags, const QString &snap, const QString &interface) : flags(flags), snap(snap), interface(interface) { callback_data = callback_data_new(request); } ~QSnapdGetConnectionsRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (established != NULL) g_ptr_array_unref(established); if (undesired != NULL) g_ptr_array_unref(undesired); if (plugs != NULL) g_ptr_array_unref(plugs); if (slots_ != NULL) g_ptr_array_unref(slots_); } int flags; QString snap; QString interface; CallbackData *callback_data; GPtrArray *established = NULL; GPtrArray *undesired = NULL; GPtrArray *plugs = NULL; GPtrArray *slots_ = NULL; }; class QSnapdGetInterfacesRequestPrivate { public: QSnapdGetInterfacesRequestPrivate(gpointer request) { callback_data = callback_data_new(request); } ~QSnapdGetInterfacesRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (plugs != NULL) g_ptr_array_unref(plugs); if (slots_ != NULL) g_ptr_array_unref(slots_); } CallbackData *callback_data; GPtrArray *plugs = NULL; GPtrArray *slots_ = NULL; }; class QSnapdGetInterfaces2RequestPrivate { public: QSnapdGetInterfaces2RequestPrivate(gpointer request, int flags, const QStringList &names) : flags(flags), names(names) { callback_data = callback_data_new(request); } ~QSnapdGetInterfaces2RequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (interfaces != NULL) g_ptr_array_unref(interfaces); } int flags; QStringList names; CallbackData *callback_data; GPtrArray *interfaces = NULL; }; class QSnapdConnectInterfaceRequestPrivate { public: QSnapdConnectInterfaceRequestPrivate(gpointer request, const QString &plug_snap, const QString &plug_name, const QString &slot_snap, const QString &slot_name) : plug_snap(plug_snap), plug_name(plug_name), slot_snap(slot_snap), slot_name(slot_name) { callback_data = callback_data_new(request); } ~QSnapdConnectInterfaceRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString plug_snap; QString plug_name; QString slot_snap; QString slot_name; CallbackData *callback_data; }; class QSnapdDisconnectInterfaceRequestPrivate { public: QSnapdDisconnectInterfaceRequestPrivate(gpointer request, const QString &plug_snap, const QString &plug_name, const QString &slot_snap, const QString &slot_name) : plug_snap(plug_snap), plug_name(plug_name), slot_snap(slot_snap), slot_name(slot_name) { callback_data = callback_data_new(request); } ~QSnapdDisconnectInterfaceRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString plug_snap; QString plug_name; QString slot_snap; QString slot_name; CallbackData *callback_data; }; class QSnapdFindRequestPrivate { public: QSnapdFindRequestPrivate(gpointer request, int flags, const QString §ion, const QString &category, const QString &name) : flags(flags), section(section), category(category), name(name) { callback_data = callback_data_new(request); } ~QSnapdFindRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (snaps != NULL) g_ptr_array_unref(snaps); } int flags; QString section; QString category; QString name; CallbackData *callback_data; GPtrArray *snaps = NULL; QString suggestedCurrency; }; class QSnapdFindRefreshableRequestPrivate { public: QSnapdFindRefreshableRequestPrivate(gpointer request) { callback_data = callback_data_new(request); } ~QSnapdFindRefreshableRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (snaps != NULL) g_ptr_array_unref(snaps); } CallbackData *callback_data; GPtrArray *snaps = NULL; }; class QSnapdInstallRequestPrivate : public QObject { public: QSnapdInstallRequestPrivate(gpointer request, int flags, const QString &name, const QString &channel, const QString &revision, QIODevice *ioDevice, QObject *parent = NULL) : QObject(parent), flags(flags), name(name), channel(channel), revision(revision) { callback_data = callback_data_new(request); if (ioDevice != NULL) { wrapper = (StreamWrapper *)g_object_new(stream_wrapper_get_type(), NULL); wrapper->ioDevice = ioDevice; } } ~QSnapdInstallRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); g_clear_object(&wrapper); } int flags; QString name; QString channel; QString revision; CallbackData *callback_data; StreamWrapper *wrapper = NULL; }; class QSnapdTryRequestPrivate { public: QSnapdTryRequestPrivate(gpointer request, const QString &path) : path(path) { callback_data = callback_data_new(request); } ~QSnapdTryRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString path; CallbackData *callback_data; }; class QSnapdRefreshRequestPrivate { public: QSnapdRefreshRequestPrivate(gpointer request, const QString &name, const QString &channel) : name(name), channel(channel) { callback_data = callback_data_new(request); } ~QSnapdRefreshRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString name; QString channel; CallbackData *callback_data; }; class QSnapdRefreshAllRequestPrivate { public: QSnapdRefreshAllRequestPrivate(gpointer request) { callback_data = callback_data_new(request); } ~QSnapdRefreshAllRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (snap_names != NULL) g_strfreev(snap_names); } CallbackData *callback_data; GStrv snap_names = NULL; }; class QSnapdRemoveRequestPrivate { public: QSnapdRemoveRequestPrivate(gpointer request, int flags, const QString &name) : flags(flags), name(name) { callback_data = callback_data_new(request); } ~QSnapdRemoveRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } int flags; QString name; CallbackData *callback_data; }; class QSnapdEnableRequestPrivate { public: QSnapdEnableRequestPrivate(gpointer request, const QString &name) : name(name) { callback_data = callback_data_new(request); } ~QSnapdEnableRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString name; CallbackData *callback_data; }; class QSnapdDisableRequestPrivate { public: QSnapdDisableRequestPrivate(gpointer request, const QString &name) : name(name) { callback_data = callback_data_new(request); } ~QSnapdDisableRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString name; CallbackData *callback_data; }; class QSnapdSwitchChannelRequestPrivate { public: QSnapdSwitchChannelRequestPrivate(gpointer request, const QString &name, const QString &channel) : name(name), channel(channel) { callback_data = callback_data_new(request); } ~QSnapdSwitchChannelRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString name; QString channel; CallbackData *callback_data; }; class QSnapdCheckBuyRequestPrivate { public: QSnapdCheckBuyRequestPrivate(gpointer request) { callback_data = callback_data_new(request); } ~QSnapdCheckBuyRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } CallbackData *callback_data; bool canBuy; }; class QSnapdBuyRequestPrivate { public: QSnapdBuyRequestPrivate(gpointer request, const QString &id, double amount, const QString ¤cy) : id(id), amount(amount), currency(currency) { callback_data = callback_data_new(request); } ~QSnapdBuyRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString id; double amount; QString currency; CallbackData *callback_data; }; class QSnapdCreateUserRequestPrivate { public: QSnapdCreateUserRequestPrivate(gpointer request, const QString &email, int flags) : email(email), flags(flags) { callback_data = callback_data_new(request); } ~QSnapdCreateUserRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (info != NULL) g_object_unref(info); } QString email; int flags; CallbackData *callback_data; SnapdUserInformation *info = NULL; }; class QSnapdCreateUsersRequestPrivate { public: QSnapdCreateUsersRequestPrivate(gpointer request) { callback_data = callback_data_new(request); } ~QSnapdCreateUsersRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (info != NULL) g_ptr_array_unref(info); } CallbackData *callback_data; GPtrArray *info = NULL; }; class QSnapdGetUsersRequestPrivate { public: QSnapdGetUsersRequestPrivate(gpointer request) { callback_data = callback_data_new(request); } ~QSnapdGetUsersRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (info != NULL) g_ptr_array_unref(info); } CallbackData *callback_data; GPtrArray *info = NULL; }; class QSnapdGetSectionsRequestPrivate { public: QSnapdGetSectionsRequestPrivate(gpointer request) { callback_data = callback_data_new(request); } ~QSnapdGetSectionsRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (sections != NULL) g_strfreev(sections); } CallbackData *callback_data; GStrv sections = NULL; }; class QSnapdGetCategoriesRequestPrivate { public: QSnapdGetCategoriesRequestPrivate(gpointer request) { callback_data = callback_data_new(request); } ~QSnapdGetCategoriesRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (categories != NULL) g_ptr_array_unref(categories); } CallbackData *callback_data; GPtrArray *categories = NULL; }; class QSnapdGetAliasesRequestPrivate { public: QSnapdGetAliasesRequestPrivate(gpointer request) { callback_data = callback_data_new(request); } ~QSnapdGetAliasesRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (aliases != NULL) g_ptr_array_unref(aliases); } CallbackData *callback_data; GPtrArray *aliases = NULL; }; class QSnapdAliasRequestPrivate { public: QSnapdAliasRequestPrivate(gpointer request, const QString &snap, const QString &app, const QString &alias) : snap(snap), app(app), alias(alias) { callback_data = callback_data_new(request); } ~QSnapdAliasRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString snap; QString app; QString alias; CallbackData *callback_data; }; class QSnapdUnaliasRequestPrivate { public: QSnapdUnaliasRequestPrivate(gpointer request, const QString &snap, const QString &alias) : snap(snap), alias(alias) { callback_data = callback_data_new(request); } ~QSnapdUnaliasRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString snap; QString alias; CallbackData *callback_data; }; class QSnapdPreferRequestPrivate { public: QSnapdPreferRequestPrivate(gpointer request, const QString &snap) : snap(snap) { callback_data = callback_data_new(request); } ~QSnapdPreferRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString snap; CallbackData *callback_data; QString app; QString alias; }; class QSnapdEnableAliasesRequestPrivate { public: QSnapdEnableAliasesRequestPrivate(gpointer request, const QString &snap, const QStringList &aliases) : snap(snap), aliases(aliases) { callback_data = callback_data_new(request); } ~QSnapdEnableAliasesRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString snap; QStringList aliases; CallbackData *callback_data; }; class QSnapdDisableAliasesRequestPrivate { public: QSnapdDisableAliasesRequestPrivate(gpointer request, const QString &snap, const QStringList &aliases) : snap(snap), aliases(aliases) { callback_data = callback_data_new(request); } ~QSnapdDisableAliasesRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString snap; QStringList aliases; CallbackData *callback_data; }; class QSnapdResetAliasesRequestPrivate { public: QSnapdResetAliasesRequestPrivate(gpointer request, const QString &snap, const QStringList &aliases) : snap(snap), aliases(aliases) { callback_data = callback_data_new(request); } ~QSnapdResetAliasesRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QString snap; QStringList aliases; CallbackData *callback_data; }; class QSnapdRunSnapCtlRequestPrivate { public: QSnapdRunSnapCtlRequestPrivate(gpointer request, const QString &contextId, const QStringList &args) : contextId(contextId), args(args) { callback_data = callback_data_new(request); } ~QSnapdRunSnapCtlRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (stdout_output != NULL) g_free(stdout_output); if (stderr_output != NULL) g_free(stderr_output); } QString contextId; QStringList args; CallbackData *callback_data; gchar *stdout_output = NULL; gchar *stderr_output = NULL; int exit_code = 0; }; class QSnapdDownloadRequestPrivate { public: QSnapdDownloadRequestPrivate(gpointer request, const QString &name, const QString &channel, const QString &revision) : name(name), channel(channel), revision(revision) { callback_data = callback_data_new(request); } ~QSnapdDownloadRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (data != NULL) g_bytes_unref(data); } QString name; QString channel; QString revision; CallbackData *callback_data; GBytes *data = NULL; }; class QSnapdCheckThemesRequestPrivate { public: QSnapdCheckThemesRequestPrivate(gpointer request, const QStringList >kThemeNames, const QStringList &iconThemeNames, const QStringList &soundThemeNames) : gtkThemeNames(gtkThemeNames), iconThemeNames(iconThemeNames), soundThemeNames(soundThemeNames) { callback_data = callback_data_new(request); } ~QSnapdCheckThemesRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); if (gtk_theme_status != NULL) g_hash_table_unref(gtk_theme_status); if (icon_theme_status != NULL) g_hash_table_unref(icon_theme_status); if (sound_theme_status != NULL) g_hash_table_unref(sound_theme_status); } QStringList gtkThemeNames; QStringList iconThemeNames; QStringList soundThemeNames; CallbackData *callback_data; GHashTable *gtk_theme_status; GHashTable *icon_theme_status; GHashTable *sound_theme_status; }; class QSnapdInstallThemesRequestPrivate { public: QSnapdInstallThemesRequestPrivate(gpointer request, const QStringList >kThemeNames, const QStringList &iconThemeNames, const QStringList &soundThemeNames) : gtkThemeNames(gtkThemeNames), iconThemeNames(iconThemeNames), soundThemeNames(soundThemeNames) { callback_data = callback_data_new(request); } ~QSnapdInstallThemesRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); } QStringList gtkThemeNames; QStringList iconThemeNames; QStringList soundThemeNames; CallbackData *callback_data; }; class QSnapdNoticesRequestPrivate { public: QSnapdNoticesRequestPrivate(gpointer request) { notices = NULL; callback_data = callback_data_new(request); } ~QSnapdNoticesRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); g_clear_pointer(¬ices, g_ptr_array_unref); } void updateNoticesData(GPtrArray *data) { g_clear_pointer(¬ices, g_ptr_array_unref); notices = data; } CallbackData *callback_data; GPtrArray *notices; }; class QSnapdGetModelAssertionRequestPrivate { public: QSnapdGetModelAssertionRequestPrivate(gpointer request) { model_assertion = NULL; callback_data = callback_data_new(request); } ~QSnapdGetModelAssertionRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); g_clear_pointer(&model_assertion, g_free); } CallbackData *callback_data; gchar *model_assertion; }; class QSnapdGetSerialAssertionRequestPrivate { public: QSnapdGetSerialAssertionRequestPrivate(gpointer request) { serial_assertion = NULL; callback_data = callback_data_new(request); } ~QSnapdGetSerialAssertionRequestPrivate() { callback_data->request = NULL; g_object_unref(callback_data); g_clear_pointer(&serial_assertion, g_free); } CallbackData *callback_data; gchar *serial_assertion; }; #endif snapd-glib-1.67/snapd-qt/client.cpp000066400000000000000000004124221477073115000172120ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/client.h" #include "client-private.h" #include "variant.h" #include G_DEFINE_TYPE(CallbackData, callback_data, G_TYPE_OBJECT) static void callback_data_init(CallbackData *self) {} static void callback_data_class_init(CallbackDataClass *klass) {} CallbackData *callback_data_new(gpointer request) { CallbackData *data = (CallbackData *)g_object_new(callback_data_get_type(), NULL); data->request = request; return data; } class QSnapdClientPrivate { public: QSnapdClientPrivate() { client = snapd_client_new(); } QSnapdClientPrivate(int fd) { g_autoptr(GSocket) socket = NULL; socket = g_socket_new_from_fd(fd, NULL); client = snapd_client_new_from_socket(socket); } ~QSnapdClientPrivate() { g_object_unref(client); } SnapdClient *client; }; QSnapdClient::QSnapdClient(QObject *parent) : QObject(parent), d_ptr(new QSnapdClientPrivate()) {} QSnapdClient::QSnapdClient(int fd, QObject *parent) : QObject(parent), d_ptr(new QSnapdClientPrivate(fd)) {} QSnapdClient::~QSnapdClient() {} QSnapdConnectRequest::~QSnapdConnectRequest() {} QSnapdConnectRequest *QSnapdClient::connect() { Q_D(QSnapdClient); return new QSnapdConnectRequest(d->client); } QSnapdLoginRequest::~QSnapdLoginRequest() {} QSnapdLoginRequest *login(const QString &email, const QString &password) { return new QSnapdLoginRequest(NULL, email, password, NULL); } QSnapdLoginRequest *login(const QString &email, const QString &password, const QString &otp) { return new QSnapdLoginRequest(NULL, email, password, otp); } QSnapdLoginRequest *QSnapdClient::login(const QString &email, const QString &password) { Q_D(QSnapdClient); return new QSnapdLoginRequest(d->client, email, password, NULL); } QSnapdLoginRequest *QSnapdClient::login(const QString &email, const QString &password, const QString &otp) { Q_D(QSnapdClient); return new QSnapdLoginRequest(d->client, email, password, otp); } QSnapdLogoutRequest::~QSnapdLogoutRequest() {} QSnapdLogoutRequest *QSnapdClient::logout(qint64 id) { Q_D(QSnapdClient); return new QSnapdLogoutRequest(d->client, id); } void QSnapdClient::setSocketPath(const QString &socketPath) { Q_D(QSnapdClient); snapd_client_set_socket_path( d->client, socketPath.isNull() ? NULL : socketPath.toStdString().c_str()); } QString QSnapdClient::socketPath() const { Q_D(const QSnapdClient); return snapd_client_get_socket_path(d->client); } void QSnapdClient::setUserAgent(const QString &userAgent) { Q_D(QSnapdClient); snapd_client_set_user_agent( d->client, userAgent.isNull() ? NULL : userAgent.toStdString().c_str()); } QString QSnapdClient::userAgent() const { Q_D(const QSnapdClient); return snapd_client_get_user_agent(d->client); } void QSnapdClient::setAllowInteraction(bool allowInteraction) { Q_D(QSnapdClient); snapd_client_set_allow_interaction(d->client, allowInteraction); } bool QSnapdClient::allowInteraction() const { Q_D(const QSnapdClient); return snapd_client_get_allow_interaction(d->client); } QSnapdMaintenance *QSnapdClient::maintenance() const { Q_D(const QSnapdClient); SnapdMaintenance *m = snapd_client_get_maintenance(d->client); if (m == NULL) return NULL; else return new QSnapdMaintenance(m); } void QSnapdClient::setAuthData(QSnapdAuthData *authData) { Q_D(QSnapdClient); snapd_client_set_auth_data(d->client, SNAPD_AUTH_DATA(authData->wrappedObject())); } // NOTE: This should be const but we can't do that without breaking ABI.. QSnapdAuthData *QSnapdClient::authData() { Q_D(QSnapdClient); return new QSnapdAuthData(snapd_client_get_auth_data(d->client)); } QSnapdGetChangesRequest::~QSnapdGetChangesRequest() {} QSnapdGetChangesRequest *QSnapdClient::getChanges() { Q_D(QSnapdClient); return new QSnapdGetChangesRequest(FilterAll, NULL, d->client); } QSnapdGetChangesRequest *QSnapdClient::getChanges(ChangeFilter filter) { Q_D(QSnapdClient); return new QSnapdGetChangesRequest(filter, NULL, d->client); } QSnapdGetChangesRequest *QSnapdClient::getChanges(const QString &snapName) { Q_D(QSnapdClient); return new QSnapdGetChangesRequest(FilterAll, snapName, d->client); } QSnapdGetChangesRequest *QSnapdClient::getChanges(ChangeFilter filter, const QString &snapName) { Q_D(QSnapdClient); return new QSnapdGetChangesRequest(filter, snapName, d->client); } QSnapdGetChangeRequest::~QSnapdGetChangeRequest() {} QSnapdGetChangeRequest *QSnapdClient::getChange(const QString &id) { Q_D(QSnapdClient); return new QSnapdGetChangeRequest(id, d->client); } QSnapdAbortChangeRequest::~QSnapdAbortChangeRequest() {} QSnapdAbortChangeRequest *QSnapdClient::abortChange(const QString &id) { Q_D(QSnapdClient); return new QSnapdAbortChangeRequest(id, d->client); } QSnapdGetSystemInformationRequest::~QSnapdGetSystemInformationRequest() {} QSnapdGetSystemInformationRequest *QSnapdClient::getSystemInformation() { Q_D(QSnapdClient); return new QSnapdGetSystemInformationRequest(d->client); } QSnapdListRequest::~QSnapdListRequest() {} QSnapdListRequest *QSnapdClient::list() { Q_D(QSnapdClient); return new QSnapdListRequest(d->client); } QSnapdGetSnapsRequest::~QSnapdGetSnapsRequest() {} QSnapdGetSnapsRequest *QSnapdClient::getSnaps(GetSnapsFlags flags, const QStringList &snaps) { Q_D(QSnapdClient); return new QSnapdGetSnapsRequest(flags, snaps, d->client); } QSnapdGetSnapsRequest *QSnapdClient::getSnaps(GetSnapsFlags flags, const QString &snap) { return getSnaps(flags, QStringList(snap)); } QSnapdGetSnapsRequest *QSnapdClient::getSnaps(const QStringList &snaps) { return getSnaps(GetSnapsFlags(), snaps); } QSnapdGetSnapsRequest *QSnapdClient::getSnaps(const QString &snap) { return getSnaps(GetSnapsFlags(), QStringList(snap)); } QSnapdGetSnapsRequest *QSnapdClient::getSnaps() { return getSnaps(GetSnapsFlags(), QStringList()); } QSnapdListOneRequest::~QSnapdListOneRequest() {} QSnapdListOneRequest *QSnapdClient::listOne(const QString &name) { Q_D(QSnapdClient); return new QSnapdListOneRequest(name, d->client); } QSnapdGetSnapRequest::~QSnapdGetSnapRequest() {} QSnapdGetSnapRequest *QSnapdClient::getSnap(const QString &name) { Q_D(QSnapdClient); return new QSnapdGetSnapRequest(name, d->client); } QSnapdGetSnapConfRequest::~QSnapdGetSnapConfRequest() {} QSnapdGetSnapConfRequest *QSnapdClient::getSnapConf(const QString &name, const QStringList &keys) { Q_D(QSnapdClient); return new QSnapdGetSnapConfRequest(name, keys, d->client); } QSnapdGetSnapConfRequest *QSnapdClient::getSnapConf(const QString &name) { Q_D(QSnapdClient); return new QSnapdGetSnapConfRequest(name, QStringList(), d->client); } QSnapdSetSnapConfRequest::~QSnapdSetSnapConfRequest() {} QSnapdSetSnapConfRequest * QSnapdClient::setSnapConf(const QString &name, const QHash &configuration) { Q_D(QSnapdClient); return new QSnapdSetSnapConfRequest(name, configuration, d->client); } QSnapdGetAppsRequest::~QSnapdGetAppsRequest() {} QSnapdGetAppsRequest *QSnapdClient::getApps(GetAppsFlags flags, const QStringList &snaps) { Q_D(QSnapdClient); return new QSnapdGetAppsRequest(flags, snaps, d->client); } QSnapdGetAppsRequest *QSnapdClient::getApps(GetAppsFlags flags, const QString &snap) { return getApps(flags, QStringList(snap)); } QSnapdGetAppsRequest *QSnapdClient::getApps(GetAppsFlags flags) { return getApps(flags, QStringList()); } QSnapdGetAppsRequest *QSnapdClient::getApps(const QStringList &snaps) { return getApps(GetAppsFlags(), snaps); } QSnapdGetAppsRequest *QSnapdClient::getApps(const QString &snap) { return getApps(GetAppsFlags(), QStringList(snap)); } QSnapdGetAppsRequest *QSnapdClient::getApps() { return getApps(GetAppsFlags(), QStringList()); } QSnapdGetIconRequest::~QSnapdGetIconRequest() {} QSnapdGetIconRequest *QSnapdClient::getIcon(const QString &name) { Q_D(QSnapdClient); return new QSnapdGetIconRequest(name, d->client); } QSnapdGetAssertionsRequest::~QSnapdGetAssertionsRequest() {} QSnapdGetAssertionsRequest *QSnapdClient::getAssertions(const QString &type) { Q_D(QSnapdClient); return new QSnapdGetAssertionsRequest(type, d->client); } QSnapdAddAssertionsRequest::~QSnapdAddAssertionsRequest() {} QSnapdAddAssertionsRequest * QSnapdClient::addAssertions(const QStringList &assertions) { Q_D(QSnapdClient); return new QSnapdAddAssertionsRequest(assertions, d->client); } QSnapdGetConnectionsRequest::~QSnapdGetConnectionsRequest() {} QSnapdGetConnectionsRequest *QSnapdClient::getConnections() { Q_D(QSnapdClient); return new QSnapdGetConnectionsRequest(0, QString(), QString(), d->client); } QSnapdGetConnectionsRequest * QSnapdClient::getConnections(GetConnectionsFlags flags) { Q_D(QSnapdClient); return new QSnapdGetConnectionsRequest(flags, QString(), QString(), d->client); } QSnapdGetConnectionsRequest * QSnapdClient::getConnections(const QString &snap, const QString &interface) { Q_D(QSnapdClient); return new QSnapdGetConnectionsRequest(0, snap, interface, d->client); } QSnapdGetConnectionsRequest * QSnapdClient::getConnections(GetConnectionsFlags flags, const QString &snap, const QString &interface) { Q_D(QSnapdClient); return new QSnapdGetConnectionsRequest(flags, snap, interface, d->client); } QSnapdGetInterfacesRequest::~QSnapdGetInterfacesRequest() {} QSnapdGetInterfacesRequest *QSnapdClient::getInterfaces() { Q_D(QSnapdClient); return new QSnapdGetInterfacesRequest(d->client); } QSnapdGetInterfaces2Request::~QSnapdGetInterfaces2Request() {} QSnapdGetInterfaces2Request *QSnapdClient::getInterfaces2() { return getInterfaces2(InterfaceFlags(), QStringList()); } QSnapdGetInterfaces2Request * QSnapdClient::getInterfaces2(InterfaceFlags flags) { return getInterfaces2(flags, QStringList()); } QSnapdGetInterfaces2Request * QSnapdClient::getInterfaces2(const QStringList &names) { return getInterfaces2(InterfaceFlags(), names); } QSnapdGetInterfaces2Request * QSnapdClient::getInterfaces2(InterfaceFlags flags, const QStringList &names) { Q_D(QSnapdClient); return new QSnapdGetInterfaces2Request(flags, names, d->client); } QSnapdConnectInterfaceRequest::~QSnapdConnectInterfaceRequest() {} QSnapdConnectInterfaceRequest *QSnapdClient::connectInterface( const QString &plug_snap, const QString &plug_name, const QString &slot_snap, const QString &slot_name) { Q_D(QSnapdClient); return new QSnapdConnectInterfaceRequest(plug_snap, plug_name, slot_snap, slot_name, d->client); } QSnapdDisconnectInterfaceRequest::~QSnapdDisconnectInterfaceRequest() {} QSnapdDisconnectInterfaceRequest *QSnapdClient::disconnectInterface( const QString &plug_snap, const QString &plug_name, const QString &slot_snap, const QString &slot_name) { Q_D(QSnapdClient); return new QSnapdDisconnectInterfaceRequest(plug_snap, plug_name, slot_snap, slot_name, d->client); } QSnapdFindRequest::~QSnapdFindRequest() {} QSnapdFindRequest *QSnapdClient::find(const QString &name) { Q_D(QSnapdClient); return new QSnapdFindRequest(QSnapdClient::FindFlag::None, NULL, NULL, name, d->client); } QSnapdFindRequest *QSnapdClient::find(FindFlags flags) { Q_D(QSnapdClient); return new QSnapdFindRequest(flags, NULL, NULL, NULL, d->client); } QSnapdFindRequest *QSnapdClient::find(FindFlags flags, const QString &name) { Q_D(QSnapdClient); return new QSnapdFindRequest(flags, NULL, NULL, name, d->client); } QSnapdFindRequest *QSnapdClient::findSection(const QString §ion, const QString &name) { Q_D(QSnapdClient); return new QSnapdFindRequest(QSnapdClient::FindFlag::None, section, NULL, name, d->client); } QSnapdFindRequest *QSnapdClient::findSection(FindFlags flags, const QString §ion, const QString &name) { Q_D(QSnapdClient); return new QSnapdFindRequest(flags, section, NULL, name, d->client); } QSnapdFindRequest *QSnapdClient::findCategory(const QString &category, const QString &name) { Q_D(QSnapdClient); return new QSnapdFindRequest(QSnapdClient::FindFlag::None, NULL, category, name, d->client); } QSnapdFindRequest *QSnapdClient::findCategory(FindFlags flags, const QString &category, const QString &name) { Q_D(QSnapdClient); return new QSnapdFindRequest(flags, NULL, category, name, d->client); } QSnapdFindRefreshableRequest::~QSnapdFindRefreshableRequest() {} QSnapdFindRefreshableRequest *QSnapdClient::findRefreshable() { Q_D(QSnapdClient); return new QSnapdFindRefreshableRequest(d->client); } QSnapdInstallRequest::~QSnapdInstallRequest() {} QSnapdInstallRequest *QSnapdClient::install(const QString &name) { Q_D(QSnapdClient); return new QSnapdInstallRequest(0, name, NULL, NULL, NULL, d->client); } QSnapdInstallRequest *QSnapdClient::install(const QString &name, const QString &channel) { Q_D(QSnapdClient); return new QSnapdInstallRequest(0, name, channel, NULL, NULL, d->client); } QSnapdInstallRequest *QSnapdClient::install(const QString &name, const QString &channel, const QString &revision) { Q_D(QSnapdClient); return new QSnapdInstallRequest(0, name, channel, revision, NULL, d->client); } QSnapdInstallRequest *QSnapdClient::install(InstallFlags flags, const QString &name) { Q_D(QSnapdClient); return new QSnapdInstallRequest(flags, name, NULL, NULL, NULL, d->client); } QSnapdInstallRequest *QSnapdClient::install(InstallFlags flags, const QString &name, const QString &channel) { Q_D(QSnapdClient); return new QSnapdInstallRequest(flags, name, channel, NULL, NULL, d->client); } QSnapdInstallRequest *QSnapdClient::install(InstallFlags flags, const QString &name, const QString &channel, const QString &revision) { Q_D(QSnapdClient); return new QSnapdInstallRequest(flags, name, channel, revision, NULL, d->client); } QSnapdInstallRequest *QSnapdClient::install(QIODevice *ioDevice) { Q_D(QSnapdClient); return new QSnapdInstallRequest(0, NULL, NULL, NULL, ioDevice, d->client); } QSnapdInstallRequest *QSnapdClient::install(InstallFlags flags, QIODevice *ioDevice) { Q_D(QSnapdClient); return new QSnapdInstallRequest(flags, NULL, NULL, NULL, ioDevice, d->client); } QSnapdTryRequest::~QSnapdTryRequest() {} QSnapdTryRequest *QSnapdClient::trySnap(const QString &path) { Q_D(QSnapdClient); return new QSnapdTryRequest(path, d->client); } QSnapdRefreshRequest::~QSnapdRefreshRequest() {} QSnapdRefreshRequest *QSnapdClient::refresh(const QString &name) { Q_D(QSnapdClient); return new QSnapdRefreshRequest(name, NULL, d->client); } QSnapdRefreshRequest *QSnapdClient::refresh(const QString &name, const QString &channel) { Q_D(QSnapdClient); return new QSnapdRefreshRequest(name, channel, d->client); } QSnapdRefreshAllRequest::~QSnapdRefreshAllRequest() {} QSnapdRefreshAllRequest *QSnapdClient::refreshAll() { Q_D(QSnapdClient); return new QSnapdRefreshAllRequest(d->client); } QSnapdRemoveRequest::~QSnapdRemoveRequest() {} QSnapdRemoveRequest *QSnapdClient::remove(const QString &name) { Q_D(QSnapdClient); return new QSnapdRemoveRequest(0, name, d->client); } QSnapdRemoveRequest *QSnapdClient::remove(RemoveFlags flags, const QString &name) { Q_D(QSnapdClient); return new QSnapdRemoveRequest(flags, name, d->client); } QSnapdEnableRequest::~QSnapdEnableRequest() {} QSnapdEnableRequest *QSnapdClient::enable(const QString &name) { Q_D(QSnapdClient); return new QSnapdEnableRequest(name, d->client); } QSnapdDisableRequest::~QSnapdDisableRequest() {} QSnapdDisableRequest *QSnapdClient::disable(const QString &name) { Q_D(QSnapdClient); return new QSnapdDisableRequest(name, d->client); } QSnapdSwitchChannelRequest::~QSnapdSwitchChannelRequest() {} QSnapdSwitchChannelRequest * QSnapdClient::switchChannel(const QString &name, const QString &channel) { Q_D(QSnapdClient); return new QSnapdSwitchChannelRequest(name, channel, d->client); } QSnapdCheckBuyRequest::~QSnapdCheckBuyRequest() {} QSnapdCheckBuyRequest *QSnapdClient::checkBuy() { Q_D(QSnapdClient); return new QSnapdCheckBuyRequest(d->client); } QSnapdBuyRequest::~QSnapdBuyRequest() {} QSnapdBuyRequest *QSnapdClient::buy(const QString &id, double amount, const QString ¤cy) { Q_D(QSnapdClient); return new QSnapdBuyRequest(id, amount, currency, d->client); } QSnapdCreateUserRequest::~QSnapdCreateUserRequest() {} QSnapdCreateUserRequest *QSnapdClient::createUser(const QString &email) { Q_D(QSnapdClient); return new QSnapdCreateUserRequest(email, 0, d->client); } QSnapdCreateUserRequest *QSnapdClient::createUser(const QString &email, CreateUserFlags flags) { Q_D(QSnapdClient); return new QSnapdCreateUserRequest(email, flags, d->client); } QSnapdCreateUsersRequest::~QSnapdCreateUsersRequest() {} QSnapdCreateUsersRequest *QSnapdClient::createUsers() { Q_D(QSnapdClient); return new QSnapdCreateUsersRequest(d->client); } QSnapdGetUsersRequest::~QSnapdGetUsersRequest() {} QSnapdGetUsersRequest *QSnapdClient::getUsers() { Q_D(QSnapdClient); return new QSnapdGetUsersRequest(d->client); } QSnapdGetSectionsRequest::~QSnapdGetSectionsRequest() {} QSnapdGetSectionsRequest *QSnapdClient::getSections() { Q_D(QSnapdClient); return new QSnapdGetSectionsRequest(d->client); } QSnapdGetCategoriesRequest::~QSnapdGetCategoriesRequest() {} QSnapdGetCategoriesRequest *QSnapdClient::getCategories() { Q_D(QSnapdClient); return new QSnapdGetCategoriesRequest(d->client); } QSnapdGetAliasesRequest::~QSnapdGetAliasesRequest() {} QSnapdGetAliasesRequest *QSnapdClient::getAliases() { Q_D(QSnapdClient); return new QSnapdGetAliasesRequest(d->client); } QSnapdAliasRequest::~QSnapdAliasRequest() {} QSnapdAliasRequest *QSnapdClient::alias(const QString &snap, const QString &app, const QString &alias) { Q_D(QSnapdClient); return new QSnapdAliasRequest(snap, app, alias, d->client); } QSnapdUnaliasRequest::~QSnapdUnaliasRequest() {} QSnapdUnaliasRequest *QSnapdClient::unalias(const QString &snap, const QString &alias) { Q_D(QSnapdClient); return new QSnapdUnaliasRequest(snap, alias, d->client); } QSnapdUnaliasRequest *QSnapdClient::unalias(const QString &alias) { Q_D(QSnapdClient); return new QSnapdUnaliasRequest(NULL, alias, d->client); } QSnapdPreferRequest::~QSnapdPreferRequest() {} QSnapdPreferRequest *QSnapdClient::prefer(const QString &snap) { Q_D(QSnapdClient); return new QSnapdPreferRequest(snap, d->client); } QSnapdEnableAliasesRequest::~QSnapdEnableAliasesRequest() {} QSnapdEnableAliasesRequest * QSnapdClient::enableAliases(const QString snap, const QStringList &aliases) { Q_D(QSnapdClient); return new QSnapdEnableAliasesRequest(snap, aliases, d->client); } QSnapdDisableAliasesRequest::~QSnapdDisableAliasesRequest() {} QSnapdDisableAliasesRequest * QSnapdClient::disableAliases(const QString snap, const QStringList &aliases) { Q_D(QSnapdClient); return new QSnapdDisableAliasesRequest(snap, aliases, d->client); } QSnapdResetAliasesRequest::~QSnapdResetAliasesRequest() {} QSnapdResetAliasesRequest * QSnapdClient::resetAliases(const QString snap, const QStringList &aliases) { Q_D(QSnapdClient); return new QSnapdResetAliasesRequest(snap, aliases, d->client); } QSnapdRunSnapCtlRequest::~QSnapdRunSnapCtlRequest() {} QSnapdRunSnapCtlRequest *QSnapdClient::runSnapCtl(const QString contextId, const QStringList &args) { Q_D(QSnapdClient); return new QSnapdRunSnapCtlRequest(contextId, args, d->client); } QSnapdDownloadRequest::~QSnapdDownloadRequest() {} QSnapdDownloadRequest *QSnapdClient::download(const QString &name) { Q_D(QSnapdClient); return new QSnapdDownloadRequest(name, NULL, NULL, d->client); } QSnapdDownloadRequest *QSnapdClient::download(const QString &name, const QString &channel, const QString &revision) { Q_D(QSnapdClient); return new QSnapdDownloadRequest(name, channel, revision, d->client); } QSnapdCheckThemesRequest::~QSnapdCheckThemesRequest() {} QSnapdCheckThemesRequest * QSnapdClient::checkThemes(const QStringList >kThemeNames, const QStringList &iconThemeNames, const QStringList &soundThemeNames) { Q_D(QSnapdClient); return new QSnapdCheckThemesRequest(gtkThemeNames, iconThemeNames, soundThemeNames, d->client); } QSnapdInstallThemesRequest::~QSnapdInstallThemesRequest() {} QSnapdInstallThemesRequest * QSnapdClient::installThemes(const QStringList >kThemeNames, const QStringList &iconThemeNames, const QStringList &soundThemeNames) { Q_D(QSnapdClient); return new QSnapdInstallThemesRequest(gtkThemeNames, iconThemeNames, soundThemeNames, d->client); } QSnapdConnectRequest::QSnapdConnectRequest(void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdConnectRequestPrivate(this)) {} void QSnapdConnectRequest::runSync() { finish(NULL); } void QSnapdConnectRequest::handleResult(void *object, void *result) { finish(NULL); } void QSnapdConnectRequest::runAsync() { handleResult(NULL, NULL); } QSnapdLoginRequest::QSnapdLoginRequest(void *snapd_client, const QString &email, const QString &password, const QString &otp, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdLoginRequestPrivate(this, email, password, otp)) {} void QSnapdLoginRequest::runSync() { Q_D(QSnapdLoginRequest); g_autoptr(GError) error = NULL; if (getClient() != NULL) d->user_information = snapd_client_login2_sync( SNAPD_CLIENT(getClient()), d->email.toStdString().c_str(), d->password.toStdString().c_str(), d->otp.isNull() ? NULL : d->otp.toStdString().c_str(), G_CANCELLABLE(getCancellable()), &error); else G_GNUC_BEGIN_IGNORE_DEPRECATIONS d->auth_data = snapd_login_sync( d->email.toStdString().c_str(), d->password.toStdString().c_str(), d->otp.isNull() ? NULL : d->otp.toStdString().c_str(), G_CANCELLABLE(getCancellable()), &error); G_GNUC_END_IGNORE_DEPRECATIONS finish(error); } void QSnapdLoginRequest::handleResult(void *object, void *result) { Q_D(QSnapdLoginRequest); g_autoptr(GError) error = NULL; if (getClient() != NULL) d->user_information = snapd_client_login2_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); else G_GNUC_BEGIN_IGNORE_DEPRECATIONS d->auth_data = snapd_login_finish(G_ASYNC_RESULT(result), &error); G_GNUC_END_IGNORE_DEPRECATIONS finish(error); } static void login_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdLoginRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdLoginRequest::runAsync() { Q_D(QSnapdLoginRequest); if (getClient() != NULL) snapd_client_login2_async( SNAPD_CLIENT(getClient()), d->email.toStdString().c_str(), d->password.toStdString().c_str(), d->otp.isNull() ? NULL : d->otp.toStdString().c_str(), G_CANCELLABLE(getCancellable()), login_ready_cb, g_object_ref(d->callback_data)); else G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_login_async(d->email.toStdString().c_str(), d->password.toStdString().c_str(), d->otp.isNull() ? NULL : d->otp.toStdString().c_str(), G_CANCELLABLE(getCancellable()), login_ready_cb, g_object_ref(d->callback_data)); G_GNUC_END_IGNORE_DEPRECATIONS } QSnapdUserInformation *QSnapdLoginRequest::userInformation() { Q_D(QSnapdLoginRequest); return new QSnapdUserInformation(d->user_information); } QSnapdAuthData *QSnapdLoginRequest::authData() { Q_D(QSnapdLoginRequest); if (d->auth_data != NULL) return new QSnapdAuthData(d->auth_data); else return new QSnapdAuthData( snapd_user_information_get_auth_data(d->user_information)); } QSnapdLogoutRequest::QSnapdLogoutRequest(void *snapd_client, qint64 id, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdLogoutRequestPrivate(this, id)) {} void QSnapdLogoutRequest::runSync() { Q_D(QSnapdLogoutRequest); g_autoptr(GError) error = NULL; snapd_client_logout_sync(SNAPD_CLIENT(getClient()), d->id, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdLogoutRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_logout_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void logout_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdLogoutRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdLogoutRequest::runAsync() { Q_D(QSnapdLogoutRequest); snapd_client_logout_async(SNAPD_CLIENT(getClient()), d->id, G_CANCELLABLE(getCancellable()), logout_ready_cb, g_object_ref(d->callback_data)); } static SnapdChangeFilter convertChangeFilter(int filter) { switch (filter) { default: case QSnapdClient::ChangeFilter::FilterAll: return SNAPD_CHANGE_FILTER_ALL; case QSnapdClient::ChangeFilter::FilterInProgress: return SNAPD_CHANGE_FILTER_IN_PROGRESS; case QSnapdClient::ChangeFilter::FilterReady: return SNAPD_CHANGE_FILTER_READY; } } QSnapdGetChangesRequest::QSnapdGetChangesRequest(int filter, const QString &snapName, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetChangesRequestPrivate(this, filter, snapName)) {} void QSnapdGetChangesRequest::runSync() { Q_D(QSnapdGetChangesRequest); g_autoptr(GError) error = NULL; d->changes = snapd_client_get_changes_sync( SNAPD_CLIENT(getClient()), convertChangeFilter(d->filter), d->snapName.isNull() ? NULL : d->snapName.toStdString().c_str(), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetChangesRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetChangesRequest); g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) changes = snapd_client_get_changes_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->changes = (GPtrArray *)g_steal_pointer(&changes); finish(error); } static void changes_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetChangesRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetChangesRequest::runAsync() { Q_D(QSnapdGetChangesRequest); snapd_client_get_changes_async( SNAPD_CLIENT(getClient()), convertChangeFilter(d->filter), d->snapName.isNull() ? NULL : d->snapName.toStdString().c_str(), G_CANCELLABLE(getCancellable()), changes_ready_cb, g_object_ref(d->callback_data)); } int QSnapdGetChangesRequest::changeCount() const { Q_D(const QSnapdGetChangesRequest); return d->changes != NULL ? d->changes->len : 0; } QSnapdChange *QSnapdGetChangesRequest::change(int n) const { Q_D(const QSnapdGetChangesRequest); if (d->changes == NULL || n < 0 || (guint)n >= d->changes->len) return NULL; return new QSnapdChange(d->changes->pdata[n]); } QSnapdGetChangeRequest::QSnapdGetChangeRequest(const QString &id, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetChangeRequestPrivate(this, id)) {} void QSnapdGetChangeRequest::runSync() { Q_D(QSnapdGetChangeRequest); g_autoptr(GError) error = NULL; d->change = snapd_client_get_change_sync( SNAPD_CLIENT(getClient()), d->id.toStdString().c_str(), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetChangeRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetChangeRequest); g_autoptr(GError) error = NULL; g_autoptr(SnapdChange) change = snapd_client_get_change_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->change = (SnapdChange *)g_steal_pointer(&change); finish(error); } static void change_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetChangeRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetChangeRequest::runAsync() { Q_D(QSnapdGetChangeRequest); snapd_client_get_change_async( SNAPD_CLIENT(getClient()), d->id.toStdString().c_str(), G_CANCELLABLE(getCancellable()), change_ready_cb, g_object_ref(d->callback_data)); } QSnapdChange *QSnapdGetChangeRequest::change() const { Q_D(const QSnapdGetChangeRequest); return new QSnapdChange(d->change); } QSnapdAbortChangeRequest::QSnapdAbortChangeRequest(const QString &id, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdAbortChangeRequestPrivate(this, id)) {} void QSnapdAbortChangeRequest::runSync() { Q_D(QSnapdAbortChangeRequest); g_autoptr(GError) error = NULL; d->change = snapd_client_abort_change_sync( SNAPD_CLIENT(getClient()), d->id.toStdString().c_str(), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdAbortChangeRequest::handleResult(void *object, void *result) { Q_D(QSnapdAbortChangeRequest); g_autoptr(GError) error = NULL; g_autoptr(SnapdChange) change = snapd_client_abort_change_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->change = (SnapdChange *)g_steal_pointer(&change); finish(error); } static void abort_change_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdAbortChangeRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdAbortChangeRequest::runAsync() { Q_D(QSnapdAbortChangeRequest); snapd_client_abort_change_async( SNAPD_CLIENT(getClient()), d->id.toStdString().c_str(), G_CANCELLABLE(getCancellable()), abort_change_ready_cb, g_object_ref(d->callback_data)); } QSnapdChange *QSnapdAbortChangeRequest::change() const { Q_D(const QSnapdAbortChangeRequest); return new QSnapdChange(d->change); } QSnapdGetSystemInformationRequest::QSnapdGetSystemInformationRequest( void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetSystemInformationRequestPrivate(this)) {} void QSnapdGetSystemInformationRequest::runSync() { Q_D(QSnapdGetSystemInformationRequest); g_autoptr(GError) error = NULL; d->info = snapd_client_get_system_information_sync( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetSystemInformationRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetSystemInformationRequest); g_autoptr(GError) error = NULL; g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->info = (SnapdSystemInformation *)g_steal_pointer(&info); finish(error); } static void system_information_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetSystemInformationRequest *request = static_cast( callback_data->request); request->handleResult(object, result); } } void QSnapdGetSystemInformationRequest::runAsync() { Q_D(QSnapdGetSystemInformationRequest); snapd_client_get_system_information_async( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), system_information_ready_cb, g_object_ref(d->callback_data)); } QSnapdSystemInformation * QSnapdGetSystemInformationRequest::systemInformation() { Q_D(QSnapdGetSystemInformationRequest); return new QSnapdSystemInformation(d->info); } QSnapdListRequest::QSnapdListRequest(void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdListRequestPrivate(this)) {} void QSnapdListRequest::runSync() { Q_D(QSnapdListRequest); g_autoptr(GError) error = NULL; d->snaps = snapd_client_get_snaps_sync( SNAPD_CLIENT(getClient()), SNAPD_GET_SNAPS_FLAGS_NONE, NULL, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdListRequest::handleResult(void *object, void *result) { Q_D(QSnapdListRequest); g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) snaps = snapd_client_get_snaps_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->snaps = (GPtrArray *)g_steal_pointer(&snaps); finish(error); } static void list_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdListRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdListRequest::runAsync() { Q_D(QSnapdListRequest); snapd_client_get_snaps_async(SNAPD_CLIENT(getClient()), SNAPD_GET_SNAPS_FLAGS_NONE, NULL, G_CANCELLABLE(getCancellable()), list_ready_cb, g_object_ref(d->callback_data)); } int QSnapdListRequest::snapCount() const { Q_D(const QSnapdListRequest); return d->snaps != NULL ? d->snaps->len : 0; } QSnapdSnap *QSnapdListRequest::snap(int n) const { Q_D(const QSnapdListRequest); if (d->snaps == NULL || n < 0 || (guint)n >= d->snaps->len) return NULL; return new QSnapdSnap(d->snaps->pdata[n]); } static GStrv string_list_to_strv(const QStringList &list) { GStrv value; int size, i; size = list.size(); value = (GStrv)malloc(sizeof(gchar *) * (size + 1)); for (i = 0; i < size; i++) value[i] = g_strdup(list[i].toStdString().c_str()); value[size] = NULL; return value; } static SnapdGetSnapsFlags convertGetSnapsFlags(int flags) { int result = SNAPD_GET_SNAPS_FLAGS_NONE; if ((flags & QSnapdClient::GetSnapsFlag::IncludeInactive) != 0) result |= SNAPD_GET_SNAPS_FLAGS_INCLUDE_INACTIVE; if ((flags & QSnapdClient::GetSnapsFlag::RefreshInhibited) != 0) result |= SNAPD_GET_SNAPS_FLAGS_REFRESH_INHIBITED; return (SnapdGetSnapsFlags)result; } QSnapdGetSnapsRequest::QSnapdGetSnapsRequest(int flags, const QStringList &snaps, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetSnapsRequestPrivate(this, flags, snaps)) {} void QSnapdGetSnapsRequest::runSync() { Q_D(QSnapdGetSnapsRequest); g_auto(GStrv) snaps = string_list_to_strv(d->filter_snaps); g_autoptr(GError) error = NULL; d->snaps = snapd_client_get_snaps_sync( SNAPD_CLIENT(getClient()), convertGetSnapsFlags(d->flags), snaps, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetSnapsRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetSnapsRequest); g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) snaps = snapd_client_get_snaps_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->snaps = (GPtrArray *)g_steal_pointer(&snaps); finish(error); } static void get_snaps_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetSnapsRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetSnapsRequest::runAsync() { Q_D(QSnapdGetSnapsRequest); g_auto(GStrv) snaps = string_list_to_strv(d->filter_snaps); snapd_client_get_snaps_async( SNAPD_CLIENT(getClient()), convertGetSnapsFlags(d->flags), snaps, G_CANCELLABLE(getCancellable()), get_snaps_ready_cb, g_object_ref(d->callback_data)); } int QSnapdGetSnapsRequest::snapCount() const { Q_D(const QSnapdGetSnapsRequest); return d->snaps != NULL ? d->snaps->len : 0; } QSnapdSnap *QSnapdGetSnapsRequest::snap(int n) const { Q_D(const QSnapdGetSnapsRequest); if (d->snaps == NULL || n < 0 || (guint)n >= d->snaps->len) return NULL; return new QSnapdSnap(d->snaps->pdata[n]); } QSnapdListOneRequest::QSnapdListOneRequest(const QString &name, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdListOneRequestPrivate(this, name)) {} void QSnapdListOneRequest::runSync() { Q_D(QSnapdListOneRequest); g_autoptr(GError) error = NULL; d->snap = snapd_client_get_snap_sync( SNAPD_CLIENT(getClient()), d->name.isNull() ? NULL : d->name.toStdString().c_str(), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdListOneRequest::handleResult(void *object, void *result) { Q_D(QSnapdListOneRequest); g_autoptr(GError) error = NULL; g_autoptr(SnapdSnap) snap = snapd_client_get_snap_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->snap = (SnapdSnap *)g_steal_pointer(&snap); finish(error); } static void list_one_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdListOneRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdListOneRequest::runAsync() { Q_D(QSnapdListOneRequest); snapd_client_get_snap_async( SNAPD_CLIENT(getClient()), d->name.isNull() ? NULL : d->name.toStdString().c_str(), G_CANCELLABLE(getCancellable()), list_one_ready_cb, g_object_ref(d->callback_data)); } QSnapdSnap *QSnapdListOneRequest::snap() const { Q_D(const QSnapdListOneRequest); return new QSnapdSnap(d->snap); } QSnapdGetSnapRequest::QSnapdGetSnapRequest(const QString &name, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetSnapRequestPrivate(this, name)) {} void QSnapdGetSnapRequest::runSync() { Q_D(QSnapdGetSnapRequest); g_autoptr(GError) error = NULL; d->snap = snapd_client_get_snap_sync( SNAPD_CLIENT(getClient()), d->name.isNull() ? NULL : d->name.toStdString().c_str(), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetSnapRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetSnapRequest); g_autoptr(GError) error = NULL; g_autoptr(SnapdSnap) snap = snapd_client_get_snap_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->snap = (SnapdSnap *)g_steal_pointer(&snap); finish(error); } static void get_snap_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetSnapRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetSnapRequest::runAsync() { Q_D(QSnapdGetSnapRequest); snapd_client_get_snap_async( SNAPD_CLIENT(getClient()), d->name.isNull() ? NULL : d->name.toStdString().c_str(), G_CANCELLABLE(getCancellable()), get_snap_ready_cb, g_object_ref(d->callback_data)); } QSnapdSnap *QSnapdGetSnapRequest::snap() const { Q_D(const QSnapdGetSnapRequest); return new QSnapdSnap(d->snap); } QSnapdGetSnapConfRequest::QSnapdGetSnapConfRequest(const QString &name, const QStringList &keys, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetSnapConfRequestPrivate(this, name, keys)) {} void QSnapdGetSnapConfRequest::runSync() { Q_D(QSnapdGetSnapConfRequest); g_auto(GStrv) keys = string_list_to_strv(d->keys); g_autoptr(GError) error = NULL; d->configuration = snapd_client_get_snap_conf_sync( SNAPD_CLIENT(getClient()), d->name.isNull() ? NULL : d->name.toStdString().c_str(), keys, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetSnapConfRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetSnapConfRequest); g_autoptr(GError) error = NULL; g_autoptr(GHashTable) configuration = snapd_client_get_snap_conf_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->configuration = (GHashTable *)g_steal_pointer(&configuration); finish(error); } static void get_snap_conf_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetSnapConfRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetSnapConfRequest::runAsync() { Q_D(QSnapdGetSnapConfRequest); g_auto(GStrv) keys = string_list_to_strv(d->keys); snapd_client_get_snap_conf_async( SNAPD_CLIENT(getClient()), d->name.isNull() ? NULL : d->name.toStdString().c_str(), keys, G_CANCELLABLE(getCancellable()), get_snap_conf_ready_cb, g_object_ref(d->callback_data)); } QHash *QSnapdGetSnapConfRequest::configuration() const { Q_D(const QSnapdGetSnapConfRequest); QHash *conf = new QHash(); GHashTableIter iter; g_hash_table_iter_init(&iter, d->configuration); gpointer key, value; while (g_hash_table_iter_next(&iter, &key, &value)) { const gchar *conf_key = (const gchar *)key; GVariant *conf_value = (GVariant *)value; conf->insert(conf_key, gvariant_to_qvariant(conf_value)); } return conf; } QSnapdSetSnapConfRequest::QSnapdSetSnapConfRequest( const QString &name, const QHash &configuration, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdSetSnapConfRequestPrivate(this, name, configuration)) {} static GVariant *qvariant_to_gvariant(const QVariant &variant) { if (variant.isNull()) return g_variant_new("mv", NULL); switch (variant.type()) { case QMetaType::Bool: return g_variant_new_boolean(variant.value()); case QMetaType::Int: return g_variant_new_int64(variant.value()); case QMetaType::LongLong: return g_variant_new_int64(variant.value()); case QMetaType::QString: return g_variant_new_string(variant.value().toStdString().c_str()); case QMetaType::Double: return g_variant_new_double(variant.value()); case QMetaType::QVariantList: { g_autoptr(GVariantBuilder) builder = g_variant_builder_new(G_VARIANT_TYPE("av")); QList list = variant.toList(); for (int i = 0; i < list.length(); i++) { GVariant *v = qvariant_to_gvariant(list[i]); g_variant_builder_add(builder, "v", v); } return g_variant_ref_sink(g_variant_builder_end(builder)); } case QMetaType::QVariantMap: case QMetaType::QVariantHash: { g_autoptr(GVariantBuilder) builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); QMap map = variant.toMap(); QMapIterator i(map); while (i.hasNext()) { i.next(); GVariant *v = qvariant_to_gvariant(i.value()); g_variant_builder_add(builder, "{sv}", i.key().toStdString().c_str(), v); } return g_variant_ref_sink(g_variant_builder_end(builder)); } default: return g_variant_new("mv", NULL); } } static GHashTable * configuration_to_key_values(const QHash &configuration) { g_autoptr(GHashTable) conf = NULL; conf = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref); QHashIterator i(configuration); while (i.hasNext()) { i.next(); g_hash_table_insert(conf, g_strdup(i.key().toStdString().c_str()), qvariant_to_gvariant(i.value())); } return (GHashTable *)g_steal_pointer(&conf); } void QSnapdSetSnapConfRequest::runSync() { Q_D(QSnapdSetSnapConfRequest); g_autoptr(GHashTable) key_values = configuration_to_key_values(d->configuration); g_autoptr(GError) error = NULL; snapd_client_set_snap_conf_sync( SNAPD_CLIENT(getClient()), d->name.isNull() ? NULL : d->name.toStdString().c_str(), key_values, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdSetSnapConfRequest::handleResult(void *object, void *result) { g_autoptr(GHashTable) configuration = NULL; g_autoptr(GError) error = NULL; snapd_client_set_snap_conf_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void set_snap_conf_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdSetSnapConfRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdSetSnapConfRequest::runAsync() { Q_D(QSnapdSetSnapConfRequest); g_autoptr(GHashTable) key_values = configuration_to_key_values(d->configuration); snapd_client_set_snap_conf_async( SNAPD_CLIENT(getClient()), d->name.isNull() ? NULL : d->name.toStdString().c_str(), key_values, G_CANCELLABLE(getCancellable()), set_snap_conf_ready_cb, g_object_ref(d->callback_data)); } static SnapdGetAppsFlags convertGetAppsFlags(int flags) { int result = SNAPD_GET_APPS_FLAGS_NONE; if ((flags & QSnapdClient::GetAppsFlag::SelectServices) != 0) result |= SNAPD_GET_APPS_FLAGS_SELECT_SERVICES; return (SnapdGetAppsFlags)result; } QSnapdGetAppsRequest::QSnapdGetAppsRequest(int flags, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetAppsRequestPrivate(this, flags, QStringList())) {} QSnapdGetAppsRequest::QSnapdGetAppsRequest(int flags, const QStringList &snaps, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetAppsRequestPrivate(this, flags, snaps)) {} void QSnapdGetAppsRequest::runSync() { Q_D(QSnapdGetAppsRequest); g_auto(GStrv) snaps = string_list_to_strv(d->filter_snaps); g_autoptr(GError) error = NULL; d->apps = snapd_client_get_apps2_sync( SNAPD_CLIENT(getClient()), convertGetAppsFlags(d->flags), snaps, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetAppsRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetAppsRequest); g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) apps = snapd_client_get_apps2_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->apps = (GPtrArray *)g_steal_pointer(&apps); finish(error); } static void get_apps_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetAppsRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetAppsRequest::runAsync() { Q_D(QSnapdGetAppsRequest); g_auto(GStrv) snaps = string_list_to_strv(d->filter_snaps); snapd_client_get_apps2_async( SNAPD_CLIENT(getClient()), convertGetAppsFlags(d->flags), snaps, G_CANCELLABLE(getCancellable()), get_apps_ready_cb, g_object_ref(d->callback_data)); } int QSnapdGetAppsRequest::appCount() const { Q_D(const QSnapdGetAppsRequest); return d->apps != NULL ? d->apps->len : 0; } QSnapdApp *QSnapdGetAppsRequest::app(int n) const { Q_D(const QSnapdGetAppsRequest); if (d->apps == NULL || n < 0 || (guint)n >= d->apps->len) return NULL; return new QSnapdApp(d->apps->pdata[n]); } QSnapdGetIconRequest::QSnapdGetIconRequest(const QString &name, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetIconRequestPrivate(this, name)) {} void QSnapdGetIconRequest::runSync() { Q_D(QSnapdGetIconRequest); g_autoptr(GError) error = NULL; d->icon = snapd_client_get_icon_sync(SNAPD_CLIENT(getClient()), d->name.toStdString().c_str(), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetIconRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetIconRequest); g_autoptr(GError) error = NULL; g_autoptr(SnapdIcon) icon = snapd_client_get_icon_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->icon = (SnapdIcon *)g_steal_pointer(&icon); finish(error); } static void get_icon_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetIconRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetIconRequest::runAsync() { Q_D(QSnapdGetIconRequest); snapd_client_get_icon_async( SNAPD_CLIENT(getClient()), d->name.toStdString().c_str(), G_CANCELLABLE(getCancellable()), get_icon_ready_cb, g_object_ref(d->callback_data)); } QSnapdIcon *QSnapdGetIconRequest::icon() const { Q_D(const QSnapdGetIconRequest); return new QSnapdIcon(d->icon); } QSnapdGetAssertionsRequest::QSnapdGetAssertionsRequest(const QString &type, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetAssertionsRequestPrivate(this, type)) {} void QSnapdGetAssertionsRequest::runSync() { Q_D(QSnapdGetAssertionsRequest); g_autoptr(GError) error = NULL; d->assertions = snapd_client_get_assertions_sync( SNAPD_CLIENT(getClient()), d->type.toStdString().c_str(), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetAssertionsRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetAssertionsRequest); g_autoptr(GError) error = NULL; g_auto(GStrv) assertions = snapd_client_get_assertions_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->assertions = (GStrv)g_steal_pointer(&assertions); finish(error); } static void get_assertions_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetAssertionsRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetAssertionsRequest::runAsync() { Q_D(QSnapdGetAssertionsRequest); snapd_client_get_assertions_async( SNAPD_CLIENT(getClient()), d->type.toStdString().c_str(), G_CANCELLABLE(getCancellable()), get_assertions_ready_cb, g_object_ref(d->callback_data)); } QStringList QSnapdGetAssertionsRequest::assertions() const { Q_D(const QSnapdGetAssertionsRequest); QStringList result; for (int i = 0; d->assertions[i] != NULL; i++) result.append(d->assertions[i]); return result; } QSnapdAddAssertionsRequest::QSnapdAddAssertionsRequest( const QStringList &assertions, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdAddAssertionsRequestPrivate(this, assertions)) {} void QSnapdAddAssertionsRequest::runSync() { Q_D(QSnapdAddAssertionsRequest); g_auto(GStrv) assertions = string_list_to_strv(d->assertions); g_autoptr(GError) error = NULL; snapd_client_add_assertions_sync(SNAPD_CLIENT(getClient()), assertions, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdAddAssertionsRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_add_assertions_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void add_assertions_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdAddAssertionsRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdAddAssertionsRequest::runAsync() { Q_D(QSnapdAddAssertionsRequest); g_auto(GStrv) assertions = string_list_to_strv(d->assertions); snapd_client_add_assertions_async( SNAPD_CLIENT(getClient()), assertions, G_CANCELLABLE(getCancellable()), add_assertions_ready_cb, g_object_ref(d->callback_data)); } static SnapdGetConnectionsFlags convertGetConnectionsFlags(int flags) { int result = SNAPD_GET_CONNECTIONS_FLAGS_NONE; if ((flags & QSnapdClient::GetConnectionsFlag::SelectAll) != 0) result |= SNAPD_GET_CONNECTIONS_FLAGS_SELECT_ALL; return (SnapdGetConnectionsFlags)result; } QSnapdGetConnectionsRequest::QSnapdGetConnectionsRequest( int flags, const QString &snap, const QString &interface, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetConnectionsRequestPrivate(this, flags, snap, interface)) {} void QSnapdGetConnectionsRequest::runSync() { Q_D(QSnapdGetConnectionsRequest); g_autoptr(GError) error = NULL; snapd_client_get_connections2_sync( SNAPD_CLIENT(getClient()), convertGetConnectionsFlags(d->flags), d->snap.isNull() ? NULL : d->snap.toStdString().c_str(), d->interface.isNull() ? NULL : d->interface.toStdString().c_str(), &d->established, &d->undesired, &d->plugs, &d->slots_, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetConnectionsRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetConnectionsRequest); g_autoptr(GPtrArray) established = NULL; g_autoptr(GPtrArray) undesired = NULL; g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots_ = NULL; g_autoptr(GError) error = NULL; snapd_client_get_connections2_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &established, &undesired, &plugs, &slots_, &error); d->established = (GPtrArray *)g_steal_pointer(&established); d->undesired = (GPtrArray *)g_steal_pointer(&undesired); d->plugs = (GPtrArray *)g_steal_pointer(&plugs); d->slots_ = (GPtrArray *)g_steal_pointer(&slots_); finish(error); } static void get_connections_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetConnectionsRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetConnectionsRequest::runAsync() { Q_D(QSnapdGetConnectionsRequest); snapd_client_get_connections2_async( SNAPD_CLIENT(getClient()), convertGetConnectionsFlags(d->flags), d->snap.isNull() ? NULL : d->snap.toStdString().c_str(), d->interface.isNull() ? NULL : d->interface.toStdString().c_str(), G_CANCELLABLE(getCancellable()), get_connections_ready_cb, g_object_ref(d->callback_data)); } int QSnapdGetConnectionsRequest::establishedCount() const { Q_D(const QSnapdGetConnectionsRequest); return d->established != NULL ? d->established->len : 0; } QSnapdConnection *QSnapdGetConnectionsRequest::established(int n) const { Q_D(const QSnapdGetConnectionsRequest); if (d->established == NULL || n < 0 || (guint)n >= d->established->len) return NULL; return new QSnapdConnection(d->established->pdata[n]); } int QSnapdGetConnectionsRequest::undesiredCount() const { Q_D(const QSnapdGetConnectionsRequest); return d->undesired != NULL ? d->undesired->len : 0; } QSnapdConnection *QSnapdGetConnectionsRequest::undesired(int n) const { Q_D(const QSnapdGetConnectionsRequest); if (d->undesired == NULL || n < 0 || (guint)n >= d->undesired->len) return NULL; return new QSnapdConnection(d->undesired->pdata[n]); } int QSnapdGetConnectionsRequest::plugCount() const { Q_D(const QSnapdGetConnectionsRequest); return d->plugs != NULL ? d->plugs->len : 0; } QSnapdPlug *QSnapdGetConnectionsRequest::plug(int n) const { Q_D(const QSnapdGetConnectionsRequest); if (d->plugs == NULL || n < 0 || (guint)n >= d->plugs->len) return NULL; return new QSnapdPlug(d->plugs->pdata[n]); } int QSnapdGetConnectionsRequest::slotCount() const { Q_D(const QSnapdGetConnectionsRequest); return d->slots_ != NULL ? d->slots_->len : 0; } QSnapdSlot *QSnapdGetConnectionsRequest::slot(int n) const { Q_D(const QSnapdGetConnectionsRequest); if (d->slots_ == NULL || n < 0 || (guint)n >= d->slots_->len) return NULL; return new QSnapdSlot(d->slots_->pdata[n]); } QSnapdGetInterfacesRequest::QSnapdGetInterfacesRequest(void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetInterfacesRequestPrivate(this)) {} void QSnapdGetInterfacesRequest::runSync() { Q_D(QSnapdGetInterfacesRequest); g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_get_interfaces_sync(SNAPD_CLIENT(getClient()), &d->plugs, &d->slots_, G_CANCELLABLE(getCancellable()), &error); G_GNUC_END_IGNORE_DEPRECATIONS finish(error); } void QSnapdGetInterfacesRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetInterfacesRequest); g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots_ = NULL; g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_get_interfaces_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &plugs, &slots_, &error); G_GNUC_END_IGNORE_DEPRECATIONS d->plugs = (GPtrArray *)g_steal_pointer(&plugs); d->slots_ = (GPtrArray *)g_steal_pointer(&slots_); finish(error); } static void get_interfaces_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetInterfacesRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetInterfacesRequest::runAsync() { Q_D(QSnapdGetInterfacesRequest); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_get_interfaces_async( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), get_interfaces_ready_cb, g_object_ref(d->callback_data)); G_GNUC_END_IGNORE_DEPRECATIONS } int QSnapdGetInterfacesRequest::plugCount() const { Q_D(const QSnapdGetInterfacesRequest); return d->plugs != NULL ? d->plugs->len : 0; } QSnapdPlug *QSnapdGetInterfacesRequest::plug(int n) const { Q_D(const QSnapdGetInterfacesRequest); if (d->plugs == NULL || n < 0 || (guint)n >= d->plugs->len) return NULL; return new QSnapdPlug(d->plugs->pdata[n]); } int QSnapdGetInterfacesRequest::slotCount() const { Q_D(const QSnapdGetInterfacesRequest); return d->slots_ != NULL ? d->slots_->len : 0; } QSnapdSlot *QSnapdGetInterfacesRequest::slot(int n) const { Q_D(const QSnapdGetInterfacesRequest); if (d->slots_ == NULL || n < 0 || (guint)n >= d->slots_->len) return NULL; return new QSnapdSlot(d->slots_->pdata[n]); } QSnapdGetInterfaces2Request::QSnapdGetInterfaces2Request( int flags, const QStringList &names, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetInterfaces2RequestPrivate(this, flags, names)) {} static SnapdGetInterfacesFlags convertInterfaceFlags(int flags) { int result = SNAPD_GET_INTERFACES_FLAGS_NONE; if ((flags & QSnapdClient::InterfaceFlag::IncludeDocs) != 0) result |= SNAPD_GET_INTERFACES_FLAGS_INCLUDE_DOCS; if ((flags & QSnapdClient::InterfaceFlag::IncludePlugs) != 0) result |= SNAPD_GET_INTERFACES_FLAGS_INCLUDE_PLUGS; if ((flags & QSnapdClient::InterfaceFlag::IncludeSlots) != 0) result |= SNAPD_GET_INTERFACES_FLAGS_INCLUDE_SLOTS; if ((flags & QSnapdClient::InterfaceFlag::OnlyConnected) != 0) result |= SNAPD_GET_INTERFACES_FLAGS_ONLY_CONNECTED; return (SnapdGetInterfacesFlags)result; } void QSnapdGetInterfaces2Request::runSync() { Q_D(QSnapdGetInterfaces2Request); g_auto(GStrv) names = string_list_to_strv(d->names); g_autoptr(GError) error = NULL; d->interfaces = snapd_client_get_interfaces2_sync( SNAPD_CLIENT(getClient()), convertInterfaceFlags(d->flags), names, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetInterfaces2Request::handleResult(void *object, void *result) { Q_D(QSnapdGetInterfaces2Request); g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) interfaces = snapd_client_get_interfaces2_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->interfaces = (GPtrArray *)g_steal_pointer(&interfaces); finish(error); } static void get_interfaces2_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetInterfaces2Request *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetInterfaces2Request::runAsync() { Q_D(QSnapdGetInterfaces2Request); g_auto(GStrv) names = string_list_to_strv(d->names); snapd_client_get_interfaces2_async( SNAPD_CLIENT(getClient()), convertInterfaceFlags(d->flags), names, G_CANCELLABLE(getCancellable()), get_interfaces2_ready_cb, g_object_ref(d->callback_data)); } int QSnapdGetInterfaces2Request::interfaceCount() const { Q_D(const QSnapdGetInterfaces2Request); return d->interfaces != NULL ? d->interfaces->len : 0; } QSnapdInterface *QSnapdGetInterfaces2Request::interface(int n) const { Q_D(const QSnapdGetInterfaces2Request); if (d->interfaces == NULL || n < 0 || (guint)n >= d->interfaces->len) return NULL; return new QSnapdInterface(d->interfaces->pdata[n]); } QSnapdConnectInterfaceRequest::QSnapdConnectInterfaceRequest( const QString &plug_snap, const QString &plug_name, const QString &slot_snap, const QString &slot_name, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdConnectInterfaceRequestPrivate(this, plug_snap, plug_name, slot_snap, slot_name)) {} static void progress_cb(SnapdClient *client, SnapdChange *change, gpointer, gpointer data) { CallbackData *callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdRequest *request = static_cast(callback_data->request); request->handleProgress(change); } } void QSnapdConnectInterfaceRequest::runSync() { Q_D(QSnapdConnectInterfaceRequest); g_autoptr(GError) error = NULL; snapd_client_connect_interface_sync( SNAPD_CLIENT(getClient()), d->plug_snap.toStdString().c_str(), d->plug_name.toStdString().c_str(), d->slot_snap.toStdString().c_str(), d->slot_name.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdConnectInterfaceRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_connect_interface_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void connect_interface_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdConnectInterfaceRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdConnectInterfaceRequest::runAsync() { Q_D(QSnapdConnectInterfaceRequest); snapd_client_connect_interface_async( SNAPD_CLIENT(getClient()), d->plug_snap.toStdString().c_str(), d->plug_name.toStdString().c_str(), d->slot_snap.toStdString().c_str(), d->slot_name.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), connect_interface_ready_cb, g_object_ref(d->callback_data)); } QSnapdDisconnectInterfaceRequest::QSnapdDisconnectInterfaceRequest( const QString &plug_snap, const QString &plug_name, const QString &slot_snap, const QString &slot_name, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdDisconnectInterfaceRequestPrivate( this, plug_snap, plug_name, slot_snap, slot_name)) {} void QSnapdDisconnectInterfaceRequest::runSync() { Q_D(QSnapdDisconnectInterfaceRequest); g_autoptr(GError) error = NULL; snapd_client_disconnect_interface_sync( SNAPD_CLIENT(getClient()), d->plug_snap.toStdString().c_str(), d->plug_name.toStdString().c_str(), d->slot_snap.toStdString().c_str(), d->slot_name.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdDisconnectInterfaceRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_disconnect_interface_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void disconnect_interface_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdDisconnectInterfaceRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdDisconnectInterfaceRequest::runAsync() { Q_D(QSnapdDisconnectInterfaceRequest); snapd_client_disconnect_interface_async( SNAPD_CLIENT(getClient()), d->plug_snap.toStdString().c_str(), d->plug_name.toStdString().c_str(), d->slot_snap.toStdString().c_str(), d->slot_name.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), disconnect_interface_ready_cb, g_object_ref(d->callback_data)); } static SnapdFindFlags convertFindFlags(int flags) { int result = SNAPD_FIND_FLAGS_NONE; if ((flags & QSnapdClient::FindFlag::MatchName) != 0) result |= SNAPD_FIND_FLAGS_MATCH_NAME; if ((flags & QSnapdClient::FindFlag::MatchCommonId) != 0) result |= SNAPD_FIND_FLAGS_MATCH_COMMON_ID; if ((flags & QSnapdClient::FindFlag::SelectPrivate) != 0) result |= SNAPD_FIND_FLAGS_SELECT_PRIVATE; if ((flags & QSnapdClient::FindFlag::ScopeWide) != 0) result |= SNAPD_FIND_FLAGS_SCOPE_WIDE; return (SnapdFindFlags)result; } QSnapdFindRequest::QSnapdFindRequest(int flags, const QString §ion, const QString &category, const QString &name, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr( new QSnapdFindRequestPrivate(this, flags, section, category, name)) {} void QSnapdFindRequest::runSync() { Q_D(QSnapdFindRequest); g_autoptr(GError) error = NULL; g_autofree gchar *suggested_currency = NULL; if (d->section.isNull()) { d->snaps = snapd_client_find_category_sync( SNAPD_CLIENT(getClient()), convertFindFlags(d->flags), d->category.isNull() ? NULL : d->category.toStdString().c_str(), d->name.isNull() ? NULL : d->name.toStdString().c_str(), &suggested_currency, G_CANCELLABLE(getCancellable()), &error); } else { G_GNUC_BEGIN_IGNORE_DEPRECATIONS d->snaps = snapd_client_find_section_sync( SNAPD_CLIENT(getClient()), convertFindFlags(d->flags), d->section.isNull() ? NULL : d->section.toStdString().c_str(), d->name.isNull() ? NULL : d->name.toStdString().c_str(), &suggested_currency, G_CANCELLABLE(getCancellable()), &error); G_GNUC_END_IGNORE_DEPRECATIONS } d->suggestedCurrency = suggested_currency; finish(error); } void QSnapdFindRequest::handleResult(void *object, void *result) { Q_D(QSnapdFindRequest); g_autofree gchar *suggested_currency = NULL; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) snaps = NULL; if (d->section.isNull()) { snaps = snapd_client_find_category_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &suggested_currency, &error); } else { G_GNUC_BEGIN_IGNORE_DEPRECATIONS snaps = snapd_client_find_section_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &suggested_currency, &error); G_GNUC_END_IGNORE_DEPRECATIONS } d->snaps = (GPtrArray *)g_steal_pointer(&snaps); d->suggestedCurrency = suggested_currency; finish(error); } static void find_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdFindRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdFindRequest::runAsync() { Q_D(QSnapdFindRequest); if (d->section.isNull()) { snapd_client_find_category_async( SNAPD_CLIENT(getClient()), convertFindFlags(d->flags), d->category.isNull() ? NULL : d->category.toStdString().c_str(), d->name.isNull() ? NULL : d->name.toStdString().c_str(), G_CANCELLABLE(getCancellable()), find_ready_cb, g_object_ref(d->callback_data)); } else { G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_find_section_async( SNAPD_CLIENT(getClient()), convertFindFlags(d->flags), d->section.isNull() ? NULL : d->section.toStdString().c_str(), d->name.isNull() ? NULL : d->name.toStdString().c_str(), G_CANCELLABLE(getCancellable()), find_ready_cb, g_object_ref(d->callback_data)); G_GNUC_END_IGNORE_DEPRECATIONS } } int QSnapdFindRequest::snapCount() const { Q_D(const QSnapdFindRequest); return d->snaps != NULL ? d->snaps->len : 0; } QSnapdSnap *QSnapdFindRequest::snap(int n) const { Q_D(const QSnapdFindRequest); if (d->snaps == NULL || n < 0 || (guint)n >= d->snaps->len) return NULL; return new QSnapdSnap(d->snaps->pdata[n]); } const QString QSnapdFindRequest::suggestedCurrency() const { Q_D(const QSnapdFindRequest); return d->suggestedCurrency; } QSnapdFindRefreshableRequest::QSnapdFindRefreshableRequest(void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdFindRefreshableRequestPrivate(this)) {} void QSnapdFindRefreshableRequest::runSync() { Q_D(QSnapdFindRefreshableRequest); g_autoptr(GError) error = NULL; d->snaps = snapd_client_find_refreshable_sync( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdFindRefreshableRequest::handleResult(void *object, void *result) { Q_D(QSnapdFindRefreshableRequest); g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) snaps = snapd_client_find_refreshable_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->snaps = (GPtrArray *)g_steal_pointer(&snaps); finish(error); } static void find_refreshable_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdFindRefreshableRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdFindRefreshableRequest::runAsync() { Q_D(QSnapdFindRefreshableRequest); snapd_client_find_refreshable_async( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), find_refreshable_ready_cb, g_object_ref(d->callback_data)); } int QSnapdFindRefreshableRequest::snapCount() const { Q_D(const QSnapdFindRefreshableRequest); return d->snaps != NULL ? d->snaps->len : 0; } QSnapdSnap *QSnapdFindRefreshableRequest::snap(int n) const { Q_D(const QSnapdFindRefreshableRequest); if (d->snaps == NULL || n < 0 || (guint)n >= d->snaps->len) return NULL; return new QSnapdSnap(d->snaps->pdata[n]); } static SnapdInstallFlags convertInstallFlags(int flags) { int result = SNAPD_INSTALL_FLAGS_NONE; if ((flags & QSnapdClient::InstallFlag::Classic) != 0) result |= SNAPD_INSTALL_FLAGS_CLASSIC; if ((flags & QSnapdClient::InstallFlag::Dangerous) != 0) result |= SNAPD_INSTALL_FLAGS_DANGEROUS; if ((flags & QSnapdClient::InstallFlag::Devmode) != 0) result |= SNAPD_INSTALL_FLAGS_DEVMODE; if ((flags & QSnapdClient::InstallFlag::Jailmode) != 0) result |= SNAPD_INSTALL_FLAGS_JAILMODE; return (SnapdInstallFlags)result; } QSnapdInstallRequest::QSnapdInstallRequest(int flags, const QString &name, const QString &channel, const QString &revision, QIODevice *ioDevice, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdInstallRequestPrivate(this, flags, name, channel, revision, ioDevice)) {} void QSnapdInstallRequest::runSync() { Q_D(QSnapdInstallRequest); g_autoptr(GError) error = NULL; if (d->wrapper != NULL) { snapd_client_install_stream_sync( SNAPD_CLIENT(getClient()), convertInstallFlags(d->flags), G_INPUT_STREAM(d->wrapper), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); } else { snapd_client_install2_sync( SNAPD_CLIENT(getClient()), convertInstallFlags(d->flags), d->name.toStdString().c_str(), d->channel.isNull() ? NULL : d->channel.toStdString().c_str(), d->revision.isNull() ? NULL : d->revision.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); } finish(error); } void QSnapdInstallRequest::handleResult(void *object, void *result) { Q_D(QSnapdInstallRequest); g_autoptr(GError) error = NULL; if (d->wrapper != NULL) snapd_client_install_stream_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); else snapd_client_install2_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void install_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdInstallRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdInstallRequest::runAsync() { Q_D(QSnapdInstallRequest); if (d->wrapper != NULL) snapd_client_install_stream_async( SNAPD_CLIENT(getClient()), convertInstallFlags(d->flags), G_INPUT_STREAM(d->wrapper), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), install_ready_cb, g_object_ref(d->callback_data)); else snapd_client_install2_async( SNAPD_CLIENT(getClient()), convertInstallFlags(d->flags), d->name.toStdString().c_str(), d->channel.isNull() ? NULL : d->channel.toStdString().c_str(), d->revision.isNull() ? NULL : d->revision.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), install_ready_cb, g_object_ref(d->callback_data)); } QSnapdTryRequest::QSnapdTryRequest(const QString &path, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdTryRequestPrivate(this, path)) {} void QSnapdTryRequest::runSync() { Q_D(QSnapdTryRequest); g_autoptr(GError) error = NULL; snapd_client_try_sync( SNAPD_CLIENT(getClient()), d->path.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdTryRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_try_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void try_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdTryRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdTryRequest::runAsync() { Q_D(QSnapdTryRequest); snapd_client_try_async(SNAPD_CLIENT(getClient()), d->path.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), try_ready_cb, g_object_ref(d->callback_data)); } QSnapdRefreshRequest::QSnapdRefreshRequest(const QString &name, const QString &channel, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdRefreshRequestPrivate(this, name, channel)) {} void QSnapdRefreshRequest::runSync() { Q_D(QSnapdRefreshRequest); g_autoptr(GError) error = NULL; snapd_client_refresh_sync( SNAPD_CLIENT(getClient()), d->name.toStdString().c_str(), d->channel.isNull() ? NULL : d->channel.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdRefreshRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_refresh_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void refresh_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdRefreshRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdRefreshRequest::runAsync() { Q_D(QSnapdRefreshRequest); snapd_client_refresh_async( SNAPD_CLIENT(getClient()), d->name.toStdString().c_str(), d->channel.isNull() ? NULL : d->channel.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), refresh_ready_cb, g_object_ref(d->callback_data)); } QSnapdRefreshAllRequest::QSnapdRefreshAllRequest(void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdRefreshAllRequestPrivate(this)) {} void QSnapdRefreshAllRequest::runSync() { Q_D(QSnapdRefreshAllRequest); g_autoptr(GError) error = NULL; d->snap_names = snapd_client_refresh_all_sync( SNAPD_CLIENT(getClient()), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdRefreshAllRequest::handleResult(void *object, void *result) { Q_D(QSnapdRefreshAllRequest); g_autoptr(GError) error = NULL; g_auto(GStrv) snap_names = snapd_client_refresh_all_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->snap_names = (GStrv)g_steal_pointer(&snap_names); finish(error); } static void refresh_all_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdRefreshAllRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdRefreshAllRequest::runAsync() { Q_D(QSnapdRefreshAllRequest); snapd_client_refresh_all_async( SNAPD_CLIENT(getClient()), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), refresh_all_ready_cb, g_object_ref(d->callback_data)); } QStringList QSnapdRefreshAllRequest::snapNames() const { Q_D(const QSnapdRefreshAllRequest); QStringList result; for (int i = 0; d->snap_names[i] != NULL; i++) result.append(d->snap_names[i]); return result; } static SnapdRemoveFlags convertRemoveFlags(int flags) { int result = SNAPD_REMOVE_FLAGS_NONE; if ((flags & QSnapdClient::RemoveFlag::Purge) != 0) result |= SNAPD_REMOVE_FLAGS_PURGE; return (SnapdRemoveFlags)result; } QSnapdRemoveRequest::QSnapdRemoveRequest(int flags, const QString &name, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdRemoveRequestPrivate(this, flags, name)) {} void QSnapdRemoveRequest::runSync() { Q_D(QSnapdRemoveRequest); g_autoptr(GError) error = NULL; snapd_client_remove2_sync( SNAPD_CLIENT(getClient()), convertRemoveFlags(d->flags), d->name.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdRemoveRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_remove2_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void remove_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdRemoveRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdRemoveRequest::runAsync() { Q_D(QSnapdRemoveRequest); snapd_client_remove2_async(SNAPD_CLIENT(getClient()), convertRemoveFlags(d->flags), d->name.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), remove_ready_cb, g_object_ref(d->callback_data)); } QSnapdEnableRequest::QSnapdEnableRequest(const QString &name, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdEnableRequestPrivate(this, name)) {} void QSnapdEnableRequest::runSync() { Q_D(QSnapdEnableRequest); g_autoptr(GError) error = NULL; snapd_client_enable_sync( SNAPD_CLIENT(getClient()), d->name.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdEnableRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_enable_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void enable_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdEnableRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdEnableRequest::runAsync() { Q_D(QSnapdEnableRequest); snapd_client_enable_async(SNAPD_CLIENT(getClient()), d->name.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), enable_ready_cb, g_object_ref(d->callback_data)); } QSnapdDisableRequest::QSnapdDisableRequest(const QString &name, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdDisableRequestPrivate(this, name)) {} void QSnapdDisableRequest::runSync() { Q_D(QSnapdDisableRequest); g_autoptr(GError) error = NULL; snapd_client_disable_sync( SNAPD_CLIENT(getClient()), d->name.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdDisableRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_disable_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void disable_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdDisableRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdDisableRequest::runAsync() { Q_D(QSnapdDisableRequest); snapd_client_disable_async(SNAPD_CLIENT(getClient()), d->name.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), disable_ready_cb, g_object_ref(d->callback_data)); } QSnapdSwitchChannelRequest::QSnapdSwitchChannelRequest(const QString &name, const QString &channel, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdSwitchChannelRequestPrivate(this, name, channel)) {} void QSnapdSwitchChannelRequest::runSync() { Q_D(QSnapdSwitchChannelRequest); g_autoptr(GError) error = NULL; snapd_client_switch_sync( SNAPD_CLIENT(getClient()), d->name.toStdString().c_str(), d->channel.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdSwitchChannelRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_switch_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void switch_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdSwitchChannelRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdSwitchChannelRequest::runAsync() { Q_D(QSnapdSwitchChannelRequest); snapd_client_switch_async(SNAPD_CLIENT(getClient()), d->name.toStdString().c_str(), d->channel.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), switch_ready_cb, g_object_ref(d->callback_data)); } QSnapdCheckBuyRequest::QSnapdCheckBuyRequest(void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdCheckBuyRequestPrivate(this)) {} void QSnapdCheckBuyRequest::runSync() { Q_D(QSnapdCheckBuyRequest); g_autoptr(GError) error = NULL; d->canBuy = snapd_client_check_buy_sync( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdCheckBuyRequest::handleResult(void *object, void *result) { Q_D(QSnapdCheckBuyRequest); g_autoptr(GError) error = NULL; gboolean can_buy = snapd_client_check_buy_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->canBuy = can_buy; finish(error); } static void check_buy_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdCheckBuyRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdCheckBuyRequest::runAsync() { Q_D(QSnapdCheckBuyRequest); snapd_client_check_buy_async( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), check_buy_ready_cb, g_object_ref(d->callback_data)); } bool QSnapdCheckBuyRequest::canBuy() const { Q_D(const QSnapdCheckBuyRequest); return d->canBuy; } QSnapdBuyRequest::QSnapdBuyRequest(const QString &id, double amount, const QString ¤cy, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdBuyRequestPrivate(this, id, amount, currency)) {} void QSnapdBuyRequest::runSync() { Q_D(QSnapdBuyRequest); g_autoptr(GError) error = NULL; snapd_client_buy_sync(SNAPD_CLIENT(getClient()), d->id.toStdString().c_str(), d->amount, d->currency.toStdString().c_str(), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdBuyRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_buy_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void buy_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdBuyRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdBuyRequest::runAsync() { Q_D(QSnapdBuyRequest); snapd_client_buy_async(SNAPD_CLIENT(getClient()), d->id.toStdString().c_str(), d->amount, d->currency.toStdString().c_str(), G_CANCELLABLE(getCancellable()), buy_ready_cb, g_object_ref(d->callback_data)); } static SnapdCreateUserFlags convertCreateUserFlags(int flags) { int result = SNAPD_CREATE_USER_FLAGS_NONE; if ((flags & QSnapdClient::CreateUserFlag::Sudo) != 0) result |= SNAPD_CREATE_USER_FLAGS_SUDO; if ((flags & QSnapdClient::CreateUserFlag::Known) != 0) result |= SNAPD_CREATE_USER_FLAGS_KNOWN; return (SnapdCreateUserFlags)result; } QSnapdCreateUserRequest::QSnapdCreateUserRequest(const QString &email, int flags, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdCreateUserRequestPrivate(this, email, flags)) {} void QSnapdCreateUserRequest::runSync() { Q_D(QSnapdCreateUserRequest); g_autoptr(GError) error = NULL; d->info = snapd_client_create_user_sync( SNAPD_CLIENT(getClient()), d->email.toStdString().c_str(), convertCreateUserFlags(d->flags), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdCreateUserRequest::handleResult(void *object, void *result) { Q_D(QSnapdCreateUserRequest); g_autoptr(GError) error = NULL; d->info = snapd_client_create_user_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void create_user_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdCreateUserRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdCreateUserRequest::runAsync() { Q_D(QSnapdCreateUserRequest); snapd_client_create_user_async( SNAPD_CLIENT(getClient()), d->email.toStdString().c_str(), convertCreateUserFlags(d->flags), G_CANCELLABLE(getCancellable()), create_user_ready_cb, g_object_ref(d->callback_data)); } QSnapdUserInformation *QSnapdCreateUserRequest::userInformation() const { Q_D(const QSnapdCreateUserRequest); return new QSnapdUserInformation(d->info); } QSnapdCreateUsersRequest::QSnapdCreateUsersRequest(void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdCreateUsersRequestPrivate(this)) {} void QSnapdCreateUsersRequest::runSync() { Q_D(QSnapdCreateUsersRequest); g_autoptr(GError) error = NULL; d->info = snapd_client_create_users_sync( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdCreateUsersRequest::handleResult(void *object, void *result) { Q_D(QSnapdCreateUsersRequest); g_autoptr(GError) error = NULL; d->info = snapd_client_create_users_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void create_users_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdCreateUsersRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdCreateUsersRequest::runAsync() { Q_D(QSnapdCreateUsersRequest); snapd_client_create_users_async( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), create_users_ready_cb, g_object_ref(d->callback_data)); } int QSnapdCreateUsersRequest::userInformationCount() const { Q_D(const QSnapdCreateUsersRequest); return d->info != NULL ? d->info->len : 0; } QSnapdUserInformation *QSnapdCreateUsersRequest::userInformation(int n) const { Q_D(const QSnapdCreateUsersRequest); if (d->info == NULL || n < 0 || (guint)n >= d->info->len) return NULL; return new QSnapdUserInformation(d->info->pdata[n]); } QSnapdGetUsersRequest::QSnapdGetUsersRequest(void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetUsersRequestPrivate(this)) {} void QSnapdGetUsersRequest::runSync() { Q_D(QSnapdGetUsersRequest); g_autoptr(GError) error = NULL; d->info = snapd_client_get_users_sync( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetUsersRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetUsersRequest); g_autoptr(GError) error = NULL; d->info = snapd_client_get_users_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void get_users_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetUsersRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetUsersRequest::runAsync() { Q_D(QSnapdGetUsersRequest); snapd_client_get_users_async( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), get_users_ready_cb, g_object_ref(d->callback_data)); } int QSnapdGetUsersRequest::userInformationCount() const { Q_D(const QSnapdGetUsersRequest); return d->info != NULL ? d->info->len : 0; } QSnapdUserInformation *QSnapdGetUsersRequest::userInformation(int n) const { Q_D(const QSnapdGetUsersRequest); if (d->info == NULL || n < 0 || (guint)n >= d->info->len) return NULL; return new QSnapdUserInformation(d->info->pdata[n]); } QSnapdGetSectionsRequest::QSnapdGetSectionsRequest(void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetSectionsRequestPrivate(this)) {} void QSnapdGetSectionsRequest::runSync() { Q_D(QSnapdGetSectionsRequest); g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS d->sections = snapd_client_get_sections_sync( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), &error); G_GNUC_END_IGNORE_DEPRECATIONS finish(error); } void QSnapdGetSectionsRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetSectionsRequest); g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_auto(GStrv) sections = snapd_client_get_sections_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); G_GNUC_END_IGNORE_DEPRECATIONS d->sections = (GStrv)g_steal_pointer(§ions); finish(error); } static void get_sections_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetSectionsRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetSectionsRequest::runAsync() { Q_D(QSnapdGetSectionsRequest); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_get_sections_async( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), get_sections_ready_cb, g_object_ref(d->callback_data)); G_GNUC_END_IGNORE_DEPRECATIONS } QStringList QSnapdGetSectionsRequest::sections() const { Q_D(const QSnapdGetSectionsRequest); QStringList result; for (int i = 0; d->sections[i] != NULL; i++) result.append(d->sections[i]); return result; } QSnapdGetCategoriesRequest::QSnapdGetCategoriesRequest(void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetCategoriesRequestPrivate(this)) {} void QSnapdGetCategoriesRequest::runSync() { Q_D(QSnapdGetCategoriesRequest); g_autoptr(GError) error = NULL; d->categories = snapd_client_get_categories_sync( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetCategoriesRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetCategoriesRequest); g_autoptr(GError) error = NULL; d->categories = snapd_client_get_categories_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void get_categories_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetCategoriesRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetCategoriesRequest::runAsync() { Q_D(QSnapdGetCategoriesRequest); snapd_client_get_categories_async( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), get_categories_ready_cb, g_object_ref(d->callback_data)); } int QSnapdGetCategoriesRequest::categoryCount() const { Q_D(const QSnapdGetCategoriesRequest); return d->categories != NULL ? d->categories->len : 0; } QSnapdCategoryDetails *QSnapdGetCategoriesRequest::category(int n) const { Q_D(const QSnapdGetCategoriesRequest); if (d->categories == NULL || n < 0 || (guint)n >= d->categories->len) return NULL; return new QSnapdCategoryDetails(d->categories->pdata[n]); } QSnapdGetAliasesRequest::QSnapdGetAliasesRequest(void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetAliasesRequestPrivate(this)) {} void QSnapdGetAliasesRequest::runSync() { Q_D(QSnapdGetAliasesRequest); g_autoptr(GError) error = NULL; d->aliases = snapd_client_get_aliases_sync( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetAliasesRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetAliasesRequest); g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) aliases = snapd_client_get_aliases_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); d->aliases = (GPtrArray *)g_steal_pointer(&aliases); finish(error); } static void get_aliases_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetAliasesRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetAliasesRequest::runAsync() { Q_D(QSnapdGetAliasesRequest); snapd_client_get_aliases_async( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), get_aliases_ready_cb, g_object_ref(d->callback_data)); } int QSnapdGetAliasesRequest::aliasCount() const { Q_D(const QSnapdGetAliasesRequest); return d->aliases != NULL ? d->aliases->len : 0; } QSnapdAlias *QSnapdGetAliasesRequest::alias(int n) const { Q_D(const QSnapdGetAliasesRequest); if (d->aliases == NULL || n < 0 || (guint)n >= d->aliases->len) return NULL; return new QSnapdAlias(d->aliases->pdata[n]); } QSnapdAliasRequest::QSnapdAliasRequest(const QString &snap, const QString &app, const QString &alias, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdAliasRequestPrivate(this, snap, app, alias)) {} void QSnapdAliasRequest::runSync() { Q_D(QSnapdAliasRequest); g_autoptr(GError) error = NULL; snapd_client_alias_sync( SNAPD_CLIENT(getClient()), d->snap.toStdString().c_str(), d->app.toStdString().c_str(), d->alias.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdAliasRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_alias_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void alias_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdAliasRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdAliasRequest::runAsync() { Q_D(QSnapdAliasRequest); snapd_client_alias_async( SNAPD_CLIENT(getClient()), d->snap.toStdString().c_str(), d->app.toStdString().c_str(), d->alias.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), alias_ready_cb, g_object_ref(d->callback_data)); } QSnapdUnaliasRequest::QSnapdUnaliasRequest(const QString &snap, const QString &alias, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdUnaliasRequestPrivate(this, snap, alias)) {} void QSnapdUnaliasRequest::runSync() { Q_D(QSnapdUnaliasRequest); g_autoptr(GError) error = NULL; snapd_client_unalias_sync( SNAPD_CLIENT(getClient()), d->snap.isNull() ? NULL : d->snap.toStdString().c_str(), d->alias.isNull() ? NULL : d->alias.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdUnaliasRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_unalias_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void unalias_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdUnaliasRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdUnaliasRequest::runAsync() { Q_D(QSnapdUnaliasRequest); snapd_client_unalias_async( SNAPD_CLIENT(getClient()), d->snap.isNull() ? NULL : d->snap.toStdString().c_str(), d->alias.isNull() ? NULL : d->alias.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), unalias_ready_cb, g_object_ref(d->callback_data)); } QSnapdPreferRequest::QSnapdPreferRequest(const QString &snap, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdPreferRequestPrivate(this, snap)) {} void QSnapdPreferRequest::runSync() { Q_D(QSnapdPreferRequest); g_autoptr(GError) error = NULL; snapd_client_prefer_sync( SNAPD_CLIENT(getClient()), d->snap.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdPreferRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_prefer_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void prefer_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdPreferRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdPreferRequest::runAsync() { Q_D(QSnapdPreferRequest); snapd_client_prefer_async(SNAPD_CLIENT(getClient()), d->snap.toStdString().c_str(), progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), prefer_ready_cb, g_object_ref(d->callback_data)); } QSnapdEnableAliasesRequest::QSnapdEnableAliasesRequest( const QString &name, const QStringList &aliases, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdEnableAliasesRequestPrivate(this, name, aliases)) {} void QSnapdEnableAliasesRequest::runSync() { Q_D(QSnapdEnableAliasesRequest); g_auto(GStrv) aliases = string_list_to_strv(d->aliases); g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_enable_aliases_sync( SNAPD_CLIENT(getClient()), d->snap.toStdString().c_str(), aliases, progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); G_GNUC_END_IGNORE_DEPRECATIONS finish(error); } void QSnapdEnableAliasesRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_enable_aliases_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); G_GNUC_END_IGNORE_DEPRECATIONS finish(error); } static void enable_aliases_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdEnableAliasesRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdEnableAliasesRequest::runAsync() { Q_D(QSnapdEnableAliasesRequest); g_auto(GStrv) aliases = string_list_to_strv(d->aliases); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_disable_aliases_async( SNAPD_CLIENT(getClient()), d->snap.toStdString().c_str(), aliases, progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), enable_aliases_ready_cb, g_object_ref(d->callback_data)); G_GNUC_END_IGNORE_DEPRECATIONS } QSnapdDisableAliasesRequest::QSnapdDisableAliasesRequest( const QString &name, const QStringList &aliases, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdDisableAliasesRequestPrivate(this, name, aliases)) {} void QSnapdDisableAliasesRequest::runSync() { Q_D(QSnapdDisableAliasesRequest); g_auto(GStrv) aliases = string_list_to_strv(d->aliases); g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_disable_aliases_sync( SNAPD_CLIENT(getClient()), d->snap.toStdString().c_str(), aliases, progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); G_GNUC_END_IGNORE_DEPRECATIONS finish(error); } void QSnapdDisableAliasesRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_disable_aliases_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); G_GNUC_END_IGNORE_DEPRECATIONS finish(error); } static void disable_aliases_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdDisableAliasesRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdDisableAliasesRequest::runAsync() { Q_D(QSnapdDisableAliasesRequest); g_auto(GStrv) aliases = string_list_to_strv(d->aliases); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_disable_aliases_async( SNAPD_CLIENT(getClient()), d->snap.toStdString().c_str(), aliases, progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), disable_aliases_ready_cb, g_object_ref(d->callback_data)); G_GNUC_END_IGNORE_DEPRECATIONS } QSnapdResetAliasesRequest::QSnapdResetAliasesRequest(const QString &name, const QStringList &aliases, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdResetAliasesRequestPrivate(this, name, aliases)) {} void QSnapdResetAliasesRequest::runSync() { Q_D(QSnapdResetAliasesRequest); g_auto(GStrv) aliases = string_list_to_strv(d->aliases); g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_reset_aliases_sync( SNAPD_CLIENT(getClient()), d->snap.toStdString().c_str(), aliases, progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); G_GNUC_END_IGNORE_DEPRECATIONS finish(error); } void QSnapdResetAliasesRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_reset_aliases_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); G_GNUC_END_IGNORE_DEPRECATIONS finish(error); } static void reset_aliases_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdResetAliasesRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdResetAliasesRequest::runAsync() { Q_D(QSnapdResetAliasesRequest); g_auto(GStrv) aliases = string_list_to_strv(d->aliases); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_reset_aliases_async( SNAPD_CLIENT(getClient()), d->snap.toStdString().c_str(), aliases, progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), reset_aliases_ready_cb, g_object_ref(d->callback_data)); G_GNUC_END_IGNORE_DEPRECATIONS } QSnapdRunSnapCtlRequest::QSnapdRunSnapCtlRequest(const QString &contextId, const QStringList &args, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdRunSnapCtlRequestPrivate(this, contextId, args)) {} void QSnapdRunSnapCtlRequest::runSync() { Q_D(QSnapdRunSnapCtlRequest); g_auto(GStrv) aliases = string_list_to_strv(d->args); g_autoptr(GError) error = NULL; snapd_client_run_snapctl2_sync( SNAPD_CLIENT(getClient()), d->contextId.toStdString().c_str(), aliases, &d->stdout_output, &d->stderr_output, &d->exit_code, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdRunSnapCtlRequest::handleResult(void *object, void *result) { Q_D(QSnapdRunSnapCtlRequest); g_autoptr(GError) error = NULL; snapd_client_run_snapctl2_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &d->stdout_output, &d->stderr_output, &d->exit_code, &error); finish(error); } static void run_snapctl_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdRunSnapCtlRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdRunSnapCtlRequest::runAsync() { Q_D(QSnapdRunSnapCtlRequest); g_auto(GStrv) aliases = string_list_to_strv(d->args); snapd_client_run_snapctl2_async( SNAPD_CLIENT(getClient()), d->contextId.toStdString().c_str(), aliases, G_CANCELLABLE(getCancellable()), run_snapctl_ready_cb, g_object_ref(d->callback_data)); } QString QSnapdRunSnapCtlRequest::stdout() const { Q_D(const QSnapdRunSnapCtlRequest); return d->stdout_output; } QString QSnapdRunSnapCtlRequest::stderr() const { Q_D(const QSnapdRunSnapCtlRequest); return d->stderr_output; } int QSnapdRunSnapCtlRequest::exitCode() const { Q_D(const QSnapdRunSnapCtlRequest); return d->exit_code; } QSnapdDownloadRequest::QSnapdDownloadRequest(const QString &name, const QString &channel, const QString &revision, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdDownloadRequestPrivate(this, name, channel, revision)) {} void QSnapdDownloadRequest::runSync() { Q_D(QSnapdDownloadRequest); g_autoptr(GError) error = NULL; d->data = snapd_client_download_sync( SNAPD_CLIENT(getClient()), d->name.toStdString().c_str(), d->channel.isNull() ? NULL : d->channel.toStdString().c_str(), d->revision.isNull() ? NULL : d->revision.toStdString().c_str(), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdDownloadRequest::handleResult(void *object, void *result) { Q_D(QSnapdDownloadRequest); g_autoptr(GError) error = NULL; d->data = snapd_client_download_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void download_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdDownloadRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdDownloadRequest::runAsync() { Q_D(QSnapdDownloadRequest); snapd_client_download_async( SNAPD_CLIENT(getClient()), d->name.toStdString().c_str(), d->channel.isNull() ? NULL : d->channel.toStdString().c_str(), d->revision.isNull() ? NULL : d->revision.toStdString().c_str(), G_CANCELLABLE(getCancellable()), download_ready_cb, g_object_ref(d->callback_data)); } QByteArray QSnapdDownloadRequest::data() const { Q_D(const QSnapdDownloadRequest); gsize length; gchar *raw_data = (gchar *)g_bytes_get_data(d->data, &length); return QByteArray::fromRawData(raw_data, length); } QSnapdCheckThemesRequest::QSnapdCheckThemesRequest( const QStringList >kThemeNames, const QStringList &iconThemeNames, const QStringList &soundThemeNames, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdCheckThemesRequestPrivate( this, gtkThemeNames, iconThemeNames, soundThemeNames)) {} void QSnapdCheckThemesRequest::runSync() { Q_D(QSnapdCheckThemesRequest); g_auto(GStrv) gtk_theme_names = string_list_to_strv(d->gtkThemeNames); g_auto(GStrv) icon_theme_names = string_list_to_strv(d->iconThemeNames); g_auto(GStrv) sound_theme_names = string_list_to_strv(d->soundThemeNames); g_autoptr(GError) error = NULL; snapd_client_check_themes_sync( SNAPD_CLIENT(getClient()), gtk_theme_names, icon_theme_names, sound_theme_names, &d->gtk_theme_status, &d->icon_theme_status, &d->sound_theme_status, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdCheckThemesRequest::handleResult(void *object, void *result) { Q_D(QSnapdCheckThemesRequest); g_autoptr(GError) error = NULL; snapd_client_check_themes_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &d->gtk_theme_status, &d->icon_theme_status, &d->sound_theme_status, &error); finish(error); } static void check_themes_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdCheckThemesRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdCheckThemesRequest::runAsync() { Q_D(QSnapdCheckThemesRequest); g_auto(GStrv) gtk_theme_names = string_list_to_strv(d->gtkThemeNames); g_auto(GStrv) icon_theme_names = string_list_to_strv(d->iconThemeNames); g_auto(GStrv) sound_theme_names = string_list_to_strv(d->soundThemeNames); snapd_client_check_themes_async( SNAPD_CLIENT(getClient()), gtk_theme_names, icon_theme_names, sound_theme_names, G_CANCELLABLE(getCancellable()), check_themes_ready_cb, g_object_ref(d->callback_data)); } static QSnapdCheckThemesRequest::ThemeStatus convertThemeStatus(int status) { switch (status) { case SNAPD_THEME_STATUS_INSTALLED: return QSnapdCheckThemesRequest::ThemeInstalled; case SNAPD_THEME_STATUS_AVAILABLE: return QSnapdCheckThemesRequest::ThemeAvailable; default: case SNAPD_THEME_STATUS_UNAVAILABLE: return QSnapdCheckThemesRequest::ThemeUnavailable; } } QSnapdCheckThemesRequest::ThemeStatus QSnapdCheckThemesRequest::gtkThemeStatus(const QString &name) const { Q_D(const QSnapdCheckThemesRequest); return convertThemeStatus(GPOINTER_TO_INT( g_hash_table_lookup(d->gtk_theme_status, name.toStdString().c_str()))); } QSnapdCheckThemesRequest::ThemeStatus QSnapdCheckThemesRequest::iconThemeStatus(const QString &name) const { Q_D(const QSnapdCheckThemesRequest); return convertThemeStatus(GPOINTER_TO_INT( g_hash_table_lookup(d->icon_theme_status, name.toStdString().c_str()))); } QSnapdCheckThemesRequest::ThemeStatus QSnapdCheckThemesRequest::soundThemeStatus(const QString &name) const { Q_D(const QSnapdCheckThemesRequest); return convertThemeStatus(GPOINTER_TO_INT( g_hash_table_lookup(d->sound_theme_status, name.toStdString().c_str()))); } QSnapdInstallThemesRequest::QSnapdInstallThemesRequest( const QStringList >kThemeNames, const QStringList &iconThemeNames, const QStringList &soundThemeNames, void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdInstallThemesRequestPrivate( this, gtkThemeNames, iconThemeNames, soundThemeNames)) {} void QSnapdInstallThemesRequest::runSync() { Q_D(QSnapdInstallThemesRequest); g_auto(GStrv) gtk_theme_names = string_list_to_strv(d->gtkThemeNames); g_auto(GStrv) icon_theme_names = string_list_to_strv(d->iconThemeNames); g_auto(GStrv) sound_theme_names = string_list_to_strv(d->soundThemeNames); g_autoptr(GError) error = NULL; snapd_client_install_themes_sync(SNAPD_CLIENT(getClient()), gtk_theme_names, icon_theme_names, sound_theme_names, progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdInstallThemesRequest::handleResult(void *object, void *result) { g_autoptr(GError) error = NULL; snapd_client_install_themes_finish(SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void install_themes_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdInstallThemesRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdInstallThemesRequest::runAsync() { Q_D(QSnapdInstallThemesRequest); g_auto(GStrv) gtk_theme_names = string_list_to_strv(d->gtkThemeNames); g_auto(GStrv) icon_theme_names = string_list_to_strv(d->iconThemeNames); g_auto(GStrv) sound_theme_names = string_list_to_strv(d->soundThemeNames); snapd_client_install_themes_async( SNAPD_CLIENT(getClient()), gtk_theme_names, icon_theme_names, sound_theme_names, progress_cb, d->callback_data, G_CANCELLABLE(getCancellable()), install_themes_ready_cb, g_object_ref(d->callback_data)); } QSnapdNoticesRequest *QSnapdClient::getNotices() { Q_D(QSnapdClient); return new QSnapdNoticesRequest(d->client); } QSnapdNoticesRequest::QSnapdNoticesRequest(void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdNoticesRequestPrivate(this)) { this->timeout = 0; this->resetFilters(); } QSnapdNoticesRequest::~QSnapdNoticesRequest() {} void QSnapdNoticesRequest::resetFilters() { this->sinceFilterSet = false; this->userIdFilter = ""; this->usersFilter = ""; this->typesFilter = ""; this->keysFilter = ""; this->sinceNanosecondsFilter = -1; } static GDateTime *getSinceDateTime(QDateTime &dateTime) { #if GLIB_CHECK_VERSION(2, 58, 0) g_autoptr(GTimeZone) timeZone = g_time_zone_new_offset(dateTime.timeZone().offsetFromUtc(dateTime)); #else int timeOffset = dateTime.timeZone().offsetFromUtc(dateTime) / 60; g_autofree gchar *timeOffsetStr = g_strdup_printf("%02d:%02d", timeOffset / 60, timeOffset % 60); g_autoptr(GTimeZone) timeZone = g_time_zone_new(timeOffsetStr); #endif GDateTime *gDateTime = g_date_time_new(timeZone, dateTime.date().year(), dateTime.date().month(), dateTime.date().day(), dateTime.time().hour(), dateTime.time().minute(), dateTime.time().second()); return gDateTime; } void QSnapdNoticesRequest::runSync() { Q_D(QSnapdNoticesRequest); if (this->sinceNanosecondsFilter != -1) snapd_client_notices_set_since_nanoseconds(SNAPD_CLIENT(getClient()), this->sinceNanosecondsFilter); this->sinceNanosecondsFilter = -1; g_autoptr(GError) error = NULL; g_autoptr(GDateTime) dateTime = this->sinceFilterSet ? getSinceDateTime(this->sinceFilter) : NULL; d->updateNoticesData(snapd_client_get_notices_with_filters_sync( SNAPD_CLIENT(getClient()), (gchar *)this->userIdFilter.toStdString().c_str(), (gchar *)this->usersFilter.toStdString().c_str(), (gchar *)this->typesFilter.toStdString().c_str(), (gchar *)this->keysFilter.toStdString().c_str(), dateTime, this->timeout, G_CANCELLABLE(getCancellable()), &error)); finish(error); } void QSnapdNoticesRequest::handleResult(void *object, void *result) { Q_D(QSnapdNoticesRequest); g_autoptr(GError) error = NULL; d->updateNoticesData(snapd_client_get_notices_with_filters_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error)); finish(error); } static void notices_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdNoticesRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdNoticesRequest::runAsync() { Q_D(QSnapdNoticesRequest); if (this->sinceNanosecondsFilter != -1) snapd_client_notices_set_since_nanoseconds(SNAPD_CLIENT(getClient()), this->sinceNanosecondsFilter); this->sinceNanosecondsFilter = -1; g_autoptr(GDateTime) dateTime = this->sinceFilterSet ? getSinceDateTime(this->sinceFilter) : NULL; snapd_client_get_notices_with_filters_async( SNAPD_CLIENT(getClient()), (gchar *)this->userIdFilter.toStdString().c_str(), (gchar *)this->usersFilter.toStdString().c_str(), (gchar *)this->typesFilter.toStdString().c_str(), (gchar *)this->keysFilter.toStdString().c_str(), dateTime, this->timeout, G_CANCELLABLE(getCancellable()), notices_ready_cb, g_object_ref(d->callback_data)); } uint QSnapdNoticesRequest::noticesCount() const { Q_D(const QSnapdNoticesRequest); return d->notices->len; } QSnapdNotice *QSnapdNoticesRequest::getNotice(quint64 n) const { Q_D(const QSnapdNoticesRequest); if (d->notices == NULL || n >= d->notices->len) return NULL; return new QSnapdNotice(SNAPD_NOTICE(d->notices->pdata[n])); } void QSnapdNoticesRequest::setSinceDateFilterFromNotice(QSnapdNotice *notice) { this->sinceFilterSet = true; this->sinceFilter = notice->lastOccurred(); this->sinceNanosecondsFilter = notice->lastOccurredNanoseconds(); } void QSnapdNoticesRequest::setSinceDateFilterFromDateNanoseconds( QDateTime dateTime, qint32 nanoseconds) { this->sinceFilterSet = true; this->sinceFilter = dateTime; this->sinceNanosecondsFilter = nanoseconds; } QSnapdGetModelAssertionRequest *QSnapdClient::getModelAssertion() { Q_D(QSnapdClient); return new QSnapdGetModelAssertionRequest(d->client); } QSnapdGetModelAssertionRequest::QSnapdGetModelAssertionRequest( void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetModelAssertionRequestPrivate(this)) {} QSnapdGetModelAssertionRequest::~QSnapdGetModelAssertionRequest() {} void QSnapdGetModelAssertionRequest::runSync() { Q_D(QSnapdGetModelAssertionRequest); g_autoptr(GError) error = NULL; d->model_assertion = snapd_client_get_model_assertion_sync( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetModelAssertionRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetModelAssertionRequest); g_autoptr(GError) error = NULL; d->model_assertion = snapd_client_get_model_assertion_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void get_model_assertion_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetModelAssertionRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetModelAssertionRequest::runAsync() { Q_D(QSnapdGetModelAssertionRequest); snapd_client_get_model_assertion_async( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), get_model_assertion_ready_cb, g_object_ref(d->callback_data)); } QString QSnapdGetModelAssertionRequest::modelAssertion() const { Q_D(const QSnapdGetModelAssertionRequest); return d->model_assertion; } QSnapdGetSerialAssertionRequest *QSnapdClient::getSerialAssertion() { Q_D(QSnapdClient); return new QSnapdGetSerialAssertionRequest(d->client); } QSnapdGetSerialAssertionRequest::QSnapdGetSerialAssertionRequest( void *snapd_client, QObject *parent) : QSnapdRequest(snapd_client, parent), d_ptr(new QSnapdGetSerialAssertionRequestPrivate(this)) {} QSnapdGetSerialAssertionRequest::~QSnapdGetSerialAssertionRequest() {} void QSnapdGetSerialAssertionRequest::runSync() { Q_D(QSnapdGetSerialAssertionRequest); g_autoptr(GError) error = NULL; d->serial_assertion = snapd_client_get_serial_assertion_sync( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), &error); finish(error); } void QSnapdGetSerialAssertionRequest::handleResult(void *object, void *result) { Q_D(QSnapdGetSerialAssertionRequest); g_autoptr(GError) error = NULL; d->serial_assertion = snapd_client_get_serial_assertion_finish( SNAPD_CLIENT(object), G_ASYNC_RESULT(result), &error); finish(error); } static void get_serial_assertion_ready_cb(GObject *object, GAsyncResult *result, gpointer data) { g_autoptr(CallbackData) callback_data = (CallbackData *)data; if (callback_data->request != NULL) { QSnapdGetSerialAssertionRequest *request = static_cast(callback_data->request); request->handleResult(object, result); } } void QSnapdGetSerialAssertionRequest::runAsync() { Q_D(QSnapdGetSerialAssertionRequest); snapd_client_get_serial_assertion_async( SNAPD_CLIENT(getClient()), G_CANCELLABLE(getCancellable()), get_serial_assertion_ready_cb, g_object_ref(d->callback_data)); } QString QSnapdGetSerialAssertionRequest::serialAssertion() const { Q_D(const QSnapdGetSerialAssertionRequest); return d->serial_assertion; } snapd-glib-1.67/snapd-qt/connection.cpp000066400000000000000000000062641477073115000200760ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/connection.h" #include "variant.h" QSnapdConnection::QSnapdConnection(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QSnapdSlotRef *QSnapdConnection::slot() const { SnapdSlotRef *slot_ref = snapd_connection_get_slot(SNAPD_CONNECTION(wrapped_object)); if (slot_ref == NULL) return NULL; return new QSnapdSlotRef(slot_ref); } QSnapdPlugRef *QSnapdConnection::plug() const { SnapdPlugRef *plug_ref = snapd_connection_get_plug(SNAPD_CONNECTION(wrapped_object)); if (plug_ref == NULL) return NULL; return new QSnapdPlugRef(plug_ref); } QString QSnapdConnection::interface() const { return snapd_connection_get_interface(SNAPD_CONNECTION(wrapped_object)); } bool QSnapdConnection::manual() const { return snapd_connection_get_manual(SNAPD_CONNECTION(wrapped_object)); } bool QSnapdConnection::gadget() const { return snapd_connection_get_gadget(SNAPD_CONNECTION(wrapped_object)); } QStringList QSnapdConnection::slotAttributeNames() const { g_auto(GStrv) names = snapd_connection_get_slot_attribute_names( SNAPD_CONNECTION(wrapped_object), NULL); QStringList result; for (int i = 0; names[i] != NULL; i++) result.append(names[i]); return result; } bool QSnapdConnection::hasSlotAttribute(const QString &name) const { return snapd_connection_has_slot_attribute(SNAPD_CONNECTION(wrapped_object), name.toStdString().c_str()); } QVariant QSnapdConnection::slotAttribute(const QString &name) const { GVariant *value = snapd_connection_get_slot_attribute( SNAPD_CONNECTION(wrapped_object), name.toStdString().c_str()); return gvariant_to_qvariant(value); } QStringList QSnapdConnection::plugAttributeNames() const { g_auto(GStrv) names = snapd_connection_get_plug_attribute_names( SNAPD_CONNECTION(wrapped_object), NULL); QStringList result; for (int i = 0; names[i] != NULL; i++) result.append(names[i]); return result; } bool QSnapdConnection::hasPlugAttribute(const QString &name) const { return snapd_connection_has_plug_attribute(SNAPD_CONNECTION(wrapped_object), name.toStdString().c_str()); } QVariant QSnapdConnection::plugAttribute(const QString &name) const { GVariant *value = snapd_connection_get_plug_attribute( SNAPD_CONNECTION(wrapped_object), name.toStdString().c_str()); return gvariant_to_qvariant(value); } QString QSnapdConnection::name() const { QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED return snapd_connection_get_name(SNAPD_CONNECTION(wrapped_object)); QT_WARNING_POP } QString QSnapdConnection::snap() const { QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED return snapd_connection_get_snap(SNAPD_CONNECTION(wrapped_object)); QT_WARNING_POP } snapd-glib-1.67/snapd-qt/icon.cpp000066400000000000000000000016011477073115000166550ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/icon.h" QSnapdIcon::QSnapdIcon(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdIcon::mimeType() const { return snapd_icon_get_mime_type(SNAPD_ICON(wrapped_object)); } QByteArray QSnapdIcon::data() const { GBytes *data = snapd_icon_get_data(SNAPD_ICON(wrapped_object)); gsize length; gchar *raw_data = (gchar *)g_bytes_get_data(data, &length); return QByteArray::fromRawData(raw_data, length); } snapd-glib-1.67/snapd-qt/interface.cpp000066400000000000000000000036251477073115000176750ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/interface.h" QSnapdInterface::QSnapdInterface(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdInterface::name() const { return snapd_interface_get_name(SNAPD_INTERFACE(wrapped_object)); } QString QSnapdInterface::summary() const { return snapd_interface_get_summary(SNAPD_INTERFACE(wrapped_object)); } QString QSnapdInterface::docUrl() const { return snapd_interface_get_doc_url(SNAPD_INTERFACE(wrapped_object)); } int QSnapdInterface::slotCount() const { GPtrArray *slots; slots = snapd_interface_get_slots(SNAPD_INTERFACE(wrapped_object)); return slots != NULL ? slots->len : 0; } QSnapdSlot *QSnapdInterface::slot(int n) const { GPtrArray *slots; slots = snapd_interface_get_slots(SNAPD_INTERFACE(wrapped_object)); if (slots == NULL || n < 0 || (guint)n >= slots->len) return NULL; return new QSnapdSlot(slots->pdata[n]); } int QSnapdInterface::plugCount() const { GPtrArray *plugs; plugs = snapd_interface_get_plugs(SNAPD_INTERFACE(wrapped_object)); return plugs != NULL ? plugs->len : 0; } QSnapdPlug *QSnapdInterface::plug(int n) const { GPtrArray *plugs; plugs = snapd_interface_get_plugs(SNAPD_INTERFACE(wrapped_object)); if (plugs == NULL || n < 0 || (guint)n >= plugs->len) return NULL; return new QSnapdPlug(plugs->pdata[n]); } QString QSnapdInterface::makeLabel() const { g_autofree gchar *label = snapd_interface_make_label(SNAPD_INTERFACE(wrapped_object)); return label; } snapd-glib-1.67/snapd-qt/maintenance.cpp000066400000000000000000000021661477073115000202160ustar00rootroot00000000000000/* * Copyright (C) 2018 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/maintenance.h" QSnapdMaintenance::QSnapdMaintenance(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QSnapdEnums::MaintenanceKind QSnapdMaintenance::kind() const { switch (snapd_maintenance_get_kind(SNAPD_MAINTENANCE(wrapped_object))) { default: case SNAPD_MAINTENANCE_KIND_UNKNOWN: return QSnapdEnums::MaintenanceKindUnknown; case SNAPD_MAINTENANCE_KIND_DAEMON_RESTART: return QSnapdEnums::MaintenanceKindDaemonRestart; case SNAPD_MAINTENANCE_KIND_SYSTEM_RESTART: return QSnapdEnums::MaintenanceKindSystemRestart; } } QString QSnapdMaintenance::message() const { return snapd_maintenance_get_message(SNAPD_MAINTENANCE(wrapped_object)); } snapd-glib-1.67/snapd-qt/markdown-node.cpp000066400000000000000000000050701477073115000204760ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/markdown-node.h" QSnapdMarkdownNode::QSnapdMarkdownNode(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QSnapdMarkdownNode::QSnapdMarkdownNode(const QSnapdMarkdownNode &node) : QSnapdMarkdownNode(node.wrapped_object, node.parent()) {} QSnapdMarkdownNode::NodeType QSnapdMarkdownNode::type() const { switch ( snapd_markdown_node_get_node_type(SNAPD_MARKDOWN_NODE(wrapped_object))) { default: case SNAPD_MARKDOWN_NODE_TYPE_TEXT: return QSnapdMarkdownNode::NodeTypeText; case SNAPD_MARKDOWN_NODE_TYPE_PARAGRAPH: return QSnapdMarkdownNode::NodeTypeParagraph; case SNAPD_MARKDOWN_NODE_TYPE_UNORDERED_LIST: return QSnapdMarkdownNode::NodeTypeUnorderedList; case SNAPD_MARKDOWN_NODE_TYPE_LIST_ITEM: return QSnapdMarkdownNode::NodeTypeListItem; case SNAPD_MARKDOWN_NODE_TYPE_CODE_BLOCK: return QSnapdMarkdownNode::NodeTypeCodeBlock; case SNAPD_MARKDOWN_NODE_TYPE_CODE_SPAN: return QSnapdMarkdownNode::NodeTypeCodeSpan; case SNAPD_MARKDOWN_NODE_TYPE_EMPHASIS: return QSnapdMarkdownNode::NodeTypeEmphasis; case SNAPD_MARKDOWN_NODE_TYPE_STRONG_EMPHASIS: return QSnapdMarkdownNode::NodeTypeStrongEmphasis; case SNAPD_MARKDOWN_NODE_TYPE_URL: return QSnapdMarkdownNode::NodeTypeUrl; } } QString QSnapdMarkdownNode::text() const { return snapd_markdown_node_get_text(SNAPD_MARKDOWN_NODE(wrapped_object)); } int QSnapdMarkdownNode::childCount() const { GPtrArray *children; children = snapd_markdown_node_get_children(SNAPD_MARKDOWN_NODE(wrapped_object)); return children != NULL ? children->len : 0; } QSnapdMarkdownNode *QSnapdMarkdownNode::child(int n) const { GPtrArray *children; children = snapd_markdown_node_get_children(SNAPD_MARKDOWN_NODE(wrapped_object)); if (children == NULL || n < 0 || (guint)n >= children->len) return NULL; return new QSnapdMarkdownNode(children->pdata[n]); } QSnapdMarkdownNode & QSnapdMarkdownNode::operator=(const QSnapdMarkdownNode &node) { if (&node == this) { return *this; } g_object_unref(wrapped_object); wrapped_object = node.wrapped_object; g_object_ref(wrapped_object); return *this; } snapd-glib-1.67/snapd-qt/markdown-parser.cpp000066400000000000000000000036041477073115000210460ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/markdown-parser.h" class QSnapdMarkdownParserPrivate { public: QSnapdMarkdownParserPrivate(QSnapdMarkdownParser::MarkdownVersion version) { SnapdMarkdownVersion v; switch (version) { default: case QSnapdMarkdownParser::MarkdownVersion0: v = SNAPD_MARKDOWN_VERSION_0; break; } parser = snapd_markdown_parser_new(v); } ~QSnapdMarkdownParserPrivate() { g_object_unref(parser); } SnapdMarkdownParser *parser; }; QSnapdMarkdownParser::QSnapdMarkdownParser( QSnapdMarkdownParser::MarkdownVersion version, QObject *parent) : QObject(parent), d_ptr(new QSnapdMarkdownParserPrivate(version)) {} QSnapdMarkdownParser::~QSnapdMarkdownParser() {} void QSnapdMarkdownParser::setPreserveWhitespace( bool preserveWhitespace) const { Q_D(const QSnapdMarkdownParser); snapd_markdown_parser_set_preserve_whitespace(d->parser, preserveWhitespace); } bool QSnapdMarkdownParser::preserveWhitespace() const { Q_D(const QSnapdMarkdownParser); return snapd_markdown_parser_get_preserve_whitespace(d->parser); } QList QSnapdMarkdownParser::parse(const QString &text) const { Q_D(const QSnapdMarkdownParser); g_autoptr(GPtrArray) nodes = snapd_markdown_parser_parse(d->parser, text.toUtf8().constData()); QList nodes_list; for (uint i = 0; i < nodes->len; i++) { SnapdMarkdownNode *node = (SnapdMarkdownNode *)g_ptr_array_index(nodes, i); nodes_list.append(QSnapdMarkdownNode(node)); } return nodes_list; } snapd-glib-1.67/snapd-qt/media.cpp000066400000000000000000000017041477073115000170100ustar00rootroot00000000000000/* * Copyright (C) 2018 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/media.h" QSnapdMedia::QSnapdMedia(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdMedia::type() const { return snapd_media_get_media_type(SNAPD_MEDIA(wrapped_object)); } QString QSnapdMedia::url() const { return snapd_media_get_url(SNAPD_MEDIA(wrapped_object)); } quint64 QSnapdMedia::width() const { return snapd_media_get_width(SNAPD_MEDIA(wrapped_object)); } quint64 QSnapdMedia::height() const { return snapd_media_get_height(SNAPD_MEDIA(wrapped_object)); } snapd-glib-1.67/snapd-qt/meson.build000066400000000000000000000132671477073115000173760ustar00rootroot00000000000000if get_option('qt5') and get_option('qt6') error('Both the "qt5" and "qt6" bindings are selected, snapd-glib only supports building one Qt major version at a time.') endif if get_option('qt5') qt_min_version = '5.9.5' qt_version = 'qt5' qt_core_camel = 'Qt5Core' description = 'Snapd Qt' cmake_base_name = 'SnapdQt5' library_name = 'snapd-qt' qt_core_dep = dependency ('qt5', modules: [ 'Core' ]) qt_network_dep = dependency ('qt5', modules: [ 'Network' ]) qml_dep = dependency ('qt5', modules: [ 'Qml' ]) endif if get_option('qt6') qt_min_version = '6.2.4' qt_version = 'qt6' qt_core_camel = 'Qt6Core' description = 'Snapd Qt' cmake_base_name = 'SnapdQt6' library_name = 'snapd-qt' qt6_core_dep = dependency ('qt6', modules: [ 'Core' ]) qt6_network_dep = dependency ('qt6', modules: [ 'Network' ]) qml_dep = dependency ('qt6', modules: [ 'Qml' ]) endif qt_name = 'Snapd' if not get_option('soup2') library_name += '-2' qt_name += '2' endif qt = import(qt_version) qt_dep = dependency( qt_version, modules: ['Core', 'Network'], version: f'>= @qt_min_version@', include_type: 'system' ) install_header_dir = join_paths (includedir, library_name, 'Snapd') qml_dir = join_paths (libdir, f'@qt_version@', 'qml', f'@qt_name@') cmake_dir = join_paths (libdir, 'cmake', qt_name) source_cpp = [ 'alias.cpp', 'app.cpp', 'assertion.cpp', 'auth-data.cpp', 'category.cpp', 'category-details.cpp', 'change.cpp', 'change-autorefresh-data.cpp', 'change-data.cpp', 'channel.cpp', 'client.cpp', 'connection.cpp', 'icon.cpp', 'interface.cpp', 'markdown-node.cpp', 'markdown-parser.cpp', 'maintenance.cpp', 'media.cpp', 'notice.cpp', 'plug.cpp', 'plug-ref.cpp', 'price.cpp', 'request.cpp', 'screenshot.cpp', 'slot.cpp', 'slot-ref.cpp', 'snap.cpp', 'stream-wrapper.cpp', 'system-information.cpp', 'task.cpp', 'task-data.cpp', 'user-information.cpp', ] source_h = [ 'Snapd/alias.h', 'Snapd/app.h', 'Snapd/assertion.h', 'Snapd/auth-data.h', 'Snapd/category.h', 'Snapd/category-details.h', 'Snapd/change.h', 'Snapd/change-autorefresh-data.h', 'Snapd/change-data.h', 'Snapd/channel.h', 'Snapd/client.h', 'Snapd/connection.h', 'Snapd/enums.h', 'Snapd/icon.h', 'Snapd/interface.h', 'Snapd/maintenance.h', 'Snapd/markdown-node.h', 'Snapd/markdown-parser.h', 'Snapd/media.h', 'Snapd/notice.h', 'Snapd/plug.h', 'Snapd/plug-ref.h', 'Snapd/price.h', 'Snapd/request.h', 'Snapd/screenshot.h', 'Snapd/slot.h', 'Snapd/slot-ref.h', 'Snapd/snap.h', 'Snapd/system-information.h', 'Snapd/task.h', 'Snapd/task-data.h', 'Snapd/user-information.h', 'Snapd/wrapped-object.h', ] source_alias_h = [ 'Snapd/Alias', 'Snapd/App', 'Snapd/Assertion', 'Snapd/AuthData', 'Snapd/Category', 'Snapd/CategoryDetails', 'Snapd/Change', 'Snapd/Channel', 'Snapd/Client', 'Snapd/Connection', 'Snapd/Enums', 'Snapd/Icon', 'Snapd/Interface', 'Snapd/Maintenance', 'Snapd/MarkdownNode', 'Snapd/MarkdownParser', 'Snapd/Media', 'Snapd/Notice', 'Snapd/Plug', 'Snapd/PlugRef', 'Snapd/Price', 'Snapd/Request', 'Snapd/Screenshot', 'Snapd/Slot', 'Snapd/SlotRef', 'Snapd/Snap', 'Snapd/SystemInformation', 'Snapd/Task', 'Snapd/TaskData', 'Snapd/UserInformation', 'Snapd/WrappedObject', ] source_private_h = [ 'client-private.h', 'stream-wrapper.h', 'variant.h', ] moc_files = qt.preprocess (moc_headers: [ source_h, source_private_h ], dependencies: [ qt_dep ]) snapd_qt_lib = library (library_name, source_cpp, moc_files, version: '1.0.0', dependencies: [ qt_dep, glib_dep, gio_dep, snapd_glib_dep ], cpp_args: [ '-DQT_NO_SIGNALS_SLOTS_KEYWORDS', '-DLIBSNAPDQT' ], install: true) snapd_qt_dep = declare_dependency (link_with: snapd_qt_lib, dependencies: qt_dep, include_directories: include_directories ('.')) install_headers (source_h + source_alias_h, install_dir: install_header_dir) pc = import ('pkgconfig') pc_required_qt=f'@qt_core_camel@' pc.generate (libraries: snapd_qt_lib, filebase: library_name, name: 'Snapd Qt', description: 'Library for accessing snapd', version: meson.project_version (), requires: pc_required_qt,) install_data ('qmldir', install_dir: qml_dir) cmake_conf = configuration_data () cmake_conf.set ('libdir', libdir) cmake_conf.set ('includedir', includedir) cmake_conf.set ('version', meson.project_version ()) cmake_conf.set ('library_name', library_name) cmake_file = configure_file (input: f'@cmake_base_name@Config.cmake.in', output: 'SnapdConfig.cmake', configuration: cmake_conf) cmake_version_file = configure_file (input: f'@cmake_base_name@ConfigVersion.cmake.in', output: 'SnapdConfigVersion.cmake', configuration: cmake_conf) install_data (cmake_file, cmake_version_file, install_dir: cmake_dir) if get_option ('qml-bindings') install_data ('qmldir', install_dir: qml_dir) qml_moc_files = qt.preprocess (moc_headers: 'qml-plugin.h', dependencies: qml_dep) library (qt_name, 'qml-plugin.cpp', qml_moc_files, dependencies: [ qml_dep, snapd_qt_dep ], build_rpath: qml_dir, install: true, install_dir: qml_dir) endif snapd-glib-1.67/snapd-qt/notice.cpp000066400000000000000000000063331477073115000172150ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "Snapd/notice.h" #include QSnapdNotice::QSnapdNotice(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdNotice::id() const { return snapd_notice_get_id(SNAPD_NOTICE(wrapped_object)); } QString QSnapdNotice::userId() const { return snapd_notice_get_user_id(SNAPD_NOTICE(wrapped_object)); } QSnapdEnums::SnapNoticeType QSnapdNotice::noticeType() const { switch (snapd_notice_get_notice_type(SNAPD_NOTICE(wrapped_object))) { case SNAPD_NOTICE_TYPE_CHANGE_UPDATE: return QSnapdEnums::SnapNoticeTypeChangeUpdate; case SNAPD_NOTICE_TYPE_REFRESH_INHIBIT: return QSnapdEnums::SnapNoticeTypeRefreshInhibit; case SNAPD_NOTICE_TYPE_SNAP_RUN_INHIBIT: return QSnapdEnums::SnapNoticeTypeSnapRunInhibit; case SNAPD_NOTICE_TYPE_UNKNOWN: default: return QSnapdEnums::SnapNoticeTypeUnknown; } } QString QSnapdNotice::key() const { return snapd_notice_get_key(SNAPD_NOTICE(wrapped_object)); } static QDateTime convertDateTime(GDateTime *datetime) { if (datetime == NULL) return QDateTime(); QDate date(g_date_time_get_year(datetime), g_date_time_get_month(datetime), g_date_time_get_day_of_month(datetime)); QTime time(g_date_time_get_hour(datetime), g_date_time_get_minute(datetime), g_date_time_get_second(datetime), g_date_time_get_microsecond(datetime) / 1000); return QDateTime(date, time, Qt::OffsetFromUTC, g_date_time_get_utc_offset(datetime) / 1000000); } QDateTime QSnapdNotice::firstOccurred() const { return convertDateTime( snapd_notice_get_first_occurred2(SNAPD_NOTICE(wrapped_object))); } QDateTime QSnapdNotice::lastOccurred() const { return convertDateTime( snapd_notice_get_last_occurred2(SNAPD_NOTICE(wrapped_object))); } QDateTime QSnapdNotice::lastRepeated() const { return convertDateTime( snapd_notice_get_last_repeated2(SNAPD_NOTICE(wrapped_object))); } qint32 QSnapdNotice::occurrences() const { return snapd_notice_get_occurrences(SNAPD_NOTICE(wrapped_object)); } qint64 QSnapdNotice::repeatAfter() const { return snapd_notice_get_repeat_after(SNAPD_NOTICE(wrapped_object)); } qint64 QSnapdNotice::expireAfter() const { return snapd_notice_get_expire_after(SNAPD_NOTICE(wrapped_object)); } qint32 QSnapdNotice::lastOccurredNanoseconds() const { return snapd_notice_get_last_occurred_nanoseconds( SNAPD_NOTICE(wrapped_object)); } static void addItemToQHash(gchar *key, gchar *value, QHash *lastData) { lastData->insert(key, value); } QHash QSnapdNotice::lastData() const { QHash lastData; GHashTable *last_data = snapd_notice_get_last_data2(SNAPD_NOTICE(wrapped_object)); g_hash_table_foreach(last_data, (GHFunc)addItemToQHash, &lastData); return lastData; } snapd-glib-1.67/snapd-qt/plug-ref.cpp000066400000000000000000000014131477073115000174470ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/plug-ref.h" QSnapdPlugRef::QSnapdPlugRef(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdPlugRef::plug() const { return snapd_plug_ref_get_plug(SNAPD_PLUG_REF(wrapped_object)); } QString QSnapdPlugRef::snap() const { return snapd_plug_ref_get_snap(SNAPD_PLUG_REF(wrapped_object)); } snapd-glib-1.67/snapd-qt/plug.cpp000066400000000000000000000053521477073115000167030ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/plug.h" #include "variant.h" QSnapdPlug::QSnapdPlug(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdPlug::name() const { return snapd_plug_get_name(SNAPD_PLUG(wrapped_object)); } QString QSnapdPlug::snap() const { return snapd_plug_get_snap(SNAPD_PLUG(wrapped_object)); } QString QSnapdPlug::interface() const { return snapd_plug_get_interface(SNAPD_PLUG(wrapped_object)); } QStringList QSnapdPlug::attributeNames() const { g_auto(GStrv) names = snapd_plug_get_attribute_names(SNAPD_PLUG(wrapped_object), NULL); QStringList result; for (int i = 0; names[i] != NULL; i++) result.append(names[i]); return result; } bool QSnapdPlug::hasAttribute(const QString &name) const { return snapd_plug_has_attribute(SNAPD_PLUG(wrapped_object), name.toStdString().c_str()); } QVariant QSnapdPlug::attribute(const QString &name) const { GVariant *value = snapd_plug_get_attribute(SNAPD_PLUG(wrapped_object), name.toStdString().c_str()); return gvariant_to_qvariant(value); } QString QSnapdPlug::label() const { return snapd_plug_get_label(SNAPD_PLUG(wrapped_object)); } int QSnapdPlug::connectionCount() const { GPtrArray *connections; QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED connections = snapd_plug_get_connections(SNAPD_PLUG(wrapped_object)); QT_WARNING_POP return connections != NULL ? connections->len : 0; } QSnapdConnection *QSnapdPlug::connection(int n) const { GPtrArray *connections; QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED connections = snapd_plug_get_connections(SNAPD_PLUG(wrapped_object)); QT_WARNING_POP if (connections == NULL || n < 0 || (guint)n >= connections->len) return NULL; return new QSnapdConnection(connections->pdata[n]); } int QSnapdPlug::connectedSlotCount() const { GPtrArray *connections; connections = snapd_plug_get_connected_slots(SNAPD_PLUG(wrapped_object)); return connections != NULL ? connections->len : 0; } QSnapdSlotRef *QSnapdPlug::connectedSlot(int n) const { GPtrArray *connections; connections = snapd_plug_get_connected_slots(SNAPD_PLUG(wrapped_object)); if (connections == NULL || n < 0 || (guint)n >= connections->len) return NULL; return new QSnapdSlotRef(connections->pdata[n]); } snapd-glib-1.67/snapd-qt/price.cpp000066400000000000000000000013771477073115000170410ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/price.h" QSnapdPrice::QSnapdPrice(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} double QSnapdPrice::amount() const { return snapd_price_get_amount(SNAPD_PRICE(wrapped_object)); } QString QSnapdPrice::currency() const { return snapd_price_get_currency(SNAPD_PRICE(wrapped_object)); } snapd-glib-1.67/snapd-qt/qml-plugin.cpp000066400000000000000000000064301477073115000200170ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical, Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "qml-plugin.h" #include #include void SnapdQmlPlugin::registerTypes(const char *uri) { Q_ASSERT(uri == QLatin1String("Snapd")); qmlRegisterType(uri, 1, 0, "SnapdClient"); qmlRegisterType(uri, 1, 0, "SnapdAuthData"); qmlRegisterUncreatableType(uri, 1, 0, "SnapdIcon", "Can't create"); qmlRegisterUncreatableType(uri, 1, 0, "SnapdConnection", "Can't create"); qmlRegisterUncreatableType(uri, 1, 0, "SnapdSnap", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdSystemInformation", "Can't create"); qmlRegisterUncreatableType(uri, 1, 0, "SnapdRequest", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdConnectRequest", "Can't create"); qmlRegisterUncreatableType(uri, 1, 0, "SnapdLoginRequest", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdGetSystemInformationRequest", "Can't create"); qmlRegisterUncreatableType(uri, 1, 0, "SnapdListRequest", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdListOneRequest", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdGetIconRequest", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdGetInterfacesRequest", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdConnectInterfaceRequest", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdDisconnectInterfaceRequest", "Can't create"); qmlRegisterUncreatableType(uri, 1, 0, "SnapdFindRequest", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdInstallRequest", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdRefreshRequest", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdRemoveRequest", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdEnableRequest", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdDisableRequest", "Can't create"); qmlRegisterUncreatableType( uri, 1, 0, "SnapdCheckBuyRequest", "Can't create"); qmlRegisterUncreatableType(uri, 1, 0, "SnapdBuyRequest", "Can't create"); } snapd-glib-1.67/snapd-qt/qml-plugin.h000066400000000000000000000011611477073115000174600ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical, Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef QML_PLUGIN_H #define QML_PLUGIN_H #include class SnapdQmlPlugin : public QQmlExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") public: void registerTypes(const char *uri); }; #endif snapd-glib-1.67/snapd-qt/qmldir000066400000000000000000000000321477073115000164310ustar00rootroot00000000000000module Snapd plugin Snapd snapd-glib-1.67/snapd-qt/request.cpp000066400000000000000000000154441477073115000174270ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/request.h" class QSnapdRequestPrivate { public: QSnapdRequestPrivate(void *snapd_client) { client = SNAPD_CLIENT(g_object_ref(snapd_client)); cancellable = g_cancellable_new(); } ~QSnapdRequestPrivate() { g_cancellable_cancel(cancellable); g_object_unref(cancellable); g_object_unref(client); if (change != NULL) g_object_unref(change); } SnapdClient *client; GCancellable *cancellable; bool finished = false; QSnapdRequest::QSnapdError error = QSnapdRequest::NoError; QString errorString; SnapdChange *change = NULL; }; QSnapdRequest::QSnapdRequest(void *snapd_client, QObject *parent) : QObject(parent), d_ptr(new QSnapdRequestPrivate(snapd_client)) {} QSnapdRequest::~QSnapdRequest() {} void *QSnapdRequest::getClient() const { Q_D(const QSnapdRequest); return d->client; } void *QSnapdRequest::getCancellable() const { Q_D(const QSnapdRequest); return d->cancellable; } void QSnapdRequest::finish(void *error) { Q_D(QSnapdRequest); d->finished = true; if (error == NULL) { d->error = NoError; d->errorString = ""; } else { GError *e = (GError *)error; if (e->domain == SNAPD_ERROR) { switch ((SnapdError)e->code) { case SNAPD_ERROR_CONNECTION_FAILED: d->error = QSnapdRequest::QSnapdError::ConnectionFailed; break; case SNAPD_ERROR_WRITE_FAILED: d->error = QSnapdRequest::QSnapdError::WriteFailed; break; case SNAPD_ERROR_READ_FAILED: d->error = QSnapdRequest::QSnapdError::ReadFailed; break; case SNAPD_ERROR_BAD_REQUEST: d->error = QSnapdRequest::QSnapdError::BadRequest; break; case SNAPD_ERROR_BAD_RESPONSE: d->error = QSnapdRequest::QSnapdError::BadResponse; break; case SNAPD_ERROR_AUTH_DATA_REQUIRED: d->error = QSnapdRequest::QSnapdError::AuthDataRequired; break; case SNAPD_ERROR_AUTH_DATA_INVALID: d->error = QSnapdRequest::QSnapdError::AuthDataInvalid; break; case SNAPD_ERROR_TWO_FACTOR_REQUIRED: d->error = QSnapdRequest::QSnapdError::TwoFactorRequired; break; case SNAPD_ERROR_TWO_FACTOR_INVALID: d->error = QSnapdRequest::QSnapdError::TwoFactorInvalid; break; case SNAPD_ERROR_PERMISSION_DENIED: d->error = QSnapdRequest::QSnapdError::PermissionDenied; break; case SNAPD_ERROR_FAILED: d->error = QSnapdRequest::QSnapdError::Failed; break; case SNAPD_ERROR_TERMS_NOT_ACCEPTED: d->error = QSnapdRequest::QSnapdError::TermsNotAccepted; break; case SNAPD_ERROR_PAYMENT_NOT_SETUP: d->error = QSnapdRequest::QSnapdError::PaymentNotSetup; break; case SNAPD_ERROR_PAYMENT_DECLINED: d->error = QSnapdRequest::QSnapdError::PaymentDeclined; break; case SNAPD_ERROR_ALREADY_INSTALLED: d->error = QSnapdRequest::QSnapdError::AlreadyInstalled; break; case SNAPD_ERROR_NOT_INSTALLED: d->error = QSnapdRequest::QSnapdError::NotInstalled; break; case SNAPD_ERROR_NO_UPDATE_AVAILABLE: d->error = QSnapdRequest::QSnapdError::NoUpdateAvailable; break; case SNAPD_ERROR_PASSWORD_POLICY_ERROR: d->error = QSnapdRequest::QSnapdError::PasswordPolicyError; break; case SNAPD_ERROR_NEEDS_DEVMODE: d->error = QSnapdRequest::QSnapdError::NeedsDevmode; break; case SNAPD_ERROR_NEEDS_CLASSIC: d->error = QSnapdRequest::QSnapdError::NeedsClassic; break; case SNAPD_ERROR_NEEDS_CLASSIC_SYSTEM: d->error = QSnapdRequest::QSnapdError::NeedsClassicSystem; break; case SNAPD_ERROR_BAD_QUERY: d->error = QSnapdRequest::QSnapdError::BadQuery; break; case SNAPD_ERROR_NETWORK_TIMEOUT: d->error = QSnapdRequest::QSnapdError::NetworkTimeout; break; case SNAPD_ERROR_NOT_FOUND: d->error = QSnapdRequest::QSnapdError::NotFound; break; case SNAPD_ERROR_NOT_IN_STORE: d->error = QSnapdRequest::QSnapdError::NotInStore; break; case SNAPD_ERROR_AUTH_CANCELLED: d->error = QSnapdRequest::QSnapdError::AuthCancelled; break; case SNAPD_ERROR_NOT_CLASSIC: d->error = QSnapdRequest::QSnapdError::NotClassic; break; case SNAPD_ERROR_REVISION_NOT_AVAILABLE: d->error = QSnapdRequest::QSnapdError::RevisionNotAvailable; break; case SNAPD_ERROR_CHANNEL_NOT_AVAILABLE: d->error = QSnapdRequest::QSnapdError::ChannelNotAvailable; break; case SNAPD_ERROR_NOT_A_SNAP: d->error = QSnapdRequest::QSnapdError::NotASnap; break; case SNAPD_ERROR_DNS_FAILURE: d->error = QSnapdRequest::QSnapdError::DNSFailure; break; case SNAPD_ERROR_OPTION_NOT_FOUND: d->error = QSnapdRequest::QSnapdError::OptionNotFound; break; case SNAPD_ERROR_APP_NOT_FOUND: d->error = QSnapdRequest::QSnapdError::AppNotFound; break; case SNAPD_ERROR_ARCHITECTURE_NOT_AVAILABLE: d->error = QSnapdRequest::QSnapdError::ArchitectureNotAvailable; break; case SNAPD_ERROR_CHANGE_CONFLICT: d->error = QSnapdRequest::QSnapdError::ChangeConflict; break; case SNAPD_ERROR_INTERFACES_UNCHANGED: d->error = QSnapdRequest::QSnapdError::InterfacesUnchanged; break; default: /* This indicates we should add a new entry here... */ d->error = QSnapdRequest::QSnapdError::UnknownError; break; } } else if (g_error_matches(e, G_IO_ERROR, G_IO_ERROR_CANCELLED)) d->error = QSnapdRequest::QSnapdError::Cancelled; else d->error = QSnapdRequest::QSnapdError::UnknownError; d->errorString = e->message; } emit complete(); } bool QSnapdRequest::isFinished() const { Q_D(const QSnapdRequest); return d->finished; } QSnapdRequest::QSnapdError QSnapdRequest::error() const { Q_D(const QSnapdRequest); return d->error; } QString QSnapdRequest::errorString() const { Q_D(const QSnapdRequest); return d->errorString; } void QSnapdRequest::cancel() { Q_D(QSnapdRequest); g_cancellable_cancel(d->cancellable); } void QSnapdRequest::handleProgress(void *change) { Q_D(QSnapdRequest); d->change = SNAPD_CHANGE(g_object_ref(change)); emit progress(); } QSnapdChange *QSnapdRequest::change() const { Q_D(const QSnapdRequest); return new QSnapdChange(d->change); } snapd-glib-1.67/snapd-qt/screenshot.cpp000066400000000000000000000016271477073115000201120ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/screenshot.h" QSnapdScreenshot::QSnapdScreenshot(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdScreenshot::url() const { return snapd_screenshot_get_url(SNAPD_SCREENSHOT(wrapped_object)); } quint64 QSnapdScreenshot::width() const { return snapd_screenshot_get_width(SNAPD_SCREENSHOT(wrapped_object)); } quint64 QSnapdScreenshot::height() const { return snapd_screenshot_get_height(SNAPD_SCREENSHOT(wrapped_object)); } snapd-glib-1.67/snapd-qt/slot-ref.cpp000066400000000000000000000014131477073115000174610ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/slot-ref.h" QSnapdSlotRef::QSnapdSlotRef(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdSlotRef::slot() const { return snapd_slot_ref_get_slot(SNAPD_SLOT_REF(wrapped_object)); } QString QSnapdSlotRef::snap() const { return snapd_slot_ref_get_snap(SNAPD_SLOT_REF(wrapped_object)); } snapd-glib-1.67/snapd-qt/slot.cpp000066400000000000000000000053521477073115000167150ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/slot.h" #include "variant.h" QSnapdSlot::QSnapdSlot(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdSlot::name() const { return snapd_slot_get_name(SNAPD_SLOT(wrapped_object)); } QString QSnapdSlot::snap() const { return snapd_slot_get_snap(SNAPD_SLOT(wrapped_object)); } QString QSnapdSlot::interface() const { return snapd_slot_get_interface(SNAPD_SLOT(wrapped_object)); } QStringList QSnapdSlot::attributeNames() const { g_auto(GStrv) names = snapd_slot_get_attribute_names(SNAPD_SLOT(wrapped_object), NULL); QStringList result; for (int i = 0; names[i] != NULL; i++) result.append(names[i]); return result; } bool QSnapdSlot::hasAttribute(const QString &name) const { return snapd_slot_has_attribute(SNAPD_SLOT(wrapped_object), name.toStdString().c_str()); } QVariant QSnapdSlot::attribute(const QString &name) const { GVariant *value = snapd_slot_get_attribute(SNAPD_SLOT(wrapped_object), name.toStdString().c_str()); return gvariant_to_qvariant(value); } QString QSnapdSlot::label() const { return snapd_slot_get_label(SNAPD_SLOT(wrapped_object)); } int QSnapdSlot::connectionCount() const { GPtrArray *connections; QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED connections = snapd_slot_get_connections(SNAPD_SLOT(wrapped_object)); QT_WARNING_POP return connections != NULL ? connections->len : 0; } QSnapdConnection *QSnapdSlot::connection(int n) const { GPtrArray *connections; QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED connections = snapd_slot_get_connections(SNAPD_SLOT(wrapped_object)); QT_WARNING_POP if (connections == NULL || n < 0 || (guint)n >= connections->len) return NULL; return new QSnapdConnection(connections->pdata[n]); } int QSnapdSlot::connectedPlugCount() const { GPtrArray *connections; connections = snapd_slot_get_connected_plugs(SNAPD_SLOT(wrapped_object)); return connections != NULL ? connections->len : 0; } QSnapdPlugRef *QSnapdSlot::connectedPlug(int n) const { GPtrArray *connections; connections = snapd_slot_get_connected_plugs(SNAPD_SLOT(wrapped_object)); if (connections == NULL || n < 0 || (guint)n >= connections->len) return NULL; return new QSnapdPlugRef(connections->pdata[n]); } snapd-glib-1.67/snapd-qt/snap.cpp000066400000000000000000000237061477073115000167000ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/snap.h" QSnapdSnap::QSnapdSnap(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} int QSnapdSnap::appCount() const { GPtrArray *apps; apps = snapd_snap_get_apps(SNAPD_SNAP(wrapped_object)); return apps != NULL ? apps->len : 0; } QSnapdApp *QSnapdSnap::app(int n) const { GPtrArray *apps; apps = snapd_snap_get_apps(SNAPD_SNAP(wrapped_object)); if (apps == NULL || n < 0 || (guint)n >= apps->len) return NULL; return new QSnapdApp(apps->pdata[n]); } QString QSnapdSnap::base() const { return snapd_snap_get_base(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::broken() const { return snapd_snap_get_broken(SNAPD_SNAP(wrapped_object)); } int QSnapdSnap::categoryCount() const { GPtrArray *categories; categories = snapd_snap_get_categories(SNAPD_SNAP(wrapped_object)); return categories != NULL ? categories->len : 0; } QSnapdCategory *QSnapdSnap::category(int n) const { GPtrArray *categories; categories = snapd_snap_get_categories(SNAPD_SNAP(wrapped_object)); if (categories == NULL || n < 0 || (guint)n >= categories->len) return NULL; return new QSnapdCategory(categories->pdata[n]); } QString QSnapdSnap::channel() const { return snapd_snap_get_channel(SNAPD_SNAP(wrapped_object)); } int QSnapdSnap::channelCount() const { GPtrArray *channels; channels = snapd_snap_get_channels(SNAPD_SNAP(wrapped_object)); return channels != NULL ? channels->len : 0; } QSnapdChannel *QSnapdSnap::channel(int n) const { GPtrArray *channels; channels = snapd_snap_get_channels(SNAPD_SNAP(wrapped_object)); if (channels == NULL || n < 0 || (guint)n >= channels->len) return NULL; return new QSnapdChannel(channels->pdata[n]); } QSnapdChannel *QSnapdSnap::matchChannel(const QString &name) const { SnapdChannel *channel = snapd_snap_match_channel(SNAPD_SNAP(wrapped_object), name.toStdString().c_str()); if (channel == NULL) return NULL; return new QSnapdChannel(channel); } QStringList QSnapdSnap::commonIds() const { GStrv common_ids = snapd_snap_get_common_ids(SNAPD_SNAP(wrapped_object)); QStringList result; for (int i = 0; common_ids[i] != NULL; i++) result.append(common_ids[i]); return result; } QSnapdEnums::SnapConfinement QSnapdSnap::confinement() const { switch (snapd_snap_get_confinement(SNAPD_SNAP(wrapped_object))) { case SNAPD_CONFINEMENT_STRICT: return QSnapdEnums::SnapConfinementStrict; case SNAPD_CONFINEMENT_CLASSIC: return QSnapdEnums::SnapConfinementClassic; case SNAPD_CONFINEMENT_DEVMODE: return QSnapdEnums::SnapConfinementDevmode; case SNAPD_CONFINEMENT_UNKNOWN: default: return QSnapdEnums::SnapConfinementUnknown; } } QString QSnapdSnap::contact() const { return snapd_snap_get_contact(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::description() const { return snapd_snap_get_description(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::developer() const { G_GNUC_BEGIN_IGNORE_DEPRECATIONS return snapd_snap_get_developer(SNAPD_SNAP(wrapped_object)); G_GNUC_END_IGNORE_DEPRECATIONS } bool QSnapdSnap::devmode() const { return snapd_snap_get_devmode(SNAPD_SNAP(wrapped_object)); } qint64 QSnapdSnap::downloadSize() const { return snapd_snap_get_download_size(SNAPD_SNAP(wrapped_object)); } static QDateTime convertDateTime(GDateTime *datetime) { if (datetime == NULL) return QDateTime(); QDate date(g_date_time_get_year(datetime), g_date_time_get_month(datetime), g_date_time_get_day_of_month(datetime)); QTime time(g_date_time_get_hour(datetime), g_date_time_get_minute(datetime), g_date_time_get_second(datetime), g_date_time_get_microsecond(datetime) / 1000); return QDateTime(date, time, Qt::OffsetFromUTC, g_date_time_get_utc_offset(datetime) / 1000000); } QDateTime QSnapdSnap::hold() const { return convertDateTime(snapd_snap_get_hold(SNAPD_SNAP(wrapped_object))); } QDateTime QSnapdSnap::proceedTime() const { return convertDateTime( snapd_snap_get_proceed_time(SNAPD_SNAP(wrapped_object))); } QString QSnapdSnap::icon() const { return snapd_snap_get_icon(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::id() const { return snapd_snap_get_id(SNAPD_SNAP(wrapped_object)); } QDateTime QSnapdSnap::installDate() const { return convertDateTime( snapd_snap_get_install_date(SNAPD_SNAP(wrapped_object))); } qint64 QSnapdSnap::installedSize() const { return snapd_snap_get_installed_size(SNAPD_SNAP(wrapped_object)); } bool QSnapdSnap::jailmode() const { return snapd_snap_get_jailmode(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::license() const { return snapd_snap_get_license(SNAPD_SNAP(wrapped_object)); } int QSnapdSnap::mediaCount() const { GPtrArray *media; media = snapd_snap_get_media(SNAPD_SNAP(wrapped_object)); return media != NULL ? media->len : 0; } QSnapdMedia *QSnapdSnap::media(int n) const { GPtrArray *media; media = snapd_snap_get_media(SNAPD_SNAP(wrapped_object)); if (media == NULL || n < 0 || (guint)n >= media->len) return NULL; return new QSnapdMedia(media->pdata[n]); } QString QSnapdSnap::mountedFrom() const { return snapd_snap_get_mounted_from(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::name() const { return snapd_snap_get_name(SNAPD_SNAP(wrapped_object)); } int QSnapdSnap::priceCount() const { GPtrArray *prices; prices = snapd_snap_get_prices(SNAPD_SNAP(wrapped_object)); return prices != NULL ? prices->len : 0; } QSnapdPrice *QSnapdSnap::price(int n) const { GPtrArray *prices; prices = snapd_snap_get_prices(SNAPD_SNAP(wrapped_object)); if (prices == NULL || n < 0 || (guint)n >= prices->len) return NULL; return new QSnapdPrice(prices->pdata[n]); } bool QSnapdSnap::isPrivate() const { return snapd_snap_get_private(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::publisherDisplayName() const { return snapd_snap_get_publisher_display_name(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::publisherId() const { return snapd_snap_get_publisher_id(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::publisherUsername() const { return snapd_snap_get_publisher_username(SNAPD_SNAP(wrapped_object)); } QSnapdEnums::PublisherValidation QSnapdSnap::publisherValidation() const { switch (snapd_snap_get_publisher_validation(SNAPD_SNAP(wrapped_object))) { case SNAPD_PUBLISHER_VALIDATION_UNPROVEN: return QSnapdEnums::PublisherValidationUnproven; case SNAPD_PUBLISHER_VALIDATION_STARRED: return QSnapdEnums::PublisherValidationStarred; case SNAPD_PUBLISHER_VALIDATION_VERIFIED: return QSnapdEnums::PublisherValidationVerified; case SNAPD_PUBLISHER_VALIDATION_UNKNOWN: default: return QSnapdEnums::PublisherValidationUnknown; } } QString QSnapdSnap::revision() const { return snapd_snap_get_revision(SNAPD_SNAP(wrapped_object)); } int QSnapdSnap::screenshotCount() const { GPtrArray *screenshots; G_GNUC_BEGIN_IGNORE_DEPRECATIONS screenshots = snapd_snap_get_screenshots(SNAPD_SNAP(wrapped_object)); G_GNUC_END_IGNORE_DEPRECATIONS return screenshots != NULL ? screenshots->len : 0; } QSnapdScreenshot *QSnapdSnap::screenshot(int n) const { GPtrArray *screenshots; G_GNUC_BEGIN_IGNORE_DEPRECATIONS screenshots = snapd_snap_get_screenshots(SNAPD_SNAP(wrapped_object)); G_GNUC_END_IGNORE_DEPRECATIONS if (screenshots == NULL || n < 0 || (guint)n >= screenshots->len) return NULL; return new QSnapdScreenshot(screenshots->pdata[n]); } QSnapdEnums::SnapType QSnapdSnap::snapType() const { switch (snapd_snap_get_snap_type(SNAPD_SNAP(wrapped_object))) { case SNAPD_SNAP_TYPE_APP: return QSnapdEnums::SnapTypeApp; case SNAPD_SNAP_TYPE_KERNEL: return QSnapdEnums::SnapTypeKernel; case SNAPD_SNAP_TYPE_GADGET: return QSnapdEnums::SnapTypeGadget; case SNAPD_SNAP_TYPE_OS: return QSnapdEnums::SnapTypeOperatingSystem; case SNAPD_SNAP_TYPE_CORE: return QSnapdEnums::SnapTypeCore; case SNAPD_SNAP_TYPE_BASE: return QSnapdEnums::SnapTypeBase; case SNAPD_SNAP_TYPE_SNAPD: return QSnapdEnums::SnapTypeSnapd; case SNAPD_SNAP_TYPE_UNKNOWN: default: return QSnapdEnums::SnapTypeUnknown; } } QSnapdEnums::SnapStatus QSnapdSnap::status() const { switch (snapd_snap_get_status(SNAPD_SNAP(wrapped_object))) { case SNAPD_SNAP_STATUS_AVAILABLE: return QSnapdEnums::SnapStatusAvailable; case SNAPD_SNAP_STATUS_PRICED: return QSnapdEnums::SnapStatusPriced; case SNAPD_SNAP_STATUS_INSTALLED: return QSnapdEnums::SnapStatusInstalled; case SNAPD_SNAP_STATUS_ACTIVE: return QSnapdEnums::SnapStatusActive; case SNAPD_SNAP_STATUS_UNKNOWN: default: return QSnapdEnums::SnapStatusUnknown; } } QString QSnapdSnap::storeUrl() const { return snapd_snap_get_store_url(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::summary() const { return snapd_snap_get_summary(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::title() const { return snapd_snap_get_title(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::trackingChannel() const { return snapd_snap_get_tracking_channel(SNAPD_SNAP(wrapped_object)); } QStringList QSnapdSnap::tracks() const { GStrv tracks = snapd_snap_get_tracks(SNAPD_SNAP(wrapped_object)); QStringList result; for (int i = 0; tracks[i] != NULL; i++) result.append(tracks[i]); return result; } bool QSnapdSnap::trymode() const { return snapd_snap_get_trymode(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::version() const { return snapd_snap_get_version(SNAPD_SNAP(wrapped_object)); } QString QSnapdSnap::website() const { return snapd_snap_get_website(SNAPD_SNAP(wrapped_object)); } snapd-glib-1.67/snapd-qt/snapd-qt.pc.in000066400000000000000000000003671477073115000177110ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: Snapd Qt Description: Library for accessing snapd Version: @VERSION@ Libs: -L${libdir} -lsnapd-qt Cflags: -I${includedir}/snapd-qt Requires: @pc_required_qt@ snapd-glib-1.67/snapd-qt/stream-wrapper.cpp000066400000000000000000000032571477073115000207070ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include "stream-wrapper.h" #include G_DEFINE_TYPE(StreamWrapper, stream_wrapper, G_TYPE_INPUT_STREAM) static gssize stream_wrapper_read_fn(GInputStream *stream, void *buffer, gsize count, GCancellable *cancellable, GError **error) { StreamWrapper *wrapper = SNAPD_STREAM_WRAPPER(stream); qint64 nRead; if (wrapper->ioDevice == NULL) return 0; nRead = wrapper->ioDevice->read((char *)buffer, count); if (nRead >= 0) return nRead; g_set_error_literal(error, G_FILE_ERROR, G_FILE_ERROR_FAILED, wrapper->ioDevice->errorString().toStdString().c_str()); return -1; } static gboolean stream_wrapper_close_fn(GInputStream *stream, GCancellable *cancellable, GError **error) { StreamWrapper *wrapper = SNAPD_STREAM_WRAPPER(stream); if (wrapper->ioDevice == NULL) return TRUE; wrapper->ioDevice->close(); return TRUE; } static void stream_wrapper_init(StreamWrapper *wrapper) {} static void stream_wrapper_class_init(StreamWrapperClass *klass) { GInputStreamClass *input_stream_class = G_INPUT_STREAM_CLASS(klass); input_stream_class->read_fn = stream_wrapper_read_fn; input_stream_class->close_fn = stream_wrapper_close_fn; } snapd-glib-1.67/snapd-qt/stream-wrapper.h000066400000000000000000000014361477073115000203510ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef STREAM_WRAPPER_H #define STREAM_WRAPPER_H #include #include #include #include G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(StreamWrapper, stream_wrapper, SNAPD, STREAM_WRAPPER, GInputStream) struct _StreamWrapper { GInputStream parent_instance; QPointer ioDevice; }; struct _StreamWrapperClass { GInputStreamClass parent_class; }; G_END_DECLS #endif snapd-glib-1.67/snapd-qt/system-information.cpp000066400000000000000000000114201477073115000215740ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/system-information.h" QSnapdSystemInformation::QSnapdSystemInformation(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdSystemInformation::binariesDirectory() const { return snapd_system_information_get_binaries_directory( SNAPD_SYSTEM_INFORMATION(wrapped_object)); } QString QSnapdSystemInformation::buildId() const { return snapd_system_information_get_build_id( SNAPD_SYSTEM_INFORMATION(wrapped_object)); } QSnapdEnums::SystemConfinement QSnapdSystemInformation::confinement() const { switch (snapd_system_information_get_confinement( SNAPD_SYSTEM_INFORMATION(wrapped_object))) { case SNAPD_SYSTEM_CONFINEMENT_STRICT: return QSnapdEnums::SystemConfinement::SystemConfinementStrict; case SNAPD_SYSTEM_CONFINEMENT_PARTIAL: return QSnapdEnums::SystemConfinement::SystemConfinementPartial; case SNAPD_SYSTEM_CONFINEMENT_UNKNOWN: default: return QSnapdEnums::SystemConfinement::SystemConfinementUnknown; } } QString QSnapdSystemInformation::kernelVersion() const { return snapd_system_information_get_kernel_version( SNAPD_SYSTEM_INFORMATION(wrapped_object)); } QString QSnapdSystemInformation::mountDirectory() const { return snapd_system_information_get_mount_directory( SNAPD_SYSTEM_INFORMATION(wrapped_object)); } QString QSnapdSystemInformation::osId() const { return snapd_system_information_get_os_id( SNAPD_SYSTEM_INFORMATION(wrapped_object)); } QString QSnapdSystemInformation::osVersion() const { return snapd_system_information_get_os_version( SNAPD_SYSTEM_INFORMATION(wrapped_object)); } QString QSnapdSystemInformation::refreshSchedule() const { return snapd_system_information_get_refresh_schedule( SNAPD_SYSTEM_INFORMATION(wrapped_object)); } static QDateTime convertDateTime(GDateTime *datetime) { if (datetime == NULL) return QDateTime(); QDate date(g_date_time_get_year(datetime), g_date_time_get_month(datetime), g_date_time_get_day_of_month(datetime)); QTime time(g_date_time_get_hour(datetime), g_date_time_get_minute(datetime), g_date_time_get_second(datetime), g_date_time_get_microsecond(datetime) / 1000); return QDateTime(date, time, Qt::OffsetFromUTC, g_date_time_get_utc_offset(datetime) / 1000000); } QDateTime QSnapdSystemInformation::refreshHold() const { return convertDateTime(snapd_system_information_get_refresh_hold( SNAPD_SYSTEM_INFORMATION(wrapped_object))); } QDateTime QSnapdSystemInformation::refreshLast() const { return convertDateTime(snapd_system_information_get_refresh_last( SNAPD_SYSTEM_INFORMATION(wrapped_object))); } QDateTime QSnapdSystemInformation::refreshNext() const { return convertDateTime(snapd_system_information_get_refresh_next( SNAPD_SYSTEM_INFORMATION(wrapped_object))); } QString QSnapdSystemInformation::refreshTimer() const { return snapd_system_information_get_refresh_timer( SNAPD_SYSTEM_INFORMATION(wrapped_object)); } QHash QSnapdSystemInformation::sandboxFeatures() const { QHash sandboxFeatures; GHashTable *features = snapd_system_information_get_sandbox_features( SNAPD_SYSTEM_INFORMATION(wrapped_object)); GHashTableIter iter; g_hash_table_iter_init(&iter, features); gpointer key, value; while (g_hash_table_iter_next(&iter, &key, &value)) { const gchar *backend = (const gchar *)key; GStrv features = (GStrv)value; int i; for (i = 0; features[i] != NULL; i++) sandboxFeatures[backend] << features[i]; } return sandboxFeatures; } QString QSnapdSystemInformation::series() const { return snapd_system_information_get_series( SNAPD_SYSTEM_INFORMATION(wrapped_object)); } QString QSnapdSystemInformation::store() const { return snapd_system_information_get_store( SNAPD_SYSTEM_INFORMATION(wrapped_object)); } QString QSnapdSystemInformation::version() const { return snapd_system_information_get_version( SNAPD_SYSTEM_INFORMATION(wrapped_object)); } bool QSnapdSystemInformation::onClassic() const { return snapd_system_information_get_on_classic( SNAPD_SYSTEM_INFORMATION(wrapped_object)); } bool QSnapdSystemInformation::managed() const { return snapd_system_information_get_managed( SNAPD_SYSTEM_INFORMATION(wrapped_object)); } snapd-glib-1.67/snapd-qt/task-data.cpp000066400000000000000000000015141477073115000176010ustar00rootroot00000000000000/* * Copyright (C) 2024 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/task-data.h" QSnapdTaskData::QSnapdTaskData(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QStringList QSnapdTaskData::affectedSnaps() const { QStringList retval; GStrv data = snapd_task_data_get_affected_snaps(SNAPD_TASK_DATA(wrapped_object)); if (data != NULL) for (; *data != NULL; data++) retval.append((gchar *)*data); return retval; } snapd-glib-1.67/snapd-qt/task.cpp000066400000000000000000000044231477073115000166740ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/task.h" QSnapdTask::QSnapdTask(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} QString QSnapdTask::id() const { return snapd_task_get_id(SNAPD_TASK(wrapped_object)); } QString QSnapdTask::kind() const { return snapd_task_get_kind(SNAPD_TASK(wrapped_object)); } QString QSnapdTask::summary() const { return snapd_task_get_summary(SNAPD_TASK(wrapped_object)); } QString QSnapdTask::status() const { return snapd_task_get_status(SNAPD_TASK(wrapped_object)); } QString QSnapdTask::progressLabel() const { return snapd_task_get_progress_label(SNAPD_TASK(wrapped_object)); } qint64 QSnapdTask::progressDone() const { return snapd_task_get_progress_done(SNAPD_TASK(wrapped_object)); } qint64 QSnapdTask::progressTotal() const { return snapd_task_get_progress_total(SNAPD_TASK(wrapped_object)); } static QDateTime convertDateTime(GDateTime *datetime) { if (datetime == NULL) return QDateTime(); QDate date(g_date_time_get_year(datetime), g_date_time_get_month(datetime), g_date_time_get_day_of_month(datetime)); QTime time(g_date_time_get_hour(datetime), g_date_time_get_minute(datetime), g_date_time_get_second(datetime), g_date_time_get_microsecond(datetime) / 1000); return QDateTime(date, time, Qt::OffsetFromUTC, g_date_time_get_utc_offset(datetime) / 1000000); } QDateTime QSnapdTask::spawnTime() const { return convertDateTime(snapd_task_get_spawn_time(SNAPD_TASK(wrapped_object))); } QDateTime QSnapdTask::readyTime() const { return convertDateTime(snapd_task_get_ready_time(SNAPD_TASK(wrapped_object))); } QSnapdTaskData *QSnapdTask::taskData() const { SnapdTaskData *data = SNAPD_TASK_DATA(snapd_task_get_data(SNAPD_TASK(wrapped_object))); if (data == NULL) return NULL; return new QSnapdTaskData(SNAPD_TASK_DATA(data), NULL); } snapd-glib-1.67/snapd-qt/user-information.cpp000066400000000000000000000027241477073115000212350ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include "Snapd/user-information.h" QSnapdUserInformation::QSnapdUserInformation(void *snapd_object, QObject *parent) : QSnapdWrappedObject(g_object_ref(snapd_object), g_object_unref, parent) {} int QSnapdUserInformation::id() const { return snapd_user_information_get_id(SNAPD_USER_INFORMATION(wrapped_object)); } QString QSnapdUserInformation::username() const { return snapd_user_information_get_username( SNAPD_USER_INFORMATION(wrapped_object)); } QString QSnapdUserInformation::email() const { return snapd_user_information_get_email( SNAPD_USER_INFORMATION(wrapped_object)); } QStringList QSnapdUserInformation::sshKeys() const { GStrv ssh_keys = snapd_user_information_get_ssh_keys( SNAPD_USER_INFORMATION(wrapped_object)); QStringList result; for (int i = 0; ssh_keys[i] != NULL; i++) result.append(ssh_keys[i]); return result; } QSnapdAuthData *QSnapdUserInformation::authData() const { return new QSnapdAuthData(snapd_user_information_get_auth_data( SNAPD_USER_INFORMATION(wrapped_object))); } snapd-glib-1.67/snapd-qt/variant.h000066400000000000000000000033141477073115000170410ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef VARIANT_H #define VARIANT_H static QVariant gvariant_to_qvariant(GVariant *variant) { if (variant == NULL) return QVariant(); if (g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)) return QVariant((bool)g_variant_get_boolean(variant)); if (g_variant_is_of_type(variant, G_VARIANT_TYPE_INT64)) return QVariant((qlonglong)g_variant_get_int64(variant)); if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) return QVariant(g_variant_get_string(variant, NULL)); if (g_variant_is_of_type(variant, G_VARIANT_TYPE_DOUBLE)) return QVariant(g_variant_get_double(variant)); if (g_variant_is_of_type(variant, G_VARIANT_TYPE("av"))) { QList list; GVariantIter iter; g_variant_iter_init(&iter, variant); GVariant *value; while (g_variant_iter_loop(&iter, "v", &value)) list.append(gvariant_to_qvariant(value)); return QVariant(list); } if (g_variant_is_of_type(variant, G_VARIANT_TYPE("a{sv}"))) { QHash object; GVariantIter iter; g_variant_iter_init(&iter, variant); const gchar *key; GVariant *value; while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) object.insert(key, gvariant_to_qvariant(value)); return QVariant(object); } if (g_variant_is_of_type(variant, G_VARIANT_TYPE("mv"))) return QVariant(); return QVariant(); } #endif snapd-glib-1.67/tests/000077500000000000000000000000001477073115000146365ustar00rootroot00000000000000snapd-glib-1.67/tests/meson.build000066400000000000000000000071771477073115000170140ustar00rootroot00000000000000installed_tests_exec_dir = join_paths (get_option ('libexecdir'), 'installed-tests', meson.project_name()) installed_tests_data_dir = join_paths (get_option ('datadir'), 'installed-tests', meson.project_name()) if not get_option('soup2') installed_tests_exec_dir += '-2' installed_tests_data_dir += '-2' endif test_data_conf = configuration_data () test_data_conf.set ('installed_tests_exec_dir', join_paths (get_option ('prefix'), installed_tests_exec_dir)) mock_snapd_lib = static_library ('mock-snapd', [ 'mock-snapd.c', 'mock-snapd.h' ], dependencies: [ glib_dep, gio_unix_dep, libsoup_dep, json_glib_dep ]) test_executable = executable ('test-glib', 'test-glib.c', dependencies: [ glib_dep, snapd_glib_dep, json_glib_dep ], link_with: [ mock_snapd_lib ], c_args: [ '-DVERSION="@0@"'.format (meson.project_version ()) ], install_dir: installed_tests_exec_dir, install: true) test ('Tests', test_executable, timeout: 600) test_file = configure_file (input: 'test-glib.test.in', output: 'test-glib.test', configuration: test_data_conf) install_data (test_file, install_dir: installed_tests_data_dir) test_executable = executable ('test-markdown-glib', 'test-markdown-glib.c', dependencies: [ glib_dep, snapd_glib_dep ], link_with: [ mock_snapd_lib ], install_dir: installed_tests_exec_dir, install: true) test ('Markdown tests', test_executable, timeout: 600) test_file = configure_file (input: 'test-markdown-glib.test.in', output: 'test-markdown-glib.test', configuration: test_data_conf) install_data (test_file, install_dir: installed_tests_data_dir) if get_option('qt5') or get_option('qt6') moc_files = qt.preprocess (moc_headers: [ 'test-qt.h' ]) test_executable = executable (f'test-@qt_version@', 'test-qt.cpp', moc_files, dependencies: [ glib_dep, snapd_qt_dep, json_glib_dep ], link_with: [ mock_snapd_lib ], cpp_args: [ '-DVERSION="@0@"'.format (meson.project_version ()) ], install_dir: installed_tests_exec_dir, install: true) test (f'Tests (@qt_version@', test_executable, timeout: 600) test_file = configure_file (input: f'test-@qt_version@.test.in', output: f'test-@qt_version@.test', configuration: test_data_conf) install_data (test_file, install_dir: installed_tests_data_dir) test_executable = executable (f'test-markdown-@qt_version@', 'test-markdown-qt.cpp', dependencies: [ glib_dep, snapd_qt_dep ], link_with: [ mock_snapd_lib ], install_dir: installed_tests_exec_dir, install: true) test (f'Markdown tests (@qt_version@)', test_executable, timeout: 600) test_file = configure_file (input: f'test-markdown-@qt_version@.test.in', output: f'test-markdown-@qt_version@.test', configuration: test_data_conf) install_data (test_file, install_dir: installed_tests_data_dir) endif snapd-glib-1.67/tests/mock-snapd.c000066400000000000000000005526171477073115000170560ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include #include #include #include #include #include #include #include #include "mock-snapd.h" #if !GLIB_CHECK_VERSION(2, 66, 0) // Transforms an ASCII, one-digit, lowercase hexadecimal number into // its value. #define HEX_CHAR_TO_NUMBER(c) (((c) < 'a') ? (c) - '0' : ((c) - 'a' + 10)) // a quick&dirty replacement to allow the tests to work, since // g_uri_parse_params wasn't added until GLib 2.66 // Replaces IN-PLACE any %XY token with the corresponding 0xXY byte. // The passed string is modified, so it must be a memory block that belongs // to the calling function. static void decode_url_escape_codes(gchar *str) { gchar *from = str; gchar *to = str; for (; *from != 0; from++, to++) { if (*from != '%') { *to = *from; continue; } from++; // jump over '%' character // set bit 5 to convert letters to lowercase (numbers are // unaffected) *from |= 32; gchar value = 16 * HEX_CHAR_TO_NUMBER(*from); from++; *from |= 32; value += HEX_CHAR_TO_NUMBER(*from); *to = value; } *to = 0; // ensure to zero-ending the string } GHashTable *g_uri_parse_params(const gchar *params, gssize lenght, const gchar *separators, int flags, GError **error) { g_auto(GStrv) param_list = g_strsplit(params, "&", 0); GHashTable *table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); for (GStrv p = param_list; *p != NULL; p++) { g_auto(GStrv) param = g_strsplit(*p, "=", 0); decode_url_escape_codes(param[0]); decode_url_escape_codes(param[1]); g_hash_table_insert(table, g_strdup(param[0]), g_strdup(param[1])); } return table; } #endif /* For soup 2 pretend to use the new server API */ #if !SOUP_CHECK_VERSION(2, 99, 2) typedef SoupMessage SoupServerMessage; #endif struct _MockSnapd { GObject parent_instance; GMutex mutex; GCond condition; GThread *thread; GError **thread_init_error; GMainLoop *loop; GMainContext *context; gchar *dir_path; gchar *socket_path; gboolean close_on_request; gboolean decline_auth; GList *accounts; GList *users; GList *interfaces; GList *snaps; GList *snapshots; gchar *architecture; gchar *build_id; gchar *confinement; GHashTable *sandbox_features; gchar *store; gchar *maintenance_kind; gchar *maintenance_message; gboolean managed; gboolean on_classic; gchar *refresh_hold; gchar *refresh_last; gchar *refresh_next; gchar *refresh_schedule; gchar *refresh_timer; GList *store_categories; GList *store_snaps; GList *established_connections; GList *undesired_connections; GList *assertions; int change_index; GList *changes; gchar *suggested_currency; gchar *spawn_time; gchar *ready_time; SoupMessageHeaders *last_request_headers; GHashTable *gtk_theme_status; GHashTable *icon_theme_status; GHashTable *sound_theme_status; GList *logs; GList *notices; gchar *notices_parameters; }; G_DEFINE_TYPE(MockSnapd, mock_snapd, G_TYPE_OBJECT) struct _MockNotice { gchar *id; gchar *user_id; gchar *key; GDateTime *first_occurred; GDateTime *last_occurred; GDateTime *last_repeated; int last_occurred_nanoseconds; int occurrences; gchar *expire_after; gchar *repeat_after; gchar *type; GHashTable *last_data; }; struct _MockAccount { gint64 id; gchar *email; gchar *username; gchar *password; gchar *otp; GStrv ssh_keys; gchar *macaroon; GStrv discharges; gboolean sudoer; gboolean known; gboolean terms_accepted; gboolean has_payment_methods; GList *private_snaps; }; struct _MockAlias { gchar *name; gboolean automatic; gboolean enabled; }; struct _MockApp { gchar *name; gchar *common_id; gchar *daemon; gchar *desktop_file; gboolean enabled; gboolean active; GList *aliases; }; typedef struct { gchar *name; gboolean featured; } MockCategory; struct _MockChange { gchar *id; gchar *kind; gchar *summary; gchar *spawn_time; gchar *ready_time; gchar *status; int task_index; GList *tasks; JsonNode *data; gboolean force_data; }; struct _MockChannel { gchar *risk; gchar *branch; gchar *confinement; gchar *epoch; gchar *released_at; gchar *revision; int size; gchar *version; }; struct _MockLog { gchar *timestamp; gchar *message; gchar *sid; gchar *pid; }; struct _MockPrice { gdouble amount; gchar *currency; }; struct _MockMedia { gchar *type; gchar *url; int width; int height; }; struct _MockInterface { gchar *name; gchar *summary; gchar *doc_url; }; struct _MockPlug { MockSnap *snap; gchar *name; MockInterface *interface; GHashTable *attributes; gchar *label; }; struct _MockSlot { MockSnap *snap; gchar *name; MockInterface *interface; GHashTable *attributes; gchar *label; }; struct _MockConnection { MockPlug *plug; MockSlot *slot; gboolean manual; gboolean gadget; }; struct _MockSnap { GList *apps; gchar *base; gchar *broken; GList *categories; gchar *channel; GHashTable *configuration; gchar *confinement; gchar *contact; gchar *description; gboolean devmode; int download_size; gchar *hold; gchar *icon; gchar *icon_mime_type; GBytes *icon_data; gchar *id; gchar *install_date; int installed_size; gboolean jailmode; gchar *license; GList *media; gchar *mounted_from; gchar *name; gchar *proceed_time; GList *prices; gboolean is_private; gchar *publisher_display_name; gchar *publisher_id; gchar *publisher_username; gchar *publisher_validation; gchar *revision; gchar *status; gchar *store_url; gchar *summary; gchar *title; gchar *tracking_channel; GList *tracks; gboolean trymode; gchar *type; gchar *version; gchar *website; GList *store_categories; GList *plugs; GList *slots_; gboolean disabled; gboolean dangerous; gchar *snap_data; gchar *snap_path; gchar *error; gboolean restart_required; gboolean preferred; gboolean scope_is_wide; }; struct _MockSnapshot { gchar *name; }; struct _MockTask { gchar *id; gchar *kind; gchar *summary; gchar *status; gchar *progress_label; int progress_done; int progress_total; gchar *spawn_time; gchar *ready_time; MockSnap *snap; gchar *snap_name; gchar *error; gboolean purge; GPtrArray *affected_snaps; }; struct _MockTrack { gchar *name; GList *channels; }; static void mock_notice_free(MockNotice *notice) { g_free(notice->id); g_free(notice->user_id); g_free(notice->key); g_free(notice->type); g_free(notice->expire_after); g_free(notice->repeat_after); g_clear_pointer(¬ice->first_occurred, g_date_time_unref); g_clear_pointer(¬ice->last_occurred, g_date_time_unref); g_clear_pointer(¬ice->last_repeated, g_date_time_unref); g_clear_pointer(¬ice->last_data, g_hash_table_unref); g_slice_free(MockNotice, notice); } static void mock_alias_free(MockAlias *alias) { g_free(alias->name); g_slice_free(MockAlias, alias); } static void mock_app_free(MockApp *app) { g_free(app->name); g_free(app->common_id); g_free(app->daemon); g_free(app->desktop_file); g_list_free_full(app->aliases, (GDestroyNotify)mock_alias_free); g_slice_free(MockApp, app); } static void mock_category_free(MockCategory *category) { g_free(category->name); g_slice_free(MockCategory, category); } static void mock_channel_free(MockChannel *channel) { g_free(channel->risk); g_free(channel->branch); g_free(channel->confinement); g_free(channel->epoch); g_free(channel->released_at); g_free(channel->revision); g_free(channel->version); g_slice_free(MockChannel, channel); } static void mock_track_free(MockTrack *track) { g_free(track->name); g_list_free_full(track->channels, (GDestroyNotify)mock_channel_free); g_slice_free(MockTrack, track); } static void mock_log_free(MockLog *log) { g_free(log->timestamp); g_free(log->message); g_free(log->sid); g_free(log->pid); g_slice_free(MockLog, log); } static void mock_price_free(MockPrice *price) { g_free(price->currency); g_slice_free(MockPrice, price); } static void mock_media_free(MockMedia *media) { g_free(media->type); g_free(media->url); g_slice_free(MockMedia, media); } static void mock_interface_free(MockInterface *interface) { g_free(interface->name); g_free(interface->summary); g_free(interface->doc_url); g_slice_free(MockInterface, interface); } static void mock_plug_free(MockPlug *plug) { g_free(plug->name); g_hash_table_unref(plug->attributes); g_free(plug->label); g_slice_free(MockPlug, plug); } static void mock_slot_free(MockSlot *slot) { g_free(slot->name); g_hash_table_unref(slot->attributes); g_free(slot->label); g_slice_free(MockSlot, slot); } static void mock_connection_free(MockConnection *connection) { g_slice_free(MockConnection, connection); } static void mock_snap_free(MockSnap *snap) { g_list_free_full(snap->apps, (GDestroyNotify)mock_app_free); g_free(snap->base); g_free(snap->broken); g_list_free_full(snap->categories, (GDestroyNotify)mock_category_free); g_free(snap->channel); g_hash_table_unref(snap->configuration); g_free(snap->confinement); g_free(snap->contact); g_free(snap->description); g_free(snap->hold); g_free(snap->icon); g_free(snap->icon_mime_type); g_bytes_unref(snap->icon_data); g_free(snap->id); g_free(snap->install_date); g_free(snap->license); g_list_free_full(snap->media, (GDestroyNotify)mock_media_free); g_free(snap->mounted_from); g_free(snap->name); g_list_free_full(snap->prices, (GDestroyNotify)mock_price_free); g_free(snap->publisher_display_name); g_free(snap->publisher_id); g_free(snap->publisher_username); g_free(snap->publisher_validation); g_free(snap->revision); g_free(snap->status); g_free(snap->proceed_time); g_free(snap->store_url); g_free(snap->summary); g_free(snap->title); g_free(snap->tracking_channel); g_list_free_full(snap->tracks, (GDestroyNotify)mock_track_free); g_free(snap->type); g_free(snap->version); g_free(snap->website); g_list_free_full(snap->store_categories, g_free); g_list_free_full(snap->plugs, (GDestroyNotify)mock_plug_free); g_list_free_full(snap->slots_, (GDestroyNotify)mock_slot_free); g_free(snap->snap_data); g_free(snap->snap_path); g_free(snap->error); g_slice_free(MockSnap, snap); } static gint compare_date_time_with_nanoseconds(GDateTime *date1, gint date1_nanoseconds, GDateTime *date2, gint date2_nanoseconds) { g_return_val_if_fail(date1 != NULL, 0); g_return_val_if_fail(date2 != NULL, 0); // first, compare without micro/nanoseconds. This is a must to avoid errors // due to rounding, because the g_date_time objects are created using a // gdouble. gint c = g_date_time_compare(date1, date2); if (c != 0) return c; // now take into account the nanoseconds if available if (date1_nanoseconds == -1) date1_nanoseconds = 1000 * g_date_time_get_microsecond(date1); if (date2_nanoseconds == -1) date2_nanoseconds = 1000 * g_date_time_get_microsecond(date2); if (date1_nanoseconds < date2_nanoseconds) return -1; if (date1_nanoseconds == date2_nanoseconds) return 0; return 1; } MockSnapd *mock_snapd_new(void) { return g_object_new(MOCK_TYPE_SNAPD, NULL); } const gchar *mock_snapd_get_socket_path(MockSnapd *self) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); return self->socket_path; } void mock_snapd_set_close_on_request(MockSnapd *self, gboolean close_on_request) { g_return_if_fail(MOCK_IS_SNAPD(self)); self->close_on_request = close_on_request; } void mock_snapd_set_decline_auth(MockSnapd *self, gboolean decline_auth) { g_return_if_fail(MOCK_IS_SNAPD(self)); self->decline_auth = decline_auth; } void mock_snapd_set_maintenance(MockSnapd *self, const gchar *kind, const gchar *message) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_free(self->maintenance_kind); self->maintenance_kind = g_strdup(kind); g_free(self->maintenance_message); self->maintenance_message = g_strdup(message); } void mock_snapd_set_architecture(MockSnapd *self, const gchar *architecture) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); g_free(self->architecture); self->architecture = g_strdup(architecture); } void mock_snapd_set_build_id(MockSnapd *self, const gchar *build_id) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); g_free(self->build_id); self->build_id = g_strdup(build_id); } void mock_snapd_set_confinement(MockSnapd *self, const gchar *confinement) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); g_free(self->confinement); self->confinement = g_strdup(confinement); } void mock_snapd_add_sandbox_feature(MockSnapd *self, const gchar *backend, const gchar *feature) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); GPtrArray *backend_features = g_hash_table_lookup(self->sandbox_features, backend); if (backend_features == NULL) { backend_features = g_ptr_array_new_with_free_func(g_free); g_hash_table_insert(self->sandbox_features, g_strdup(backend), backend_features); } g_ptr_array_add(backend_features, g_strdup(feature)); } void mock_snapd_set_store(MockSnapd *self, const gchar *name) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); g_free(self->store); self->store = g_strdup(name); } void mock_snapd_set_managed(MockSnapd *self, gboolean managed) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); self->managed = managed; } void mock_snapd_set_on_classic(MockSnapd *self, gboolean on_classic) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); self->on_classic = on_classic; } void mock_snapd_set_refresh_hold(MockSnapd *self, const gchar *refresh_hold) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); g_free(self->refresh_hold); self->refresh_hold = g_strdup(refresh_hold); } void mock_snapd_set_refresh_last(MockSnapd *self, const gchar *refresh_last) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); g_free(self->refresh_last); self->refresh_last = g_strdup(refresh_last); } void mock_snapd_set_refresh_next(MockSnapd *self, const gchar *refresh_next) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); g_free(self->refresh_next); self->refresh_next = g_strdup(refresh_next); } void mock_snapd_set_refresh_schedule(MockSnapd *self, const gchar *schedule) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); g_free(self->refresh_schedule); self->refresh_schedule = g_strdup(schedule); } void mock_snapd_set_refresh_timer(MockSnapd *self, const gchar *timer) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); g_free(self->refresh_timer); self->refresh_timer = g_strdup(timer); } void mock_snapd_set_suggested_currency(MockSnapd *self, const gchar *currency) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); g_free(self->suggested_currency); self->suggested_currency = g_strdup(currency); } void mock_snapd_set_spawn_time(MockSnapd *self, const gchar *spawn_time) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); g_free(self->spawn_time); self->spawn_time = g_strdup(spawn_time); } void mock_snapd_set_ready_time(MockSnapd *self, const gchar *ready_time) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); g_free(self->ready_time); self->ready_time = g_strdup(ready_time); } static MockAccount *add_account(MockSnapd *self, const gchar *email, const gchar *username, const gchar *password) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); MockAccount *account = g_slice_new0(MockAccount); account->email = g_strdup(email); account->username = g_strdup(username); account->password = g_strdup(password); account->macaroon = g_strdup_printf("MACAROON-%s", username); account->discharges = g_malloc(sizeof(gchar *) * 2); account->discharges[0] = g_strdup_printf("DISCHARGE-%s", username); account->discharges[1] = NULL; self->accounts = g_list_append(self->accounts, account); account->id = g_list_length(self->accounts); return account; } MockAccount *mock_snapd_add_account(MockSnapd *self, const gchar *email, const gchar *username, const gchar *password) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); return add_account(self, email, username, password); } MockNotice *mock_snapd_add_notice(MockSnapd *self, const gchar *id, const gchar *key, const gchar *type) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); MockNotice *notice = g_slice_new0(MockNotice); notice->id = g_strdup(id); notice->key = g_strdup(key); notice->type = g_strdup(type); notice->last_data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); notice->last_occurred_nanoseconds = -1; self->notices = g_list_append(self->notices, notice); return notice; } void mock_notice_set_nanoseconds(MockNotice *self, int nanoseconds) { self->last_occurred_nanoseconds = nanoseconds; } void mock_notice_set_user_id(MockNotice *self, const gchar *user_id) { self->user_id = g_strdup(user_id); } void mock_notice_set_dates(MockNotice *self, GDateTime *first_occurred, GDateTime *last_occurred, GDateTime *last_repeated, int occurrences) { self->first_occurred = g_date_time_ref(first_occurred); self->last_occurred = g_date_time_ref(last_occurred); self->last_repeated = g_date_time_ref(last_repeated); self->occurrences = occurrences; } void mock_notice_set_expire_after(MockNotice *self, const gchar *expire_after) { self->expire_after = g_strdup(expire_after); } void mock_notice_set_repeat_after(MockNotice *self, const gchar *repeat_after) { self->repeat_after = g_strdup(repeat_after); } void mock_notice_add_data_pair(MockNotice *self, const gchar *entry, const gchar *data) { g_hash_table_insert(self->last_data, g_strdup(entry), g_strdup(data)); } void mock_notice_set_key(MockNotice *self, const gchar *key) { g_clear_pointer(&self->key, g_free); self->key = g_strdup(key); } void mock_account_set_terms_accepted(MockAccount *account, gboolean terms_accepted) { account->terms_accepted = terms_accepted; } void mock_account_set_has_payment_methods(MockAccount *account, gboolean has_payment_methods) { account->has_payment_methods = has_payment_methods; } gint64 mock_account_get_id(MockAccount *account) { return account->id; } const gchar *mock_account_get_macaroon(MockAccount *account) { return account->macaroon; } GStrv mock_account_get_discharges(MockAccount *account) { return account->discharges; } gboolean mock_account_get_sudoer(MockAccount *account) { return account->sudoer; } gboolean mock_account_get_known(MockAccount *account) { return account->known; } void mock_account_set_otp(MockAccount *account, const gchar *otp) { g_clear_pointer(&account->otp, g_free); account->otp = g_strdup(otp); } void mock_account_set_ssh_keys(MockAccount *account, GStrv ssh_keys) { g_clear_pointer(&account->ssh_keys, g_strfreev); account->ssh_keys = g_strdupv(ssh_keys); } static MockAccount *find_account_by_id(MockSnapd *self, int id) { for (GList *link = self->accounts; link; link = link->next) { MockAccount *account = link->data; if (account->id == id) return account; } return NULL; } MockAccount *mock_snapd_find_account_by_id(MockSnapd *self, gint64 id) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); return find_account_by_id(self, id); } static MockAccount *find_account_by_username(MockSnapd *self, const gchar *username) { for (GList *link = self->accounts; link; link = link->next) { MockAccount *user = link->data; if (strcmp(user->username, username) == 0) return user; } return NULL; } MockAccount *mock_snapd_find_account_by_username(MockSnapd *self, const gchar *username) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); return find_account_by_username(self, username); } static MockAccount *find_account_by_email(MockSnapd *self, const gchar *email) { for (GList *link = self->accounts; link; link = link->next) { MockAccount *user = link->data; if (strcmp(user->email, email) == 0) return user; } return NULL; } MockAccount *mock_snapd_find_account_by_email(MockSnapd *self, const gchar *email) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); return find_account_by_email(self, email); } static MockChange *add_change(MockSnapd *self) { MockChange *change = g_slice_new0(MockChange); self->change_index++; change->id = g_strdup_printf("%d", self->change_index); change->kind = g_strdup("KIND"); change->summary = g_strdup("SUMMARY"); change->task_index = self->change_index * 100; self->changes = g_list_append(self->changes, change); return change; } MockChange *mock_snapd_add_change(MockSnapd *self) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); return add_change(self); } const gchar *mock_change_get_id(MockChange *change) { return change->id; } void mock_change_set_status(MockChange *change, const gchar *status) { g_free(change->status); change->status = g_strdup(status); } const gchar *mock_change_get_status(MockChange *change) { return change->status; } void mock_change_set_kind(MockChange *change, const gchar *kind) { g_free(change->kind); change->kind = g_strdup(kind); } void mock_change_add_data(MockChange *change, JsonNode *data) { if (change->data != NULL) { json_node_unref(change->data); } change->data = json_node_ref((JsonNode *)data); } void mock_change_set_force_data(MockChange *change, gboolean force_data) { change->force_data = force_data; } MockTask *mock_change_add_task(MockChange *change, const gchar *kind) { MockTask *task = g_slice_new0(MockTask); task->id = g_strdup_printf("%d", change->task_index); change->task_index++; task->kind = g_strdup(kind); task->summary = g_strdup("SUMMARY"); task->status = g_strdup("Do"); task->progress_label = g_strdup("LABEL"); task->progress_done = 0; task->progress_total = 1; task->affected_snaps = g_ptr_array_new_with_free_func(g_free); change->tasks = g_list_append(change->tasks, task); return task; } void mock_task_set_snap_name(MockTask *task, const gchar *snap_name) { task->snap_name = g_strdup(snap_name); } const gchar *mock_task_get_status(MockTask *task) { return task->status; } void mock_task_set_status(MockTask *task, const gchar *status) { g_free(task->status); task->status = g_strdup(status); } void mock_task_set_progress(MockTask *task, int done, int total) { task->progress_done = done; task->progress_total = total; } void mock_task_set_spawn_time(MockTask *task, const gchar *spawn_time) { g_free(task->spawn_time); task->spawn_time = g_strdup(spawn_time); } void mock_task_set_ready_time(MockTask *task, const gchar *ready_time) { g_free(task->ready_time); task->ready_time = g_strdup(ready_time); } void mock_task_add_affected_snap(MockTask *task, const gchar *snap) { g_ptr_array_add(task->affected_snaps, g_strdup(snap)); } void mock_change_set_spawn_time(MockChange *change, const gchar *spawn_time) { g_free(change->spawn_time); change->spawn_time = g_strdup(spawn_time); } void mock_change_set_ready_time(MockChange *change, const gchar *ready_time) { g_free(change->ready_time); change->ready_time = g_strdup(ready_time); } static MockSnap *mock_snap_new(const gchar *name) { MockSnap *snap = g_slice_new0(MockSnap); snap->configuration = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); snap->confinement = g_strdup("strict"); snap->publisher_display_name = g_strdup("PUBLISHER-DISPLAY-NAME"); snap->publisher_id = g_strdup("PUBLISHER-ID"); snap->publisher_username = g_strdup("PUBLISHER-USERNAME"); snap->icon = g_strdup("ICON"); snap->id = g_strdup("ID"); snap->name = g_strdup(name); snap->revision = g_strdup("REVISION"); snap->status = g_strdup("active"); snap->type = g_strdup("app"); snap->version = g_strdup("VERSION"); return snap; } static void mock_snapshot_free(MockSnapshot *snapshot) { g_free(snapshot->name); g_slice_free(MockSnapshot, snapshot); } static MockSnapshot *mock_snapshot_new(const gchar *name) { MockSnapshot *snapshot = g_slice_new0(MockSnapshot); snapshot->name = g_strdup(name); return snapshot; } MockSnap *mock_account_add_private_snap(MockAccount *account, const gchar *name) { MockSnap *snap = mock_snap_new(name); snap->download_size = 65535; snap->is_private = TRUE; account->private_snaps = g_list_append(account->private_snaps, snap); return snap; } static gboolean discharges_match(GStrv discharges0, GStrv discharges1) { int i; for (i = 0; discharges0[i] && discharges1[i]; i++) if (strcmp(discharges0[i], discharges1[i]) != 0) return FALSE; if (discharges0[i] != discharges1[i]) return FALSE; return discharges0[i] == NULL; } static MockAccount *find_account_by_macaroon(MockSnapd *self, const gchar *macaroon, GStrv discharges) { for (GList *link = self->accounts; link; link = link->next) { MockAccount *account = link->data; if (strcmp(account->macaroon, macaroon) == 0 && discharges_match(account->discharges, discharges)) return account; } return NULL; } static void mock_account_free(MockAccount *account) { g_free(account->email); g_free(account->username); g_free(account->password); g_free(account->otp); g_strfreev(account->ssh_keys); g_free(account->macaroon); g_strfreev(account->discharges); g_list_free_full(account->private_snaps, (GDestroyNotify)mock_snap_free); g_slice_free(MockAccount, account); } static MockInterface *mock_interface_new(const gchar *name) { MockInterface *interface = g_slice_new0(MockInterface); interface->name = g_strdup(name); return interface; } MockInterface *mock_snapd_add_interface(MockSnapd *self, const gchar *name) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); MockInterface *interface = mock_interface_new(name); self->interfaces = g_list_append(self->interfaces, interface); return interface; } void mock_interface_set_summary(MockInterface *interface, const gchar *summary) { g_free(interface->summary); interface->summary = g_strdup(summary); } void mock_interface_set_doc_url(MockInterface *interface, const gchar *url) { g_free(interface->doc_url); interface->doc_url = g_strdup(url); } MockSnap *mock_snapd_add_snap(MockSnapd *self, const gchar *name) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); MockSnap *snap = mock_snap_new(name); self->snaps = g_list_append(self->snaps, snap); return snap; } static MockSnap *find_snap(MockSnapd *self, const gchar *name) { for (GList *link = self->snaps; link; link = link->next) { MockSnap *snap = link->data; if (strcmp(snap->name, name) == 0) return snap; } return NULL; } MockSnap *mock_snapd_find_snap(MockSnapd *self, const gchar *name) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); return find_snap(self, name); } static MockSnapshot *find_snapshot(MockSnapd *self, const gchar *name) { for (GList *link = self->snapshots; link; link = link->next) { MockSnapshot *snapshot = link->data; if (strcmp(snapshot->name, name) == 0) return snapshot; } return NULL; } MockSnapshot *mock_snapd_find_snapshot(MockSnapd *self, const gchar *name) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); return find_snapshot(self, name); } void mock_snapd_add_store_category(MockSnapd *self, const gchar *name) { g_return_if_fail(MOCK_IS_SNAPD(self)); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); self->store_categories = g_list_append(self->store_categories, g_strdup(name)); } MockSnap *mock_snapd_add_store_snap(MockSnapd *self, const gchar *name) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); MockSnap *snap = mock_snap_new(name); snap->download_size = 65535; self->store_snaps = g_list_append(self->store_snaps, snap); mock_snap_add_track(snap, "latest"); return snap; } static MockSnap *find_store_snap_by_name(MockSnapd *self, const gchar *name, const gchar *channel, const gchar *revision) { for (GList *link = self->store_snaps; link; link = link->next) { MockSnap *snap = link->data; if (strcmp(snap->name, name) == 0 && (channel == NULL || g_strcmp0(snap->channel, channel) == 0) && (revision == NULL || g_strcmp0(snap->revision, revision) == 0)) return snap; } return NULL; } static MockSnap *find_store_snap_by_id(MockSnapd *self, const gchar *id) { for (GList *link = self->store_snaps; link; link = link->next) { MockSnap *snap = link->data; if (strcmp(snap->id, id) == 0) return snap; } return NULL; } MockApp *mock_snap_add_app(MockSnap *snap, const gchar *name) { MockApp *app = g_slice_new0(MockApp); app->name = g_strdup(name); snap->apps = g_list_append(snap->apps, app); return app; } MockApp *mock_snap_find_app(MockSnap *snap, const gchar *name) { for (GList *link = snap->apps; link; link = link->next) { MockApp *app = link->data; if (strcmp(app->name, name) == 0) return app; } return NULL; } void mock_app_set_active(MockApp *app, gboolean active) { app->active = active; } void mock_app_set_enabled(MockApp *app, gboolean enabled) { app->enabled = enabled; } void mock_app_set_common_id(MockApp *app, const gchar *id) { g_free(app->common_id); app->common_id = g_strdup(id); } void mock_app_set_daemon(MockApp *app, const gchar *daemon) { g_free(app->daemon); app->daemon = g_strdup(daemon); } void mock_app_set_desktop_file(MockApp *app, const gchar *desktop_file) { g_free(app->desktop_file); app->desktop_file = g_strdup(desktop_file); } static void add_alias(MockApp *app, const gchar *name, gboolean automatic, gboolean enabled) { MockAlias *a = g_slice_new(MockAlias); a->name = g_strdup(name); a->automatic = automatic; a->enabled = enabled; app->aliases = g_list_append(app->aliases, a); } void mock_app_add_auto_alias(MockApp *app, const gchar *name) { add_alias(app, name, TRUE, TRUE); } void mock_app_add_manual_alias(MockApp *app, const gchar *name, gboolean enabled) { MockAlias *alias = mock_app_find_alias(app, name); if (alias != NULL) { alias->enabled = enabled; return; } add_alias(app, name, FALSE, enabled); } MockAlias *mock_app_find_alias(MockApp *app, const gchar *name) { for (GList *link = app->aliases; link; link = link->next) { MockAlias *alias = link->data; if (strcmp(alias->name, name) == 0) return alias; } return NULL; } void mock_snap_set_base(MockSnap *snap, const gchar *base) { g_free(snap->base); snap->base = g_strdup(base); } void mock_snap_set_broken(MockSnap *snap, const gchar *broken) { g_free(snap->broken); snap->broken = g_strdup(broken); } void mock_snap_add_category(MockSnap *snap, const gchar *name, gboolean featured) { MockCategory *category = g_slice_new0(MockCategory); category->name = g_strdup(name); category->featured = featured; snap->categories = g_list_append(snap->categories, category); } void mock_snap_set_channel(MockSnap *snap, const gchar *channel) { g_free(snap->channel); snap->channel = g_strdup(channel); } const gchar *mock_snap_get_channel(MockSnap *snap) { return snap->channel; } void mock_snap_set_conf(MockSnap *snap, const gchar *name, const gchar *value) { g_hash_table_insert(snap->configuration, g_strdup(name), g_strdup(value)); } gsize mock_snap_get_conf_count(MockSnap *snap) { return g_hash_table_size(snap->configuration); } const gchar *mock_snap_get_conf(MockSnap *snap, const gchar *name) { return g_hash_table_lookup(snap->configuration, name); } MockTrack *mock_snap_add_track(MockSnap *snap, const gchar *name) { for (GList *link = snap->tracks; link; link = link->next) { MockTrack *track = link->data; if (g_strcmp0(track->name, name) == 0) return track; } MockTrack *track = g_slice_new0(MockTrack); track->name = g_strdup(name); snap->tracks = g_list_append(snap->tracks, track); return track; } MockChannel *mock_track_add_channel(MockTrack *track, const gchar *risk, const gchar *branch) { MockChannel *channel = g_slice_new0(MockChannel); channel->risk = g_strdup(risk); channel->branch = g_strdup(branch); channel->confinement = g_strdup("strict"); channel->epoch = g_strdup("0"); channel->revision = g_strdup("REVISION"); channel->size = 65535; channel->version = g_strdup("VERSION"); track->channels = g_list_append(track->channels, channel); return channel; } void mock_channel_set_branch(MockChannel *channel, const gchar *branch) { g_free(channel->branch); channel->branch = g_strdup(branch); } void mock_channel_set_confinement(MockChannel *channel, const gchar *confinement) { g_free(channel->confinement); channel->confinement = g_strdup(confinement); } void mock_channel_set_epoch(MockChannel *channel, const gchar *epoch) { g_free(channel->epoch); channel->epoch = g_strdup(epoch); } void mock_channel_set_released_at(MockChannel *channel, const gchar *released_at) { g_free(channel->released_at); channel->released_at = g_strdup(released_at); } void mock_channel_set_revision(MockChannel *channel, const gchar *revision) { g_free(channel->revision); channel->revision = g_strdup(revision); } const gchar *mock_snap_get_revision(MockSnap *snap) { return snap->revision; } void mock_channel_set_size(MockChannel *channel, int size) { channel->size = size; } void mock_channel_set_version(MockChannel *channel, const gchar *version) { g_free(channel->version); channel->version = g_strdup(version); } void mock_snap_set_confinement(MockSnap *snap, const gchar *confinement) { g_free(snap->confinement); snap->confinement = g_strdup(confinement); } const gchar *mock_snap_get_confinement(MockSnap *snap) { return snap->confinement; } void mock_snap_set_contact(MockSnap *snap, const gchar *contact) { g_free(snap->contact); snap->contact = g_strdup(contact); } gboolean mock_snap_get_dangerous(MockSnap *snap) { return snap->dangerous; } const gchar *mock_snap_get_data(MockSnap *snap) { return snap->snap_data; } void mock_snap_set_description(MockSnap *snap, const gchar *description) { g_free(snap->description); snap->description = g_strdup(description); } void mock_snap_set_devmode(MockSnap *snap, gboolean devmode) { snap->devmode = devmode; } gboolean mock_snap_get_devmode(MockSnap *snap) { return snap->devmode; } void mock_snap_set_disabled(MockSnap *snap, gboolean disabled) { snap->disabled = disabled; } gboolean mock_snap_get_disabled(MockSnap *snap) { return snap->disabled; } void mock_snap_set_download_size(MockSnap *snap, int download_size) { snap->download_size = download_size; } void mock_snap_set_error(MockSnap *snap, const gchar *error) { g_free(snap->error); snap->error = g_strdup(error); } void mock_snap_set_hold(MockSnap *snap, const gchar *hold) { g_free(snap->hold); snap->hold = g_strdup(hold); } void mock_snap_set_icon(MockSnap *snap, const gchar *icon) { g_free(snap->icon); snap->icon = g_strdup(icon); } void mock_snap_set_icon_data(MockSnap *snap, const gchar *mime_type, GBytes *data) { g_free(snap->icon_mime_type); snap->icon_mime_type = g_strdup(mime_type); g_bytes_unref(snap->icon_data); snap->icon_data = g_bytes_ref(data); } void mock_snap_set_id(MockSnap *snap, const gchar *id) { g_free(snap->id); snap->id = g_strdup(id); } void mock_snap_set_install_date(MockSnap *snap, const gchar *install_date) { g_free(snap->install_date); snap->install_date = g_strdup(install_date); } void mock_snap_set_installed_size(MockSnap *snap, int installed_size) { snap->installed_size = installed_size; } void mock_snap_set_jailmode(MockSnap *snap, gboolean jailmode) { snap->jailmode = jailmode; } gboolean mock_snap_get_jailmode(MockSnap *snap) { return snap->jailmode; } void mock_snap_set_license(MockSnap *snap, const gchar *license) { g_free(snap->license); snap->license = g_strdup(license); } void mock_snap_set_mounted_from(MockSnap *snap, const gchar *mounted_from) { g_free(snap->mounted_from); snap->mounted_from = g_strdup(mounted_from); } const gchar *mock_snap_get_path(MockSnap *snap) { return snap->snap_path; } gboolean mock_snap_get_preferred(MockSnap *snap) { return snap->preferred; } MockPrice *mock_snap_add_price(MockSnap *snap, gdouble amount, const gchar *currency) { MockPrice *price = g_slice_new0(MockPrice); price->amount = amount; price->currency = g_strdup(currency); snap->prices = g_list_append(snap->prices, price); return price; } static gdouble mock_snap_find_price(MockSnap *snap, const gchar *currency) { for (GList *link = snap->prices; link; link = link->next) { MockPrice *price = link->data; if (strcmp(price->currency, currency) == 0) return price->amount; } return 0.0; } void mock_snap_set_publisher_display_name(MockSnap *snap, const gchar *display_name) { g_free(snap->publisher_display_name); snap->publisher_display_name = g_strdup(display_name); } void mock_snap_set_publisher_id(MockSnap *snap, const gchar *id) { g_free(snap->publisher_id); snap->publisher_id = g_strdup(id); } void mock_snap_set_publisher_username(MockSnap *snap, const gchar *username) { g_free(snap->publisher_username); snap->publisher_username = g_strdup(username); } void mock_snap_set_publisher_validation(MockSnap *snap, const gchar *validation) { g_free(snap->publisher_validation); snap->publisher_validation = g_strdup(validation); } void mock_snap_set_restart_required(MockSnap *snap, gboolean restart_required) { snap->restart_required = restart_required; } void mock_snap_set_revision(MockSnap *snap, const gchar *revision) { g_free(snap->revision); snap->revision = g_strdup(revision); } void mock_snap_set_scope_is_wide(MockSnap *snap, gboolean scope_is_wide) { snap->scope_is_wide = scope_is_wide; } MockMedia *mock_snap_add_media(MockSnap *snap, const gchar *type, const gchar *url, int width, int height) { MockMedia *media = g_slice_new0(MockMedia); media->type = g_strdup(type); media->url = g_strdup(url); media->width = width; media->height = height; snap->media = g_list_append(snap->media, media); return media; } void mock_snap_set_status(MockSnap *snap, const gchar *status) { g_free(snap->status); snap->status = g_strdup(status); } void mock_snap_set_proceed_time(MockSnap *snap, const gchar *proceed_time) { g_free(snap->proceed_time); snap->proceed_time = g_strdup(proceed_time); } void mock_snap_set_store_url(MockSnap *snap, const gchar *store_url) { g_free(snap->store_url); snap->store_url = g_strdup(store_url); } void mock_snap_set_summary(MockSnap *snap, const gchar *summary) { g_free(snap->summary); snap->summary = g_strdup(summary); } void mock_snap_set_title(MockSnap *snap, const gchar *title) { g_free(snap->title); snap->title = g_strdup(title); } void mock_snap_set_tracking_channel(MockSnap *snap, const gchar *channel) { g_free(snap->tracking_channel); snap->tracking_channel = g_strdup(channel); } const gchar *mock_snap_get_tracking_channel(MockSnap *snap) { return snap->tracking_channel; } void mock_snap_set_trymode(MockSnap *snap, gboolean trymode) { snap->trymode = trymode; } void mock_snap_set_type(MockSnap *snap, const gchar *type) { g_free(snap->type); snap->type = g_strdup(type); } void mock_snap_set_version(MockSnap *snap, const gchar *version) { g_free(snap->version); snap->version = g_strdup(version); } void mock_snap_set_website(MockSnap *snap, const gchar *website) { g_free(snap->website); snap->website = g_strdup(website); } void mock_snap_add_store_category(MockSnap *snap, const gchar *name, gboolean featured) { snap->store_categories = g_list_append(snap->store_categories, g_strdup(name)); } MockPlug *mock_snap_add_plug(MockSnap *snap, MockInterface *interface, const gchar *name) { MockPlug *plug = g_slice_new0(MockPlug); plug->snap = snap; plug->name = g_strdup(name); plug->interface = interface; plug->attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); plug->label = g_strdup("LABEL"); snap->plugs = g_list_append(snap->plugs, plug); return plug; } MockPlug *mock_snap_find_plug(MockSnap *snap, const gchar *name) { for (GList *link = snap->plugs; link; link = link->next) { MockPlug *plug = link->data; if (strcmp(plug->name, name) == 0) return plug; } return NULL; } void mock_plug_add_attribute(MockPlug *plug, const gchar *name, const gchar *value) { g_hash_table_insert(plug->attributes, g_strdup(name), g_strdup(value)); } MockSlot *mock_snap_add_slot(MockSnap *snap, MockInterface *interface, const gchar *name) { MockSlot *slot = g_slice_new0(MockSlot); slot->snap = snap; slot->name = g_strdup(name); slot->interface = interface; slot->attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); slot->label = g_strdup("LABEL"); snap->slots_ = g_list_append(snap->slots_, slot); return slot; } MockSlot *mock_snap_find_slot(MockSnap *snap, const gchar *name) { for (GList *link = snap->slots_; link; link = link->next) { MockSlot *slot = link->data; if (strcmp(slot->name, name) == 0) return slot; } return NULL; } void mock_slot_add_attribute(MockSlot *slot, const gchar *name, const gchar *value) { g_hash_table_insert(slot->attributes, g_strdup(name), g_strdup(value)); } void mock_snapd_connect(MockSnapd *self, MockPlug *plug, MockSlot *slot, gboolean manual, gboolean gadget) { g_return_if_fail(plug != NULL); if (slot != NULL) { /* Remove existing connections */ g_autoptr(GList) old_established_connections = g_steal_pointer(&self->established_connections); for (GList *link = old_established_connections; link; link = link->next) { MockConnection *connection = link->data; if (connection->plug == plug) continue; self->established_connections = g_list_append(self->established_connections, connection); } g_autoptr(GList) old_undesired_connections = g_steal_pointer(&self->undesired_connections); for (GList *link = old_undesired_connections; link; link = link->next) { MockConnection *connection = link->data; if (connection->plug == plug) continue; self->undesired_connections = g_list_append(self->undesired_connections, connection); } MockConnection *connection = g_slice_new0(MockConnection); connection->plug = plug; connection->slot = slot; connection->manual = manual; connection->gadget = gadget; self->established_connections = g_list_append(self->established_connections, connection); } else { /* Remove existing connections */ MockSlot *autoconnected_slot = NULL; g_autoptr(GList) old_established_connections = g_steal_pointer(&self->established_connections); for (GList *link = old_established_connections; link; link = link->next) { MockConnection *connection = link->data; if (connection->plug == plug) { if (!connection->manual) autoconnected_slot = connection->slot; mock_connection_free(connection); continue; } self->established_connections = g_list_append(self->established_connections, connection); } g_autoptr(GList) old_undesired_connections = g_steal_pointer(&self->undesired_connections); for (GList *link = old_undesired_connections; link; link = link->next) { MockConnection *connection = link->data; if (connection->plug == plug) continue; self->undesired_connections = g_list_append(self->undesired_connections, connection); } /* Mark as undesired if overriding auto connection */ if (autoconnected_slot != NULL) { MockConnection *connection = g_slice_new0(MockConnection); connection->plug = plug; connection->slot = autoconnected_slot; connection->manual = manual; connection->gadget = gadget; self->undesired_connections = g_list_append(self->undesired_connections, connection); } } } MockSlot *mock_snapd_find_plug_connection(MockSnapd *self, MockPlug *plug) { for (GList *link = self->established_connections; link; link = link->next) { MockConnection *connection = link->data; if (connection->plug == plug) return connection->slot; } return NULL; } GList *mock_snapd_find_slot_connections(MockSnapd *self, MockSlot *slot) { GList *plugs = NULL; for (GList *link = self->established_connections; link; link = link->next) { MockConnection *connection = link->data; if (connection->slot == slot) plugs = g_list_append(plugs, connection->plug); } return plugs; } static void add_assertion(MockSnapd *self, const gchar *assertion) { self->assertions = g_list_append(self->assertions, g_strdup(assertion)); } void mock_snapd_add_assertion(MockSnapd *self, const gchar *assertion) { g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); add_assertion(self, assertion); } GList *mock_snapd_get_assertions(MockSnapd *self) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); return self->assertions; } const gchar *mock_snapd_get_last_user_agent(MockSnapd *self) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); if (self->last_request_headers == NULL) return NULL; return soup_message_headers_get_one(self->last_request_headers, "User-Agent"); } const gchar *mock_snapd_get_last_accept_language(MockSnapd *self) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); if (self->last_request_headers == NULL) return NULL; return soup_message_headers_get_one(self->last_request_headers, "Accept-Language"); } const gchar *mock_snapd_get_last_allow_interaction(MockSnapd *self) { g_return_val_if_fail(MOCK_IS_SNAPD(self), NULL); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); if (self->last_request_headers == NULL) return NULL; return soup_message_headers_get_one(self->last_request_headers, "X-Allow-Interaction"); } void mock_snapd_set_gtk_theme_status(MockSnapd *self, const gchar *name, const gchar *status) { g_hash_table_insert(self->gtk_theme_status, g_strdup(name), g_strdup(status)); } void mock_snapd_set_icon_theme_status(MockSnapd *self, const gchar *name, const gchar *status) { g_hash_table_insert(self->icon_theme_status, g_strdup(name), g_strdup(status)); } void mock_snapd_set_sound_theme_status(MockSnapd *self, const gchar *name, const gchar *status) { g_hash_table_insert(self->sound_theme_status, g_strdup(name), g_strdup(status)); } void mock_snapd_add_log(MockSnapd *self, const gchar *timestamp, const gchar *message, const gchar *sid, const gchar *pid) { g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); MockLog *log = g_slice_new0(MockLog); log->timestamp = g_strdup(timestamp); log->message = g_strdup(message); log->sid = g_strdup(sid); log->pid = g_strdup(pid); self->logs = g_list_append(self->logs, log); } static MockChange *get_change(MockSnapd *self, const gchar *id) { for (GList *link = self->changes; link; link = link->next) { MockChange *change = link->data; if (strcmp(change->id, id) == 0) return change; } return NULL; } static void mock_task_free(MockTask *task) { g_free(task->id); g_free(task->kind); g_free(task->summary); g_free(task->status); g_free(task->progress_label); g_free(task->spawn_time); g_free(task->ready_time); g_clear_pointer(&task->snap, mock_snap_free); g_free(task->snap_name); g_free(task->error); g_clear_pointer(&task->affected_snaps, g_ptr_array_unref); g_slice_free(MockTask, task); } static void mock_change_free(MockChange *change) { g_free(change->id); g_free(change->kind); g_free(change->summary); g_free(change->spawn_time); g_free(change->ready_time); if (change->tasks) { g_list_free_full(change->tasks, (GDestroyNotify)mock_task_free); change->tasks = NULL; } g_clear_pointer(&change->data, json_node_unref); g_slice_free(MockChange, change); } static void send_response(SoupServerMessage *message, guint status_code, const gchar *content_type, const guint8 *content, gsize content_length) { #if SOUP_CHECK_VERSION(2, 99, 2) soup_server_message_set_status(message, status_code, NULL); SoupMessageHeaders *response_headers = soup_server_message_get_response_headers(message); SoupMessageBody *response_body = soup_server_message_get_response_body(message); #else soup_message_set_status(message, status_code); SoupMessageHeaders *response_headers = message->response_headers; SoupMessageBody *response_body = message->response_body; #endif soup_message_headers_set_content_length(response_headers, content_length); soup_message_headers_set_content_type(response_headers, content_type, NULL); soup_message_body_append(response_body, SOUP_MEMORY_COPY, content, content_length); } static void send_json_response(SoupServerMessage *message, guint status_code, JsonNode *node) { g_autoptr(JsonGenerator) generator = json_generator_new(); json_generator_set_root(generator, node); gsize data_length; g_autofree gchar *data = json_generator_to_data(generator, &data_length); send_response(message, status_code, "application/json", (guint8 *)data, data_length); } static JsonNode * make_response(MockSnapd *self, const gchar *type, guint status_code, JsonNode *result, const gchar *change_id, const gchar *suggested_currency) // FIXME: sources { g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "type"); json_builder_add_string_value(builder, type); json_builder_set_member_name(builder, "status-code"); json_builder_add_int_value(builder, status_code); json_builder_set_member_name(builder, "status"); json_builder_add_string_value(builder, soup_status_get_phrase(status_code)); json_builder_set_member_name(builder, "result"); if (result != NULL) json_builder_add_value(builder, result); else json_builder_add_null_value( builder); // FIXME: Snapd sets it to null, but it might be a bug? if (change_id != NULL) { json_builder_set_member_name(builder, "change"); json_builder_add_string_value(builder, change_id); } if (suggested_currency != NULL) { json_builder_set_member_name(builder, "suggested-currency"); json_builder_add_string_value(builder, suggested_currency); } if (self->maintenance_kind != NULL) { json_builder_set_member_name(builder, "maintenance"); json_builder_begin_object(builder); json_builder_set_member_name(builder, "kind"); json_builder_add_string_value(builder, self->maintenance_kind); json_builder_set_member_name(builder, "message"); json_builder_add_string_value(builder, self->maintenance_message); json_builder_end_object(builder); } json_builder_end_object(builder); return json_builder_get_root(builder); } static void send_sync_response(MockSnapd *self, SoupServerMessage *message, guint status_code, JsonNode *result, const gchar *suggested_currency) { g_autoptr(JsonNode) response = make_response( self, "sync", status_code, result, NULL, suggested_currency); send_json_response(message, status_code, response); } static void send_async_response(MockSnapd *self, SoupServerMessage *message, guint status_code, const gchar *change_id) { g_autoptr(JsonNode) response = make_response(self, "async", status_code, NULL, change_id, NULL); send_json_response(message, status_code, response); } static void send_error_response(MockSnapd *self, SoupServerMessage *message, guint status_code, const gchar *error_message, const gchar *kind, JsonNode *error_value) { g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "message"); json_builder_add_string_value(builder, error_message); if (kind != NULL) { json_builder_set_member_name(builder, "kind"); json_builder_add_string_value(builder, kind); } if (error_value != NULL) { json_builder_set_member_name(builder, "value"); json_builder_add_value(builder, error_value); } json_builder_end_object(builder); g_autoptr(JsonNode) response = make_response( self, "error", status_code, json_builder_get_root(builder), NULL, NULL); send_json_response(message, status_code, response); } static void send_error_bad_request(MockSnapd *self, SoupServerMessage *message, const gchar *error_message, const gchar *kind) { send_error_response(self, message, 400, error_message, kind, NULL); } static void send_error_unauthorized(MockSnapd *self, SoupServerMessage *message, const gchar *error_message, const gchar *kind) { send_error_response(self, message, 401, error_message, kind, NULL); } static void send_error_forbidden(MockSnapd *self, SoupServerMessage *message, const gchar *error_message, const gchar *kind) { send_error_response(self, message, 403, error_message, kind, NULL); } static void send_error_not_found(MockSnapd *self, SoupServerMessage *message, const gchar *error_message, const gchar *kind) { send_error_response(self, message, 404, error_message, kind, NULL); } static void send_error_method_not_allowed(MockSnapd *self, SoupServerMessage *message, const gchar *error_message) { send_error_response(self, message, 405, error_message, NULL, NULL); } static void handle_system_info(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); if (self->architecture) { json_builder_set_member_name(builder, "architecture"); json_builder_add_string_value(builder, self->architecture); } if (self->build_id) { json_builder_set_member_name(builder, "build-id"); json_builder_add_string_value(builder, self->build_id); } if (self->confinement) { json_builder_set_member_name(builder, "confinement"); json_builder_add_string_value(builder, self->confinement); } json_builder_set_member_name(builder, "os-release"); json_builder_begin_object(builder); json_builder_set_member_name(builder, "id"); json_builder_add_string_value(builder, "OS-ID"); json_builder_set_member_name(builder, "version-id"); json_builder_add_string_value(builder, "OS-VERSION"); json_builder_end_object(builder); json_builder_set_member_name(builder, "series"); json_builder_add_string_value(builder, "SERIES"); json_builder_set_member_name(builder, "version"); json_builder_add_string_value(builder, "VERSION"); json_builder_set_member_name(builder, "managed"); json_builder_add_boolean_value(builder, self->managed); json_builder_set_member_name(builder, "on-classic"); json_builder_add_boolean_value(builder, self->on_classic); json_builder_set_member_name(builder, "kernel-version"); json_builder_add_string_value(builder, "KERNEL-VERSION"); json_builder_set_member_name(builder, "locations"); json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap-mount-dir"); json_builder_add_string_value(builder, "/snap"); json_builder_set_member_name(builder, "snap-bin-dir"); json_builder_add_string_value(builder, "/snap/bin"); json_builder_end_object(builder); if (g_hash_table_size(self->sandbox_features) > 0) { json_builder_set_member_name(builder, "sandbox-features"); json_builder_begin_object(builder); GHashTableIter iter; gpointer key, value; g_hash_table_iter_init(&iter, self->sandbox_features); while (g_hash_table_iter_next(&iter, &key, &value)) { const gchar *backend = key; GPtrArray *backend_features = value; json_builder_set_member_name(builder, backend); json_builder_begin_array(builder); for (guint i = 0; i < backend_features->len; i++) json_builder_add_string_value(builder, g_ptr_array_index(backend_features, i)); json_builder_end_array(builder); } json_builder_end_object(builder); } if (self->store) { json_builder_set_member_name(builder, "store"); json_builder_add_string_value(builder, self->store); } json_builder_set_member_name(builder, "refresh"); json_builder_begin_object(builder); if (self->refresh_timer) { json_builder_set_member_name(builder, "timer"); json_builder_add_string_value(builder, self->refresh_timer); } else if (self->refresh_schedule) { json_builder_set_member_name(builder, "schedule"); json_builder_add_string_value(builder, self->refresh_schedule); } if (self->refresh_last) { json_builder_set_member_name(builder, "last"); json_builder_add_string_value(builder, self->refresh_last); } if (self->refresh_next) { json_builder_set_member_name(builder, "next"); json_builder_add_string_value(builder, self->refresh_next); } if (self->refresh_hold) { json_builder_set_member_name(builder, "hold"); json_builder_add_string_value(builder, self->refresh_hold); } json_builder_end_object(builder); json_builder_end_object(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } static gboolean parse_macaroon(const gchar *authorization, gchar **macaroon, GStrv *discharges) { if (authorization == NULL) return FALSE; const gchar *i = authorization; while (isspace(*i)) i++; const gchar *start = i; while (*i && !isspace(*i)) i++; g_autofree gchar *scheme = g_strndup(start, i - start); if (strcmp(scheme, "Macaroon") != 0) return FALSE; g_autoptr(GPtrArray) d = g_ptr_array_new_with_free_func(g_free); g_autofree gchar *m = NULL; while (TRUE) { while (isspace(*i)) i++; if (*i == '\0') break; start = i; while (*i && !(isspace(*i) || *i == '=')) i++; g_autofree gchar *param_name = g_strndup(start, i - start); if (*i == '\0') break; i++; while (isspace(*i)) i++; if (*i == '\0') break; g_autofree gchar *param_value = NULL; if (*i == '"') { i++; start = i; while (*i && *i != '"') i++; param_value = g_strndup(start, i - start); i++; while (isspace(*i)) i++; while (*i && *i != ',') i++; } else { start = i; while (*i && *i != ',') i++; param_value = g_strndup(start, i - start); } if (strcmp(param_name, "root") == 0) { g_free(m); m = g_steal_pointer(¶m_value); } else if (strcmp(param_name, "discharge") == 0) { g_ptr_array_add(d, g_steal_pointer(¶m_value)); } if (*i != ',') break; i++; } g_ptr_array_add(d, NULL); if (m == NULL) return FALSE; *macaroon = g_steal_pointer(&m); *discharges = (GStrv)d->pdata; g_ptr_array_free(d, FALSE); d = NULL; return TRUE; } static MockAccount *get_account(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) SoupMessageHeaders *request_headers = soup_server_message_get_request_headers(message); #else SoupMessageHeaders *request_headers = message->request_headers; #endif const gchar *authorization = soup_message_headers_get_one(request_headers, "Authorization"); if (authorization == NULL) return NULL; g_autofree gchar *macaroon = NULL; g_auto(GStrv) discharges = NULL; if (!parse_macaroon(authorization, &macaroon, &discharges)) return NULL; return find_account_by_macaroon(self, macaroon, discharges); } static JsonNode *get_json(SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) SoupMessageHeaders *request_headers = soup_server_message_get_request_headers(message); SoupMessageBody *request_body = soup_server_message_get_request_body(message); #else SoupMessageHeaders *request_headers = message->request_headers; SoupMessageBody *request_body = message->request_body; #endif const gchar *content_type = soup_message_headers_get_content_type(request_headers, NULL); if (content_type == NULL) return NULL; g_autoptr(JsonParser) parser = json_parser_new(); g_autoptr(GError) error = NULL; if (!json_parser_load_from_data(parser, request_body->data, request_body->length, &error)) { g_warning("Failed to parse request: %s", error->message); return NULL; } return json_node_ref(json_parser_get_root(parser)); } static void add_user_response(JsonBuilder *builder, MockAccount *account, gboolean send_macaroon, gboolean send_ssh_keys, gboolean send_email) { json_builder_begin_object(builder); json_builder_set_member_name(builder, "id"); json_builder_add_int_value(builder, account->id); if (send_email && account->email != NULL) { json_builder_set_member_name(builder, "email"); json_builder_add_string_value(builder, account->email); } json_builder_set_member_name(builder, "username"); json_builder_add_string_value(builder, account->username); if (send_ssh_keys && account->ssh_keys != NULL) { json_builder_set_member_name(builder, "ssh-keys"); json_builder_begin_array(builder); for (int i = 0; account->ssh_keys[i] != NULL; i++) json_builder_add_string_value(builder, account->ssh_keys[i]); json_builder_end_array(builder); } if (send_macaroon && account->macaroon != NULL) { json_builder_set_member_name(builder, "macaroon"); json_builder_add_string_value(builder, account->macaroon); json_builder_set_member_name(builder, "discharges"); json_builder_begin_array(builder); for (int i = 0; account->discharges[i] != NULL; i++) json_builder_add_string_value(builder, account->discharges[i]); json_builder_end_array(builder); } json_builder_end_object(builder); } static void handle_login(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "POST") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } g_autoptr(JsonNode) request = get_json(message); if (request == NULL) { send_error_bad_request(self, message, "unknown content type", NULL); return; } JsonObject *o = json_node_get_object(request); const gchar *email = json_object_get_string_member(o, "email"); if (email == NULL) email = json_object_get_string_member(o, "username"); const gchar *password = json_object_get_string_member(o, "password"); const gchar *otp = NULL; if (json_object_has_member(o, "otp")) otp = json_object_get_string_member(o, "otp"); if (strstr(email, "@") == NULL) { send_error_bad_request(self, message, "please use a valid email address.", "invalid-auth-data"); return; } MockAccount *account = find_account_by_email(self, email); if (account == NULL) { send_error_unauthorized(self, message, "cannot authenticate to snap store: Provided " "email/password is not correct.", "login-required"); return; } if (strcmp(account->password, password) != 0) { send_error_unauthorized(self, message, "cannot authenticate to snap store: Provided " "email/password is not correct.", "login-required"); return; } if (account->otp != NULL) { if (otp == NULL) { send_error_unauthorized(self, message, "two factor authentication required", "two-factor-required"); return; } if (strcmp(account->otp, otp) != 0) { send_error_unauthorized(self, message, "two factor authentication failed", "two-factor-failed"); return; } } g_autoptr(JsonBuilder) builder = json_builder_new(); add_user_response(builder, account, TRUE, FALSE, TRUE); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } static void handle_logout(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "POST") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } g_autoptr(JsonNode) request = get_json(message); if (request == NULL) { send_error_bad_request(self, message, "unknown content type", NULL); return; } JsonObject *o = json_node_get_object(request); int id = json_object_get_int_member(o, "id"); MockAccount *account = find_account_by_id(self, id); if (account == NULL || get_account(self, message) != account) { send_error_bad_request(self, message, "not logged in", NULL); return; } self->accounts = g_list_remove(self->accounts, account); mock_account_free(account); send_sync_response(self, message, 200, NULL, NULL); } static JsonNode *make_app_node(MockApp *app, const gchar *snap_name) { g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); if (snap_name != NULL) { json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, snap_name); } if (app->name != NULL) { json_builder_set_member_name(builder, "name"); json_builder_add_string_value(builder, app->name); } if (app->common_id != NULL) { json_builder_set_member_name(builder, "common-id"); json_builder_add_string_value(builder, app->common_id); } if (app->daemon != NULL) { json_builder_set_member_name(builder, "daemon"); json_builder_add_string_value(builder, app->daemon); } if (app->desktop_file != NULL) { json_builder_set_member_name(builder, "desktop-file"); json_builder_add_string_value(builder, app->desktop_file); } if (app->active) { json_builder_set_member_name(builder, "active"); json_builder_add_boolean_value(builder, TRUE); } if (app->enabled) { json_builder_set_member_name(builder, "enabled"); json_builder_add_boolean_value(builder, TRUE); } json_builder_end_object(builder); return json_builder_get_root(builder); } static JsonNode *make_snap_node(MockSnap *snap) { g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); if (snap->apps != NULL) { json_builder_set_member_name(builder, "apps"); json_builder_begin_array(builder); for (GList *link = snap->apps; link; link = link->next) { MockApp *app = link->data; json_builder_add_value(builder, make_app_node(app, NULL)); } json_builder_end_array(builder); } if (snap->broken) { json_builder_set_member_name(builder, "broken"); json_builder_add_string_value(builder, snap->broken); } if (snap->base) { json_builder_set_member_name(builder, "base"); json_builder_add_string_value(builder, snap->base); } if (snap->categories) { json_builder_set_member_name(builder, "categories"); json_builder_begin_array(builder); for (GList *link = snap->categories; link; link = link->next) { MockCategory *category = link->data; json_builder_begin_object(builder); json_builder_set_member_name(builder, "name"); json_builder_add_string_value(builder, category->name); json_builder_set_member_name(builder, "featured"); json_builder_add_boolean_value(builder, category->featured); json_builder_end_object(builder); } json_builder_end_array(builder); } if (snap->channel) { json_builder_set_member_name(builder, "channel"); json_builder_add_string_value(builder, snap->channel); } if (snap->tracks != NULL) { json_builder_set_member_name(builder, "channels"); json_builder_begin_object(builder); for (GList *link = snap->tracks; link; link = link->next) { MockTrack *track = link->data; for (GList *channel_link = track->channels; channel_link; channel_link = channel_link->next) { MockChannel *channel = channel_link->data; g_autofree gchar *key = NULL; if (channel->branch != NULL) key = g_strdup_printf("%s/%s/%s", track->name, channel->risk, channel->branch); else key = g_strdup_printf("%s/%s", track->name, channel->risk); g_autofree gchar *name = NULL; if (g_strcmp0(track->name, "latest") == 0) { if (channel->branch != NULL) name = g_strdup_printf("%s/%s", channel->risk, channel->branch); else name = g_strdup(channel->risk); } else name = g_strdup(key); json_builder_set_member_name(builder, key); json_builder_begin_object(builder); json_builder_set_member_name(builder, "revision"); json_builder_add_string_value(builder, channel->revision); json_builder_set_member_name(builder, "confinement"); json_builder_add_string_value(builder, channel->confinement); json_builder_set_member_name(builder, "version"); json_builder_add_string_value(builder, channel->version); json_builder_set_member_name(builder, "channel"); json_builder_add_string_value(builder, name); json_builder_set_member_name(builder, "epoch"); json_builder_add_string_value(builder, channel->epoch); json_builder_set_member_name(builder, "size"); json_builder_add_int_value(builder, channel->size); if (channel->released_at != NULL) { json_builder_set_member_name(builder, "released-at"); json_builder_add_string_value(builder, channel->released_at); } json_builder_end_object(builder); } } json_builder_end_object(builder); } if (snap->apps != NULL) { int id_count = 0; for (GList *link = snap->apps; link; link = link->next) { MockApp *app = link->data; if (app->common_id == NULL) continue; if (id_count == 0) { json_builder_set_member_name(builder, "common-ids"); json_builder_begin_array(builder); } id_count++; json_builder_add_string_value(builder, app->common_id); } if (id_count > 0) json_builder_end_array(builder); } json_builder_set_member_name(builder, "confinement"); json_builder_add_string_value(builder, snap->confinement); if (snap->contact) { json_builder_set_member_name(builder, "contact"); json_builder_add_string_value(builder, snap->contact); } if (snap->description) { json_builder_set_member_name(builder, "description"); json_builder_add_string_value(builder, snap->description); } json_builder_set_member_name(builder, "developer"); json_builder_add_string_value(builder, snap->publisher_username); json_builder_set_member_name(builder, "devmode"); json_builder_add_boolean_value(builder, snap->devmode); if (snap->download_size > 0) { json_builder_set_member_name(builder, "download-size"); json_builder_add_int_value(builder, snap->download_size); } if (snap->hold != NULL) { json_builder_set_member_name(builder, "hold"); json_builder_add_string_value(builder, snap->hold); } json_builder_set_member_name(builder, "icon"); json_builder_add_string_value(builder, snap->icon); json_builder_set_member_name(builder, "id"); json_builder_add_string_value(builder, snap->id); if (snap->install_date != NULL) { json_builder_set_member_name(builder, "install-date"); json_builder_add_string_value(builder, snap->install_date); } if (snap->installed_size > 0) { json_builder_set_member_name(builder, "installed-size"); json_builder_add_int_value(builder, snap->installed_size); } json_builder_set_member_name(builder, "jailmode"); json_builder_add_boolean_value(builder, snap->jailmode); if (snap->license) { json_builder_set_member_name(builder, "license"); json_builder_add_string_value(builder, snap->license); } if (snap->mounted_from) { json_builder_set_member_name(builder, "mounted-from"); json_builder_add_string_value(builder, snap->mounted_from); } int screenshot_count = 0; if (snap->media != NULL) { json_builder_set_member_name(builder, "media"); json_builder_begin_array(builder); for (GList *link = snap->media; link; link = link->next) { MockMedia *media = link->data; if (strcmp(media->type, "screenshot") == 0) screenshot_count++; json_builder_begin_object(builder); json_builder_set_member_name(builder, "type"); json_builder_add_string_value(builder, media->type); json_builder_set_member_name(builder, "url"); json_builder_add_string_value(builder, media->url); if (media->width > 0 && media->height > 0) { json_builder_set_member_name(builder, "width"); json_builder_add_int_value(builder, media->width); json_builder_set_member_name(builder, "height"); json_builder_add_int_value(builder, media->height); } json_builder_end_object(builder); } json_builder_end_array(builder); } json_builder_set_member_name(builder, "name"); json_builder_add_string_value(builder, snap->name); if (snap->prices != NULL) { json_builder_set_member_name(builder, "prices"); json_builder_begin_object(builder); for (GList *link = snap->prices; link; link = link->next) { MockPrice *price = link->data; json_builder_set_member_name(builder, price->currency); json_builder_add_double_value(builder, price->amount); } json_builder_end_object(builder); } if (snap->is_private) { json_builder_set_member_name(builder, "private"); json_builder_add_boolean_value(builder, TRUE); } json_builder_set_member_name(builder, "publisher"); json_builder_begin_object(builder); json_builder_set_member_name(builder, "id"); json_builder_add_string_value(builder, snap->publisher_id); json_builder_set_member_name(builder, "username"); json_builder_add_string_value(builder, snap->publisher_username); json_builder_set_member_name(builder, "display-name"); json_builder_add_string_value(builder, snap->publisher_display_name); if (snap->publisher_validation != NULL) { json_builder_set_member_name(builder, "validation"); json_builder_add_string_value(builder, snap->publisher_validation); } json_builder_end_object(builder); json_builder_set_member_name(builder, "resource"); g_autofree gchar *resource = g_strdup_printf("/v2/snaps/%s", snap->name); json_builder_add_string_value(builder, resource); json_builder_set_member_name(builder, "revision"); json_builder_add_string_value(builder, snap->revision); json_builder_set_member_name(builder, "screenshots"); json_builder_begin_array(builder); json_builder_begin_object(builder); json_builder_set_member_name(builder, "note"); json_builder_add_string_value( builder, "'screenshots' is deprecated; use 'media' instead. More info at " "https://forum.snapcraft.io/t/8086"); json_builder_end_object(builder); json_builder_end_array(builder); json_builder_set_member_name(builder, "status"); json_builder_add_string_value(builder, snap->status); if (snap->store_url) { json_builder_set_member_name(builder, "store-url"); json_builder_add_string_value(builder, snap->store_url); } if (snap->summary) { json_builder_set_member_name(builder, "summary"); json_builder_add_string_value(builder, snap->summary); } if (snap->title) { json_builder_set_member_name(builder, "title"); json_builder_add_string_value(builder, snap->title); } if (snap->tracking_channel) { json_builder_set_member_name(builder, "tracking-channel"); json_builder_add_string_value(builder, snap->tracking_channel); } if (snap->tracks) { json_builder_set_member_name(builder, "tracks"); json_builder_begin_array(builder); for (GList *link = snap->tracks; link; link = link->next) { MockTrack *track = link->data; json_builder_add_string_value(builder, track->name); } json_builder_end_array(builder); } json_builder_set_member_name(builder, "trymode"); json_builder_add_boolean_value(builder, snap->trymode); json_builder_set_member_name(builder, "type"); json_builder_add_string_value(builder, snap->type); json_builder_set_member_name(builder, "version"); json_builder_add_string_value(builder, snap->version); if (snap->website) { json_builder_set_member_name(builder, "website"); json_builder_add_string_value(builder, snap->website); } if (snap->proceed_time != NULL) { json_builder_set_member_name(builder, "refresh-inhibit"); json_builder_begin_object(builder); json_builder_set_member_name(builder, "proceed-time"); json_builder_add_string_value(builder, snap->proceed_time); json_builder_end_object(builder); } json_builder_end_object(builder); return json_builder_get_root(builder); } static GList *get_refreshable_snaps(MockSnapd *self) { g_autoptr(GList) refreshable_snaps = NULL; for (GList *link = self->store_snaps; link; link = link->next) { MockSnap *store_snap = link->data; MockSnap *snap; snap = find_snap(self, store_snap->name); if (snap != NULL && strcmp(store_snap->revision, snap->revision) > 0) refreshable_snaps = g_list_append(refreshable_snaps, store_snap); } return g_steal_pointer(&refreshable_snaps); } static gboolean filter_snaps(GStrv selected_snaps, MockSnap *snap) { /* If no filter selected, then return all snaps */ if (selected_snaps == NULL || selected_snaps[0] == NULL) return TRUE; for (int i = 0; selected_snaps[i] != NULL; i++) { if (strcmp(selected_snaps[i], snap->name) == 0) return TRUE; } return FALSE; } static void handle_snaps(MockSnapd *self, SoupServerMessage *message, GHashTable *query) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); SoupMessageHeaders *request_headers = soup_server_message_get_request_headers(message); SoupMessageBody *request_body = soup_server_message_get_request_body(message); #else const gchar *method = message->method; SoupMessageHeaders *request_headers = message->request_headers; SoupMessageBody *request_body = message->request_body; #endif const gchar *content_type = soup_message_headers_get_content_type(request_headers, NULL); if (strcmp(method, "GET") == 0) { const gchar *select_param = NULL; g_auto(GStrv) selected_snaps = NULL; if (query != NULL) { const gchar *snaps_param = NULL; select_param = g_hash_table_lookup(query, "select"); snaps_param = g_hash_table_lookup(query, "snaps"); if (snaps_param != NULL) selected_snaps = g_strsplit(snaps_param, ",", -1); } g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_array(builder); for (GList *link = self->snaps; link; link = link->next) { MockSnap *snap = link->data; if (!filter_snaps(selected_snaps, snap)) continue; if ((select_param == NULL || strcmp(select_param, "enabled") == 0) && strcmp(snap->status, "active") != 0) continue; if ((select_param != NULL) && g_str_equal(select_param, "refresh-inhibited") && (snap->proceed_time == NULL)) continue; json_builder_add_value(builder, make_snap_node(snap)); } json_builder_end_array(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } else if (strcmp(method, "POST") == 0 && g_strcmp0(content_type, "application/json") == 0) { g_autoptr(JsonNode) request = get_json(message); if (request == NULL) { send_error_bad_request(self, message, "unknown content type", NULL); return; } JsonObject *o = json_node_get_object(request); const gchar *action = json_object_get_string_member(o, "action"); if (strcmp(action, "refresh") == 0) { g_autoptr(GList) refreshable_snaps = get_refreshable_snaps(self); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap-names"); json_builder_begin_array(builder); for (GList *link = refreshable_snaps; link; link = link->next) { MockSnap *snap = link->data; json_builder_add_string_value(builder, snap->name); } json_builder_end_array(builder); json_builder_end_object(builder); MockChange *change = add_change(self); change->data = json_builder_get_root(builder); mock_change_add_task(change, "refresh"); send_async_response(self, message, 202, change->id); } else { send_error_bad_request(self, message, "unsupported multi-snap operation", NULL); return; } } else if (strcmp(method, "POST") == 0 && g_str_has_prefix(content_type, "multipart/")) { #if SOUP_CHECK_VERSION(2, 99, 2) g_autoptr(GBytes) b = g_bytes_new(request_body->data, request_body->length); g_autoptr(SoupMultipart) multipart = soup_multipart_new_from_message(request_headers, b); #else g_autoptr(SoupMultipart) multipart = soup_multipart_new_from_message(request_headers, request_body); #endif if (multipart == NULL) { send_error_bad_request(self, message, "cannot read POST form", NULL); return; } gboolean classic = FALSE, dangerous = FALSE, devmode = FALSE, jailmode = FALSE; g_autofree gchar *action = NULL; g_autofree gchar *snap = NULL; g_autofree gchar *snap_path = NULL; for (int i = 0; i < soup_multipart_get_length(multipart); i++) { SoupMessageHeaders *part_headers; #if SOUP_CHECK_VERSION(2, 99, 2) GBytes *part_body; #else SoupBuffer *part_body; #endif g_autofree gchar *disposition = NULL; g_autoptr(GHashTable) params = NULL; if (!soup_multipart_get_part(multipart, i, &part_headers, &part_body)) continue; if (!soup_message_headers_get_content_disposition(part_headers, &disposition, ¶ms)) continue; if (strcmp(disposition, "form-data") == 0) { const gchar *name = g_hash_table_lookup(params, "name"); #if SOUP_CHECK_VERSION(2, 99, 2) g_autofree gchar *value = g_strndup(g_bytes_get_data(part_body, NULL), g_bytes_get_size(part_body)); #else g_autofree gchar *value = g_strndup(part_body->data, part_body->length); #endif if (g_strcmp0(name, "action") == 0) action = g_strdup(value); else if (g_strcmp0(name, "classic") == 0) classic = strcmp(value, "true") == 0; else if (g_strcmp0(name, "dangerous") == 0) dangerous = strcmp(value, "true") == 0; else if (g_strcmp0(name, "devmode") == 0) devmode = strcmp(value, "true") == 0; else if (g_strcmp0(name, "jailmode") == 0) jailmode = strcmp(value, "true") == 0; else if (g_strcmp0(name, "snap") == 0) snap = g_strdup(value); else if (g_strcmp0(name, "snap-path") == 0) snap_path = g_strdup(value); } } if (g_strcmp0(action, "try") == 0) { if (snap_path == NULL) { send_error_bad_request(self, message, "need 'snap-path' value in form", NULL); return; } if (strcmp(snap_path, "*") == 0) { send_error_bad_request(self, message, "directory does not contain an unpacked snap", "snap-not-a-snap"); return; } MockChange *change = add_change(self); mock_change_set_spawn_time(change, self->spawn_time); mock_change_set_ready_time(change, self->ready_time); MockTask *task = mock_change_add_task(change, "try"); task->snap = mock_snap_new("try"); task->snap->trymode = TRUE; task->snap->snap_path = g_steal_pointer(&snap_path); send_async_response(self, message, 202, change->id); } else { if (snap == NULL) { send_error_bad_request(self, message, "cannot find \"snap\" file field in provided " "multipart/form-data payload", NULL); return; } MockChange *change = add_change(self); mock_change_set_spawn_time(change, self->spawn_time); mock_change_set_ready_time(change, self->ready_time); MockTask *task = mock_change_add_task(change, "install"); task->snap = mock_snap_new("sideload"); if (classic) mock_snap_set_confinement(task->snap, "classic"); task->snap->dangerous = dangerous; task->snap->devmode = devmode; // FIXME: Should set confinement to devmode? task->snap->jailmode = jailmode; g_free(task->snap->snap_data); task->snap->snap_data = g_steal_pointer(&snap); send_async_response(self, message, 202, change->id); } } else { send_error_method_not_allowed(self, message, "method not allowed"); return; } } static void handle_snap(MockSnapd *self, SoupServerMessage *message, const gchar *name) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") == 0) { MockSnap *snap = find_snap(self, name); if (snap != NULL) send_sync_response(self, message, 200, make_snap_node(snap), NULL); else send_error_not_found(self, message, "cannot find snap", "snap-not-found"); } else if (strcmp(method, "POST") == 0) { g_autoptr(JsonNode) request = get_json(message); if (request == NULL) { send_error_bad_request(self, message, "unknown content type", NULL); return; } JsonObject *o = json_node_get_object(request); const gchar *action = json_object_get_string_member(o, "action"); const gchar *channel = NULL, *revision = NULL; gboolean classic = FALSE, dangerous = FALSE, devmode = FALSE, jailmode = FALSE, purge = FALSE; if (json_object_has_member(o, "channel")) channel = json_object_get_string_member(o, "channel"); if (json_object_has_member(o, "revision")) revision = json_object_get_string_member(o, "revision"); if (json_object_has_member(o, "classic")) classic = json_object_get_boolean_member(o, "classic"); if (json_object_has_member(o, "dangerous")) dangerous = json_object_get_boolean_member(o, "dangerous"); if (json_object_has_member(o, "devmode")) devmode = json_object_get_boolean_member(o, "devmode"); if (json_object_has_member(o, "jailmode")) jailmode = json_object_get_boolean_member(o, "jailmode"); if (json_object_has_member(o, "purge")) purge = json_object_get_boolean_member(o, "purge"); if (strcmp(action, "install") == 0) { if (self->decline_auth) { send_error_forbidden(self, message, "cancelled", "auth-cancelled"); return; } MockSnap *snap = find_snap(self, name); if (snap != NULL) { send_error_bad_request(self, message, "snap is already installed", "snap-already-installed"); return; } snap = find_store_snap_by_name(self, name, NULL, NULL); if (snap == NULL) { send_error_not_found(self, message, "cannot install, snap not found", "snap-not-found"); return; } snap = find_store_snap_by_name(self, name, channel, NULL); if (snap == NULL) { send_error_not_found(self, message, "no snap revision on specified channel", "snap-channel-not-available"); return; } snap = find_store_snap_by_name(self, name, channel, revision); if (snap == NULL) { send_error_not_found(self, message, "no snap revision available as specified", "snap-revision-not-available"); return; } if (strcmp(snap->confinement, "classic") == 0 && !classic) { send_error_bad_request(self, message, "requires classic confinement", "snap-needs-classic"); return; } if (strcmp(snap->confinement, "classic") == 0 && !self->on_classic) { send_error_bad_request(self, message, "requires classic confinement which is only " "available on classic systems", "snap-needs-classic-system"); return; } if (classic && strcmp(snap->confinement, "classic") != 0) { send_error_bad_request(self, message, "snap not compatible with --classic", "snap-not-classic"); return; } if (strcmp(snap->confinement, "devmode") == 0 && !devmode) { send_error_bad_request(self, message, "requires devmode or confinement override", "snap-needs-devmode"); return; } MockChange *change = add_change(self); mock_change_set_spawn_time(change, self->spawn_time); mock_change_set_ready_time(change, self->ready_time); MockTask *task = mock_change_add_task(change, "install"); task->snap = mock_snap_new(name); mock_snap_set_confinement(task->snap, snap->confinement); mock_snap_set_channel(task->snap, snap->channel); mock_snap_set_revision(task->snap, snap->revision); task->snap->devmode = devmode; task->snap->jailmode = jailmode; task->snap->dangerous = dangerous; if (snap->error != NULL) task->error = g_strdup(snap->error); send_async_response(self, message, 202, change->id); } else if (strcmp(action, "refresh") == 0) { MockSnap *snap = find_snap(self, name); if (snap != NULL) { /* Find if we have a store snap with a newer revision */ MockSnap *store_snap = find_store_snap_by_name(self, name, channel, NULL); if (store_snap == NULL) { send_error_bad_request(self, message, "cannot perform operation on local snap", "snap-local"); } else if (strcmp(store_snap->revision, snap->revision) > 0) { mock_snap_set_channel(snap, channel); MockChange *change = add_change(self); mock_change_set_spawn_time(change, self->spawn_time); mock_change_set_ready_time(change, self->ready_time); mock_change_add_task(change, "refresh"); send_async_response(self, message, 202, change->id); } else send_error_bad_request(self, message, "snap has no updates available", "snap-no-update-available"); } else send_error_bad_request(self, message, "cannot refresh: cannot find snap", "snap-not-installed"); } else if (strcmp(action, "remove") == 0) { if (self->decline_auth) { send_error_forbidden(self, message, "cancelled", "auth-cancelled"); return; } MockSnap *snap = find_snap(self, name); if (snap != NULL) { MockChange *change = add_change(self); mock_change_set_spawn_time(change, self->spawn_time); mock_change_set_ready_time(change, self->ready_time); MockTask *task = mock_change_add_task(change, "remove"); mock_task_set_snap_name(task, name); task->purge = purge; if (snap->error != NULL) task->error = g_strdup(snap->error); send_async_response(self, message, 202, change->id); } else send_error_bad_request(self, message, "snap is not installed", "snap-not-installed"); } else if (strcmp(action, "enable") == 0) { MockSnap *snap = find_snap(self, name); if (snap != NULL) { if (!snap->disabled) { send_error_bad_request( self, message, "cannot enable: snap is already enabled", NULL); return; } snap->disabled = FALSE; MockChange *change = add_change(self); mock_change_add_task(change, "enable"); send_async_response(self, message, 202, change->id); } else send_error_bad_request(self, message, "cannot enable: cannot find snap", "snap-not-installed"); } else if (strcmp(action, "disable") == 0) { MockSnap *snap = find_snap(self, name); if (snap != NULL) { if (snap->disabled) { send_error_bad_request( self, message, "cannot disable: snap is already disabled", NULL); return; } snap->disabled = TRUE; MockChange *change = add_change(self); mock_change_set_spawn_time(change, self->spawn_time); mock_change_set_ready_time(change, self->ready_time); mock_change_add_task(change, "disable"); send_async_response(self, message, 202, change->id); } else send_error_bad_request(self, message, "cannot disable: cannot find snap", "snap-not-installed"); } else if (strcmp(action, "switch") == 0) { MockSnap *snap = find_snap(self, name); if (snap != NULL) { mock_snap_set_tracking_channel(snap, channel); MockChange *change = add_change(self); mock_change_set_spawn_time(change, self->spawn_time); mock_change_set_ready_time(change, self->ready_time); mock_change_add_task(change, "switch"); send_async_response(self, message, 202, change->id); } else send_error_bad_request(self, message, "cannot switch: cannot find snap", "snap-not-installed"); } else send_error_bad_request(self, message, "unknown action", NULL); } else send_error_method_not_allowed(self, message, "method not allowed"); } static gint compare_keys(gconstpointer a, gconstpointer b) { gchar *name_a = *((gchar **)a); gchar *name_b = *((gchar **)b); return strcmp(name_a, name_b); } static void handle_snap_conf(MockSnapd *self, SoupServerMessage *message, const gchar *name, GHashTable *query) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") == 0) { MockSnap *snap; if (strcmp(name, "system") == 0) snap = find_snap(self, "core"); else snap = find_snap(self, name); g_autoptr(GPtrArray) keys = g_ptr_array_new_with_free_func(g_free); const gchar *keys_param = NULL; if (query != NULL) keys_param = g_hash_table_lookup(query, "keys"); if (keys_param != NULL) { g_auto(GStrv) key_names = g_strsplit(keys_param, ",", -1); for (int i = 0; key_names[i] != NULL; i++) g_ptr_array_add(keys, g_strdup(g_strstrip(key_names[i]))); } if (keys->len == 0 && snap != NULL) { g_autofree GStrv key_names = (GStrv)g_hash_table_get_keys_as_array(snap->configuration, NULL); for (int i = 0; key_names[i] != NULL; i++) g_ptr_array_add(keys, g_strdup(g_strstrip(key_names[i]))); } g_ptr_array_sort(keys, compare_keys); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); for (guint i = 0; i < keys->len; i++) { const gchar *key = g_ptr_array_index(keys, i); const gchar *value = NULL; if (snap != NULL) value = g_hash_table_lookup(snap->configuration, key); if (value == NULL) { g_autofree gchar *error_message = g_strdup_printf( "snap \"%s\" has no \"%s\" configuration option", name, key); send_error_bad_request(self, message, error_message, "option-not-found"); return; } g_autoptr(JsonParser) parser = json_parser_new(); gboolean result = json_parser_load_from_data(parser, value, -1, NULL); g_assert_true(result); json_builder_set_member_name(builder, key); json_builder_add_value(builder, json_node_ref(json_parser_get_root(parser))); } json_builder_end_object(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } else if (strcmp(method, "PUT") == 0) { g_autoptr(JsonNode) request = get_json(message); if (request == NULL) { send_error_bad_request( self, message, "cannot decode request body into patch values", NULL); return; } MockSnap *snap; if (strcmp(name, "system") == 0) snap = find_snap(self, "core"); else snap = find_snap(self, name); if (snap == NULL) { send_error_not_found(self, message, "snap is not installed", "snap-not-found"); return; } JsonObject *o = json_node_get_object(request); JsonObjectIter iter; const gchar *key; JsonNode *value_node; json_object_iter_init(&iter, o); while (json_object_iter_next(&iter, &key, &value_node)) { g_autoptr(JsonGenerator) generator = json_generator_new(); json_generator_set_root(generator, value_node); g_autofree gchar *value = json_generator_to_data(generator, NULL); mock_snap_set_conf(snap, key, value); } MockChange *change = add_change(self); send_async_response(self, message, 202, change->id); } else send_error_method_not_allowed(self, message, "method not allowed"); } static void handle_apps(MockSnapd *self, SoupServerMessage *message, GHashTable *query) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } const gchar *select_param = NULL; g_auto(GStrv) selected_snaps = NULL; if (query != NULL) { const gchar *snaps_param = NULL; select_param = g_hash_table_lookup(query, "select"); snaps_param = g_hash_table_lookup(query, "names"); if (snaps_param != NULL) selected_snaps = g_strsplit(snaps_param, ",", -1); } g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_array(builder); for (GList *link = self->snaps; link; link = link->next) { MockSnap *snap = link->data; GList *app_link; if (!filter_snaps(selected_snaps, snap)) continue; for (app_link = snap->apps; app_link; app_link = app_link->next) { MockApp *app = app_link->data; if (g_strcmp0(select_param, "service") == 0 && app->daemon == NULL) continue; json_builder_add_value(builder, make_app_node(app, snap->name)); } } json_builder_end_array(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } static void handle_icon(MockSnapd *self, SoupServerMessage *message, const gchar *path) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } if (!g_str_has_suffix(path, "/icon")) { send_error_not_found(self, message, "not found", NULL); return; } g_autofree gchar *name = g_strndup(path, strlen(path) - strlen("/icon")); MockSnap *snap = find_snap(self, name); if (snap == NULL) send_error_not_found(self, message, "cannot find snap", NULL); else if (snap->icon_data == NULL) send_error_not_found(self, message, "not found", NULL); else send_response(message, 200, snap->icon_mime_type, (const guint8 *)g_bytes_get_data(snap->icon_data, NULL), g_bytes_get_size(snap->icon_data)); } static void handle_assertions(MockSnapd *self, SoupServerMessage *message, const gchar *type) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); SoupMessageBody *request_body = soup_server_message_get_request_body(message); #else const gchar *method = message->method; SoupMessageBody *request_body = message->request_body; #endif if (strcmp(method, "GET") == 0) { g_autoptr(GString) response_content = g_string_new(NULL); g_autofree gchar *type_header = g_strdup_printf("type: %s\n", type); int count = 0; for (GList *link = self->assertions; link; link = link->next) { const gchar *assertion = link->data; if (!g_str_has_prefix(assertion, type_header)) continue; count++; if (count != 1) g_string_append(response_content, "\n\n"); g_string_append(response_content, assertion); } if (count == 0) { send_error_bad_request(self, message, "invalid assert type", NULL); return; } // FIXME: X-Ubuntu-Assertions-Count header send_response(message, 200, "application/x.ubuntu.assertion; bundle=y", (guint8 *)response_content->str, response_content->len); } else if (strcmp(method, "POST") == 0) { g_autofree gchar *assertion = g_strndup(request_body->data, request_body->length); add_assertion(self, assertion); send_sync_response(self, message, 200, NULL, NULL); } else { send_error_method_not_allowed(self, message, "method not allowed"); return; } } static void make_attributes(GHashTable *attributes, JsonBuilder *builder) { g_autoptr(GPtrArray) keys = g_ptr_array_new_with_free_func(g_free); g_autofree GStrv key_names = (GStrv)g_hash_table_get_keys_as_array(attributes, NULL); for (int i = 0; key_names[i] != NULL; i++) g_ptr_array_add(keys, g_strdup(g_strstrip(key_names[i]))); g_ptr_array_sort(keys, compare_keys); json_builder_begin_object(builder); for (guint i = 0; i < keys->len; i++) { const gchar *key = g_ptr_array_index(keys, i); const gchar *value = g_hash_table_lookup(attributes, key); g_autoptr(JsonParser) parser = json_parser_new(); gboolean result = json_parser_load_from_data(parser, value, -1, NULL); g_assert_true(result); json_builder_set_member_name(builder, key); json_builder_add_value(builder, json_node_ref(json_parser_get_root(parser))); } json_builder_end_object(builder); } static void make_connections(MockSnapd *self, JsonBuilder *builder) { json_builder_begin_object(builder); json_builder_set_member_name(builder, "plugs"); json_builder_begin_array(builder); for (GList *link = self->snaps; link; link = link->next) { MockSnap *snap = link->data; for (GList *l = snap->plugs; l; l = l->next) { MockPlug *plug = l->data; g_autoptr(GList) slots = NULL; for (GList *l2 = self->established_connections; l2; l2 = l2->next) { MockConnection *connection = l2->data; if (connection->plug == plug) slots = g_list_append(slots, connection->slot); } json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, snap->name); json_builder_set_member_name(builder, "plug"); json_builder_add_string_value(builder, plug->name); json_builder_set_member_name(builder, "interface"); json_builder_add_string_value(builder, plug->interface->name); if (g_hash_table_size(plug->attributes) > 0) { json_builder_set_member_name(builder, "attrs"); make_attributes(plug->attributes, builder); } json_builder_set_member_name(builder, "label"); json_builder_add_string_value(builder, plug->label); if (slots != NULL) { json_builder_set_member_name(builder, "connections"); json_builder_begin_array(builder); for (GList *l2 = slots; l2; l2 = l2->next) { MockSlot *slot = l2->data; json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, slot->snap->name); json_builder_set_member_name(builder, "slot"); json_builder_add_string_value(builder, slot->name); json_builder_end_object(builder); } json_builder_end_array(builder); } json_builder_end_object(builder); } } json_builder_end_array(builder); json_builder_set_member_name(builder, "slots"); json_builder_begin_array(builder); for (GList *link = self->snaps; link; link = link->next) { MockSnap *snap = link->data; for (GList *l = snap->slots_; l; l = l->next) { MockSlot *slot = l->data; g_autoptr(GList) plugs = NULL; for (GList *l2 = self->established_connections; l2; l2 = l2->next) { MockConnection *connection = l2->data; if (connection->slot == slot) plugs = g_list_append(plugs, connection->plug); } json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, snap->name); json_builder_set_member_name(builder, "slot"); json_builder_add_string_value(builder, slot->name); json_builder_set_member_name(builder, "interface"); json_builder_add_string_value(builder, slot->interface->name); if (g_hash_table_size(slot->attributes) > 0) { json_builder_set_member_name(builder, "attrs"); make_attributes(slot->attributes, builder); } json_builder_set_member_name(builder, "label"); json_builder_add_string_value(builder, slot->label); if (plugs != NULL) { json_builder_set_member_name(builder, "connections"); json_builder_begin_array(builder); for (GList *l2 = plugs; l2; l2 = l2->next) { MockPlug *plug = l2->data; json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, plug->snap->name); json_builder_set_member_name(builder, "plug"); json_builder_add_string_value(builder, plug->name); json_builder_end_object(builder); } json_builder_end_array(builder); } json_builder_end_object(builder); } } json_builder_end_array(builder); json_builder_end_object(builder); } static gboolean filter_interfaces(GStrv selected_interfaces, MockInterface *interface) { /* If no filter selected, then return all interfaces */ if (selected_interfaces == NULL || selected_interfaces[0] == NULL) return TRUE; for (int i = 0; selected_interfaces[i] != NULL; i++) { if (strcmp(selected_interfaces[i], interface->name) == 0) return TRUE; } return FALSE; } static gboolean interface_connected(MockSnapd *self, MockInterface *interface) { for (GList *l = self->snaps; l != NULL; l = l->next) { MockSnap *snap = l->data; for (GList *l2 = snap->plugs; l2 != NULL; l2 = l2->next) { MockPlug *plug = l2->data; if (plug->interface == interface) return TRUE; } for (GList *l2 = snap->slots_; l2 != NULL; l2 = l2->next) { MockSlot *slot = l2->data; if (slot->interface == interface) return TRUE; } } return FALSE; } static void make_interfaces(MockSnapd *self, GHashTable *query, JsonBuilder *builder) { const gchar *names_param = g_hash_table_lookup(query, "names"); g_auto(GStrv) selected_interfaces = NULL; if (names_param != NULL) selected_interfaces = g_strsplit(names_param, ",", -1); gboolean only_connected = g_strcmp0(g_hash_table_lookup(query, "select"), "connected") == 0; gboolean include_plugs = g_strcmp0(g_hash_table_lookup(query, "plugs"), "true") == 0; gboolean include_slots = g_strcmp0(g_hash_table_lookup(query, "slots"), "true") == 0; json_builder_begin_array(builder); for (GList *l = self->interfaces; l != NULL; l = l->next) { MockInterface *interface = l->data; if (!filter_interfaces(selected_interfaces, interface)) continue; if (only_connected && !interface_connected(self, interface)) continue; json_builder_begin_object(builder); json_builder_set_member_name(builder, "name"); json_builder_add_string_value(builder, interface->name); json_builder_set_member_name(builder, "summary"); json_builder_add_string_value(builder, interface->summary); json_builder_set_member_name(builder, "doc-url"); json_builder_add_string_value(builder, interface->doc_url); if (include_plugs) { json_builder_set_member_name(builder, "plugs"); json_builder_begin_array(builder); for (GList *l2 = self->snaps; l2 != NULL; l2 = l2->next) { MockSnap *snap = l2->data; for (GList *l3 = snap->plugs; l3 != NULL; l3 = l3->next) { MockPlug *plug = l3->data; if (plug->interface != interface) continue; json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, plug->snap->name); json_builder_set_member_name(builder, "plug"); json_builder_add_string_value(builder, plug->name); json_builder_end_object(builder); } } json_builder_end_array(builder); } if (include_slots) { json_builder_set_member_name(builder, "slots"); json_builder_begin_array(builder); for (GList *l2 = self->snaps; l2 != NULL; l2 = l2->next) { MockSnap *snap = l2->data; for (GList *l3 = snap->slots_; l3 != NULL; l3 = l3->next) { MockSlot *slot = l3->data; if (slot->interface != interface) continue; json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, slot->snap->name); json_builder_set_member_name(builder, "slot"); json_builder_add_string_value(builder, slot->name); json_builder_end_object(builder); } } json_builder_end_array(builder); } json_builder_end_object(builder); } json_builder_end_array(builder); } static void handle_interfaces(MockSnapd *self, SoupServerMessage *message, GHashTable *query) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") == 0) { g_autoptr(JsonBuilder) builder = json_builder_new(); if (query != NULL && g_hash_table_lookup(query, "select") != NULL) { make_interfaces(self, query, builder); } else { make_connections(self, builder); } send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } else if (strcmp(method, "POST") == 0) { g_autoptr(JsonNode) request = get_json(message); if (request == NULL) { send_error_bad_request(self, message, "unknown content type", NULL); return; } JsonObject *o = json_node_get_object(request); const gchar *action = json_object_get_string_member(o, "action"); JsonArray *a = json_object_get_array_member(o, "plugs"); g_autoptr(GList) plugs = NULL; g_autoptr(GList) slots = NULL; for (guint i = 0; i < json_array_get_length(a); i++) { JsonObject *po = json_array_get_object_element(a, i); MockSnap *snap = find_snap(self, json_object_get_string_member(po, "snap")); if (snap == NULL) { send_error_bad_request(self, message, "invalid snap", NULL); return; } MockPlug *plug = mock_snap_find_plug(snap, json_object_get_string_member(po, "plug")); if (plug == NULL) { send_error_bad_request(self, message, "invalid plug", NULL); return; } plugs = g_list_append(plugs, plug); } a = json_object_get_array_member(o, "slots"); for (guint i = 0; i < json_array_get_length(a); i++) { JsonObject *so = json_array_get_object_element(a, i); MockSnap *snap = find_snap(self, json_object_get_string_member(so, "snap")); if (snap == NULL) { send_error_bad_request(self, message, "invalid snap", NULL); return; } MockSlot *slot = mock_snap_find_slot(snap, json_object_get_string_member(so, "slot")); if (slot == NULL) { send_error_bad_request(self, message, "invalid slot", NULL); return; } slots = g_list_append(slots, slot); } if (strcmp(action, "connect") == 0) { if (g_list_length(plugs) < 1 || g_list_length(slots) < 1) { send_error_bad_request(self, message, "at least one plug and slot is required", NULL); return; } for (GList *link = plugs; link; link = link->next) { MockPlug *plug = link->data; mock_snapd_connect(self, plug, slots->data, TRUE, FALSE); } MockChange *change = add_change(self); mock_change_set_spawn_time(change, self->spawn_time); mock_change_set_ready_time(change, self->ready_time); mock_change_add_task(change, "connect-snap"); send_async_response(self, message, 202, change->id); } else if (strcmp(action, "disconnect") == 0) { if (g_list_length(plugs) < 1 || g_list_length(slots) < 1) { send_error_bad_request(self, message, "at least one plug and slot is required", NULL); return; } for (GList *link = plugs; link; link = link->next) { MockPlug *plug = link->data; mock_snapd_connect(self, plug, NULL, TRUE, FALSE); } MockChange *change = add_change(self); mock_change_set_spawn_time(change, self->spawn_time); mock_change_set_ready_time(change, self->ready_time); mock_change_add_task(change, "disconnect"); send_async_response(self, message, 202, change->id); } else send_error_bad_request(self, message, "unsupported interface action", NULL); } else send_error_method_not_allowed(self, message, "method not allowed"); } static void add_connection(JsonBuilder *builder, MockConnection *connection) { json_builder_begin_object(builder); MockSlot *slot = connection->slot; json_builder_set_member_name(builder, "slot"); json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, slot->snap->name); json_builder_set_member_name(builder, "slot"); json_builder_add_string_value(builder, slot->name); json_builder_end_object(builder); if (g_hash_table_size(slot->attributes) > 0) { json_builder_set_member_name(builder, "slot-attrs"); make_attributes(slot->attributes, builder); } MockPlug *plug = connection->plug; json_builder_set_member_name(builder, "plug"); json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, plug->snap->name); json_builder_set_member_name(builder, "plug"); json_builder_add_string_value(builder, plug->name); json_builder_end_object(builder); if (g_hash_table_size(plug->attributes) > 0) { json_builder_set_member_name(builder, "plug-attrs"); make_attributes(plug->attributes, builder); } json_builder_set_member_name(builder, "interface"); json_builder_add_string_value(builder, plug->interface->name); if (connection->manual) { json_builder_set_member_name(builder, "manual"); json_builder_add_boolean_value(builder, TRUE); } if (connection->gadget) { json_builder_set_member_name(builder, "gadget"); json_builder_add_boolean_value(builder, TRUE); } json_builder_end_object(builder); } static gboolean matches_name(MockSnap *snap, const gchar *name) { return name == NULL || strcmp(snap->name, name) == 0; } static gboolean matches_interface_name(MockInterface *interface, const gchar *name) { return name == NULL || strcmp(interface->name, name) == 0; } static void handle_connections(MockSnapd *self, SoupServerMessage *message, GHashTable *query) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } const gchar *snap_name = query != NULL ? g_hash_table_lookup(query, "snap") : NULL; const gchar *interface_name = query != NULL ? g_hash_table_lookup(query, "interface") : NULL; const gchar *select = query != NULL ? g_hash_table_lookup(query, "select") : NULL; if (select != NULL && strcmp(select, "all") != 0) { send_error_bad_request(self, message, "unsupported select qualifier", NULL); return; } gboolean only_connected = TRUE; if (g_strcmp0(select, "all") == 0) only_connected = FALSE; g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "established"); json_builder_begin_array(builder); for (GList *link = self->established_connections; link; link = link->next) { MockConnection *connection = link->data; if (matches_name(connection->plug->snap, snap_name) || matches_name(connection->slot->snap, snap_name)) add_connection(builder, connection); } json_builder_end_array(builder); g_autoptr(GList) undesired_connections = NULL; for (GList *link = self->undesired_connections; link; link = link->next) { MockConnection *connection = link->data; if (only_connected && snap_name == NULL) continue; if (!matches_name(connection->plug->snap, snap_name) && !matches_name(connection->slot->snap, snap_name)) continue; undesired_connections = g_list_append(undesired_connections, connection); } if (undesired_connections != NULL) { json_builder_set_member_name(builder, "undesired"); json_builder_begin_array(builder); for (GList *link = undesired_connections; link; link = link->next) { MockConnection *connection = link->data; add_connection(builder, connection); } json_builder_end_array(builder); } json_builder_set_member_name(builder, "plugs"); json_builder_begin_array(builder); for (GList *link = self->snaps; link; link = link->next) { MockSnap *snap = link->data; for (GList *l = snap->plugs; l; l = l->next) { MockPlug *plug = l->data; if (!matches_interface_name(plug->interface, interface_name)) continue; if (!matches_name(snap, snap_name) && !matches_name(plug->snap, snap_name)) continue; g_autoptr(GList) slots = NULL; for (GList *l2 = self->established_connections; l2; l2 = l2->next) { MockConnection *connection = l2->data; if (!matches_name(snap, snap_name) && !matches_name(connection->slot->snap, snap_name)) continue; if (connection->plug == plug) slots = g_list_append(slots, connection->slot); } if (!matches_name(snap, snap_name) && slots == NULL) continue; if (only_connected && slots == NULL) continue; json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, snap->name); json_builder_set_member_name(builder, "plug"); json_builder_add_string_value(builder, plug->name); json_builder_set_member_name(builder, "interface"); json_builder_add_string_value(builder, plug->interface->name); if (g_hash_table_size(plug->attributes) > 0) { json_builder_set_member_name(builder, "attrs"); make_attributes(plug->attributes, builder); } json_builder_set_member_name(builder, "label"); json_builder_add_string_value(builder, plug->label); if (slots != NULL) { json_builder_set_member_name(builder, "connections"); json_builder_begin_array(builder); for (GList *l2 = slots; l2; l2 = l2->next) { MockSlot *slot = l2->data; json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, slot->snap->name); json_builder_set_member_name(builder, "slot"); json_builder_add_string_value(builder, slot->name); json_builder_end_object(builder); } json_builder_end_array(builder); } json_builder_end_object(builder); } } json_builder_end_array(builder); json_builder_set_member_name(builder, "slots"); json_builder_begin_array(builder); for (GList *link = self->snaps; link; link = link->next) { MockSnap *snap = link->data; for (GList *l = snap->slots_; l; l = l->next) { MockSlot *slot = l->data; if (!matches_interface_name(slot->interface, interface_name)) continue; g_autoptr(GList) plugs = NULL; for (GList *l2 = self->established_connections; l2; l2 = l2->next) { MockConnection *connection = l2->data; if (!matches_name(snap, snap_name) && !matches_name(connection->plug->snap, snap_name)) continue; if (connection->slot == slot) plugs = g_list_append(plugs, connection->plug); } if (!matches_name(snap, snap_name) && plugs == NULL) continue; if (only_connected && plugs == NULL) continue; json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, snap->name); json_builder_set_member_name(builder, "slot"); json_builder_add_string_value(builder, slot->name); json_builder_set_member_name(builder, "interface"); json_builder_add_string_value(builder, slot->interface->name); if (g_hash_table_size(slot->attributes) > 0) { json_builder_set_member_name(builder, "attrs"); make_attributes(slot->attributes, builder); } json_builder_set_member_name(builder, "label"); json_builder_add_string_value(builder, slot->label); if (plugs != NULL) { json_builder_set_member_name(builder, "connections"); json_builder_begin_array(builder); for (GList *l2 = plugs; l2; l2 = l2->next) { MockPlug *plug = l2->data; json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap"); json_builder_add_string_value(builder, plug->snap->name); json_builder_set_member_name(builder, "plug"); json_builder_add_string_value(builder, plug->name); json_builder_end_object(builder); } json_builder_end_array(builder); } json_builder_end_object(builder); } } json_builder_end_array(builder); json_builder_end_object(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } static MockTask *get_current_task(MockChange *change) { for (GList *link = change->tasks; link; link = link->next) { MockTask *task = link->data; if (strcmp(task->status, "Done") != 0) return task; } return NULL; } static gboolean change_get_ready(MockChange *change) { MockTask *task = get_current_task(change); return task == NULL || strcmp(task->status, "Error") == 0; } static JsonNode *make_change_node(MockChange *change) { int progress_total = 0, progress_done = 0; for (GList *link = change->tasks; link; link = link->next) { MockTask *task = link->data; progress_done += task->progress_done; progress_total += task->progress_total; } MockTask *task = get_current_task(change); const gchar *status = task != NULL ? task->status : "Done"; const gchar *error = task != NULL && strcmp(task->status, "Error") == 0 ? task->error : NULL; if (change->status != NULL) { // no copy is needed because status is already copied in the call. status = change->status; } g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "id"); json_builder_add_string_value(builder, change->id); json_builder_set_member_name(builder, "kind"); json_builder_add_string_value(builder, change->kind); json_builder_set_member_name(builder, "summary"); json_builder_add_string_value(builder, change->summary); json_builder_set_member_name(builder, "status"); json_builder_add_string_value(builder, status); json_builder_set_member_name(builder, "tasks"); json_builder_begin_array(builder); for (GList *link = change->tasks; link; link = link->next) { MockTask *task = link->data; json_builder_begin_object(builder); json_builder_set_member_name(builder, "id"); json_builder_add_string_value(builder, task->id); json_builder_set_member_name(builder, "kind"); json_builder_add_string_value(builder, task->kind); json_builder_set_member_name(builder, "summary"); json_builder_add_string_value(builder, task->summary); json_builder_set_member_name(builder, "status"); json_builder_add_string_value(builder, task->status); json_builder_set_member_name(builder, "progress"); json_builder_begin_object(builder); json_builder_set_member_name(builder, "label"); json_builder_add_string_value(builder, task->progress_label); json_builder_set_member_name(builder, "done"); json_builder_add_int_value(builder, task->progress_done); json_builder_set_member_name(builder, "total"); json_builder_add_int_value(builder, task->progress_total); json_builder_end_object(builder); if (task->spawn_time != NULL) { json_builder_set_member_name(builder, "spawn-time"); json_builder_add_string_value(builder, task->spawn_time); } if (task->progress_done >= task->progress_total && task->ready_time != NULL) { json_builder_set_member_name(builder, "ready-time"); json_builder_add_string_value(builder, task->ready_time); } if (task->affected_snaps->len != 0) { json_builder_set_member_name(builder, "data"); json_builder_begin_object(builder); json_builder_set_member_name(builder, "affected-snaps"); json_builder_begin_array(builder); for (int i = 0; i < task->affected_snaps->len; i++) { json_builder_add_string_value(builder, task->affected_snaps->pdata[i]); } json_builder_end_array(builder); json_builder_end_object(builder); } json_builder_end_object(builder); } json_builder_end_array(builder); json_builder_set_member_name(builder, "ready"); json_builder_add_boolean_value(builder, change_get_ready(change)); json_builder_set_member_name(builder, "spawn-time"); json_builder_add_string_value(builder, change->spawn_time); if (change_get_ready(change) && change->ready_time != NULL) { json_builder_set_member_name(builder, "ready-time"); json_builder_add_string_value(builder, change->ready_time); } if ((change_get_ready(change) || change->force_data) && change->data != NULL) { json_builder_set_member_name(builder, "data"); json_builder_add_value(builder, json_node_ref(change->data)); } if (error != NULL) { json_builder_set_member_name(builder, "err"); json_builder_add_string_value(builder, error); } json_builder_end_object(builder); return json_builder_get_root(builder); } static gboolean change_relates_to_snap(MockChange *change, const gchar *snap_name) { for (GList *link = change->tasks; link; link = link->next) { MockTask *task = link->data; if (g_strcmp0(snap_name, task->snap_name) == 0) return TRUE; if (task->snap != NULL && g_strcmp0(snap_name, task->snap->name) == 0) return TRUE; } return FALSE; } static void handle_changes(MockSnapd *self, SoupServerMessage *message, GHashTable *query) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } const gchar *select_param = g_hash_table_lookup(query, "select"); if (select_param == NULL) select_param = "in-progress"; const gchar *for_param = g_hash_table_lookup(query, "for"); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_array(builder); for (GList *link = self->changes; link; link = link->next) { MockChange *change = link->data; if (g_strcmp0(select_param, "in-progress") == 0 && change_get_ready(change)) continue; if (g_strcmp0(select_param, "ready") == 0 && !change_get_ready(change)) continue; if (for_param != NULL && !change_relates_to_snap(change, for_param)) continue; json_builder_add_value(builder, make_change_node(change)); } json_builder_end_array(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } static void mock_task_complete(MockSnapd *self, MockTask *task) { if (strcmp(task->kind, "install") == 0 || strcmp(task->kind, "try") == 0) self->snaps = g_list_append(self->snaps, g_steal_pointer(&task->snap)); else if (strcmp(task->kind, "remove") == 0) { MockSnap *snap = find_snap(self, task->snap_name); self->snaps = g_list_remove(self->snaps, snap); mock_snap_free(snap); /* Add a snapshot */ if (!task->purge && find_snapshot(self, task->snap_name) == NULL) self->snapshots = g_list_append(self->snapshots, mock_snapshot_new(task->snap_name)); } mock_task_set_status(task, "Done"); } static void mock_change_progress(MockSnapd *self, MockChange *change) { for (GList *link = change->tasks; link; link = link->next) { MockTask *task = link->data; if (task->error != NULL) { mock_task_set_status(task, "Error"); return; } if (task->progress_done < task->progress_total) { mock_task_set_status(task, "Doing"); task->progress_done++; if (task->progress_done == task->progress_total) mock_task_complete(self, task); return; } } } static void handle_change(MockSnapd *self, SoupServerMessage *message, const gchar *change_id) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") == 0) { MockChange *change = get_change(self, change_id); if (change == NULL) { send_error_not_found(self, message, "cannot find change", NULL); return; } mock_change_progress(self, change); send_sync_response(self, message, 200, make_change_node(change), NULL); } else if (strcmp(method, "POST") == 0) { MockChange *change = get_change(self, change_id); if (change == NULL) { send_error_not_found(self, message, "cannot find change", NULL); return; } g_autoptr(JsonNode) request = get_json(message); if (request == NULL) { send_error_bad_request(self, message, "unknown content type", NULL); return; } JsonObject *o = json_node_get_object(request); const gchar *action = json_object_get_string_member(o, "action"); if (strcmp(action, "abort") == 0) { MockTask *task = get_current_task(change); if (task == NULL) { send_error_bad_request(self, message, "task not in progress", NULL); return; } mock_task_set_status(task, "Error"); task->error = g_strdup("cancelled"); send_sync_response(self, message, 200, make_change_node(change), NULL); } else { send_error_bad_request(self, message, "change action is unsupported", NULL); return; } } else { send_error_method_not_allowed(self, message, "method not allowed"); return; } } static gboolean matches_query(MockSnap *snap, const gchar *query) { return query == NULL || strstr(snap->name, query) != NULL; } static gboolean matches_scope(MockSnap *snap, const gchar *scope) { if (g_strcmp0(scope, "wide") == 0) return TRUE; return !snap->scope_is_wide; } static gboolean has_common_id(MockSnap *snap, const gchar *common_id) { if (common_id == NULL) return TRUE; for (GList *link = snap->apps; link; link = link->next) { MockApp *app = link->data; if (g_strcmp0(app->common_id, common_id) == 0) return TRUE; } return FALSE; } static gboolean in_category(MockSnap *snap, const gchar *category) { if (category == NULL) return TRUE; for (GList *link = snap->store_categories; link; link = link->next) if (strcmp(link->data, category) == 0) return TRUE; return FALSE; } static void handle_find(MockSnapd *self, SoupServerMessage *message, GHashTable *query) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } const gchar *common_id_param = g_hash_table_lookup(query, "common-id"); const gchar *query_param = g_hash_table_lookup(query, "q"); const gchar *name_param = g_hash_table_lookup(query, "name"); const gchar *select_param = g_hash_table_lookup(query, "select"); const gchar *section_param = g_hash_table_lookup(query, "section"); const gchar *category_param = g_hash_table_lookup(query, "category"); const gchar *scope_param = g_hash_table_lookup(query, "scope"); if (common_id_param && strcmp(common_id_param, "") == 0) common_id_param = NULL; if (query_param && strcmp(query_param, "") == 0) query_param = NULL; if (name_param && strcmp(name_param, "") == 0) name_param = NULL; if (select_param && strcmp(select_param, "") == 0) select_param = NULL; if (section_param && strcmp(section_param, "") == 0) section_param = NULL; if (category_param && strcmp(category_param, "") == 0) category_param = NULL; if (scope_param && strcmp(scope_param, "") == 0) scope_param = NULL; GList *snaps; if (g_strcmp0(select_param, "refresh") == 0) { g_autoptr(GList) refreshable_snaps = NULL; if (query_param != NULL) { send_error_bad_request(self, message, "cannot use 'q' with 'select=refresh'", NULL); return; } if (name_param != NULL) { send_error_bad_request(self, message, "cannot use 'name' with 'select=refresh'", NULL); return; } g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_array(builder); refreshable_snaps = get_refreshable_snaps(self); for (GList *link = refreshable_snaps; link; link = link->next) json_builder_add_value(builder, make_snap_node(link->data)); json_builder_end_array(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), self->suggested_currency); return; } else if (g_strcmp0(select_param, "private") == 0) { MockAccount *account = get_account(self, message); if (account == NULL) { send_error_bad_request(self, message, "you need to log in first", "login-required"); return; } snaps = account->private_snaps; } else snaps = self->store_snaps; /* Make a special query that never responds */ if (g_strcmp0(query_param, "do-not-respond") == 0) return; /* Make a special query that simulates a network timeout */ if (g_strcmp0(query_param, "network-timeout") == 0) { send_error_bad_request(self, message, "unable to contact snap store", "network-timeout"); return; } /* Make a special query that simulates a DNS Failure */ if (g_strcmp0(query_param, "dns-failure") == 0) { send_error_bad_request(self, message, "failed to resolve address", "dns-failure"); return; } /* Certain characters not allowed in queries */ if (query_param != NULL) { for (int i = 0; query_param[i] != '\0'; i++) { const gchar *invalid_chars = "+=&|>next) { MockSnap *snap = link->data; if (!has_common_id(snap, common_id_param)) continue; if (!in_category(snap, category_param)) continue; if (!in_category(snap, section_param)) continue; if (!matches_query(snap, query_param)) continue; if (!matches_name(snap, name_param)) continue; if (!matches_scope(snap, scope_param)) continue; json_builder_add_value(builder, make_snap_node(snap)); } json_builder_end_array(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), self->suggested_currency); } static void handle_buy_ready(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } MockAccount *account = get_account(self, message); if (account == NULL) { send_error_bad_request(self, message, "you need to log in first", "login-required"); return; } if (!account->terms_accepted) { send_error_bad_request(self, message, "terms of service not accepted", "terms-not-accepted"); return; } if (!account->has_payment_methods) { send_error_bad_request(self, message, "no payment methods", "no-payment-methods"); return; } JsonNode *result = json_node_new(JSON_NODE_VALUE); json_node_set_boolean(result, TRUE); send_sync_response(self, message, 200, result, NULL); } static void handle_buy(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "POST") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } MockAccount *account = get_account(self, message); if (account == NULL) { send_error_bad_request(self, message, "you need to log in first", "login-required"); return; } if (!account->terms_accepted) { send_error_bad_request(self, message, "terms of service not accepted", "terms-not-accepted"); return; } if (!account->has_payment_methods) { send_error_bad_request(self, message, "no payment methods", "no-payment-methods"); return; } g_autoptr(JsonNode) request = get_json(message); if (request == NULL) { send_error_bad_request(self, message, "unknown content type", NULL); return; } JsonObject *o = json_node_get_object(request); const gchar *snap_id = json_object_get_string_member(o, "snap-id"); gdouble price = json_object_get_double_member(o, "price"); const gchar *currency = json_object_get_string_member(o, "currency"); MockSnap *snap = find_store_snap_by_id(self, snap_id); if (snap == NULL) { send_error_not_found(self, message, "not found", NULL); // FIXME: Check is error snapd returns return; } gdouble amount = mock_snap_find_price(snap, currency); if (amount == 0) { send_error_bad_request( self, message, "no price found", "payment-declined"); // FIXME: Check is error snapd returns return; } if (amount != price) { send_error_bad_request( self, message, "invalid price", "payment-declined"); // FIXME: Check is error snapd returns return; } send_sync_response(self, message, 200, NULL, NULL); } static void handle_sections(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_array(builder); for (GList *link = self->store_categories; link; link = link->next) json_builder_add_string_value(builder, link->data); json_builder_end_array(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } static void handle_categories(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_array(builder); for (GList *link = self->store_categories; link; link = link->next) { json_builder_begin_object(builder); json_builder_set_member_name(builder, "name"); json_builder_add_string_value(builder, link->data); json_builder_end_object(builder); } json_builder_end_array(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } static MockSnap *find_snap_by_alias(MockSnapd *self, const gchar *name) { GList *link; for (link = self->snaps; link; link = link->next) { MockSnap *snap = link->data; GList *app_link; for (app_link = snap->apps; app_link; app_link = app_link->next) { MockApp *app = app_link->data; MockAlias *alias; alias = mock_app_find_alias(app, name); if (alias != NULL) return snap; } } return NULL; } static void unalias(MockSnapd *self, const gchar *name) { for (GList *link = self->snaps; link; link = link->next) { MockSnap *snap = link->data; for (GList *app_link = snap->apps; app_link; app_link = app_link->next) { MockApp *app = app_link->data; MockAlias *alias = mock_app_find_alias(app, name); if (alias != NULL) { if (alias->automatic) alias->enabled = FALSE; else { app->aliases = g_list_remove(app->aliases, alias); mock_alias_free(alias); } return; } } } } static void handle_aliases(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") == 0) { g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); for (GList *link = self->snaps; link; link = link->next) { MockSnap *snap = link->data; int alias_count = 0; for (GList *link2 = snap->apps; link2; link2 = link2->next) { MockApp *app = link2->data; for (GList *link3 = app->aliases; link3; link3 = link3->next) { MockAlias *alias = link3->data; if (alias_count == 0) { json_builder_set_member_name(builder, snap->name); json_builder_begin_object(builder); } alias_count++; json_builder_set_member_name(builder, alias->name); json_builder_begin_object(builder); g_autofree gchar *command = g_strdup_printf("%s.%s", snap->name, app->name); json_builder_set_member_name(builder, "command"); json_builder_add_string_value(builder, command); if (alias->automatic) { json_builder_set_member_name(builder, "status"); if (alias->enabled) json_builder_add_string_value(builder, "auto"); else json_builder_add_string_value(builder, "disabled"); json_builder_set_member_name(builder, "auto"); json_builder_add_string_value(builder, app->name); } else { json_builder_set_member_name(builder, "status"); json_builder_add_string_value(builder, "manual"); json_builder_set_member_name(builder, "manual"); json_builder_add_string_value(builder, app->name); } json_builder_end_object(builder); } } if (alias_count > 0) json_builder_end_object(builder); } json_builder_end_object(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } else if (strcmp(method, "POST") == 0) { g_autoptr(JsonNode) request = get_json(message); if (request == NULL) { send_error_bad_request(self, message, "unknown content type", NULL); return; } JsonObject *o = json_node_get_object(request); const gchar *alias = NULL; if (json_object_has_member(o, "alias")) alias = json_object_get_string_member(o, "alias"); MockSnap *snap; if (json_object_has_member(o, "snap")) { snap = find_snap(self, json_object_get_string_member(o, "snap")); if (snap == NULL) { send_error_not_found(self, message, "cannot find snap", NULL); return; } } else if (alias != NULL) { snap = find_snap_by_alias(self, alias); if (snap == NULL) { send_error_not_found(self, message, "cannot find snap", NULL); return; } } else { send_error_not_found(self, message, "cannot find snap", NULL); return; } const gchar *action = json_object_get_string_member(o, "action"); if (g_strcmp0(action, "alias") == 0) { const gchar *app_name; MockApp *app; app_name = json_object_get_string_member(o, "app"); if (app_name == NULL) { send_error_not_found(self, message, "No app specified", NULL); return; } app = mock_snap_find_app(snap, app_name); if (app == NULL) { send_error_not_found(self, message, "App not found", NULL); return; } mock_app_add_manual_alias(app, alias, TRUE); } else if (g_strcmp0(action, "unalias") == 0) { unalias(self, alias); } else if (g_strcmp0(action, "prefer") == 0) { snap->preferred = TRUE; } else { send_error_bad_request(self, message, "unsupported alias action", NULL); return; } MockChange *change = add_change(self); mock_change_set_spawn_time(change, self->spawn_time); mock_change_set_ready_time(change, self->ready_time); mock_change_add_task(change, action); send_async_response(self, message, 202, change->id); } else { send_error_method_not_allowed(self, message, "method not allowed"); return; } } static void handle_snapctl(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "POST") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } g_autoptr(JsonNode) request = get_json(message); if (request == NULL) { send_error_bad_request(self, message, "unknown content type", NULL); return; } JsonObject *o = json_node_get_object(request); const gchar *context_id = json_object_get_string_member(o, "context-id"); JsonArray *args = json_object_get_array_member(o, "args"); g_autoptr(GString) stdout_text = g_string_new("STDOUT"); g_string_append_printf(stdout_text, ":%s", context_id); for (int i = 0; i < json_array_get_length(args); i++) { const gchar *arg = json_array_get_string_element(args, i); g_string_append_printf(stdout_text, ":%s", arg); } if (!g_strcmp0(context_id, "return-error")) { g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "stdout"); json_builder_add_string_value(builder, stdout_text->str); json_builder_set_member_name(builder, "stderr"); json_builder_add_string_value(builder, "STDERR"); json_builder_set_member_name(builder, "exit-code"); json_builder_add_int_value(builder, 1); json_builder_end_object(builder); send_error_response(self, message, 200, "unsuccessful with exit code: 1", "unsuccessful", json_builder_get_root(builder)); return; } g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "stdout"); json_builder_add_string_value(builder, stdout_text->str); json_builder_set_member_name(builder, "stderr"); json_builder_add_string_value(builder, "STDERR"); json_builder_end_object(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } static void handle_create_user(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "POST") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } g_autoptr(JsonNode) request = get_json(message); if (request == NULL) { send_error_bad_request(self, message, "unknown content type", NULL); return; } JsonObject *o = json_node_get_object(request); if (json_object_has_member(o, "email")) { g_autoptr(JsonBuilder) builder = json_builder_new(); const gchar *email = json_object_get_string_member(o, "email"); gboolean sudoer = FALSE; if (json_object_has_member(o, "sudoer")) sudoer = json_object_get_boolean_member(o, "sudoer"); gboolean known = FALSE; if (json_object_has_member(o, "known")) known = json_object_get_boolean_member(o, "known"); g_auto(GStrv) email_keys = g_strsplit(email, "@", 2); const gchar *username = email_keys[0]; g_auto(GStrv) ssh_keys = g_strsplit("KEY1;KEY2", ";", -1); MockAccount *a = add_account(self, email, username, "password"); a->sudoer = sudoer; a->known = known; mock_account_set_ssh_keys(a, ssh_keys); add_user_response(builder, a, FALSE, TRUE, FALSE); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); return; } else { if (json_object_has_member(o, "known") && json_object_get_boolean_member(o, "known")) { g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_array(builder); g_auto(GStrv) ssh_keys = g_strsplit("KEY1;KEY2", ";", -1); MockAccount *a = add_account(self, "admin@example.com", "admin", "password"); a->sudoer = TRUE; a->known = TRUE; mock_account_set_ssh_keys(a, ssh_keys); add_user_response(builder, a, FALSE, TRUE, FALSE); a = add_account(self, "alice@example.com", "alice", "password"); a->known = TRUE; mock_account_set_ssh_keys(a, ssh_keys); add_user_response(builder, a, FALSE, TRUE, FALSE); a = add_account(self, "bob@example.com", "bob", "password"); a->known = TRUE; mock_account_set_ssh_keys(a, ssh_keys); add_user_response(builder, a, FALSE, TRUE, FALSE); json_builder_end_array(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); return; } else { send_error_bad_request(self, message, "cannot create user", NULL); return; } } } static void handle_users(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_array(builder); for (GList *link = self->accounts; link; link = link->next) { MockAccount *a = link->data; add_user_response(builder, a, FALSE, FALSE, TRUE); } json_builder_end_array(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } static void handle_download(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "POST") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } g_autoptr(JsonNode) request = get_json(message); if (request == NULL) { send_error_bad_request(self, message, "unknown content type", NULL); return; } JsonObject *o = json_node_get_object(request); const gchar *snap_name = json_object_get_string_member(o, "snap-name"); const gchar *channel = NULL; if (json_object_has_member(o, "channel")) channel = json_object_get_string_member(o, "channel"); const gchar *revision = NULL; if (json_object_has_member(o, "revision")) revision = json_object_get_string_member(o, "revision"); g_autoptr(GString) contents = g_string_new("SNAP"); g_string_append_printf(contents, ":name=%s", snap_name); if (channel != NULL) g_string_append_printf(contents, ":channel=%s", channel); if (revision != NULL) g_string_append_printf(contents, ":revision=%s", revision); send_response(message, 200, "application/octet-stream", (const guint8 *)contents->str, contents->len); } static int count_available_themes(JsonObject *o, const char *theme_type, GHashTable *theme_status) { guint i, length; int available = 0; JsonArray *themes = json_object_get_array_member(o, theme_type); if (themes == NULL) return 0; length = json_array_get_length(themes); for (i = 0; i < length; i++) { const char *theme_name = json_array_get_string_element(themes, i); if (theme_name == NULL) continue; if (g_strcmp0(g_hash_table_lookup(theme_status, theme_name), "available") == 0) available++; } return available; } static void handle_themes(MockSnapd *self, SoupServerMessage *message) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") == 0) { #if SOUP_CHECK_VERSION(2, 99, 2) GUri *uri = soup_server_message_get_uri(message); const gchar *query = g_uri_get_query(uri); #else SoupURI *uri = soup_message_get_uri(message); const char *query = soup_uri_get_query(uri); #endif g_autoptr(JsonBuilder) gtk_themes = json_builder_new(); g_autoptr(JsonBuilder) icon_themes = json_builder_new(); g_autoptr(JsonBuilder) sound_themes = json_builder_new(); json_builder_begin_object(gtk_themes); json_builder_begin_object(icon_themes); json_builder_begin_object(sound_themes); /* We are parsing the query parameters manually because the * GHashTable API loses duplicate values */ g_auto(GStrv) pairs = g_strsplit(query, "&", -1); char *const *pair; for (pair = pairs; *pair != NULL; pair++) { char *eq = strchr(*pair, '='); if (!eq) continue; *eq = '\0'; g_autofree char *attr = g_uri_unescape_string(*pair, NULL); g_autofree char *value = g_uri_unescape_string(eq + 1, NULL); if (strcmp(attr, "gtk-theme") == 0) { const char *status = g_hash_table_lookup(self->gtk_theme_status, value); json_builder_set_member_name(gtk_themes, value); json_builder_add_string_value(gtk_themes, status ? status : "unavailable"); } else if (strcmp(attr, "icon-theme") == 0) { const char *status = g_hash_table_lookup(self->icon_theme_status, value); json_builder_set_member_name(icon_themes, value); json_builder_add_string_value(icon_themes, status ? status : "unavailable"); } else if (strcmp(attr, "sound-theme") == 0) { const char *status = g_hash_table_lookup(self->sound_theme_status, value); json_builder_set_member_name(sound_themes, value); json_builder_add_string_value(sound_themes, status ? status : "unavailable"); } } json_builder_end_object(gtk_themes); json_builder_end_object(icon_themes); json_builder_end_object(sound_themes); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "gtk-themes"); json_builder_add_value(builder, json_builder_get_root(gtk_themes)); json_builder_set_member_name(builder, "icon-themes"); json_builder_add_value(builder, json_builder_get_root(icon_themes)); json_builder_set_member_name(builder, "sound-themes"); json_builder_add_value(builder, json_builder_get_root(sound_themes)); json_builder_end_object(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } else if (strcmp(method, "POST") == 0) { g_autoptr(JsonNode) request = get_json(message); if (request == NULL) { send_error_bad_request(self, message, "unknown content type", NULL); return; } JsonObject *o = json_node_get_object(request); int available = 0; available += count_available_themes(o, "gtk-themes", self->gtk_theme_status); available += count_available_themes(o, "icon-themes", self->icon_theme_status); available += count_available_themes(o, "sound-themes", self->sound_theme_status); if (available == 0) { send_error_bad_request(self, message, "no snaps to install", NULL); return; } MockChange *change = add_change(self); mock_change_set_spawn_time(change, self->spawn_time); mock_change_set_ready_time(change, self->ready_time); MockTask *task = mock_change_add_task(change, "install"); task->snap = mock_snap_new("theme-snap"); mock_snap_set_channel(task->snap, "stable"); mock_snap_set_revision(task->snap, "1"); send_async_response(self, message, 202, change->id); } else { send_error_method_not_allowed(self, message, "method not allowed"); } } static gboolean filter_logs(GStrv names, MockLog *log) { /* If no filter selected, then return all snaps */ if (names == NULL || names[0] == NULL) return TRUE; for (int i = 0; names[i] != NULL; i++) { if (strcmp(names[i], log->sid) == 0) return TRUE; } return FALSE; } static void handle_logs(MockSnapd *self, SoupServerMessage *message, GHashTable *query) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } g_auto(GStrv) names = NULL; size_t n = 0; if (query != NULL) { const gchar *snaps_param = NULL, *n_param = NULL; snaps_param = g_hash_table_lookup(query, "names"); if (snaps_param != NULL) names = g_strsplit(snaps_param, ",", -1); n_param = g_hash_table_lookup(query, "n"); if (n_param != NULL) n = atoi(n_param); } size_t n_logs = 0; g_autoptr(GString) content = g_string_new(""); for (GList *link = self->logs; link; link = link->next) { MockLog *log = link->data; if (n != 0 && n_logs >= n) break; if (!filter_logs(names, log)) continue; g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "timestamp"); json_builder_add_string_value(builder, log->timestamp); json_builder_set_member_name(builder, "message"); json_builder_add_string_value(builder, log->message); json_builder_set_member_name(builder, "sid"); json_builder_add_string_value(builder, log->sid); json_builder_set_member_name(builder, "pid"); json_builder_add_string_value(builder, log->pid); json_builder_end_object(builder); g_autoptr(JsonGenerator) generator = json_generator_new(); g_autoptr(JsonNode) root = json_builder_get_root(builder); json_generator_set_root(generator, root); g_autofree gchar *log_json = json_generator_to_data(generator, NULL); g_string_append_unichar(content, 0x1e); g_string_append(content, log_json); n_logs++; } send_response(message, 200, "application/json-seq", (const guint8 *)content->str, content->len); } static void handle_notices(MockSnapd *self, SoupServerMessage *message, GHashTable *query) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } g_free(self->notices_parameters); #if SOUP_CHECK_VERSION(2, 99, 2) GUri *uri = soup_server_message_get_uri(message); self->notices_parameters = g_strdup(g_uri_get_query(uri)); #else SoupURI *uri = soup_message_get_uri(message); self->notices_parameters = g_strdup(soup_uri_get_query(uri)); #endif g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_array(builder); g_autoptr(GDateTime) after = NULL; guint after_nanoseconds = -1; // Check if the petition has an "after" parameter if (self->notices_parameters != NULL) { g_autoptr(GHashTable) parameters = g_uri_parse_params( self->notices_parameters, -1, "&", G_URI_PARAMS_NONE, NULL); if (g_hash_table_contains(parameters, "after")) { g_autofree gchar *after_str = g_strdup(g_hash_table_lookup(parameters, "after")); after = g_date_time_new_from_iso8601(after_str, NULL); gchar *dot_pos = strchr(after_str, '.'); after_nanoseconds = (dot_pos == NULL) ? 0 : atoi(1 + dot_pos); } } // Send the notices for (GList *link = self->notices; link; link = link->next) { MockNotice *notice = link->data; /* but if there is an "after" parameter, send only those that * happened after the specified date-time */ if ((after != NULL) && (notice->last_occurred != NULL) && (compare_date_time_with_nanoseconds(notice->last_occurred, notice->last_occurred_nanoseconds, after, after_nanoseconds) <= 0)) { continue; } json_builder_begin_object(builder); json_builder_set_member_name(builder, "id"); json_builder_add_string_value(builder, notice->id); json_builder_set_member_name(builder, "user-id"); if (notice->user_id == NULL) { json_builder_add_null_value(builder); } else { int v = atoi(notice->user_id); if (v != 0) json_builder_add_int_value(builder, v); else json_builder_add_string_value(builder, notice->user_id); } json_builder_set_member_name(builder, "type"); json_builder_add_string_value(builder, notice->type); json_builder_set_member_name(builder, "key"); json_builder_add_string_value(builder, notice->key); if (notice->first_occurred) { json_builder_set_member_name(builder, "first-occurred"); g_autofree gchar *date = g_date_time_format(notice->first_occurred, "%FT%T%z"); json_builder_add_string_value(builder, date); json_builder_set_member_name(builder, "occurrences"); json_builder_add_int_value(builder, notice->occurrences); } if (notice->last_occurred) { json_builder_set_member_name(builder, "last-occurred"); g_autofree gchar *date = NULL; if (notice->last_occurred_nanoseconds == -1) { date = g_date_time_format(notice->last_occurred, "%FT%T%z"); } else { g_autofree gchar *date_tmp = g_date_time_format(notice->last_occurred, "%FT%T.%%09d%z"); date = g_strdup_printf(date_tmp, notice->last_occurred_nanoseconds); } json_builder_add_string_value(builder, date); } if (notice->last_repeated) { json_builder_set_member_name(builder, "last-repeated"); g_autofree gchar *date = g_date_time_format(notice->last_repeated, "%FT%T%z"); json_builder_add_string_value(builder, date); } if (notice->expire_after) { json_builder_set_member_name(builder, "expire-after"); json_builder_add_string_value(builder, notice->expire_after); } if (notice->repeat_after) { json_builder_set_member_name(builder, "repeat-after"); json_builder_add_string_value(builder, notice->repeat_after); } guint data_size = g_hash_table_size(notice->last_data); if (data_size != 0) { g_autofree gchar **keys = (gchar **)g_hash_table_get_keys_as_array(notice->last_data, NULL); json_builder_set_member_name(builder, "last-data"); json_builder_begin_object(builder); for (guint i = 0; i < data_size; i++) { gchar *value = g_hash_table_lookup(notice->last_data, keys[i]); json_builder_set_member_name(builder, keys[i]); json_builder_add_string_value(builder, value); } json_builder_end_object(builder); } json_builder_end_object(builder); } json_builder_end_array(builder); send_sync_response(self, message, 200, json_builder_get_root(builder), NULL); } static void handle_model(MockSnapd *self, SoupServerMessage *message, GHashTable *query) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } g_autoptr(GString) response_content = g_string_new("type: model\n\nSIGNATURE"); send_response(message, 200, "application/x.ubuntu.assertion", (guint8 *)response_content->str, response_content->len); } static void handle_model_serial(MockSnapd *self, SoupServerMessage *message, GHashTable *query) { #if SOUP_CHECK_VERSION(2, 99, 2) const gchar *method = soup_server_message_get_method(message); #else const gchar *method = message->method; #endif if (strcmp(method, "GET") != 0) { send_error_method_not_allowed(self, message, "method not allowed"); return; } g_autoptr(GString) response_content = g_string_new("type: serial\n\nSIGNATURE"); send_response(message, 200, "application/x.ubuntu.assertion", (guint8 *)response_content->str, response_content->len); } static void handle_request(SoupServer *server, SoupServerMessage *message, const char *path, GHashTable *query, #if !SOUP_CHECK_VERSION(2, 99, 2) SoupClientContext *client, #endif gpointer user_data) { MockSnapd *self = MOCK_SNAPD(user_data); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); if (self->close_on_request) { #if SOUP_CHECK_VERSION(2, 99, 2) g_autoptr(GIOStream) stream = soup_server_message_steal_connection(message); #else g_autoptr(GIOStream) stream = soup_client_context_steal_connection(client); #endif g_autoptr(GError) error = NULL; if (!g_io_stream_close(stream, NULL, &error)) g_warning("Failed to close stream: %s", error->message); return; } #if SOUP_CHECK_VERSION(2, 99, 2) SoupMessageHeaders *request_headers = soup_server_message_get_request_headers(message); g_clear_pointer(&self->last_request_headers, soup_message_headers_unref); self->last_request_headers = soup_message_headers_ref(request_headers); #else SoupMessageHeaders *request_headers = message->request_headers; g_clear_pointer(&self->last_request_headers, soup_message_headers_free); self->last_request_headers = g_boxed_copy(SOUP_TYPE_MESSAGE_HEADERS, request_headers); #endif if (strcmp(path, "/v2/system-info") == 0) handle_system_info(self, message); else if (strcmp(path, "/v2/login") == 0) handle_login(self, message); else if (strcmp(path, "/v2/logout") == 0) handle_logout(self, message); else if (strcmp(path, "/v2/snaps") == 0) handle_snaps(self, message, query); else if (g_str_has_prefix(path, "/v2/snaps/")) { if (g_str_has_suffix(path, "/conf")) { g_autofree gchar *name = g_strndup(path + strlen("/v2/snaps/"), strlen(path) - strlen("/v2/snaps/") - strlen("/conf")); handle_snap_conf(self, message, name, query); } else handle_snap(self, message, path + strlen("/v2/snaps/")); } else if (strcmp(path, "/v2/apps") == 0) handle_apps(self, message, query); else if (g_str_has_prefix(path, "/v2/icons/")) handle_icon(self, message, path + strlen("/v2/icons/")); else if (strcmp(path, "/v2/assertions") == 0) handle_assertions(self, message, NULL); else if (g_str_has_prefix(path, "/v2/assertions/")) handle_assertions(self, message, path + strlen("/v2/assertions/")); else if (strcmp(path, "/v2/interfaces") == 0) handle_interfaces(self, message, query); else if (strcmp(path, "/v2/connections") == 0) handle_connections(self, message, query); else if (strcmp(path, "/v2/changes") == 0) handle_changes(self, message, query); else if (g_str_has_prefix(path, "/v2/changes/")) handle_change(self, message, path + strlen("/v2/changes/")); else if (strcmp(path, "/v2/find") == 0) handle_find(self, message, query); else if (strcmp(path, "/v2/buy/ready") == 0) handle_buy_ready(self, message); else if (strcmp(path, "/v2/buy") == 0) handle_buy(self, message); else if (strcmp(path, "/v2/sections") == 0) handle_sections(self, message); else if (strcmp(path, "/v2/categories") == 0) handle_categories(self, message); else if (strcmp(path, "/v2/aliases") == 0) handle_aliases(self, message); else if (strcmp(path, "/v2/snapctl") == 0) handle_snapctl(self, message); else if (strcmp(path, "/v2/create-user") == 0) handle_create_user(self, message); else if (strcmp(path, "/v2/users") == 0) handle_users(self, message); else if (strcmp(path, "/v2/download") == 0) handle_download(self, message); else if (strcmp(path, "/v2/accessories/themes") == 0) handle_themes(self, message); else if (g_str_has_prefix(path, "/v2/accessories/changes/")) handle_change(self, message, path + strlen("/v2/accessories/changes/")); else if (strcmp(path, "/v2/logs") == 0) handle_logs(self, message, query); else if (strcmp(path, "/v2/notices") == 0) handle_notices(self, message, query); else if (strcmp(path, "/v2/model") == 0) handle_model(self, message, NULL); else if (strcmp(path, "/v2/model/serial") == 0) handle_model_serial(self, message, NULL); else send_error_not_found(self, message, "not found", NULL); } static gboolean mock_snapd_thread_quit(gpointer user_data) { MockSnapd *self = MOCK_SNAPD(user_data); g_main_loop_quit(self->loop); return G_SOURCE_REMOVE; } static void mock_snapd_finalize(GObject *object) { MockSnapd *self = MOCK_SNAPD(object); /* shut down the server if it is running */ mock_snapd_stop(self); if ((self->socket_path != NULL) && (self->socket_path[0] != '@')) { if (g_unlink(self->socket_path) < 0 && errno != ENOENT) g_printerr("Failed to unlink mock snapd socket: %s\n", g_strerror(errno)); } if (g_rmdir(self->dir_path) < 0) g_printerr("Failed to remove temporary directory: %s\n", g_strerror(errno)); g_clear_pointer(&self->dir_path, g_free); g_clear_pointer(&self->socket_path, g_free); g_list_free_full(self->accounts, (GDestroyNotify)mock_account_free); self->accounts = NULL; g_list_free_full(self->interfaces, (GDestroyNotify)mock_interface_free); self->interfaces = NULL; g_list_free_full(self->snaps, (GDestroyNotify)mock_snap_free); self->snaps = NULL; g_list_free_full(self->snapshots, (GDestroyNotify)mock_snapshot_free); self->snapshots = NULL; g_free(self->architecture); g_free(self->build_id); g_free(self->confinement); g_clear_pointer(&self->sandbox_features, g_hash_table_unref); g_free(self->store); g_free(self->maintenance_kind); g_free(self->maintenance_message); g_free(self->refresh_hold); g_free(self->refresh_last); g_free(self->refresh_next); g_free(self->refresh_schedule); g_free(self->refresh_timer); g_list_free_full(self->store_categories, g_free); self->store_categories = NULL; g_list_free_full(self->store_snaps, (GDestroyNotify)mock_snap_free); self->store_snaps = NULL; g_list_free_full(self->established_connections, (GDestroyNotify)mock_connection_free); self->established_connections = NULL; g_list_free_full(self->undesired_connections, (GDestroyNotify)mock_connection_free); self->undesired_connections = NULL; g_list_free_full(self->assertions, g_free); self->assertions = NULL; g_list_free_full(self->changes, (GDestroyNotify)mock_change_free); self->changes = NULL; g_clear_pointer(&self->suggested_currency, g_free); g_clear_pointer(&self->spawn_time, g_free); g_clear_pointer(&self->ready_time, g_free); #if SOUP_CHECK_VERSION(2, 99, 2) g_clear_pointer(&self->last_request_headers, soup_message_headers_unref); #else g_clear_pointer(&self->last_request_headers, soup_message_headers_free); #endif g_clear_pointer(&self->gtk_theme_status, g_hash_table_unref); g_clear_pointer(&self->icon_theme_status, g_hash_table_unref); g_list_free_full(self->logs, (GDestroyNotify)mock_log_free); self->logs = NULL; g_clear_pointer(&self->sound_theme_status, g_hash_table_unref); g_clear_pointer(&self->context, g_main_context_unref); g_clear_pointer(&self->loop, g_main_loop_unref); if (self->notices) { g_list_free_full(self->notices, (GDestroyNotify)mock_notice_free); self->notices = NULL; } g_clear_pointer(&self->notices_parameters, g_free); g_cond_clear(&self->condition); g_mutex_clear(&self->mutex); G_OBJECT_CLASS(mock_snapd_parent_class)->finalize(object); } static GSocket *open_listening_socket(SoupServer *server, const gchar *socket_path, GError **error) { g_autoptr(GSocket) socket = NULL; g_autoptr(GSocketAddress) address = NULL; socket = g_socket_new(G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, error); if (socket == NULL) return NULL; if (socket_path[0] == '@') { address = g_unix_socket_address_new_with_type( socket_path + 1, -1, G_UNIX_SOCKET_ADDRESS_ABSTRACT); } else { address = g_unix_socket_address_new(socket_path); } if (!g_socket_bind(socket, address, TRUE, error)) return NULL; if (!g_socket_listen(socket, error)) return NULL; if (!soup_server_listen_socket(server, socket, 0, error)) return NULL; return g_steal_pointer(&socket); } gpointer mock_snapd_init_thread(gpointer user_data) { MockSnapd *self = MOCK_SNAPD(user_data); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); self->context = g_main_context_new(); g_main_context_push_thread_default(self->context); self->loop = g_main_loop_new(self->context, FALSE); g_autoptr(SoupServer) server = soup_server_new("server-header", "MockSnapd/1.0", NULL); soup_server_add_handler(server, NULL, handle_request, self, NULL); g_autoptr(GError) error = NULL; g_autoptr(GSocket) socket = open_listening_socket(server, self->socket_path, &error); g_cond_signal(&self->condition); if (socket == NULL) g_propagate_error(self->thread_init_error, error); g_clear_pointer(&locker, g_mutex_locker_free); /* run until we're told to stop */ if (socket != NULL) g_main_loop_run(self->loop); if ((self->socket_path != NULL) && (self->socket_path[0] != '@')) { if (g_unlink(self->socket_path) < 0) g_printerr("Failed to unlink mock snapd socket\n"); } g_main_context_pop_thread_default(self->context); g_clear_pointer(&self->loop, g_main_loop_unref); g_clear_pointer(&self->context, g_main_context_unref); return NULL; } void mock_snapd_use_abstract_socket(MockSnapd *self) { g_return_if_fail(self->socket_path != NULL); g_return_if_fail(self->socket_path[0] != '@'); g_autofree gchar *current_path = self->socket_path; self->socket_path = g_strdup_printf("@%s", current_path); } gboolean mock_snapd_start(MockSnapd *self, GError **dest_error) { g_return_val_if_fail(MOCK_IS_SNAPD(self), FALSE); g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex); /* Has the server already started? */ if (self->thread) return TRUE; g_autoptr(GError) error = NULL; self->thread_init_error = &error; self->thread = g_thread_new("mock_snapd_thread", mock_snapd_init_thread, self); g_cond_wait(&self->condition, &self->mutex); self->thread_init_error = NULL; /* If an error occurred during thread startup, clean it up */ if (error != NULL) { g_thread_join(self->thread); self->thread = NULL; if (dest_error) g_propagate_error(dest_error, error); else g_warning("Failed to start server: %s", error->message); } g_assert_nonnull(self->loop); g_assert_nonnull(self->context); return error == NULL; } gchar *mock_snapd_get_notices_parameters(MockSnapd *self) { return self->notices_parameters; } void mock_snapd_stop(MockSnapd *self) { g_return_if_fail(MOCK_IS_SNAPD(self)); if (!self->thread) return; g_main_context_invoke(self->context, mock_snapd_thread_quit, self); g_thread_join(self->thread); self->thread = NULL; g_assert_null(self->loop); g_assert_null(self->context); } static void mock_snapd_class_init(MockSnapdClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->finalize = mock_snapd_finalize; } static void mock_snapd_init(MockSnapd *self) { g_mutex_init(&self->mutex); g_cond_init(&self->condition); self->sandbox_features = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_ptr_array_unref); self->gtk_theme_status = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); self->icon_theme_status = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); self->sound_theme_status = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); g_autoptr(GError) error = NULL; self->dir_path = g_dir_make_tmp("mock-snapd-XXXXXX", &error); if (self->dir_path == NULL) g_warning("Failed to make temporary directory: %s", error->message); g_clear_error(&error); self->socket_path = g_build_filename(self->dir_path, "snapd.socket", NULL); } snapd-glib-1.67/tests/mock-snapd.h000066400000000000000000000346151477073115000170540ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #ifndef __MOCK_SNAPD_H__ #define __MOCK_SNAPD_H__ #include #include #include G_BEGIN_DECLS #define MOCK_TYPE_SNAPD (mock_snapd_get_type()) G_DECLARE_FINAL_TYPE(MockSnapd, mock_snapd, MOCK, SNAPD, GObject) struct _MockSnapdClass { /*< private >*/ GObjectClass parent_class; }; typedef struct _MockAccount MockAccount; typedef struct _MockAlias MockAlias; typedef struct _MockApp MockApp; typedef struct _MockChange MockChange; typedef struct _MockChannel MockChannel; typedef struct _MockConnection MockConnection; typedef struct _MockInterface MockInterface; typedef struct _MockLog MockLog; typedef struct _MockMedia MockMedia; typedef struct _MockPlug MockPlug; typedef struct _MockPrice MockPrice; typedef struct _MockSlot MockSlot; typedef struct _MockSnap MockSnap; typedef struct _MockSnapshot MockSnapshot; typedef struct _MockTask MockTask; typedef struct _MockTrack MockTrack; typedef struct _MockNotice MockNotice; #if !GLIB_CHECK_VERSION(2, 66, 0) GHashTable *g_uri_parse_params(const gchar *params, gssize lenght, const gchar *separators, int flags, GError **error); #define G_URI_PARAMS_NONE 0 #endif MockSnapd *mock_snapd_new(void); void mock_snapd_use_abstract_socket(MockSnapd *self); const gchar *mock_snapd_get_socket_path(MockSnapd *snapd); void mock_snapd_set_close_on_request(MockSnapd *snapd, gboolean close_on_request); void mock_snapd_set_decline_auth(MockSnapd *snapd, gboolean decline_auth); gboolean mock_snapd_start(MockSnapd *snapd, GError **error); void mock_snapd_stop(MockSnapd *snapd); void mock_snapd_set_maintenance(MockSnapd *snapd, const gchar *type, const gchar *message); void mock_snapd_set_architecture(MockSnapd *snapd, const gchar *architecture); void mock_snapd_set_build_id(MockSnapd *snapd, const gchar *build_id); void mock_snapd_set_confinement(MockSnapd *snapd, const gchar *confinement); void mock_snapd_add_sandbox_feature(MockSnapd *snapd, const gchar *backend, const gchar *feature); void mock_snapd_set_store(MockSnapd *snapd, const gchar *name); void mock_snapd_set_managed(MockSnapd *snapd, gboolean managed); void mock_snapd_set_on_classic(MockSnapd *snapd, gboolean on_classic); void mock_snapd_set_refresh_hold(MockSnapd *snapd, const gchar *refresh_hold); void mock_snapd_set_refresh_last(MockSnapd *snapd, const gchar *refresh_last); void mock_snapd_set_refresh_next(MockSnapd *snapd, const gchar *refresh_next); void mock_snapd_set_refresh_schedule(MockSnapd *snapd, const gchar *schedule); void mock_snapd_set_refresh_timer(MockSnapd *snapd, const gchar *timer); void mock_snapd_set_suggested_currency(MockSnapd *snapd, const gchar *currency); void mock_snapd_set_progress_total(MockSnapd *snapd, int total); void mock_snapd_set_spawn_time(MockSnapd *snapd, const gchar *spawn_time); void mock_snapd_set_ready_time(MockSnapd *snapd, const gchar *ready_time); MockAccount *mock_snapd_add_account(MockSnapd *snapd, const gchar *email, const gchar *username, const gchar *password); void mock_account_set_terms_accepted(MockAccount *account, gboolean terms_accepted); void mock_account_set_has_payment_methods(MockAccount *account, gboolean has_payment_methods); gint64 mock_account_get_id(MockAccount *account); const gchar *mock_account_get_macaroon(MockAccount *account); GStrv mock_account_get_discharges(MockAccount *account); gboolean mock_account_get_sudoer(MockAccount *account); gboolean mock_account_get_known(MockAccount *account); void mock_account_set_otp(MockAccount *account, const gchar *otp); void mock_account_set_ssh_keys(MockAccount *account, GStrv ssh_keys); MockAccount *mock_snapd_find_account_by_id(MockSnapd *snapd, gint64 id); MockAccount *mock_snapd_find_account_by_username(MockSnapd *snapd, const gchar *username); MockAccount *mock_snapd_find_account_by_email(MockSnapd *snapd, const gchar *email); MockChange *mock_snapd_add_change(MockSnapd *snapd); const gchar *mock_change_get_id(MockChange *change); MockTask *mock_change_add_task(MockChange *change, const gchar *kind); void mock_task_set_snap_name(MockTask *task, const gchar *snap_name); const gchar *mock_task_get_status(MockTask *task); void mock_task_set_status(MockTask *task, const gchar *status); void mock_task_set_progress(MockTask *task, int done, int total); void mock_task_set_spawn_time(MockTask *task, const gchar *spawn_time); void mock_task_set_ready_time(MockTask *task, const gchar *ready_time); void mock_task_add_affected_snap(MockTask *task, const gchar *snap); void mock_change_set_spawn_time(MockChange *change, const gchar *spawn_time); void mock_change_set_ready_time(MockChange *change, const gchar *ready_time); MockSnap *mock_account_add_private_snap(MockAccount *account, const gchar *name); MockInterface *mock_snapd_add_interface(MockSnapd *snapd, const gchar *name); void mock_interface_set_summary(MockInterface *interface, const gchar *summary); void mock_interface_set_doc_url(MockInterface *interface, const gchar *url); MockSnap *mock_snapd_add_snap(MockSnapd *snapd, const gchar *name); MockSnap *mock_snapd_find_snap(MockSnapd *snapd, const gchar *name); MockSnapshot *mock_snapd_find_snapshot(MockSnapd *snapd, const gchar *name); void mock_snapd_add_store_category(MockSnapd *snapd, const gchar *name); MockSnap *mock_snapd_add_store_snap(MockSnapd *snapd, const gchar *name); MockApp *mock_snap_add_app(MockSnap *snap, const gchar *name); MockApp *mock_snap_find_app(MockSnap *snap, const gchar *name); void mock_app_set_active(MockApp *app, gboolean active); void mock_app_set_enabled(MockApp *app, gboolean enabled); void mock_app_set_common_id(MockApp *app, const gchar *id); void mock_app_set_daemon(MockApp *app, const gchar *daemon); void mock_app_set_desktop_file(MockApp *app, const gchar *desktop_file); void mock_app_add_auto_alias(MockApp *app, const gchar *alias); void mock_app_add_manual_alias(MockApp *app, const gchar *alias, gboolean enabled); MockAlias *mock_app_find_alias(MockApp *app, const gchar *name); void mock_snap_set_base(MockSnap *snap, const gchar *base); void mock_snap_set_broken(MockSnap *snap, const gchar *broken); void mock_snap_add_category(MockSnap *snap, const gchar *name, gboolean featured); void mock_snap_set_channel(MockSnap *snap, const gchar *channel); const gchar *mock_snap_get_channel(MockSnap *snap); void mock_snap_set_conf(MockSnap *snap, const gchar *name, const gchar *value); gsize mock_snap_get_conf_count(MockSnap *snap); const gchar *mock_snap_get_conf(MockSnap *snap, const gchar *name); MockTrack *mock_snap_add_track(MockSnap *snap, const gchar *name); MockChannel *mock_track_add_channel(MockTrack *track, const gchar *risk, const gchar *branch); void mock_channel_set_confinement(MockChannel *channel, const gchar *confinement); void mock_channel_set_branch(MockChannel *channel, const gchar *branch); void mock_channel_set_epoch(MockChannel *channel, const gchar *epoch); void mock_channel_set_released_at(MockChannel *channel, const gchar *released_at); void mock_channel_set_revision(MockChannel *channel, const gchar *revision); void mock_channel_set_size(MockChannel *channel, int size); void mock_channel_set_version(MockChannel *channel, const gchar *version); void mock_snap_set_confinement(MockSnap *snap, const gchar *confinement); const gchar *mock_snap_get_confinement(MockSnap *snap); void mock_snap_set_contact(MockSnap *snap, const gchar *contact); gboolean mock_snap_get_dangerous(MockSnap *snap); const gchar *mock_snap_get_data(MockSnap *snap); void mock_snap_set_description(MockSnap *snap, const gchar *description); void mock_snap_set_devmode(MockSnap *snap, gboolean devmode); gboolean mock_snap_get_devmode(MockSnap *snap); void mock_snap_set_disabled(MockSnap *snap, gboolean disabled); gboolean mock_snap_get_disabled(MockSnap *snap); void mock_snap_set_download_size(MockSnap *snap, int download_size); void mock_snap_set_error(MockSnap *snap, const gchar *error); void mock_snap_set_hold(MockSnap *snap, const gchar *hold); void mock_snap_set_icon(MockSnap *snap, const gchar *icon); void mock_snap_set_icon_data(MockSnap *snap, const gchar *mime_type, GBytes *data); void mock_snap_set_id(MockSnap *snap, const gchar *id); void mock_snap_set_install_date(MockSnap *snap, const gchar *install_date); void mock_snap_set_installed_size(MockSnap *snap, int installed_size); void mock_snap_set_jailmode(MockSnap *snap, gboolean jailmode); gboolean mock_snap_get_jailmode(MockSnap *snap); void mock_snap_set_license(MockSnap *snap, const gchar *license); void mock_snap_set_mounted_from(MockSnap *snap, const gchar *mounted_from); const gchar *mock_snap_get_path(MockSnap *snap); gboolean mock_snap_get_preferred(MockSnap *snap); MockPrice *mock_snap_add_price(MockSnap *snap, gdouble amount, const gchar *currency); void mock_snap_set_publisher_display_name(MockSnap *snap, const gchar *display_name); void mock_snap_set_publisher_id(MockSnap *snap, const gchar *id); void mock_snap_set_publisher_username(MockSnap *snap, const gchar *username); void mock_snap_set_publisher_validation(MockSnap *snap, const gchar *validation); void mock_snap_set_restart_required(MockSnap *snap, gboolean restart_required); void mock_snap_set_revision(MockSnap *snap, const gchar *revision); const gchar *mock_snap_get_revision(MockSnap *snap); void mock_snap_set_scope_is_wide(MockSnap *snap, gboolean scope_is_wide); MockMedia *mock_snap_add_media(MockSnap *snap, const gchar *type, const gchar *url, int width, int height); void mock_snap_set_status(MockSnap *snap, const gchar *status); void mock_snap_set_store_url(MockSnap *snap, const gchar *store_url); void mock_snap_set_summary(MockSnap *snap, const gchar *summary); void mock_snap_set_title(MockSnap *snap, const gchar *title); void mock_snap_set_tracking_channel(MockSnap *snap, const gchar *channel); const gchar *mock_snap_get_tracking_channel(MockSnap *snap); void mock_snap_set_trymode(MockSnap *snap, gboolean trymode); void mock_snap_set_type(MockSnap *snap, const gchar *type); void mock_snap_set_version(MockSnap *snap, const gchar *version); void mock_snap_set_website(MockSnap *snap, const gchar *website); void mock_snap_add_store_category(MockSnap *snap, const gchar *category, gboolean featured); MockPlug *mock_snap_add_plug(MockSnap *snap, MockInterface *interface, const gchar *name); MockPlug *mock_snap_find_plug(MockSnap *snap, const gchar *name); void mock_plug_add_attribute(MockPlug *plug, const gchar *name, const gchar *value); MockSlot *mock_snap_add_slot(MockSnap *snap, MockInterface *interface, const gchar *name); MockSlot *mock_snap_find_slot(MockSnap *snap, const gchar *name); void mock_slot_add_attribute(MockSlot *slot, const gchar *name, const gchar *value); void mock_snapd_connect(MockSnapd *snapd, MockPlug *plug, MockSlot *slot, gboolean manual, gboolean gadget); MockSlot *mock_snapd_find_plug_connection(MockSnapd *snapd, MockPlug *plug); GList *mock_snapd_find_slot_connections(MockSnapd *snapd, MockSlot *slot); void mock_snapd_add_assertion(MockSnapd *snapd, const gchar *assertion); GList *mock_snapd_get_assertions(MockSnapd *snapd); const gchar *mock_snapd_get_last_user_agent(MockSnapd *snapd); const gchar *mock_snapd_get_last_accept_language(MockSnapd *snapd); const gchar *mock_snapd_get_last_allow_interaction(MockSnapd *snapd); void mock_snapd_set_gtk_theme_status(MockSnapd *snapd, const gchar *name, const gchar *status); void mock_snapd_set_icon_theme_status(MockSnapd *snapd, const gchar *name, const gchar *status); void mock_snapd_set_sound_theme_status(MockSnapd *snapd, const gchar *name, const gchar *status); void mock_snapd_add_log(MockSnapd *snapd, const gchar *timestamp, const gchar *message, const gchar *sid, const gchar *pid); void mock_snap_set_proceed_time(MockSnap *snap, const gchar *proceed_time); void mock_change_add_data(MockChange *change, JsonNode *data); void mock_change_set_force_data(MockChange *change, gboolean force_data); const gchar *mock_change_get_status(MockChange *change); void mock_change_set_status(MockChange *change, const gchar *status); void mock_change_set_kind(MockChange *change, const gchar *kind); MockNotice *mock_snapd_add_notice(MockSnapd *snapd, const gchar *id, const gchar *key, const gchar *type); void mock_notice_set_user_id(MockNotice *notice, const gchar *user_id); void mock_notice_set_dates(MockNotice *notice, GDateTime *first_occurred, GDateTime *last_occurred, GDateTime *last_repeat, int occurrences); void mock_notice_set_nanoseconds(MockNotice *notice, gint32 nanoseconds); void mock_notice_set_expire_after(MockNotice *notice, const gchar *expire_after); void mock_notice_set_repeat_after(MockNotice *notice, const gchar *repeat_after); void mock_notice_add_data_pair(MockNotice *notice, const gchar *entry, const gchar *data); void mock_notice_set_key(MockNotice *notice, const gchar *key); gchar *mock_snapd_get_notices_parameters(MockSnapd *snapd); G_END_DECLS #endif /* __MOCK_SNAPD_H__ */ snapd-glib-1.67/tests/test-glib.c000066400000000000000000013526641477073115000167150ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include #include #include "mock-snapd.h" typedef struct { GMainLoop *loop; MockSnapd *snapd; int counter; gint64 id; } AsyncData; static AsyncData *async_data_new(GMainLoop *loop, MockSnapd *snapd) { AsyncData *data = g_slice_new0(AsyncData); data->loop = g_main_loop_ref(loop); data->snapd = g_object_ref(snapd); return data; } static void async_data_free(AsyncData *data) { g_main_loop_unref(data->loop); g_object_unref(data->snapd); g_slice_free(AsyncData, data); } G_DEFINE_AUTOPTR_CLEANUP_FUNC(AsyncData, async_data_free) static void test_socket_closed_before_request(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); mock_snapd_stop(snapd); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_null(info); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_CONNECTION_FAILED); } static void test_socket_closed_after_request(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_close_on_request(snapd, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_null(info); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_READ_FAILED); } static void test_socket_closed_reconnect(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_clear_object(&info); mock_snapd_stop(snapd); g_assert_true(mock_snapd_start(snapd, &error)); info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_clear_object(&info); } static void test_socket_closed_reconnect_after_failure(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_clear_object(&info); mock_snapd_stop(snapd); info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_null(info); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_CONNECTION_FAILED); g_clear_error(&error); g_assert_true(mock_snapd_start(snapd, &error)); info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_clear_object(&info); } static void test_client_set_socket_path(void) { g_autoptr(SnapdClient) client = snapd_client_new(); g_autofree gchar *default_path = g_strdup(snapd_client_get_socket_path(client)); snapd_client_set_socket_path(client, "first.sock"); g_assert_cmpstr(snapd_client_get_socket_path(client), ==, "first.sock"); snapd_client_set_socket_path(client, "second.sock"); g_assert_cmpstr(snapd_client_get_socket_path(client), ==, "second.sock"); snapd_client_set_socket_path(client, NULL); g_assert_cmpstr(snapd_client_get_socket_path(client), ==, default_path); } static void test_user_agent_default(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_cmpstr(snapd_client_get_user_agent(client), ==, "snapd-glib/" VERSION); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpstr(mock_snapd_get_last_user_agent(snapd), ==, "snapd-glib/" VERSION); } static void test_user_agent_custom(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_set_user_agent(client, "Foo/1.0"); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpstr(mock_snapd_get_last_user_agent(snapd), ==, "Foo/1.0"); } static void test_user_agent_null(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_set_user_agent(client, NULL); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpstr(mock_snapd_get_last_user_agent(snapd), ==, NULL); } static void test_accept_language(void) { g_setenv("LANG", "en_US.UTF-8", TRUE); g_setenv("LANGUAGE", "en_US:fr", TRUE); g_setenv("LC_ALL", "", TRUE); g_setenv("LC_MESSAGES", "", TRUE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpstr(mock_snapd_get_last_accept_language(snapd), ==, "en-us, en;q=0.9, fr;q=0.8"); } static void test_accept_language_empty(void) { g_setenv("LANG", "", TRUE); g_setenv("LANGUAGE", "", TRUE); g_setenv("LC_ALL", "", TRUE); g_setenv("LC_MESSAGES", "", TRUE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpstr(mock_snapd_get_last_accept_language(snapd), ==, "en"); } static void test_allow_interaction(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); /* By default, interaction is allowed */ g_assert_true(snapd_client_get_allow_interaction(client)); /* ... which sends the X-Allow-Interaction header with requests */ g_autoptr(SnapdSystemInformation) info1 = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info1); g_assert_cmpstr(mock_snapd_get_last_allow_interaction(snapd), ==, "true"); /* If interaction is not allowed, the header is not sent */ snapd_client_set_allow_interaction(client, FALSE); g_assert_false(snapd_client_get_allow_interaction(client)); g_autoptr(SnapdSystemInformation) info2 = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info2); g_assert_cmpstr(mock_snapd_get_last_allow_interaction(snapd), ==, NULL); } static void test_maintenance_none(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); SnapdMaintenance *maintenance = snapd_client_get_maintenance(client); g_assert_null(maintenance); } static void test_maintenance_daemon_restart(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_maintenance(snapd, "daemon-restart", "daemon is restarting"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); SnapdMaintenance *maintenance = snapd_client_get_maintenance(client); g_assert_nonnull(maintenance); g_assert_cmpint(snapd_maintenance_get_kind(maintenance), ==, SNAPD_MAINTENANCE_KIND_DAEMON_RESTART); g_assert_cmpstr(snapd_maintenance_get_message(maintenance), ==, "daemon is restarting"); } static void test_maintenance_system_restart(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_maintenance(snapd, "system-restart", "system is restarting"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); SnapdMaintenance *maintenance = snapd_client_get_maintenance(client); g_assert_nonnull(maintenance); g_assert_cmpint(snapd_maintenance_get_kind(maintenance), ==, SNAPD_MAINTENANCE_KIND_SYSTEM_RESTART); g_assert_cmpstr(snapd_maintenance_get_message(maintenance), ==, "system is restarting"); } static void test_maintenance_unknown(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_maintenance(snapd, "no-such-kind", "MESSAGE"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); SnapdMaintenance *maintenance = snapd_client_get_maintenance(client); g_assert_nonnull(maintenance); g_assert_cmpint(snapd_maintenance_get_kind(maintenance), ==, SNAPD_MAINTENANCE_KIND_UNKNOWN); g_assert_cmpstr(snapd_maintenance_get_message(maintenance), ==, "MESSAGE"); } static gboolean date_matches(GDateTime *date, int year, int month, int day, int hour, int minute, int second) { g_autoptr(GDateTime) d = g_date_time_new_utc(year, month, day, hour, minute, second); if (date == NULL) return FALSE; return g_date_time_compare(date, d) == 0; } static void test_get_system_information_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_managed(snapd, TRUE); mock_snapd_set_on_classic(snapd, TRUE); mock_snapd_set_architecture(snapd, "amd64"); mock_snapd_set_build_id(snapd, "efdd0b5e69b0742fa5e5bad0771df4d1df2459d1"); mock_snapd_add_sandbox_feature(snapd, "backend", "feature1"); mock_snapd_add_sandbox_feature(snapd, "backend", "feature2"); mock_snapd_set_refresh_timer(snapd, "00:00~24:00/4"); mock_snapd_set_refresh_next(snapd, "2018-01-19T13:14:15Z"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpstr(snapd_system_information_get_architecture(info), ==, "amd64"); g_assert_cmpstr(snapd_system_information_get_build_id(info), ==, "efdd0b5e69b0742fa5e5bad0771df4d1df2459d1"); g_assert_cmpint(snapd_system_information_get_confinement(info), ==, SNAPD_SYSTEM_CONFINEMENT_UNKNOWN); g_assert_cmpstr(snapd_system_information_get_kernel_version(info), ==, "KERNEL-VERSION"); g_assert_cmpstr(snapd_system_information_get_os_id(info), ==, "OS-ID"); g_assert_cmpstr(snapd_system_information_get_os_version(info), ==, "OS-VERSION"); g_assert_cmpstr(snapd_system_information_get_series(info), ==, "SERIES"); g_assert_cmpstr(snapd_system_information_get_version(info), ==, "VERSION"); g_assert_true(snapd_system_information_get_managed(info)); g_assert_true(snapd_system_information_get_on_classic(info)); g_assert_cmpstr(snapd_system_information_get_mount_directory(info), ==, "/snap"); g_assert_cmpstr(snapd_system_information_get_binaries_directory(info), ==, "/snap/bin"); g_assert_null(snapd_system_information_get_refresh_schedule(info)); g_assert_cmpstr(snapd_system_information_get_refresh_timer(info), ==, "00:00~24:00/4"); g_assert_null(snapd_system_information_get_refresh_hold(info)); g_assert_null(snapd_system_information_get_refresh_last(info)); g_assert_true(date_matches(snapd_system_information_get_refresh_next(info), 2018, 1, 19, 13, 14, 15)); g_assert_null(snapd_system_information_get_store(info)); GHashTable *sandbox_features = snapd_system_information_get_sandbox_features(info); g_assert_nonnull(sandbox_features); GStrv backend_features = g_hash_table_lookup(sandbox_features, "backend"); g_assert_nonnull(backend_features); g_assert_cmpint(g_strv_length(backend_features), ==, 2); g_assert_cmpstr(backend_features[0], ==, "feature1"); g_assert_cmpstr(backend_features[1], ==, "feature2"); } static void system_information_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpint(snapd_system_information_get_confinement(info), ==, SNAPD_SYSTEM_CONFINEMENT_UNKNOWN); g_assert_cmpstr(snapd_system_information_get_kernel_version(info), ==, "KERNEL-VERSION"); g_assert_cmpstr(snapd_system_information_get_os_id(info), ==, "OS-ID"); g_assert_cmpstr(snapd_system_information_get_os_version(info), ==, "OS-VERSION"); g_assert_cmpstr(snapd_system_information_get_series(info), ==, "SERIES"); g_assert_cmpstr(snapd_system_information_get_version(info), ==, "VERSION"); g_assert_true(snapd_system_information_get_managed(info)); g_assert_true(snapd_system_information_get_on_classic(info)); g_assert_cmpstr(snapd_system_information_get_mount_directory(info), ==, "/snap"); g_assert_cmpstr(snapd_system_information_get_binaries_directory(info), ==, "/snap/bin"); g_assert_null(snapd_system_information_get_store(info)); g_main_loop_quit(data->loop); } static void test_get_system_information_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_managed(snapd, TRUE); mock_snapd_set_on_classic(snapd, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_system_information_async(client, NULL, system_information_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_get_system_information_store(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_store(snapd, "store"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpstr(snapd_system_information_get_store(info), ==, "store"); } static void test_get_system_information_refresh(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_refresh_timer(snapd, "00:00~24:00/4"); mock_snapd_set_refresh_hold(snapd, "2018-01-20T01:02:03Z"); mock_snapd_set_refresh_last(snapd, "2018-01-19T01:02:03Z"); mock_snapd_set_refresh_next(snapd, "2018-01-19T13:14:15Z"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_null(snapd_system_information_get_refresh_schedule(info)); g_assert_cmpstr(snapd_system_information_get_refresh_timer(info), ==, "00:00~24:00/4"); g_assert_true(date_matches(snapd_system_information_get_refresh_hold(info), 2018, 1, 20, 1, 2, 3)); g_assert_true(date_matches(snapd_system_information_get_refresh_last(info), 2018, 1, 19, 1, 2, 3)); g_assert_true(date_matches(snapd_system_information_get_refresh_next(info), 2018, 1, 19, 13, 14, 15)); } static void test_get_system_information_refresh_schedule(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_refresh_schedule( snapd, "00:00-04:59/5:00-10:59/11:00-16:59/17:00-23:59"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpstr(snapd_system_information_get_refresh_schedule(info), ==, "00:00-04:59/5:00-10:59/11:00-16:59/17:00-23:59"); g_assert_null(snapd_system_information_get_refresh_timer(info)); } static void test_get_system_information_confinement_strict(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_confinement(snapd, "strict"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpint(snapd_system_information_get_confinement(info), ==, SNAPD_SYSTEM_CONFINEMENT_STRICT); } static void test_get_system_information_confinement_none(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_confinement(snapd, "partial"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpint(snapd_system_information_get_confinement(info), ==, SNAPD_SYSTEM_CONFINEMENT_PARTIAL); } static void test_get_system_information_confinement_unknown(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_confinement(snapd, "NOT_DEFINED"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpint(snapd_system_information_get_confinement(info), ==, SNAPD_SYSTEM_CONFINEMENT_UNKNOWN); } static void test_login_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); g_auto(GStrv) keys = g_strsplit("KEY1;KEY2", ";", -1); mock_account_set_ssh_keys(a, keys); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(user_information); g_assert_cmpint(snapd_user_information_get_id(user_information), ==, 1); g_assert_cmpstr(snapd_user_information_get_email(user_information), ==, "test@example.com"); g_assert_cmpstr(snapd_user_information_get_username(user_information), ==, "test"); GStrv ssh_keys = snapd_user_information_get_ssh_keys(user_information); g_assert_nonnull(ssh_keys); g_assert_cmpint(g_strv_length(ssh_keys), ==, 0); SnapdAuthData *auth_data = snapd_user_information_get_auth_data(user_information); g_assert_nonnull(auth_data); g_assert_cmpstr(snapd_auth_data_get_macaroon(auth_data), ==, mock_account_get_macaroon(a)); g_assert_true(g_strv_length(snapd_auth_data_get_discharges(auth_data)) == g_strv_length(mock_account_get_discharges(a))); for (int i = 0; mock_account_get_discharges(a)[i]; i++) g_assert_cmpstr(snapd_auth_data_get_discharges(auth_data)[i], ==, mock_account_get_discharges(a)[i]); } static void login_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; MockAccount *a = mock_snapd_find_account_by_username(data->snapd, "test"); g_autoptr(GError) error = NULL; g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(user_information); g_assert_cmpint(snapd_user_information_get_id(user_information), ==, 1); g_assert_cmpstr(snapd_user_information_get_email(user_information), ==, "test@example.com"); g_assert_cmpstr(snapd_user_information_get_username(user_information), ==, "test"); GStrv ssh_keys = snapd_user_information_get_ssh_keys(user_information); g_assert_nonnull(ssh_keys); g_assert_cmpint(g_strv_length(ssh_keys), ==, 0); SnapdAuthData *auth_data = snapd_user_information_get_auth_data(user_information); g_assert_nonnull(auth_data); g_assert_cmpstr(snapd_auth_data_get_macaroon(auth_data), ==, mock_account_get_macaroon(a)); g_assert_true(g_strv_length(snapd_auth_data_get_discharges(auth_data)) == g_strv_length(mock_account_get_discharges(a))); for (int i = 0; mock_account_get_discharges(a)[i]; i++) g_assert_cmpstr(snapd_auth_data_get_discharges(auth_data)[i], ==, mock_account_get_discharges(a)[i]); g_main_loop_quit(data->loop); } static void test_login_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); g_auto(GStrv) keys = g_strsplit("KEY1;KEY2", ";", -1); mock_account_set_ssh_keys(a, keys); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_login2_async(client, "test@example.com", "secret", NULL, NULL, login_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_login_invalid_email(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "not-an-email", "secret", NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_AUTH_DATA_INVALID); g_assert_null(user_information); } static void test_login_invalid_password(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "invalid", NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_AUTH_DATA_REQUIRED); g_assert_null(user_information); } static void test_login_otp_missing(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_account_set_otp(a, "1234"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_TWO_FACTOR_REQUIRED); g_assert_null(user_information); } static void test_login_otp_invalid(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_account_set_otp(a, "1234"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", "0000", NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_TWO_FACTOR_INVALID); g_assert_null(user_information); } static void test_login_legacy(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_autoptr(SnapdAuthData) auth_data = snapd_client_login_sync( client, "test@example.com", "secret", NULL, NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_nonnull(auth_data); g_assert_cmpstr(snapd_auth_data_get_macaroon(auth_data), ==, mock_account_get_macaroon(a)); g_assert_true(g_strv_length(snapd_auth_data_get_discharges(auth_data)) == g_strv_length(mock_account_get_discharges(a))); for (int i = 0; mock_account_get_discharges(a)[i]; i++) g_assert_cmpstr(snapd_auth_data_get_discharges(auth_data)[i], ==, mock_account_get_discharges(a)[i]); } static void test_logout_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_account(snapd, "test1@example.com", "test1", "secret"); MockAccount *a = mock_snapd_add_account(snapd, "test2@example.com", "test2", "secret"); mock_snapd_add_account(snapd, "test3@example.com", "test3", "secret"); gint64 id = mock_account_get_id(a); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdAuthData) auth_data = snapd_auth_data_new( mock_account_get_macaroon(a), mock_account_get_discharges(a)); snapd_client_set_auth_data(client, auth_data); g_assert_nonnull(mock_snapd_find_account_by_id(snapd, id)); gboolean result = snapd_client_logout_sync(client, id, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_null(mock_snapd_find_account_by_id(snapd, id)); } static void logout_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_logout_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_assert_null(mock_snapd_find_account_by_id(data->snapd, data->id)); g_main_loop_quit(data->loop); } static void test_logout_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_account(snapd, "test1@example.com", "test1", "secret"); MockAccount *a = mock_snapd_add_account(snapd, "test2@example.com", "test2", "secret"); mock_snapd_add_account(snapd, "test3@example.com", "test3", "secret"); gint64 id = mock_account_get_id(a); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdAuthData) auth_data = snapd_auth_data_new( mock_account_get_macaroon(a), mock_account_get_discharges(a)); snapd_client_set_auth_data(client, auth_data); g_assert_nonnull(mock_snapd_find_account_by_id(snapd, id)); AsyncData *data = async_data_new(loop, snapd); data->id = id; snapd_client_logout_async(client, id, NULL, logout_cb, data); g_main_loop_run(loop); } static void test_logout_no_auth(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_account(snapd, "test1@example.com", "test1", "secret"); MockAccount *a = mock_snapd_add_account(snapd, "test2@example.com", "test2", "secret"); mock_snapd_add_account(snapd, "test3@example.com", "test3", "secret"); gint64 id = mock_account_get_id(a); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_nonnull(mock_snapd_find_account_by_id(snapd, id)); gboolean result = snapd_client_logout_sync(client, id, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_REQUEST); g_assert_false(result); g_assert_nonnull(mock_snapd_find_account_by_id(snapd, id)); } static void test_get_changes_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockChange *c = mock_snapd_add_change(snapd); mock_change_set_spawn_time(c, "2017-01-02T11:00:00Z"); MockTask *t = mock_change_add_task(c, "download"); mock_task_set_progress(t, 65535, 65535); mock_task_set_status(t, "Done"); mock_task_set_spawn_time(t, "2017-01-02T11:00:00Z"); mock_task_set_ready_time(t, "2017-01-02T11:00:10Z"); t = mock_change_add_task(c, "install"); mock_task_set_progress(t, 1, 1); mock_task_set_status(t, "Done"); mock_task_set_spawn_time(t, "2017-01-02T11:00:10Z"); mock_task_set_ready_time(t, "2017-01-02T11:00:30Z"); mock_change_set_ready_time(c, "2017-01-02T11:00:30Z"); c = mock_snapd_add_change(snapd); mock_change_set_spawn_time(c, "2017-01-02T11:15:00Z"); t = mock_change_add_task(c, "remove"); mock_task_set_progress(t, 0, 1); mock_task_set_spawn_time(t, "2017-01-02T11:15:00Z"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) changes = snapd_client_get_changes_sync( client, SNAPD_CHANGE_FILTER_ALL, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(changes); g_assert_cmpint(changes->len, ==, 2); g_assert_cmpstr(snapd_change_get_id(changes->pdata[0]), ==, "1"); g_assert_cmpstr(snapd_change_get_kind(changes->pdata[0]), ==, "KIND"); g_assert_cmpstr(snapd_change_get_summary(changes->pdata[0]), ==, "SUMMARY"); g_assert_cmpstr(snapd_change_get_status(changes->pdata[0]), ==, "Done"); g_assert_true(snapd_change_get_ready(changes->pdata[0])); g_assert_true(date_matches(snapd_change_get_spawn_time(changes->pdata[0]), 2017, 1, 2, 11, 0, 0)); g_assert_true(date_matches(snapd_change_get_ready_time(changes->pdata[0]), 2017, 1, 2, 11, 0, 30)); g_assert_null(snapd_change_get_error(changes->pdata[0])); GPtrArray *tasks = snapd_change_get_tasks(changes->pdata[0]); g_assert_cmpint(tasks->len, ==, 2); g_assert_cmpstr(snapd_task_get_id(tasks->pdata[0]), ==, "100"); g_assert_cmpstr(snapd_task_get_kind(tasks->pdata[0]), ==, "download"); g_assert_cmpstr(snapd_task_get_summary(tasks->pdata[0]), ==, "SUMMARY"); g_assert_cmpstr(snapd_task_get_status(tasks->pdata[0]), ==, "Done"); g_assert_cmpstr(snapd_task_get_progress_label(tasks->pdata[0]), ==, "LABEL"); g_assert_cmpint(snapd_task_get_progress_done(tasks->pdata[0]), ==, 65535); g_assert_cmpint(snapd_task_get_progress_total(tasks->pdata[0]), ==, 65535); g_assert_true(date_matches(snapd_task_get_spawn_time(tasks->pdata[0]), 2017, 1, 2, 11, 0, 0)); g_assert_true(date_matches(snapd_task_get_ready_time(tasks->pdata[0]), 2017, 1, 2, 11, 0, 10)); g_assert_cmpstr(snapd_task_get_id(tasks->pdata[1]), ==, "101"); g_assert_cmpstr(snapd_task_get_kind(tasks->pdata[1]), ==, "install"); g_assert_cmpstr(snapd_task_get_summary(tasks->pdata[1]), ==, "SUMMARY"); g_assert_cmpstr(snapd_task_get_status(tasks->pdata[1]), ==, "Done"); g_assert_cmpstr(snapd_task_get_progress_label(tasks->pdata[1]), ==, "LABEL"); g_assert_cmpint(snapd_task_get_progress_done(tasks->pdata[1]), ==, 1); g_assert_cmpint(snapd_task_get_progress_total(tasks->pdata[1]), ==, 1); g_assert_true(date_matches(snapd_task_get_spawn_time(tasks->pdata[1]), 2017, 1, 2, 11, 0, 10)); g_assert_true(date_matches(snapd_task_get_ready_time(tasks->pdata[1]), 2017, 1, 2, 11, 0, 30)); g_assert_cmpstr(snapd_change_get_id(changes->pdata[1]), ==, "2"); g_assert_cmpstr(snapd_change_get_kind(changes->pdata[1]), ==, "KIND"); g_assert_cmpstr(snapd_change_get_summary(changes->pdata[1]), ==, "SUMMARY"); g_assert_cmpstr(snapd_change_get_status(changes->pdata[1]), ==, "Do"); g_assert_false(snapd_change_get_ready(changes->pdata[1])); g_assert_true(date_matches(snapd_change_get_spawn_time(changes->pdata[1]), 2017, 1, 2, 11, 15, 0)); g_assert_null(snapd_change_get_ready_time(changes->pdata[1])); g_assert_null(snapd_change_get_error(changes->pdata[1])); tasks = snapd_change_get_tasks(changes->pdata[1]); g_assert_cmpint(tasks->len, ==, 1); g_assert_cmpstr(snapd_task_get_id(tasks->pdata[0]), ==, "200"); g_assert_cmpstr(snapd_task_get_kind(tasks->pdata[0]), ==, "remove"); g_assert_cmpstr(snapd_task_get_summary(tasks->pdata[0]), ==, "SUMMARY"); g_assert_cmpstr(snapd_task_get_status(tasks->pdata[0]), ==, "Do"); g_assert_cmpstr(snapd_task_get_progress_label(tasks->pdata[0]), ==, "LABEL"); g_assert_cmpint(snapd_task_get_progress_done(tasks->pdata[0]), ==, 0); g_assert_cmpint(snapd_task_get_progress_total(tasks->pdata[0]), ==, 1); g_assert_true(date_matches(snapd_task_get_spawn_time(tasks->pdata[0]), 2017, 1, 2, 11, 15, 0)); g_assert_null(snapd_task_get_ready_time(tasks->pdata[0])); } static void get_changes_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) changes = snapd_client_get_changes_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(changes); g_assert_cmpint(changes->len, ==, 2); g_assert_cmpstr(snapd_change_get_id(changes->pdata[0]), ==, "1"); g_assert_cmpstr(snapd_change_get_kind(changes->pdata[0]), ==, "KIND"); g_assert_cmpstr(snapd_change_get_summary(changes->pdata[0]), ==, "SUMMARY"); g_assert_cmpstr(snapd_change_get_status(changes->pdata[0]), ==, "Done"); g_assert_true(snapd_change_get_ready(changes->pdata[0])); g_assert_true(date_matches(snapd_change_get_spawn_time(changes->pdata[0]), 2017, 1, 2, 11, 0, 0)); g_assert_true(date_matches(snapd_change_get_ready_time(changes->pdata[0]), 2017, 1, 2, 11, 0, 30)); g_assert_null(snapd_change_get_error(changes->pdata[0])); GPtrArray *tasks = snapd_change_get_tasks(changes->pdata[0]); g_assert_cmpint(tasks->len, ==, 2); g_assert_cmpstr(snapd_task_get_id(tasks->pdata[0]), ==, "100"); g_assert_cmpstr(snapd_task_get_kind(tasks->pdata[0]), ==, "download"); g_assert_cmpstr(snapd_task_get_summary(tasks->pdata[0]), ==, "SUMMARY"); g_assert_cmpstr(snapd_task_get_status(tasks->pdata[0]), ==, "Done"); g_assert_cmpstr(snapd_task_get_progress_label(tasks->pdata[0]), ==, "LABEL"); g_assert_cmpint(snapd_task_get_progress_done(tasks->pdata[0]), ==, 65535); g_assert_cmpint(snapd_task_get_progress_total(tasks->pdata[0]), ==, 65535); g_assert_true(date_matches(snapd_task_get_spawn_time(tasks->pdata[0]), 2017, 1, 2, 11, 0, 0)); g_assert_true(date_matches(snapd_task_get_ready_time(tasks->pdata[0]), 2017, 1, 2, 11, 0, 10)); g_assert_cmpstr(snapd_task_get_id(tasks->pdata[1]), ==, "101"); g_assert_cmpstr(snapd_task_get_kind(tasks->pdata[1]), ==, "install"); g_assert_cmpstr(snapd_task_get_summary(tasks->pdata[1]), ==, "SUMMARY"); g_assert_cmpstr(snapd_task_get_status(tasks->pdata[1]), ==, "Done"); g_assert_cmpstr(snapd_task_get_progress_label(tasks->pdata[1]), ==, "LABEL"); g_assert_cmpint(snapd_task_get_progress_done(tasks->pdata[1]), ==, 1); g_assert_cmpint(snapd_task_get_progress_total(tasks->pdata[1]), ==, 1); g_assert_true(date_matches(snapd_task_get_spawn_time(tasks->pdata[1]), 2017, 1, 2, 11, 0, 10)); g_assert_true(date_matches(snapd_task_get_ready_time(tasks->pdata[1]), 2017, 1, 2, 11, 0, 30)); g_assert_cmpstr(snapd_change_get_id(changes->pdata[1]), ==, "2"); g_assert_cmpstr(snapd_change_get_kind(changes->pdata[1]), ==, "KIND"); g_assert_cmpstr(snapd_change_get_summary(changes->pdata[1]), ==, "SUMMARY"); g_assert_cmpstr(snapd_change_get_status(changes->pdata[1]), ==, "Do"); g_assert_false(snapd_change_get_ready(changes->pdata[1])); g_assert_true(date_matches(snapd_change_get_spawn_time(changes->pdata[1]), 2017, 1, 2, 11, 15, 0)); g_assert_null(snapd_change_get_ready_time(changes->pdata[1])); g_assert_null(snapd_change_get_error(changes->pdata[1])); tasks = snapd_change_get_tasks(changes->pdata[1]); g_assert_cmpint(tasks->len, ==, 1); g_assert_cmpstr(snapd_task_get_id(tasks->pdata[0]), ==, "200"); g_assert_cmpstr(snapd_task_get_kind(tasks->pdata[0]), ==, "remove"); g_assert_cmpstr(snapd_task_get_summary(tasks->pdata[0]), ==, "SUMMARY"); g_assert_cmpstr(snapd_task_get_status(tasks->pdata[0]), ==, "Do"); g_assert_cmpstr(snapd_task_get_progress_label(tasks->pdata[0]), ==, "LABEL"); g_assert_cmpint(snapd_task_get_progress_done(tasks->pdata[0]), ==, 0); g_assert_cmpint(snapd_task_get_progress_total(tasks->pdata[0]), ==, 1); g_assert_true(date_matches(snapd_task_get_spawn_time(tasks->pdata[0]), 2017, 1, 2, 11, 15, 0)); g_assert_null(snapd_task_get_ready_time(tasks->pdata[0])); g_main_loop_quit(data->loop); } static void test_get_changes_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockChange *c = mock_snapd_add_change(snapd); mock_change_set_spawn_time(c, "2017-01-02T11:00:00Z"); MockTask *t = mock_change_add_task(c, "download"); mock_task_set_progress(t, 65535, 65535); mock_task_set_status(t, "Done"); mock_task_set_spawn_time(t, "2017-01-02T11:00:00Z"); mock_task_set_ready_time(t, "2017-01-02T11:00:10Z"); t = mock_change_add_task(c, "install"); mock_task_set_progress(t, 1, 1); mock_task_set_status(t, "Done"); mock_task_set_spawn_time(t, "2017-01-02T11:00:10Z"); mock_task_set_ready_time(t, "2017-01-02T11:00:30Z"); mock_change_set_ready_time(c, "2017-01-02T11:00:30Z"); c = mock_snapd_add_change(snapd); mock_change_set_spawn_time(c, "2017-01-02T11:15:00Z"); t = mock_change_add_task(c, "remove"); mock_task_set_progress(t, 0, 1); mock_task_set_spawn_time(t, "2017-01-02T11:15:00Z"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_changes_async(client, SNAPD_CHANGE_FILTER_ALL, NULL, NULL, get_changes_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_get_changes_filter_in_progress(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockChange *c = mock_snapd_add_change(snapd); MockTask *t = mock_change_add_task(c, "foo"); mock_task_set_status(t, "Done"); c = mock_snapd_add_change(snapd); t = mock_change_add_task(c, "foo"); c = mock_snapd_add_change(snapd); t = mock_change_add_task(c, "foo"); mock_task_set_status(t, "Done"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) changes = snapd_client_get_changes_sync( client, SNAPD_CHANGE_FILTER_IN_PROGRESS, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(changes); g_assert_cmpint(changes->len, ==, 1); g_assert_cmpstr(snapd_change_get_id(changes->pdata[0]), ==, "2"); } static void test_get_changes_filter_ready(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockChange *c = mock_snapd_add_change(snapd); MockTask *t = mock_change_add_task(c, "foo"); c = mock_snapd_add_change(snapd); t = mock_change_add_task(c, "foo"); mock_task_set_status(t, "Done"); c = mock_snapd_add_change(snapd); t = mock_change_add_task(c, "foo"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) changes = snapd_client_get_changes_sync( client, SNAPD_CHANGE_FILTER_READY, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(changes); g_assert_cmpint(changes->len, ==, 1); g_assert_cmpstr(snapd_change_get_id(changes->pdata[0]), ==, "2"); } static void test_get_changes_filter_snap(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockChange *c = mock_snapd_add_change(snapd); MockTask *t = mock_change_add_task(c, "install"); mock_task_set_snap_name(t, "snap1"); c = mock_snapd_add_change(snapd); t = mock_change_add_task(c, "install"); mock_task_set_snap_name(t, "snap2"); c = mock_snapd_add_change(snapd); t = mock_change_add_task(c, "install"); mock_task_set_snap_name(t, "snap3"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) changes = snapd_client_get_changes_sync( client, SNAPD_CHANGE_FILTER_ALL, "snap2", NULL, &error); g_assert_no_error(error); g_assert_nonnull(changes); g_assert_cmpint(changes->len, ==, 1); g_assert_cmpstr(snapd_change_get_id(changes->pdata[0]), ==, "2"); } static void test_get_changes_filter_ready_snap(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockChange *c = mock_snapd_add_change(snapd); MockTask *t = mock_change_add_task(c, "install"); mock_task_set_snap_name(t, "snap1"); c = mock_snapd_add_change(snapd); t = mock_change_add_task(c, "install"); mock_task_set_snap_name(t, "snap2"); mock_task_set_status(t, "Done"); c = mock_snapd_add_change(snapd); t = mock_change_add_task(c, "install"); mock_task_set_snap_name(t, "snap2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) changes = snapd_client_get_changes_sync( client, SNAPD_CHANGE_FILTER_READY, "snap2", NULL, &error); g_assert_no_error(error); g_assert_nonnull(changes); g_assert_cmpint(changes->len, ==, 1); g_assert_cmpstr(snapd_change_get_id(changes->pdata[0]), ==, "2"); } static void test_get_change_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockChange *c = mock_snapd_add_change(snapd); mock_change_set_spawn_time(c, "2017-01-02T11:00:00Z"); MockTask *t = mock_change_add_task(c, "download"); mock_task_set_progress(t, 65535, 65535); mock_task_set_status(t, "Done"); mock_task_set_spawn_time(t, "2017-01-02T11:00:00Z"); mock_task_set_ready_time(t, "2017-01-02T11:00:10Z"); t = mock_change_add_task(c, "install"); mock_task_set_progress(t, 1, 1); mock_task_set_status(t, "Done"); mock_task_set_spawn_time(t, "2017-01-02T11:00:10Z"); mock_task_set_ready_time(t, "2017-01-02T11:00:30Z"); mock_change_set_ready_time(c, "2017-01-02T11:00:30Z"); c = mock_snapd_add_change(snapd); mock_change_set_spawn_time(c, "2017-01-02T11:15:00Z"); t = mock_change_add_task(c, "remove"); mock_task_set_progress(t, 0, 1); mock_task_set_spawn_time(t, "2017-01-02T11:15:00Z"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdChange) change = snapd_client_get_change_sync(client, "1", NULL, &error); g_assert_no_error(error); g_assert_nonnull(change); g_assert_cmpstr(snapd_change_get_id(change), ==, "1"); g_assert_cmpstr(snapd_change_get_kind(change), ==, "KIND"); g_assert_cmpstr(snapd_change_get_summary(change), ==, "SUMMARY"); g_assert_cmpstr(snapd_change_get_status(change), ==, "Done"); g_assert_true(snapd_change_get_ready(change)); g_assert_true( date_matches(snapd_change_get_spawn_time(change), 2017, 1, 2, 11, 0, 0)); g_assert_true( date_matches(snapd_change_get_ready_time(change), 2017, 1, 2, 11, 0, 30)); g_assert_null(snapd_change_get_error(change)); GPtrArray *tasks = snapd_change_get_tasks(change); g_assert_cmpint(tasks->len, ==, 2); g_assert_cmpstr(snapd_task_get_id(tasks->pdata[0]), ==, "100"); g_assert_cmpstr(snapd_task_get_kind(tasks->pdata[0]), ==, "download"); g_assert_cmpstr(snapd_task_get_summary(tasks->pdata[0]), ==, "SUMMARY"); g_assert_cmpstr(snapd_task_get_status(tasks->pdata[0]), ==, "Done"); g_assert_cmpstr(snapd_task_get_progress_label(tasks->pdata[0]), ==, "LABEL"); g_assert_cmpint(snapd_task_get_progress_done(tasks->pdata[0]), ==, 65535); g_assert_cmpint(snapd_task_get_progress_total(tasks->pdata[0]), ==, 65535); g_assert_true(date_matches(snapd_task_get_spawn_time(tasks->pdata[0]), 2017, 1, 2, 11, 0, 0)); g_assert_true(date_matches(snapd_task_get_ready_time(tasks->pdata[0]), 2017, 1, 2, 11, 0, 10)); } static void get_change_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(SnapdChange) change = snapd_client_get_change_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(change); g_assert_cmpstr(snapd_change_get_id(change), ==, "1"); g_assert_cmpstr(snapd_change_get_kind(change), ==, "KIND"); g_assert_cmpstr(snapd_change_get_summary(change), ==, "SUMMARY"); g_assert_cmpstr(snapd_change_get_status(change), ==, "Done"); g_assert_true(snapd_change_get_ready(change)); g_assert_true( date_matches(snapd_change_get_spawn_time(change), 2017, 1, 2, 11, 0, 0)); g_assert_true( date_matches(snapd_change_get_ready_time(change), 2017, 1, 2, 11, 0, 30)); g_assert_null(snapd_change_get_error(change)); GPtrArray *tasks = snapd_change_get_tasks(change); g_assert_cmpint(tasks->len, ==, 2); g_assert_cmpstr(snapd_task_get_id(tasks->pdata[0]), ==, "100"); g_assert_cmpstr(snapd_task_get_kind(tasks->pdata[0]), ==, "download"); g_assert_cmpstr(snapd_task_get_summary(tasks->pdata[0]), ==, "SUMMARY"); g_assert_cmpstr(snapd_task_get_status(tasks->pdata[0]), ==, "Done"); g_assert_cmpstr(snapd_task_get_progress_label(tasks->pdata[0]), ==, "LABEL"); g_assert_cmpint(snapd_task_get_progress_done(tasks->pdata[0]), ==, 65535); g_assert_cmpint(snapd_task_get_progress_total(tasks->pdata[0]), ==, 65535); g_assert_true(date_matches(snapd_task_get_spawn_time(tasks->pdata[0]), 2017, 1, 2, 11, 0, 0)); g_assert_true(date_matches(snapd_task_get_ready_time(tasks->pdata[0]), 2017, 1, 2, 11, 0, 10)); g_main_loop_quit(data->loop); } static void test_get_change_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockChange *c = mock_snapd_add_change(snapd); mock_change_set_spawn_time(c, "2017-01-02T11:00:00Z"); MockTask *t = mock_change_add_task(c, "download"); mock_task_set_progress(t, 65535, 65535); mock_task_set_status(t, "Done"); mock_task_set_spawn_time(t, "2017-01-02T11:00:00Z"); mock_task_set_ready_time(t, "2017-01-02T11:00:10Z"); t = mock_change_add_task(c, "install"); mock_task_set_progress(t, 1, 1); mock_task_set_status(t, "Done"); mock_task_set_spawn_time(t, "2017-01-02T11:00:10Z"); mock_task_set_ready_time(t, "2017-01-02T11:00:30Z"); mock_change_set_ready_time(c, "2017-01-02T11:00:30Z"); c = mock_snapd_add_change(snapd); mock_change_set_spawn_time(c, "2017-01-02T11:15:00Z"); t = mock_change_add_task(c, "remove"); mock_task_set_progress(t, 0, 1); mock_task_set_spawn_time(t, "2017-01-02T11:15:00Z"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_change_async(client, "1", NULL, get_change_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_abort_change_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockChange *c = mock_snapd_add_change(snapd); mock_change_add_task(c, "foo"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdChange) change = snapd_client_abort_change_sync(client, "1", NULL, &error); g_assert_no_error(error); g_assert_nonnull(change); g_assert_true(snapd_change_get_ready(change)); g_assert_cmpstr(snapd_change_get_status(change), ==, "Error"); g_assert_cmpstr(snapd_change_get_error(change), ==, "cancelled"); GPtrArray *tasks = snapd_change_get_tasks(change); g_assert_cmpint(tasks->len, ==, 1); g_assert_cmpstr(snapd_task_get_status(tasks->pdata[0]), ==, "Error"); } static void abort_change_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(SnapdChange) change = snapd_client_abort_change_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(change); g_assert_true(snapd_change_get_ready(change)); g_assert_cmpstr(snapd_change_get_status(change), ==, "Error"); g_assert_cmpstr(snapd_change_get_error(change), ==, "cancelled"); GPtrArray *tasks = snapd_change_get_tasks(change); g_assert_cmpint(tasks->len, ==, 1); g_assert_cmpstr(snapd_task_get_status(tasks->pdata[0]), ==, "Error"); g_main_loop_quit(data->loop); } static void test_abort_change_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockChange *c = mock_snapd_add_change(snapd); mock_change_add_task(c, "foo"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_abort_change_async(client, "1", NULL, abort_change_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_list_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_snap(snapd, "snap1"); mock_snapd_add_snap(snapd, "snap2"); mock_snapd_add_snap(snapd, "snap3"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_autoptr(GPtrArray) snaps = snapd_client_list_sync(client, NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 3); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap1"); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[1]), ==, "snap2"); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[2]), ==, "snap3"); } static void list_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_autoptr(GPtrArray) snaps = snapd_client_list_finish(SNAPD_CLIENT(object), result, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 3); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap1"); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[1]), ==, "snap2"); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[2]), ==, "snap3"); g_main_loop_quit(data->loop); } static void test_list_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_snap(snapd, "snap1"); mock_snapd_add_snap(snapd, "snap2"); mock_snapd_add_snap(snapd, "snap3"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_list_async(client, NULL, list_cb, async_data_new(loop, snapd)); G_GNUC_END_IGNORE_DEPRECATIONS g_main_loop_run(loop); } static void test_get_snaps_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_set_status(s, "installed"); mock_snapd_add_snap(snapd, "snap1"); mock_snapd_add_snap(snapd, "snap2"); mock_snapd_add_snap(snapd, "snap3"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_get_snaps_sync( client, SNAPD_GET_SNAPS_FLAGS_NONE, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 3); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap1"); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[1]), ==, "snap2"); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[2]), ==, "snap3"); } static void test_get_snaps_inhibited(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_set_proceed_time(s, "2024-03-13T15:43:32Z"); mock_snapd_add_snap(snapd, "snap1"); mock_snapd_add_snap(snapd, "snap2"); mock_snapd_add_snap(snapd, "snap3"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_get_snaps_sync( client, SNAPD_GET_SNAPS_FLAGS_REFRESH_INHIBITED, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 1); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap1"); g_assert_true(date_matches(snapd_snap_get_proceed_time(snaps->pdata[0]), 2024, 3, 13, 15, 43, 32)); } static void get_snaps_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) snaps = snapd_client_get_snaps_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 3); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap1"); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[1]), ==, "snap2"); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[2]), ==, "snap3"); g_main_loop_quit(data->loop); } static void test_get_snaps_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_set_status(s, "installed"); mock_snapd_add_snap(snapd, "snap1"); mock_snapd_add_snap(snapd, "snap2"); mock_snapd_add_snap(snapd, "snap3"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_snaps_async(client, SNAPD_GET_SNAPS_FLAGS_NONE, NULL, NULL, get_snaps_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_get_snaps_filter(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_set_status(s, "installed"); mock_snapd_add_snap(snapd, "snap1"); mock_snapd_add_snap(snapd, "snap2"); mock_snapd_add_snap(snapd, "snap3"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gchar *filter_snaps[] = {"snap1", NULL}; g_autoptr(GPtrArray) snaps = snapd_client_get_snaps_sync( client, SNAPD_GET_SNAPS_FLAGS_INCLUDE_INACTIVE, filter_snaps, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 2); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap1"); g_assert_cmpint(snapd_snap_get_status(snaps->pdata[0]), ==, SNAPD_SNAP_STATUS_INSTALLED); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[1]), ==, "snap1"); g_assert_cmpint(snapd_snap_get_status(snaps->pdata[1]), ==, SNAPD_SNAP_STATUS_ACTIVE); } static void test_list_one_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_autoptr(SnapdSnap) snap = snapd_client_list_one_sync(client, "snap", NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_nonnull(snap); g_assert_cmpint(snapd_snap_get_apps(snap)->len, ==, 0); g_assert_cmpint(snapd_snap_get_categories(snap)->len, ==, 0); g_assert_cmpstr(snapd_snap_get_channel(snap), ==, NULL); g_assert_cmpint(g_strv_length(snapd_snap_get_tracks(snap)), ==, 0); g_assert_cmpint(snapd_snap_get_channels(snap)->len, ==, 0); g_assert_cmpint(g_strv_length(snapd_snap_get_common_ids(snap)), ==, 0); g_assert_cmpint(snapd_snap_get_confinement(snap), ==, SNAPD_CONFINEMENT_STRICT); g_assert_cmpstr(snapd_snap_get_contact(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_description(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_publisher_display_name(snap), ==, "PUBLISHER-DISPLAY-NAME"); g_assert_cmpstr(snapd_snap_get_publisher_id(snap), ==, "PUBLISHER-ID"); g_assert_cmpstr(snapd_snap_get_publisher_username(snap), ==, "PUBLISHER-USERNAME"); g_assert_cmpint(snapd_snap_get_publisher_validation(snap), ==, SNAPD_PUBLISHER_VALIDATION_UNKNOWN); g_assert_false(snapd_snap_get_devmode(snap)); g_assert_cmpint(snapd_snap_get_download_size(snap), ==, 0); g_assert_null(snapd_snap_get_hold(snap)); g_assert_cmpstr(snapd_snap_get_icon(snap), ==, "ICON"); g_assert_cmpstr(snapd_snap_get_id(snap), ==, "ID"); g_assert_null(snapd_snap_get_install_date(snap)); g_assert_cmpint(snapd_snap_get_installed_size(snap), ==, 0); g_assert_false(snapd_snap_get_jailmode(snap)); g_assert_cmpint(snapd_snap_get_media(snap)->len, ==, 0); g_assert_cmpstr(snapd_snap_get_name(snap), ==, "snap"); g_assert_cmpint(snapd_snap_get_prices(snap)->len, ==, 0); g_assert_false(snapd_snap_get_private(snap)); g_assert_cmpstr(snapd_snap_get_revision(snap), ==, "REVISION"); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_assert_cmpint(snapd_snap_get_screenshots(snap)->len, ==, 0); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_cmpint(snapd_snap_get_snap_type(snap), ==, SNAPD_SNAP_TYPE_APP); g_assert_cmpint(snapd_snap_get_status(snap), ==, SNAPD_SNAP_STATUS_ACTIVE); g_assert_cmpstr(snapd_snap_get_store_url(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_summary(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_tracking_channel(snap), ==, NULL); g_assert_false(snapd_snap_get_trymode(snap)); g_assert_cmpstr(snapd_snap_get_version(snap), ==, "VERSION"); g_assert_cmpstr(snapd_snap_get_website(snap), ==, NULL); } static void list_one_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_autoptr(SnapdSnap) snap = snapd_client_list_one_finish(SNAPD_CLIENT(object), result, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_nonnull(snap); g_assert_cmpint(snapd_snap_get_apps(snap)->len, ==, 0); g_assert_cmpstr(snapd_snap_get_base(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_broken(snap), ==, NULL); g_assert_cmpint(snapd_snap_get_categories(snap)->len, ==, 0); g_assert_cmpstr(snapd_snap_get_channel(snap), ==, NULL); g_assert_cmpint(g_strv_length(snapd_snap_get_common_ids(snap)), ==, 0); g_assert_cmpint(snapd_snap_get_confinement(snap), ==, SNAPD_CONFINEMENT_STRICT); g_assert_cmpstr(snapd_snap_get_contact(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_description(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_publisher_display_name(snap), ==, "PUBLISHER-DISPLAY-NAME"); g_assert_cmpstr(snapd_snap_get_publisher_id(snap), ==, "PUBLISHER-ID"); g_assert_cmpstr(snapd_snap_get_publisher_username(snap), ==, "PUBLISHER-USERNAME"); g_assert_cmpint(snapd_snap_get_publisher_validation(snap), ==, SNAPD_PUBLISHER_VALIDATION_UNKNOWN); g_assert_false(snapd_snap_get_devmode(snap)); g_assert_cmpint(snapd_snap_get_download_size(snap), ==, 0); g_assert_null(snapd_snap_get_hold(snap)); g_assert_cmpstr(snapd_snap_get_icon(snap), ==, "ICON"); g_assert_cmpstr(snapd_snap_get_id(snap), ==, "ID"); g_assert_null(snapd_snap_get_install_date(snap)); g_assert_cmpint(snapd_snap_get_installed_size(snap), ==, 0); g_assert_false(snapd_snap_get_jailmode(snap)); g_assert_null(snapd_snap_get_license(snap)); g_assert_cmpint(snapd_snap_get_media(snap)->len, ==, 0); g_assert_null(snapd_snap_get_mounted_from(snap)); g_assert_cmpstr(snapd_snap_get_name(snap), ==, "snap"); g_assert_cmpint(snapd_snap_get_prices(snap)->len, ==, 0); g_assert_false(snapd_snap_get_private(snap)); g_assert_cmpstr(snapd_snap_get_revision(snap), ==, "REVISION"); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_assert_cmpint(snapd_snap_get_screenshots(snap)->len, ==, 0); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_cmpint(snapd_snap_get_snap_type(snap), ==, SNAPD_SNAP_TYPE_APP); g_assert_cmpint(snapd_snap_get_status(snap), ==, SNAPD_SNAP_STATUS_ACTIVE); g_assert_cmpstr(snapd_snap_get_store_url(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_summary(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_tracking_channel(snap), ==, NULL); g_assert_false(snapd_snap_get_trymode(snap)); g_assert_cmpstr(snapd_snap_get_version(snap), ==, "VERSION"); g_assert_cmpstr(snapd_snap_get_website(snap), ==, NULL); g_main_loop_quit(data->loop); } static void test_list_one_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_list_one_async(client, "snap", NULL, list_one_cb, async_data_new(loop, snapd)); G_GNUC_END_IGNORE_DEPRECATIONS g_main_loop_run(loop); } static void test_get_snap_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSnap) snap = snapd_client_get_snap_sync(client, "snap", NULL, &error); g_assert_no_error(error); g_assert_nonnull(snap); g_assert_cmpint(snapd_snap_get_apps(snap)->len, ==, 0); g_assert_cmpint(snapd_snap_get_categories(snap)->len, ==, 0); g_assert_cmpstr(snapd_snap_get_channel(snap), ==, NULL); g_assert_cmpint(g_strv_length(snapd_snap_get_tracks(snap)), ==, 0); g_assert_cmpint(snapd_snap_get_channels(snap)->len, ==, 0); g_assert_cmpint(g_strv_length(snapd_snap_get_common_ids(snap)), ==, 0); g_assert_cmpint(snapd_snap_get_confinement(snap), ==, SNAPD_CONFINEMENT_STRICT); g_assert_cmpstr(snapd_snap_get_contact(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_description(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_publisher_display_name(snap), ==, "PUBLISHER-DISPLAY-NAME"); g_assert_cmpstr(snapd_snap_get_publisher_id(snap), ==, "PUBLISHER-ID"); g_assert_cmpstr(snapd_snap_get_publisher_username(snap), ==, "PUBLISHER-USERNAME"); g_assert_cmpint(snapd_snap_get_publisher_validation(snap), ==, SNAPD_PUBLISHER_VALIDATION_UNKNOWN); g_assert_false(snapd_snap_get_devmode(snap)); g_assert_cmpint(snapd_snap_get_download_size(snap), ==, 0); g_assert_null(snapd_snap_get_hold(snap)); g_assert_cmpstr(snapd_snap_get_icon(snap), ==, "ICON"); g_assert_cmpstr(snapd_snap_get_id(snap), ==, "ID"); g_assert_null(snapd_snap_get_install_date(snap)); g_assert_cmpint(snapd_snap_get_installed_size(snap), ==, 0); g_assert_false(snapd_snap_get_jailmode(snap)); g_assert_cmpint(snapd_snap_get_media(snap)->len, ==, 0); g_assert_cmpstr(snapd_snap_get_name(snap), ==, "snap"); g_assert_cmpint(snapd_snap_get_prices(snap)->len, ==, 0); g_assert_false(snapd_snap_get_private(snap)); g_assert_cmpstr(snapd_snap_get_revision(snap), ==, "REVISION"); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_assert_cmpint(snapd_snap_get_screenshots(snap)->len, ==, 0); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_cmpint(snapd_snap_get_snap_type(snap), ==, SNAPD_SNAP_TYPE_APP); g_assert_cmpint(snapd_snap_get_status(snap), ==, SNAPD_SNAP_STATUS_ACTIVE); g_assert_cmpstr(snapd_snap_get_store_url(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_summary(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_tracking_channel(snap), ==, NULL); g_assert_false(snapd_snap_get_trymode(snap)); g_assert_cmpstr(snapd_snap_get_version(snap), ==, "VERSION"); g_assert_cmpstr(snapd_snap_get_website(snap), ==, NULL); } static void get_snap_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(SnapdSnap) snap = snapd_client_get_snap_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(snap); g_assert_cmpint(snapd_snap_get_apps(snap)->len, ==, 0); g_assert_cmpstr(snapd_snap_get_base(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_broken(snap), ==, NULL); g_assert_cmpint(snapd_snap_get_categories(snap)->len, ==, 0); g_assert_cmpstr(snapd_snap_get_channel(snap), ==, NULL); g_assert_cmpint(g_strv_length(snapd_snap_get_common_ids(snap)), ==, 0); g_assert_cmpint(snapd_snap_get_confinement(snap), ==, SNAPD_CONFINEMENT_STRICT); g_assert_cmpstr(snapd_snap_get_contact(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_description(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_publisher_display_name(snap), ==, "PUBLISHER-DISPLAY-NAME"); g_assert_cmpstr(snapd_snap_get_publisher_id(snap), ==, "PUBLISHER-ID"); g_assert_cmpstr(snapd_snap_get_publisher_username(snap), ==, "PUBLISHER-USERNAME"); g_assert_cmpint(snapd_snap_get_publisher_validation(snap), ==, SNAPD_PUBLISHER_VALIDATION_UNKNOWN); g_assert_false(snapd_snap_get_devmode(snap)); g_assert_cmpint(snapd_snap_get_download_size(snap), ==, 0); g_assert_null(snapd_snap_get_hold(snap)); g_assert_cmpstr(snapd_snap_get_icon(snap), ==, "ICON"); g_assert_cmpstr(snapd_snap_get_id(snap), ==, "ID"); g_assert_null(snapd_snap_get_install_date(snap)); g_assert_cmpint(snapd_snap_get_installed_size(snap), ==, 0); g_assert_false(snapd_snap_get_jailmode(snap)); g_assert_null(snapd_snap_get_license(snap)); g_assert_cmpint(snapd_snap_get_media(snap)->len, ==, 0); g_assert_null(snapd_snap_get_mounted_from(snap)); g_assert_cmpstr(snapd_snap_get_name(snap), ==, "snap"); g_assert_cmpint(snapd_snap_get_prices(snap)->len, ==, 0); g_assert_false(snapd_snap_get_private(snap)); g_assert_cmpstr(snapd_snap_get_revision(snap), ==, "REVISION"); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_assert_cmpint(snapd_snap_get_screenshots(snap)->len, ==, 0); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_cmpint(snapd_snap_get_snap_type(snap), ==, SNAPD_SNAP_TYPE_APP); g_assert_cmpint(snapd_snap_get_status(snap), ==, SNAPD_SNAP_STATUS_ACTIVE); g_assert_cmpstr(snapd_snap_get_store_url(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_summary(snap), ==, NULL); g_assert_cmpstr(snapd_snap_get_tracking_channel(snap), ==, NULL); g_assert_false(snapd_snap_get_trymode(snap)); g_assert_cmpstr(snapd_snap_get_version(snap), ==, "VERSION"); g_assert_cmpstr(snapd_snap_get_website(snap), ==, NULL); g_main_loop_quit(data->loop); } static void test_get_snap_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_snap_async(client, "snap", NULL, get_snap_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_get_snap_types(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "kernel"); mock_snap_set_type(s, "kernel"); s = mock_snapd_add_snap(snapd, "gadget"); mock_snap_set_type(s, "gadget"); s = mock_snapd_add_snap(snapd, "os"); mock_snap_set_type(s, "os"); s = mock_snapd_add_snap(snapd, "core"); mock_snap_set_type(s, "core"); s = mock_snapd_add_snap(snapd, "base"); mock_snap_set_type(s, "base"); s = mock_snapd_add_snap(snapd, "snapd"); mock_snap_set_type(s, "snapd"); s = mock_snapd_add_snap(snapd, "app"); mock_snap_set_type(s, "app"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSnap) kernel_snap = snapd_client_get_snap_sync(client, "kernel", NULL, &error); g_assert_no_error(error); g_assert_nonnull(kernel_snap); g_assert_cmpint(snapd_snap_get_snap_type(kernel_snap), ==, SNAPD_SNAP_TYPE_KERNEL); g_autoptr(SnapdSnap) gadget_snap = snapd_client_get_snap_sync(client, "gadget", NULL, &error); g_assert_no_error(error); g_assert_nonnull(gadget_snap); g_assert_cmpint(snapd_snap_get_snap_type(gadget_snap), ==, SNAPD_SNAP_TYPE_GADGET); g_autoptr(SnapdSnap) os_snap = snapd_client_get_snap_sync(client, "os", NULL, &error); g_assert_no_error(error); g_assert_nonnull(os_snap); g_assert_cmpint(snapd_snap_get_snap_type(os_snap), ==, SNAPD_SNAP_TYPE_OS); g_autoptr(SnapdSnap) core_snap = snapd_client_get_snap_sync(client, "core", NULL, &error); g_assert_no_error(error); g_assert_nonnull(core_snap); g_assert_cmpint(snapd_snap_get_snap_type(core_snap), ==, SNAPD_SNAP_TYPE_CORE); g_autoptr(SnapdSnap) base_snap = snapd_client_get_snap_sync(client, "base", NULL, &error); g_assert_no_error(error); g_assert_nonnull(base_snap); g_assert_cmpint(snapd_snap_get_snap_type(base_snap), ==, SNAPD_SNAP_TYPE_BASE); g_autoptr(SnapdSnap) snapd_snap = snapd_client_get_snap_sync(client, "snapd", NULL, &error); g_assert_no_error(error); g_assert_nonnull(snapd_snap); g_assert_cmpint(snapd_snap_get_snap_type(snapd_snap), ==, SNAPD_SNAP_TYPE_SNAPD); g_autoptr(SnapdSnap) app_snap = snapd_client_get_snap_sync(client, "app", NULL, &error); g_assert_no_error(error); g_assert_nonnull(app_snap); g_assert_cmpint(snapd_snap_get_snap_type(app_snap), ==, SNAPD_SNAP_TYPE_APP); } static void test_get_snap_optional_fields(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); MockApp *a = mock_snap_add_app(s, "app"); mock_app_add_auto_alias(a, "app2"); mock_app_add_auto_alias(a, "app3"); mock_app_set_desktop_file(a, "/var/lib/snapd/desktop/applications/app.desktop"); mock_snap_set_base(s, "BASE"); mock_snap_set_broken(s, "BROKEN"); mock_snap_set_confinement(s, "classic"); mock_snap_set_devmode(s, TRUE); mock_snap_set_hold(s, "2315-06-19T13:00:37Z"); mock_snap_set_install_date(s, "2017-01-02T11:23:58Z"); mock_snap_set_installed_size(s, 1024); mock_snap_set_jailmode(s, TRUE); mock_snap_set_trymode(s, TRUE); mock_snap_set_contact(s, "CONTACT"); mock_snap_set_website(s, "WEBSITE"); mock_snap_set_channel(s, "CHANNEL"); mock_snap_set_description(s, "DESCRIPTION"); mock_snap_set_license(s, "LICENSE"); mock_snap_set_mounted_from(s, "MOUNTED-FROM"); mock_snap_set_store_url(s, "https://snapcraft.io/snap"); mock_snap_set_summary(s, "SUMMARY"); mock_snap_set_tracking_channel(s, "CHANNEL"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSnap) snap = snapd_client_get_snap_sync(client, "snap", NULL, &error); g_assert_no_error(error); g_assert_nonnull(snap); g_assert_cmpint(snapd_snap_get_apps(snap)->len, ==, 1); SnapdApp *app = snapd_snap_get_apps(snap)->pdata[0]; g_assert_cmpstr(snapd_app_get_name(app), ==, "app"); g_assert_null(snapd_app_get_common_id(app)); g_assert_cmpint(snapd_app_get_daemon_type(app), ==, SNAPD_DAEMON_TYPE_NONE); g_assert_cmpstr(snapd_app_get_snap(app), ==, "snap"); g_assert_false(snapd_app_get_active(app)); g_assert_false(snapd_app_get_enabled(app)); g_assert_cmpstr(snapd_app_get_desktop_file(app), ==, "/var/lib/snapd/desktop/applications/app.desktop"); g_assert_cmpstr(snapd_snap_get_base(snap), ==, "BASE"); g_assert_cmpstr(snapd_snap_get_broken(snap), ==, "BROKEN"); g_assert_cmpstr(snapd_snap_get_channel(snap), ==, "CHANNEL"); g_assert_cmpint(snapd_snap_get_confinement(snap), ==, SNAPD_CONFINEMENT_CLASSIC); g_assert_cmpstr(snapd_snap_get_contact(snap), ==, "CONTACT"); g_assert_cmpstr(snapd_snap_get_description(snap), ==, "DESCRIPTION"); g_assert_cmpstr(snapd_snap_get_publisher_display_name(snap), ==, "PUBLISHER-DISPLAY-NAME"); g_assert_cmpstr(snapd_snap_get_publisher_id(snap), ==, "PUBLISHER-ID"); g_assert_cmpstr(snapd_snap_get_publisher_username(snap), ==, "PUBLISHER-USERNAME"); g_assert_cmpint(snapd_snap_get_publisher_validation(snap), ==, SNAPD_PUBLISHER_VALIDATION_UNKNOWN); g_assert_true(snapd_snap_get_devmode(snap)); g_assert_cmpint(snapd_snap_get_download_size(snap), ==, 0); g_assert_true( date_matches(snapd_snap_get_hold(snap), 2315, 6, 19, 13, 00, 37)); g_assert_cmpstr(snapd_snap_get_icon(snap), ==, "ICON"); g_assert_cmpstr(snapd_snap_get_id(snap), ==, "ID"); g_assert_true( date_matches(snapd_snap_get_install_date(snap), 2017, 1, 2, 11, 23, 58)); g_assert_cmpint(snapd_snap_get_installed_size(snap), ==, 1024); g_assert_true(snapd_snap_get_jailmode(snap)); g_assert_cmpstr(snapd_snap_get_license(snap), ==, "LICENSE"); g_assert_cmpint(snapd_snap_get_media(snap)->len, ==, 0); g_assert_cmpstr(snapd_snap_get_mounted_from(snap), ==, "MOUNTED-FROM"); g_assert_cmpstr(snapd_snap_get_name(snap), ==, "snap"); g_assert_cmpint(snapd_snap_get_prices(snap)->len, ==, 0); g_assert_false(snapd_snap_get_private(snap)); g_assert_cmpstr(snapd_snap_get_revision(snap), ==, "REVISION"); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_assert_cmpint(snapd_snap_get_screenshots(snap)->len, ==, 0); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_cmpint(snapd_snap_get_snap_type(snap), ==, SNAPD_SNAP_TYPE_APP); g_assert_cmpint(snapd_snap_get_status(snap), ==, SNAPD_SNAP_STATUS_ACTIVE); g_assert_cmpstr(snapd_snap_get_store_url(snap), ==, "https://snapcraft.io/snap"); g_assert_cmpstr(snapd_snap_get_summary(snap), ==, "SUMMARY"); g_assert_cmpstr(snapd_snap_get_tracking_channel(snap), ==, "CHANNEL"); g_assert_true(snapd_snap_get_trymode(snap)); g_assert_cmpstr(snapd_snap_get_version(snap), ==, "VERSION"); g_assert_cmpstr(snapd_snap_get_website(snap), ==, "WEBSITE"); } static void test_get_snap_deprecated_fields(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSnap) snap = snapd_client_get_snap_sync(client, "snap", NULL, &error); g_assert_no_error(error); g_assert_nonnull(snap); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_assert_cmpstr(snapd_snap_get_developer(snap), ==, "PUBLISHER-USERNAME"); G_GNUC_END_IGNORE_DEPRECATIONS } static void test_get_snap_common_ids(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); MockApp *a = mock_snap_add_app(s, "app1"); mock_app_set_common_id(a, "ID1"); a = mock_snap_add_app(s, "app2"); mock_app_set_common_id(a, "ID2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSnap) snap = snapd_client_get_snap_sync(client, "snap", NULL, &error); g_assert_no_error(error); g_assert_nonnull(snap); GStrv common_ids = snapd_snap_get_common_ids(snap); g_assert_cmpint(g_strv_length(common_ids), ==, 2); g_assert_cmpstr(common_ids[0], ==, "ID1"); g_assert_cmpstr(common_ids[1], ==, "ID2"); g_assert_cmpint(snapd_snap_get_apps(snap)->len, ==, 2); SnapdApp *app = snapd_snap_get_apps(snap)->pdata[0]; g_assert_cmpstr(snapd_app_get_name(app), ==, "app1"); g_assert_cmpstr(snapd_app_get_common_id(app), ==, "ID1"); app = snapd_snap_get_apps(snap)->pdata[1]; g_assert_cmpstr(snapd_app_get_name(app), ==, "app2"); g_assert_cmpstr(snapd_app_get_common_id(app), ==, "ID2"); } static void test_get_snap_not_installed(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSnap) snap = snapd_client_get_snap_sync(client, "snap", NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_FOUND); g_assert_null(snap); } static void test_get_snap_classic_confinement(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_confinement(s, "classic"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSnap) snap = snapd_client_get_snap_sync(client, "snap", NULL, &error); g_assert_no_error(error); g_assert_nonnull(snap); g_assert_cmpint(snapd_snap_get_confinement(snap), ==, SNAPD_CONFINEMENT_CLASSIC); } static void test_get_snap_devmode_confinement(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_confinement(s, "devmode"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSnap) snap = snapd_client_get_snap_sync(client, "snap", NULL, &error); g_assert_no_error(error); g_assert_nonnull(snap); g_assert_cmpint(snapd_snap_get_confinement(snap), ==, SNAPD_CONFINEMENT_DEVMODE); } static void test_get_snap_daemons(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); MockApp *a = mock_snap_add_app(s, "app1"); mock_app_set_daemon(a, "simple"); a = mock_snap_add_app(s, "app2"); mock_app_set_daemon(a, "forking"); a = mock_snap_add_app(s, "app3"); mock_app_set_daemon(a, "oneshot"); a = mock_snap_add_app(s, "app4"); mock_app_set_daemon(a, "notify"); a = mock_snap_add_app(s, "app5"); mock_app_set_daemon(a, "dbus"); a = mock_snap_add_app(s, "app6"); mock_app_set_daemon(a, "INVALID"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSnap) snap = snapd_client_get_snap_sync(client, "snap", NULL, &error); g_assert_no_error(error); g_assert_nonnull(snap); g_assert_cmpint(snapd_snap_get_apps(snap)->len, ==, 6); SnapdApp *app = snapd_snap_get_apps(snap)->pdata[0]; g_assert_cmpint(snapd_app_get_daemon_type(app), ==, SNAPD_DAEMON_TYPE_SIMPLE); app = snapd_snap_get_apps(snap)->pdata[1]; g_assert_cmpint(snapd_app_get_daemon_type(app), ==, SNAPD_DAEMON_TYPE_FORKING); app = snapd_snap_get_apps(snap)->pdata[2]; g_assert_cmpint(snapd_app_get_daemon_type(app), ==, SNAPD_DAEMON_TYPE_ONESHOT); app = snapd_snap_get_apps(snap)->pdata[3]; g_assert_cmpint(snapd_app_get_daemon_type(app), ==, SNAPD_DAEMON_TYPE_NOTIFY); app = snapd_snap_get_apps(snap)->pdata[4]; g_assert_cmpint(snapd_app_get_daemon_type(app), ==, SNAPD_DAEMON_TYPE_DBUS); app = snapd_snap_get_apps(snap)->pdata[5]; g_assert_cmpint(snapd_app_get_daemon_type(app), ==, SNAPD_DAEMON_TYPE_UNKNOWN); } static void test_get_snap_publisher_starred(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_publisher_validation(s, "starred"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSnap) snap = snapd_client_get_snap_sync(client, "snap", NULL, &error); g_assert_no_error(error); g_assert_nonnull(snap); g_assert_cmpint(snapd_snap_get_publisher_validation(snap), ==, SNAPD_PUBLISHER_VALIDATION_STARRED); } static void test_get_snap_publisher_verified(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_publisher_validation(s, "verified"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSnap) snap = snapd_client_get_snap_sync(client, "snap", NULL, &error); g_assert_no_error(error); g_assert_nonnull(snap); g_assert_cmpint(snapd_snap_get_publisher_validation(snap), ==, SNAPD_PUBLISHER_VALIDATION_VERIFIED); } static void test_get_snap_publisher_unproven(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_publisher_validation(s, "unproven"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSnap) snap = snapd_client_get_snap_sync(client, "snap", NULL, &error); g_assert_no_error(error); g_assert_nonnull(snap); g_assert_cmpint(snapd_snap_get_publisher_validation(snap), ==, SNAPD_PUBLISHER_VALIDATION_UNPROVEN); } static void test_get_snap_publisher_unknown_validation(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_publisher_validation(s, "NOT-A-VALIDIATION"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdSnap) snap = snapd_client_get_snap_sync(client, "snap", NULL, &error); g_assert_no_error(error); g_assert_nonnull(snap); g_assert_cmpint(snapd_snap_get_publisher_validation(snap), ==, SNAPD_PUBLISHER_VALIDATION_UNKNOWN); } static void setup_get_snap_conf(MockSnapd *snapd) { MockSnap *s = mock_snapd_add_snap(snapd, "core"); mock_snap_set_conf(s, "string-key", "\"value\""); mock_snap_set_conf(s, "int-key", "42"); mock_snap_set_conf(s, "bool-key", "true"); mock_snap_set_conf(s, "number-key", "1.25"); mock_snap_set_conf(s, "array-key", "[ 1, \"two\", 3.25 ]"); mock_snap_set_conf(s, "object-key", "{\"name\": \"foo\", \"value\": 42}"); } static void check_get_snap_conf_result(GHashTable *conf) { g_assert_cmpint(g_hash_table_size(conf), ==, 6); GVariant *value = g_hash_table_lookup(conf, "string-key"); g_assert_nonnull(value); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)); g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "value"); value = g_hash_table_lookup(conf, "int-key"); g_assert_nonnull(value); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_INT64)); g_assert_cmpint(g_variant_get_int64(value), ==, 42); value = g_hash_table_lookup(conf, "bool-key"); g_assert_nonnull(value); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)); g_assert_true(g_variant_get_boolean(value)); value = g_hash_table_lookup(conf, "number-key"); g_assert_nonnull(value); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_DOUBLE)); g_assert_cmpfloat(g_variant_get_double(value), ==, 1.25); } static void test_get_snap_conf_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); setup_get_snap_conf(snapd); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GHashTable) conf = snapd_client_get_snap_conf_sync(client, "system", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(conf); check_get_snap_conf_result(conf); } static void get_snap_conf_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GHashTable) conf = snapd_client_get_snap_conf_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(conf); check_get_snap_conf_result(conf); g_main_loop_quit(data->loop); } static void test_get_snap_conf_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); setup_get_snap_conf(snapd); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_snap_conf_async(client, "system", NULL, NULL, get_snap_conf_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_get_snap_conf_key_filter(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "core"); mock_snap_set_conf(s, "string-key", "\"value\""); mock_snap_set_conf(s, "int-key", "42"); mock_snap_set_conf(s, "bool-key", "true"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gchar *filter_keys[] = {"int-key", NULL}; g_autoptr(GHashTable) conf = snapd_client_get_snap_conf_sync( client, "system", filter_keys, NULL, &error); g_assert_no_error(error); g_assert_nonnull(conf); g_assert_cmpint(g_hash_table_size(conf), ==, 1); GVariant *value = g_hash_table_lookup(conf, "int-key"); g_assert_nonnull(value); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_INT64)); g_assert_cmpint(g_variant_get_int64(value), ==, 42); } static void test_get_snap_conf_invalid_key(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "core"); mock_snap_set_conf(s, "string-key", "\"value\""); mock_snap_set_conf(s, "int-key", "42"); mock_snap_set_conf(s, "bool-key", "true"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gchar *filter_keys[] = {"invalid-key", NULL}; g_autoptr(GHashTable) conf = snapd_client_get_snap_conf_sync( client, "system", filter_keys, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_OPTION_NOT_FOUND); g_assert_null(conf); } static GHashTable *setup_set_snap_conf(MockSnapd *snapd) { mock_snapd_add_snap(snapd, "core"); g_autoptr(GHashTable) key_values = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, (GDestroyNotify)g_variant_unref); g_hash_table_insert(key_values, "string-key", g_variant_new_string("value")); g_hash_table_insert(key_values, "int-key", g_variant_new_int64(42)); g_hash_table_insert(key_values, "bool-key", g_variant_new_boolean(TRUE)); g_hash_table_insert(key_values, "number-key", g_variant_new_double(1.25)); g_autoptr(GVariantBuilder) array_builder = g_variant_builder_new(G_VARIANT_TYPE("av")); g_variant_builder_add(array_builder, "v", g_variant_new_int64(1)); g_variant_builder_add(array_builder, "v", g_variant_new_string("two")); g_variant_builder_add(array_builder, "v", g_variant_new_double(3.25)); g_hash_table_insert(key_values, "array-key", g_variant_builder_end(array_builder)); g_autoptr(GVariantBuilder) object_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); g_variant_builder_add(object_builder, "{sv}", "name", g_variant_new_string("foo")); g_variant_builder_add(object_builder, "{sv}", "value", g_variant_new_int64(42)); g_hash_table_insert(key_values, "object-key", g_variant_builder_end(object_builder)); return g_steal_pointer(&key_values); } static void check_set_snap_conf_result(MockSnapd *snapd) { MockSnap *snap = mock_snapd_find_snap(snapd, "core"); g_assert_cmpint(mock_snap_get_conf_count(snap), ==, 6); g_assert_cmpstr(mock_snap_get_conf(snap, "string-key"), ==, "\"value\""); g_assert_cmpstr(mock_snap_get_conf(snap, "int-key"), ==, "42"); g_assert_cmpstr(mock_snap_get_conf(snap, "bool-key"), ==, "true"); g_assert_cmpstr(mock_snap_get_conf(snap, "number-key"), ==, "1.25"); g_assert_cmpstr(mock_snap_get_conf(snap, "array-key"), ==, "[1,\"two\",3.25]"); g_assert_cmpstr(mock_snap_get_conf(snap, "object-key"), ==, "{\"name\":\"foo\",\"value\":42}"); } static void test_set_snap_conf_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GHashTable) key_values = setup_set_snap_conf(snapd); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean r = snapd_client_set_snap_conf_sync(client, "system", key_values, NULL, &error); g_assert_no_error(error); g_assert_true(r); check_set_snap_conf_result(snapd); } static void set_snap_conf_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_set_snap_conf_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); check_set_snap_conf_result(data->snapd); g_main_loop_quit(data->loop); } static void test_set_snap_conf_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GHashTable) key_values = setup_set_snap_conf(snapd); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_set_snap_conf_async(client, "system", key_values, NULL, set_snap_conf_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_set_snap_conf_invalid(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_snap(snapd, "core"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GHashTable) key_values = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, (GDestroyNotify)g_variant_unref); g_hash_table_insert(key_values, "string-value", g_variant_new_string("value")); gboolean r = snapd_client_set_snap_conf_sync(client, "invalid", key_values, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_FOUND); g_assert_false(r); } static void test_get_apps_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); MockApp *a = mock_snap_add_app(s, "app1"); a = mock_snap_add_app(s, "app2"); mock_app_set_desktop_file(a, "foo.desktop"); a = mock_snap_add_app(s, "app3"); mock_app_set_daemon(a, "simple"); mock_app_set_active(a, TRUE); mock_app_set_enabled(a, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) apps = snapd_client_get_apps2_sync( client, SNAPD_GET_APPS_FLAGS_NONE, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(apps); g_assert_cmpint(apps->len, ==, 3); SnapdApp *app = apps->pdata[0]; g_assert_cmpstr(snapd_app_get_name(app), ==, "app1"); g_assert_cmpstr(snapd_app_get_snap(app), ==, "snap"); g_assert_cmpint(snapd_app_get_daemon_type(app), ==, SNAPD_DAEMON_TYPE_NONE); g_assert_false(snapd_app_get_active(app)); g_assert_false(snapd_app_get_enabled(app)); app = apps->pdata[1]; g_assert_cmpstr(snapd_app_get_name(app), ==, "app2"); g_assert_cmpstr(snapd_app_get_snap(app), ==, "snap"); g_assert_cmpint(snapd_app_get_daemon_type(app), ==, SNAPD_DAEMON_TYPE_NONE); g_assert_false(snapd_app_get_active(app)); g_assert_false(snapd_app_get_enabled(app)); app = apps->pdata[2]; g_assert_cmpstr(snapd_app_get_name(app), ==, "app3"); g_assert_cmpstr(snapd_app_get_snap(app), ==, "snap"); g_assert_cmpint(snapd_app_get_daemon_type(app), ==, SNAPD_DAEMON_TYPE_SIMPLE); g_assert_true(snapd_app_get_active(app)); g_assert_true(snapd_app_get_enabled(app)); } static void get_apps_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) apps = snapd_client_get_apps2_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(apps); g_assert_cmpint(apps->len, ==, 3); SnapdApp *app = apps->pdata[0]; g_assert_cmpstr(snapd_app_get_name(app), ==, "app1"); g_assert_cmpstr(snapd_app_get_snap(app), ==, "snap"); g_assert_cmpint(snapd_app_get_daemon_type(app), ==, SNAPD_DAEMON_TYPE_NONE); g_assert_false(snapd_app_get_active(app)); g_assert_false(snapd_app_get_enabled(app)); app = apps->pdata[1]; g_assert_cmpstr(snapd_app_get_name(app), ==, "app2"); g_assert_cmpstr(snapd_app_get_snap(app), ==, "snap"); g_assert_cmpint(snapd_app_get_daemon_type(app), ==, SNAPD_DAEMON_TYPE_NONE); g_assert_false(snapd_app_get_active(app)); g_assert_false(snapd_app_get_enabled(app)); app = apps->pdata[2]; g_assert_cmpstr(snapd_app_get_name(app), ==, "app3"); g_assert_cmpstr(snapd_app_get_snap(app), ==, "snap"); g_assert_cmpint(snapd_app_get_daemon_type(app), ==, SNAPD_DAEMON_TYPE_SIMPLE); g_assert_true(snapd_app_get_active(app)); g_assert_true(snapd_app_get_enabled(app)); g_main_loop_quit(data->loop); } static void test_get_apps_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); MockApp *a = mock_snap_add_app(s, "app1"); a = mock_snap_add_app(s, "app2"); mock_app_set_desktop_file(a, "foo.desktop"); a = mock_snap_add_app(s, "app3"); mock_app_set_daemon(a, "simple"); mock_app_set_active(a, TRUE); mock_app_set_enabled(a, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_apps2_async(client, SNAPD_GET_APPS_FLAGS_NONE, NULL, NULL, get_apps_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_get_apps_services(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_add_app(s, "app1"); MockApp *a = mock_snap_add_app(s, "app2"); mock_app_set_daemon(a, "simple"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) apps = snapd_client_get_apps2_sync( client, SNAPD_GET_APPS_FLAGS_SELECT_SERVICES, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(apps); g_assert_cmpint(apps->len, ==, 1); g_assert_cmpstr(snapd_app_get_name(apps->pdata[0]), ==, "app2"); } static void test_get_apps_filter(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_add_app(s, "app1"); s = mock_snapd_add_snap(snapd, "snap2"); mock_snap_add_app(s, "app2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gchar *filter_snaps[] = {"snap1", NULL}; g_autoptr(GPtrArray) apps = snapd_client_get_apps2_sync( client, SNAPD_GET_APPS_FLAGS_NONE, filter_snaps, NULL, &error); g_assert_no_error(error); g_assert_nonnull(apps); g_assert_cmpint(apps->len, ==, 1); g_assert_cmpstr(snapd_app_get_snap(apps->pdata[0]), ==, "snap1"); g_assert_cmpstr(snapd_app_get_name(apps->pdata[0]), ==, "app1"); } static void test_icon_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); g_autoptr(GBytes) icon_data = g_bytes_new("ICON-DATA", 9); mock_snap_set_icon_data(s, "image/png", icon_data); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdIcon) icon = snapd_client_get_icon_sync(client, "snap", NULL, &error); g_assert_no_error(error); g_assert_nonnull(icon); g_assert_cmpstr(snapd_icon_get_mime_type(icon), ==, "image/png"); GBytes *data = snapd_icon_get_data(icon); g_assert_cmpmem(g_bytes_get_data(data, NULL), g_bytes_get_size(data), "ICON-DATA", 9); } static void icon_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(SnapdIcon) icon = snapd_client_get_icon_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(icon); g_assert_cmpstr(snapd_icon_get_mime_type(icon), ==, "image/png"); GBytes *icon_data = snapd_icon_get_data(icon); g_assert_cmpmem(g_bytes_get_data(icon_data, NULL), g_bytes_get_size(icon_data), "ICON-DATA", 9); g_main_loop_quit(data->loop); } static void test_icon_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); g_autoptr(GBytes) icon_data = g_bytes_new("ICON-DATA", 9); mock_snap_set_icon_data(s, "image/png", icon_data); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_icon_async(client, "snap", NULL, icon_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_icon_not_installed(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdIcon) icon = snapd_client_get_icon_sync(client, "snap", NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_FOUND); g_assert_null(icon); } static void test_icon_large(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); gsize icon_buffer_length = 1048576; g_autofree gchar *icon_buffer = g_malloc(icon_buffer_length); for (gsize i = 0; i < icon_buffer_length; i++) icon_buffer[i] = i % 255; g_autoptr(GBytes) icon_data = g_bytes_new(icon_buffer, icon_buffer_length); mock_snap_set_icon_data(s, "image/png", icon_data); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdIcon) icon = snapd_client_get_icon_sync(client, "snap", NULL, &error); g_assert_no_error(error); g_assert_nonnull(icon); g_assert_cmpstr(snapd_icon_get_mime_type(icon), ==, "image/png"); GBytes *data = snapd_icon_get_data(icon); g_assert_cmpmem(g_bytes_get_data(data, NULL), g_bytes_get_size(data), icon_buffer, icon_buffer_length); } static void test_get_assertions_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_assertion(snapd, "type: account\n" "list-header:\n" " - list-value\n" "map-header:\n" " map-value: foo\n" "\n" "SIGNATURE"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_auto(GStrv) assertions = snapd_client_get_assertions_sync(client, "account", NULL, &error); g_assert_no_error(error); g_assert_nonnull(assertions); g_assert_cmpint(g_strv_length(assertions), ==, 1); g_assert_cmpstr(assertions[0], ==, "type: account\n" "list-header:\n" " - list-value\n" "map-header:\n" " map-value: foo\n" "\n" "SIGNATURE"); } static void test_get_assertions_body(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_assertion(snapd, "type: account\n" "body-length: 4\n" "\n" "BODY\n" "\n" "SIGNATURE"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_auto(GStrv) assertions = snapd_client_get_assertions_sync(client, "account", NULL, &error); g_assert_no_error(error); g_assert_nonnull(assertions); g_assert_cmpint(g_strv_length(assertions), ==, 1); g_assert_cmpstr(assertions[0], ==, "type: account\n" "body-length: 4\n" "\n" "BODY\n" "\n" "SIGNATURE"); } static void test_get_assertions_multiple(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_assertion(snapd, "type: account\n" "\n" "SIGNATURE1\n" "\n" "type: account\n" "body-length: 4\n" "\n" "BODY\n" "\n" "SIGNATURE2\n" "\n" "type: account\n" "\n" "SIGNATURE3"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_auto(GStrv) assertions = snapd_client_get_assertions_sync(client, "account", NULL, &error); g_assert_no_error(error); g_assert_nonnull(assertions); g_assert_cmpint(g_strv_length(assertions), ==, 3); g_assert_cmpstr(assertions[0], ==, "type: account\n" "\n" "SIGNATURE1"); g_assert_cmpstr(assertions[1], ==, "type: account\n" "body-length: 4\n" "\n" "BODY\n" "\n" "SIGNATURE2"); g_assert_cmpstr(assertions[2], ==, "type: account\n" "\n" "SIGNATURE3"); } static void test_get_assertions_invalid(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_auto(GStrv) assertions = snapd_client_get_assertions_sync(client, "account", NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_REQUEST); g_assert_null(assertions); } static void test_add_assertions_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_get_assertions(snapd)); gchar *assertions[2]; assertions[0] = "type: account\n" "\n" "SIGNATURE"; assertions[1] = NULL; gboolean result = snapd_client_add_assertions_sync(client, assertions, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_cmpint(g_list_length(mock_snapd_get_assertions(snapd)), ==, 1); g_assert_cmpstr(mock_snapd_get_assertions(snapd)->data, ==, "type: account\n\nSIGNATURE"); } static void test_assertions_sync(void) { g_autoptr(SnapdAssertion) assertion = snapd_assertion_new("type: account\n" "authority-id: canonical\n" "\n" "SIGNATURE"); g_auto(GStrv) headers = snapd_assertion_get_headers(assertion); g_assert_cmpint(g_strv_length(headers), ==, 2); g_assert_cmpstr(headers[0], ==, "type"); g_autofree gchar *type = snapd_assertion_get_header(assertion, "type"); g_assert_cmpstr(type, ==, "account"); g_assert_cmpstr(headers[1], ==, "authority-id"); g_autofree gchar *authority_id = snapd_assertion_get_header(assertion, "authority-id"); g_assert_cmpstr(authority_id, ==, "canonical"); g_autofree gchar *invalid_header = snapd_assertion_get_header(assertion, "invalid"); g_assert_cmpstr(invalid_header, ==, NULL); g_autofree gchar *body = snapd_assertion_get_body(assertion); g_assert_cmpstr(body, ==, NULL); g_autofree gchar *signature = snapd_assertion_get_signature(assertion); g_assert_cmpstr(signature, ==, "SIGNATURE"); } static void test_assertions_body(void) { g_autoptr(SnapdAssertion) assertion = snapd_assertion_new("type: account\n" "body-length: 4\n" "\n" "BODY\n" "\n" "SIGNATURE"); g_auto(GStrv) headers = snapd_assertion_get_headers(assertion); g_assert_cmpint(g_strv_length(headers), ==, 2); g_assert_cmpstr(headers[0], ==, "type"); g_autofree gchar *type = snapd_assertion_get_header(assertion, "type"); g_assert_cmpstr(type, ==, "account"); g_assert_cmpstr(headers[1], ==, "body-length"); g_autofree gchar *body_length = snapd_assertion_get_header(assertion, "body-length"); g_assert_cmpstr(body_length, ==, "4"); g_autofree gchar *invalid_header = snapd_assertion_get_header(assertion, "invalid"); g_assert_cmpstr(invalid_header, ==, NULL); g_autofree gchar *body = snapd_assertion_get_body(assertion); g_assert_cmpstr(body, ==, "BODY"); g_autofree gchar *signature = snapd_assertion_get_signature(assertion); g_assert_cmpstr(signature, ==, "SIGNATURE"); } static void setup_get_connections(MockSnapd *snapd) { MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *snap1 = mock_snapd_add_snap(snapd, "snap1"); MockSlot *slot1 = mock_snap_add_slot(snap1, i, "slot1"); mock_snap_add_slot(snap1, i, "slot2"); MockSnap *snap2 = mock_snapd_add_snap(snapd, "snap2"); MockPlug *plug = mock_snap_add_plug(snap2, i, "auto-plug"); mock_snapd_connect(snapd, plug, slot1, FALSE, FALSE); plug = mock_snap_add_plug(snap2, i, "manual-plug"); mock_snapd_connect(snapd, plug, slot1, TRUE, FALSE); plug = mock_snap_add_plug(snap2, i, "gadget-plug"); mock_snapd_connect(snapd, plug, slot1, FALSE, TRUE); plug = mock_snap_add_plug(snap2, i, "undesired-plug"); mock_snapd_connect(snapd, plug, slot1, FALSE, FALSE); mock_snapd_connect(snapd, plug, NULL, TRUE, FALSE); } static void check_plug_no_attributes(SnapdPlug *plug) { guint length; g_auto(GStrv) attribute_names = snapd_plug_get_attribute_names(plug, &length); g_assert_cmpint(length, ==, 0); g_assert_cmpint(g_strv_length(attribute_names), ==, 0); } static void check_slot_no_attributes(SnapdSlot *slot) { guint length; g_auto(GStrv) attribute_names = snapd_slot_get_attribute_names(slot, &length); g_assert_cmpint(length, ==, 0); g_assert_cmpint(g_strv_length(attribute_names), ==, 0); } static void check_connection_no_plug_attributes(SnapdConnection *connection) { guint length; g_auto(GStrv) attribute_names = snapd_connection_get_plug_attribute_names(connection, &length); g_assert_cmpint(length, ==, 0); g_assert_cmpint(g_strv_length(attribute_names), ==, 0); } static void check_connection_no_slot_attributes(SnapdConnection *connection) { guint length; g_auto(GStrv) attribute_names = snapd_connection_get_slot_attribute_names(connection, &length); g_assert_cmpint(length, ==, 0); g_assert_cmpint(g_strv_length(attribute_names), ==, 0); } static void check_get_connections_result(GPtrArray *established, GPtrArray *undesired, GPtrArray *plugs, GPtrArray *slots, gboolean select_all) { g_assert_nonnull(established); g_assert_cmpint(established->len, ==, 3); SnapdConnection *connection = established->pdata[0]; g_assert_cmpstr(snapd_connection_get_interface(connection), ==, "interface"); SnapdSlotRef *slot_ref = snapd_connection_get_slot(connection); g_assert_cmpstr(snapd_slot_ref_get_snap(slot_ref), ==, "snap1"); g_assert_cmpstr(snapd_slot_ref_get_slot(slot_ref), ==, "slot1"); SnapdPlugRef *plug_ref = snapd_connection_get_plug(connection); g_assert_cmpstr(snapd_plug_ref_get_snap(plug_ref), ==, "snap2"); g_assert_cmpstr(snapd_plug_ref_get_plug(plug_ref), ==, "auto-plug"); check_connection_no_slot_attributes(connection); check_connection_no_plug_attributes(connection); g_assert_false(snapd_connection_get_manual(connection)); g_assert_false(snapd_connection_get_gadget(connection)); connection = established->pdata[1]; g_assert_cmpstr(snapd_connection_get_interface(connection), ==, "interface"); slot_ref = snapd_connection_get_slot(connection); g_assert_cmpstr(snapd_slot_ref_get_snap(slot_ref), ==, "snap1"); g_assert_cmpstr(snapd_slot_ref_get_slot(slot_ref), ==, "slot1"); plug_ref = snapd_connection_get_plug(connection); g_assert_cmpstr(snapd_plug_ref_get_snap(plug_ref), ==, "snap2"); g_assert_cmpstr(snapd_plug_ref_get_plug(plug_ref), ==, "manual-plug"); check_connection_no_slot_attributes(connection); check_connection_no_plug_attributes(connection); g_assert_true(snapd_connection_get_manual(connection)); g_assert_false(snapd_connection_get_gadget(connection)); connection = established->pdata[2]; g_assert_cmpstr(snapd_connection_get_interface(connection), ==, "interface"); slot_ref = snapd_connection_get_slot(connection); g_assert_cmpstr(snapd_slot_ref_get_snap(slot_ref), ==, "snap1"); g_assert_cmpstr(snapd_slot_ref_get_slot(slot_ref), ==, "slot1"); plug_ref = snapd_connection_get_plug(connection); g_assert_cmpstr(snapd_plug_ref_get_snap(plug_ref), ==, "snap2"); g_assert_cmpstr(snapd_plug_ref_get_plug(plug_ref), ==, "gadget-plug"); check_connection_no_slot_attributes(connection); check_connection_no_plug_attributes(connection); g_assert_false(snapd_connection_get_manual(connection)); g_assert_true(snapd_connection_get_gadget(connection)); g_assert_nonnull(undesired); if (select_all) { g_assert_cmpint(undesired->len, ==, 1); connection = undesired->pdata[0]; g_assert_cmpstr(snapd_connection_get_interface(connection), ==, "interface"); slot_ref = snapd_connection_get_slot(connection); g_assert_cmpstr(snapd_slot_ref_get_snap(slot_ref), ==, "snap1"); g_assert_cmpstr(snapd_slot_ref_get_slot(slot_ref), ==, "slot1"); plug_ref = snapd_connection_get_plug(connection); g_assert_cmpstr(snapd_plug_ref_get_snap(plug_ref), ==, "snap2"); g_assert_cmpstr(snapd_plug_ref_get_plug(plug_ref), ==, "undesired-plug"); check_connection_no_slot_attributes(connection); check_connection_no_plug_attributes(connection); g_assert_true(snapd_connection_get_manual(connection)); g_assert_false(snapd_connection_get_gadget(connection)); } else g_assert_cmpint(undesired->len, ==, 0); g_assert_nonnull(plugs); if (select_all) g_assert_cmpint(plugs->len, ==, 4); else g_assert_cmpint(plugs->len, ==, 3); SnapdPlug *plug = plugs->pdata[0]; g_assert_cmpstr(snapd_plug_get_name(plug), ==, "auto-plug"); g_assert_cmpstr(snapd_plug_get_snap(plug), ==, "snap2"); g_assert_cmpstr(snapd_plug_get_interface(plug), ==, "interface"); check_plug_no_attributes(plug); g_assert_cmpstr(snapd_plug_get_label(plug), ==, "LABEL"); GPtrArray *connected_slots = snapd_plug_get_connected_slots(plug); g_assert_cmpint(connected_slots->len, ==, 1); slot_ref = connected_slots->pdata[0]; g_assert_cmpstr(snapd_slot_ref_get_snap(slot_ref), ==, "snap1"); g_assert_cmpstr(snapd_slot_ref_get_slot(slot_ref), ==, "slot1"); plug = plugs->pdata[1]; g_assert_cmpstr(snapd_plug_get_name(plug), ==, "manual-plug"); g_assert_cmpstr(snapd_plug_get_snap(plug), ==, "snap2"); g_assert_cmpstr(snapd_plug_get_interface(plug), ==, "interface"); check_plug_no_attributes(plug); g_assert_cmpstr(snapd_plug_get_label(plug), ==, "LABEL"); connected_slots = snapd_plug_get_connected_slots(plug); g_assert_cmpint(connected_slots->len, ==, 1); slot_ref = connected_slots->pdata[0]; g_assert_cmpstr(snapd_slot_ref_get_snap(slot_ref), ==, "snap1"); g_assert_cmpstr(snapd_slot_ref_get_slot(slot_ref), ==, "slot1"); plug = plugs->pdata[2]; g_assert_cmpstr(snapd_plug_get_name(plug), ==, "gadget-plug"); g_assert_cmpstr(snapd_plug_get_snap(plug), ==, "snap2"); g_assert_cmpstr(snapd_plug_get_interface(plug), ==, "interface"); check_plug_no_attributes(plug); g_assert_cmpstr(snapd_plug_get_label(plug), ==, "LABEL"); connected_slots = snapd_plug_get_connected_slots(plug); g_assert_cmpint(connected_slots->len, ==, 1); slot_ref = connected_slots->pdata[0]; g_assert_cmpstr(snapd_slot_ref_get_snap(slot_ref), ==, "snap1"); g_assert_cmpstr(snapd_slot_ref_get_slot(slot_ref), ==, "slot1"); if (select_all) { plug = plugs->pdata[3]; g_assert_cmpstr(snapd_plug_get_name(plug), ==, "undesired-plug"); g_assert_cmpstr(snapd_plug_get_snap(plug), ==, "snap2"); g_assert_cmpstr(snapd_plug_get_interface(plug), ==, "interface"); check_plug_no_attributes(plug); g_assert_cmpstr(snapd_plug_get_label(plug), ==, "LABEL"); connected_slots = snapd_plug_get_connected_slots(plug); g_assert_cmpint(connected_slots->len, ==, 0); } g_assert_nonnull(slots); if (select_all) g_assert_cmpint(slots->len, ==, 2); else g_assert_cmpint(slots->len, ==, 1); SnapdSlot *slot = slots->pdata[0]; g_assert_cmpstr(snapd_slot_get_name(slot), ==, "slot1"); g_assert_cmpstr(snapd_slot_get_snap(slot), ==, "snap1"); g_assert_cmpstr(snapd_slot_get_interface(slot), ==, "interface"); check_slot_no_attributes(slot); g_assert_cmpstr(snapd_slot_get_label(slot), ==, "LABEL"); GPtrArray *connected_plugs = snapd_slot_get_connected_plugs(slot); g_assert_cmpint(connected_plugs->len, ==, 3); plug_ref = connected_plugs->pdata[0]; g_assert_cmpstr(snapd_plug_ref_get_snap(plug_ref), ==, "snap2"); g_assert_cmpstr(snapd_plug_ref_get_plug(plug_ref), ==, "auto-plug"); plug_ref = connected_plugs->pdata[1]; g_assert_cmpstr(snapd_plug_ref_get_snap(plug_ref), ==, "snap2"); g_assert_cmpstr(snapd_plug_ref_get_plug(plug_ref), ==, "manual-plug"); plug_ref = connected_plugs->pdata[2]; g_assert_cmpstr(snapd_plug_ref_get_snap(plug_ref), ==, "snap2"); g_assert_cmpstr(snapd_plug_ref_get_plug(plug_ref), ==, "gadget-plug"); if (select_all) { slot = slots->pdata[1]; g_assert_cmpstr(snapd_slot_get_name(slot), ==, "slot2"); g_assert_cmpstr(snapd_slot_get_snap(slot), ==, "snap1"); check_slot_no_attributes(slot); connected_plugs = snapd_slot_get_connected_plugs(slot); g_assert_cmpint(connected_plugs->len, ==, 0); } } static void test_get_connections_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); setup_get_connections(snapd); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) established = NULL; g_autoptr(GPtrArray) undesired = NULL; g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots = NULL; gboolean result = snapd_client_get_connections2_sync( client, SNAPD_GET_CONNECTIONS_FLAGS_NONE, NULL, NULL, &established, &undesired, &plugs, &slots, NULL, &error); g_assert_no_error(error); g_assert_true(result); check_get_connections_result(established, undesired, plugs, slots, FALSE); } static void get_connections_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GPtrArray) established = NULL; g_autoptr(GPtrArray) undesired = NULL; g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots = NULL; g_autoptr(GError) error = NULL; gboolean r = snapd_client_get_connections2_finish( SNAPD_CLIENT(object), result, &established, &undesired, &plugs, &slots, &error); g_assert_no_error(error); g_assert_true(r); check_get_connections_result(established, undesired, plugs, slots, FALSE); g_main_loop_quit(data->loop); } static void test_get_connections_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); setup_get_connections(snapd); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_connections2_async(client, SNAPD_GET_CONNECTIONS_FLAGS_NONE, NULL, NULL, NULL, get_connections_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_get_connections_empty(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) established = NULL; g_autoptr(GPtrArray) undesired = NULL; g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots = NULL; gboolean result = snapd_client_get_connections2_sync( client, SNAPD_GET_CONNECTIONS_FLAGS_NONE, NULL, NULL, &established, &undesired, &plugs, &slots, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(established); g_assert_cmpint(established->len, ==, 0); g_assert_nonnull(undesired); g_assert_cmpint(undesired->len, ==, 0); g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 0); g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 0); } static void test_get_connections_filter_all(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); setup_get_connections(snapd); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) established = NULL; g_autoptr(GPtrArray) undesired = NULL; g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots = NULL; gboolean result = snapd_client_get_connections2_sync( client, SNAPD_GET_CONNECTIONS_FLAGS_SELECT_ALL, NULL, NULL, &established, &undesired, &plugs, &slots, NULL, &error); g_assert_no_error(error); g_assert_true(result); check_get_connections_result(established, undesired, plugs, slots, TRUE); } static void test_get_connections_filter_snap(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *core = mock_snapd_add_snap(snapd, "core"); MockSlot *s = mock_snap_add_slot(core, i, "slot"); MockSnap *snap1 = mock_snapd_add_snap(snapd, "snap1"); MockPlug *plug1 = mock_snap_add_plug(snap1, i, "plug1"); mock_snapd_connect(snapd, plug1, s, FALSE, FALSE); MockSnap *snap2 = mock_snapd_add_snap(snapd, "snap2"); MockPlug *plug2 = mock_snap_add_plug(snap2, i, "plug2"); mock_snapd_connect(snapd, plug2, s, FALSE, FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots = NULL; gboolean result = snapd_client_get_connections2_sync( client, SNAPD_GET_CONNECTIONS_FLAGS_NONE, "snap1", NULL, NULL, NULL, &plugs, &slots, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_cmpint(plugs->len, ==, 1); SnapdPlug *plug = plugs->pdata[0]; g_assert_cmpstr(snapd_plug_get_snap(plug), ==, "snap1"); g_assert_cmpint(slots->len, ==, 1); SnapdSlot *slot = slots->pdata[0]; g_assert_cmpstr(snapd_slot_get_snap(slot), ==, "core"); } static void test_get_connections_filter_interface(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i1 = mock_snapd_add_interface(snapd, "interface1"); MockInterface *i2 = mock_snapd_add_interface(snapd, "interface2"); MockSnap *core = mock_snapd_add_snap(snapd, "core"); MockSlot *slot1 = mock_snap_add_slot(core, i1, "slot1"); MockSlot *slot2 = mock_snap_add_slot(core, i2, "slot2"); MockSnap *snap = mock_snapd_add_snap(snapd, "snap"); MockPlug *plug1 = mock_snap_add_plug(snap, i1, "plug1"); MockPlug *plug2 = mock_snap_add_plug(snap, i2, "plug2"); mock_snapd_connect(snapd, plug1, slot1, FALSE, FALSE); mock_snapd_connect(snapd, plug2, slot2, FALSE, FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots = NULL; gboolean result = snapd_client_get_connections2_sync( client, SNAPD_GET_CONNECTIONS_FLAGS_NONE, NULL, "interface1", NULL, NULL, &plugs, &slots, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_cmpint(plugs->len, ==, 1); SnapdPlug *plug = plugs->pdata[0]; g_assert_cmpstr(snapd_plug_get_snap(plug), ==, "snap"); g_assert_cmpstr(snapd_plug_get_interface(plug), ==, "interface1"); g_assert_cmpint(slots->len, ==, 1); SnapdSlot *slot = slots->pdata[0]; g_assert_cmpstr(snapd_slot_get_snap(slot), ==, "core"); g_assert_cmpstr(snapd_slot_get_interface(slot), ==, "interface1"); } static gint compare_name(gconstpointer a, gconstpointer b) { gchar *name_a = *((gchar **)a); gchar *name_b = *((gchar **)b); return strcmp(name_a, name_b); } static GStrv sort_names(GStrv value) { g_autoptr(GPtrArray) result = g_ptr_array_new(); for (int i = 0; value[i] != NULL; i++) g_ptr_array_add(result, g_strdup(value[i])); g_ptr_array_sort(result, compare_name); g_ptr_array_add(result, NULL); return g_steal_pointer((GStrv *)&result->pdata); } static void check_names_match(GStrv names, guint names_length, const gchar *expected) { g_assert_cmpint(g_strv_length(names), ==, names_length); g_auto(GStrv) expected_names = g_strsplit(expected, ",", -1); g_auto(GStrv) sorted_expected_names = sort_names(expected_names); g_assert_cmpint(g_strv_length(expected_names), ==, names_length); g_auto(GStrv) sorted_names = sort_names(names); for (guint i = 0; i < names_length; i++) g_assert_cmpstr(sorted_names[i], ==, sorted_expected_names[i]); } static void test_get_connections_attributes(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); MockSlot *sl = mock_snap_add_slot(s, i, "slot1"); mock_slot_add_attribute(sl, "slot-string-key", "\"value\""); mock_slot_add_attribute(sl, "slot-int-key", "42"); mock_slot_add_attribute(sl, "slot-bool-key", "true"); mock_slot_add_attribute(sl, "slot-number-key", "1.25"); s = mock_snapd_add_snap(snapd, "snap2"); MockPlug *p = mock_snap_add_plug(s, i, "plug1"); mock_plug_add_attribute(p, "plug-string-key", "\"value\""); mock_plug_add_attribute(p, "plug-int-key", "42"); mock_plug_add_attribute(p, "plug-bool-key", "true"); mock_plug_add_attribute(p, "plug-number-key", "1.25"); mock_snapd_connect(snapd, p, sl, FALSE, FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) established = NULL; g_autoptr(GPtrArray) undesired = NULL; g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots = NULL; gboolean result = snapd_client_get_connections2_sync( client, SNAPD_GET_CONNECTIONS_FLAGS_NONE, NULL, NULL, &established, &undesired, &plugs, &slots, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(established); g_assert_cmpint(established->len, ==, 1); SnapdConnection *connection = established->pdata[0]; guint names_length; g_auto(GStrv) plug_attribute_names = snapd_connection_get_plug_attribute_names(connection, &names_length); check_names_match( plug_attribute_names, names_length, "plug-string-key,plug-int-key,plug-bool-key,plug-number-key"); g_assert_true( snapd_connection_has_plug_attribute(connection, "plug-string-key")); GVariant *value = snapd_connection_get_plug_attribute(connection, "plug-string-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)); g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "value"); g_assert_true( snapd_connection_has_plug_attribute(connection, "plug-int-key")); value = snapd_connection_get_plug_attribute(connection, "plug-int-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_INT64)); g_assert_cmpint(g_variant_get_int64(value), ==, 42); g_assert_true( snapd_connection_has_plug_attribute(connection, "plug-bool-key")); value = snapd_connection_get_plug_attribute(connection, "plug-bool-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)); g_assert_true(g_variant_get_boolean(value)); value = snapd_connection_get_plug_attribute(connection, "plug-number-key"); g_assert_nonnull(value); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_DOUBLE)); g_assert_cmpfloat(g_variant_get_double(value), ==, 1.25); g_assert_false( snapd_connection_has_plug_attribute(connection, "plug-invalid-key")); g_assert_null( snapd_connection_get_plug_attribute(connection, "plug-invalid-key")); g_auto(GStrv) slot_attribute_names = snapd_connection_get_slot_attribute_names(connection, &names_length); check_names_match( slot_attribute_names, names_length, "slot-string-key,slot-int-key,slot-bool-key,slot-number-key"); g_assert_true( snapd_connection_has_slot_attribute(connection, "slot-string-key")); value = snapd_connection_get_slot_attribute(connection, "slot-string-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)); g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "value"); g_assert_true( snapd_connection_has_slot_attribute(connection, "slot-int-key")); value = snapd_connection_get_slot_attribute(connection, "slot-int-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_INT64)); g_assert_cmpint(g_variant_get_int64(value), ==, 42); g_assert_true( snapd_connection_has_slot_attribute(connection, "slot-bool-key")); value = snapd_connection_get_slot_attribute(connection, "slot-bool-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)); value = snapd_connection_get_slot_attribute(connection, "slot-number-key"); g_assert_nonnull(value); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_DOUBLE)); g_assert_cmpfloat(g_variant_get_double(value), ==, 1.25); g_assert_false( snapd_connection_has_slot_attribute(connection, "slot-invalid-key")); g_assert_null( snapd_connection_get_slot_attribute(connection, "slot-invalid-key")); g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 1); SnapdPlug *plug = plugs->pdata[0]; g_auto(GStrv) plug_names = snapd_plug_get_attribute_names(plug, &names_length); check_names_match( plug_names, names_length, "plug-string-key,plug-int-key,plug-bool-key,plug-number-key"); g_assert_true(snapd_plug_has_attribute(plug, "plug-string-key")); value = snapd_plug_get_attribute(plug, "plug-string-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)); g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "value"); g_assert_true(snapd_plug_has_attribute(plug, "plug-int-key")); value = snapd_plug_get_attribute(plug, "plug-int-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_INT64)); g_assert_cmpint(g_variant_get_int64(value), ==, 42); g_assert_true(snapd_plug_has_attribute(plug, "plug-bool-key")); value = snapd_plug_get_attribute(plug, "plug-bool-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)); g_assert_true(g_variant_get_boolean(value)); value = snapd_plug_get_attribute(plug, "plug-number-key"); g_assert_nonnull(value); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_DOUBLE)); g_assert_cmpfloat(g_variant_get_double(value), ==, 1.25); value = snapd_plug_get_attribute(plug, "plug-invalid-key"); g_assert_false(snapd_plug_has_attribute(plug, "plug-invalid-key")); g_assert_null(snapd_plug_get_attribute(plug, "plug-invalid-key")); g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 1); SnapdSlot *slot = slots->pdata[0]; g_auto(GStrv) slot_names = snapd_slot_get_attribute_names(slot, &names_length); check_names_match( slot_names, names_length, "slot-string-key,slot-int-key,slot-bool-key,slot-number-key"); g_assert_true(snapd_slot_has_attribute(slot, "slot-string-key")); value = snapd_slot_get_attribute(slot, "slot-string-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)); g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "value"); g_assert_true(snapd_slot_has_attribute(slot, "slot-int-key")); value = snapd_slot_get_attribute(slot, "slot-int-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_INT64)); g_assert_cmpint(g_variant_get_int64(value), ==, 42); g_assert_true(snapd_slot_has_attribute(slot, "slot-bool-key")); value = snapd_slot_get_attribute(slot, "slot-bool-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)); g_assert_true(g_variant_get_boolean(value)); value = snapd_slot_get_attribute(slot, "slot-number-key"); g_assert_nonnull(value); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_DOUBLE)); g_assert_cmpfloat(g_variant_get_double(value), ==, 1.25); value = snapd_slot_get_attribute(slot, "slot-invalid-key"); g_assert_false(snapd_slot_has_attribute(slot, "slot-invalid-key")); g_assert_null(snapd_slot_get_attribute(slot, "slot-invalid-key")); } static void setup_get_interfaces(MockSnapd *snapd) { MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *snap1 = mock_snapd_add_snap(snapd, "snap1"); MockSlot *slot1 = mock_snap_add_slot(snap1, i, "slot1"); mock_snap_add_slot(snap1, i, "slot2"); MockSnap *snap2 = mock_snapd_add_snap(snapd, "snap2"); MockPlug *plug1 = mock_snap_add_plug(snap2, i, "plug1"); mock_snapd_connect(snapd, plug1, slot1, TRUE, FALSE); } static void check_get_interfaces_result(GPtrArray *plugs, GPtrArray *slots) { g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 1); SnapdPlug *plug = plugs->pdata[0]; g_assert_cmpstr(snapd_plug_get_name(plug), ==, "plug1"); g_assert_cmpstr(snapd_plug_get_snap(plug), ==, "snap2"); g_assert_cmpstr(snapd_plug_get_interface(plug), ==, "interface"); check_plug_no_attributes(plug); g_assert_cmpstr(snapd_plug_get_label(plug), ==, "LABEL"); GPtrArray *connected_slots = snapd_plug_get_connected_slots(plug); g_assert_cmpint(connected_slots->len, ==, 1); SnapdSlotRef *slot_ref = connected_slots->pdata[0]; g_assert_cmpstr(snapd_slot_ref_get_snap(slot_ref), ==, "snap1"); g_assert_cmpstr(snapd_slot_ref_get_slot(slot_ref), ==, "slot1"); g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 2); SnapdSlot *slot = slots->pdata[0]; g_assert_cmpstr(snapd_slot_get_name(slot), ==, "slot1"); g_assert_cmpstr(snapd_slot_get_snap(slot), ==, "snap1"); g_assert_cmpstr(snapd_slot_get_interface(slot), ==, "interface"); check_slot_no_attributes(slot); g_assert_cmpstr(snapd_slot_get_label(slot), ==, "LABEL"); GPtrArray *connected_plugs = snapd_slot_get_connected_plugs(slot); g_assert_cmpint(connected_plugs->len, ==, 1); SnapdPlugRef *plug_ref = connected_plugs->pdata[0]; g_assert_cmpstr(snapd_plug_ref_get_snap(plug_ref), ==, "snap2"); g_assert_cmpstr(snapd_plug_ref_get_plug(plug_ref), ==, "plug1"); slot = slots->pdata[1]; g_assert_cmpstr(snapd_slot_get_name(slot), ==, "slot2"); g_assert_cmpstr(snapd_slot_get_snap(slot), ==, "snap1"); check_slot_no_attributes(slot); connected_plugs = snapd_slot_get_connected_plugs(slot); g_assert_cmpint(connected_plugs->len, ==, 0); } static void test_get_interfaces_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); setup_get_interfaces(snapd); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS gboolean result = snapd_client_get_interfaces_sync(client, &plugs, &slots, NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_true(result); check_get_interfaces_result(plugs, slots); } static void get_interfaces_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots = NULL; g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS gboolean r = snapd_client_get_interfaces_finish(SNAPD_CLIENT(object), result, &plugs, &slots, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_true(r); check_get_interfaces_result(plugs, slots); g_main_loop_quit(data->loop); } static void test_get_interfaces_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); setup_get_interfaces(snapd); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_get_interfaces_async(client, NULL, get_interfaces_cb, async_data_new(loop, snapd)); G_GNUC_END_IGNORE_DEPRECATIONS g_main_loop_run(loop); } static void test_get_interfaces_no_snaps(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS gboolean result = snapd_client_get_interfaces_sync(client, &plugs, &slots, NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 0); g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 0); g_assert_true(result); } static void test_get_interfaces_attributes(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); MockSlot *sl = mock_snap_add_slot(s, i, "slot1"); mock_slot_add_attribute(sl, "slot-string-key", "\"value\""); mock_slot_add_attribute(sl, "slot-int-key", "42"); mock_slot_add_attribute(sl, "slot-bool-key", "true"); s = mock_snapd_add_snap(snapd, "snap2"); MockPlug *p = mock_snap_add_plug(s, i, "plug1"); mock_plug_add_attribute(p, "plug-string-key", "\"value\""); mock_plug_add_attribute(p, "plug-int-key", "42"); mock_plug_add_attribute(p, "plug-bool-key", "true"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS gboolean result = snapd_client_get_interfaces_sync(client, &plugs, &slots, NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 1); SnapdPlug *plug = plugs->pdata[0]; guint names_length; g_auto(GStrv) plug_names = snapd_plug_get_attribute_names(plug, &names_length); check_names_match(plug_names, names_length, "plug-string-key,plug-int-key,plug-bool-key"); g_assert_true(snapd_plug_has_attribute(plug, "plug-string-key")); GVariant *value = snapd_plug_get_attribute(plug, "plug-string-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)); g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "value"); g_assert_true(snapd_plug_has_attribute(plug, "plug-int-key")); value = snapd_plug_get_attribute(plug, "plug-int-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_INT64)); g_assert_cmpint(g_variant_get_int64(value), ==, 42); g_assert_true(snapd_plug_has_attribute(plug, "plug-bool-key")); value = snapd_plug_get_attribute(plug, "plug-bool-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)); g_assert_true(g_variant_get_boolean(value)); value = snapd_plug_get_attribute(plug, "plug-invalid-key"); g_assert_false(snapd_plug_has_attribute(plug, "plug-invalid-key")); g_assert_null(snapd_plug_get_attribute(plug, "plug-invalid-key")); g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 1); SnapdSlot *slot = slots->pdata[0]; g_auto(GStrv) slot_names = snapd_slot_get_attribute_names(slot, &names_length); check_names_match(slot_names, names_length, "slot-string-key,slot-int-key,slot-bool-key"); g_assert_true(snapd_slot_has_attribute(slot, "slot-string-key")); value = snapd_slot_get_attribute(slot, "slot-string-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)); g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "value"); g_assert_true(snapd_slot_has_attribute(slot, "slot-int-key")); value = snapd_slot_get_attribute(slot, "slot-int-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_INT64)); g_assert_cmpint(g_variant_get_int64(value), ==, 42); g_assert_true(snapd_slot_has_attribute(slot, "slot-bool-key")); value = snapd_slot_get_attribute(slot, "slot-bool-key"); g_assert_true(g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)); g_assert_true(g_variant_get_boolean(value)); value = snapd_slot_get_attribute(slot, "slot-invalid-key"); g_assert_false(snapd_slot_has_attribute(slot, "slot-invalid-key")); g_assert_null(snapd_slot_get_attribute(slot, "slot-invalid-key")); } static void test_get_interfaces_legacy(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); MockSlot *sl = mock_snap_add_slot(s, i, "slot1"); mock_snap_add_slot(s, i, "slot2"); s = mock_snapd_add_snap(snapd, "snap2"); MockPlug *p = mock_snap_add_plug(s, i, "plug1"); mock_snapd_connect(snapd, p, sl, TRUE, FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) plugs = NULL; g_autoptr(GPtrArray) slots = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS gboolean result = snapd_client_get_interfaces_sync(client, &plugs, &slots, NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 1); SnapdPlug *plug = plugs->pdata[0]; G_GNUC_BEGIN_IGNORE_DEPRECATIONS GPtrArray *connections = snapd_plug_get_connections(plug); g_assert_cmpint(connections->len, ==, 1); SnapdConnection *connection = connections->pdata[0]; g_assert_cmpstr(snapd_connection_get_snap(connection), ==, "snap1"); g_assert_cmpstr(snapd_connection_get_name(connection), ==, "slot1"); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 2); SnapdSlot *slot = slots->pdata[0]; G_GNUC_BEGIN_IGNORE_DEPRECATIONS connections = snapd_slot_get_connections(slot); g_assert_cmpint(connections->len, ==, 1); connection = connections->pdata[0]; g_assert_cmpstr(snapd_connection_get_snap(connection), ==, "snap2"); g_assert_cmpstr(snapd_connection_get_name(connection), ==, "plug1"); G_GNUC_END_IGNORE_DEPRECATIONS slot = slots->pdata[1]; G_GNUC_BEGIN_IGNORE_DEPRECATIONS connections = snapd_slot_get_connections(slot); g_assert_cmpint(connections->len, ==, 0); G_GNUC_END_IGNORE_DEPRECATIONS } static void test_get_interfaces2_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i1 = mock_snapd_add_interface(snapd, "interface1"); mock_interface_set_summary(i1, "summary1"); mock_interface_set_doc_url(i1, "url1"); MockInterface *i2 = mock_snapd_add_interface(snapd, "interface2"); mock_interface_set_summary(i2, "summary2"); mock_interface_set_doc_url(i2, "url2"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_add_plug(s, i1, "plug1"); mock_snap_add_slot(s, i2, "slot1"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) ifaces = snapd_client_get_interfaces2_sync( client, SNAPD_GET_INTERFACES_FLAGS_NONE, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(ifaces); g_assert_cmpint(ifaces->len, ==, 2); SnapdInterface *iface = ifaces->pdata[0]; g_assert_cmpstr(snapd_interface_get_name(iface), ==, "interface1"); g_assert_cmpstr(snapd_interface_get_summary(iface), ==, "summary1"); g_assert_cmpstr(snapd_interface_get_doc_url(iface), ==, "url1"); GPtrArray *plugs = snapd_interface_get_plugs(iface); GPtrArray *slots = snapd_interface_get_slots(iface); g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 0); g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 0); iface = ifaces->pdata[1]; g_assert_cmpstr(snapd_interface_get_name(iface), ==, "interface2"); g_assert_cmpstr(snapd_interface_get_summary(iface), ==, "summary2"); g_assert_cmpstr(snapd_interface_get_doc_url(iface), ==, "url2"); plugs = snapd_interface_get_plugs(iface); slots = snapd_interface_get_slots(iface); g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 0); g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 0); } static void get_interfaces2_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) ifaces = snapd_client_get_interfaces2_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(ifaces); g_assert_cmpint(ifaces->len, ==, 2); SnapdInterface *iface = ifaces->pdata[0]; g_assert_cmpstr(snapd_interface_get_name(iface), ==, "interface1"); g_assert_cmpstr(snapd_interface_get_summary(iface), ==, "summary1"); g_assert_cmpstr(snapd_interface_get_doc_url(iface), ==, "url1"); GPtrArray *plugs = snapd_interface_get_plugs(iface); GPtrArray *slots = snapd_interface_get_slots(iface); g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 0); g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 0); iface = ifaces->pdata[1]; g_assert_cmpstr(snapd_interface_get_name(iface), ==, "interface2"); g_assert_cmpstr(snapd_interface_get_summary(iface), ==, "summary2"); g_assert_cmpstr(snapd_interface_get_doc_url(iface), ==, "url2"); plugs = snapd_interface_get_plugs(iface); slots = snapd_interface_get_slots(iface); g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 0); g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 0); g_main_loop_quit(data->loop); } static void test_get_interfaces2_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i1 = mock_snapd_add_interface(snapd, "interface1"); mock_interface_set_summary(i1, "summary1"); mock_interface_set_doc_url(i1, "url1"); MockInterface *i2 = mock_snapd_add_interface(snapd, "interface2"); mock_interface_set_summary(i2, "summary2"); mock_interface_set_doc_url(i2, "url2"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_add_plug(s, i1, "plug1"); mock_snap_add_slot(s, i2, "slot1"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_interfaces2_async(client, SNAPD_GET_INTERFACES_FLAGS_NONE, NULL, NULL, get_interfaces2_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_get_interfaces2_only_connected(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i = mock_snapd_add_interface(snapd, "interface1"); mock_snapd_add_interface(snapd, "interface2"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); MockSlot *sl = mock_snap_add_slot(s, i, "slot1"); s = mock_snapd_add_snap(snapd, "snap2"); MockPlug *p = mock_snap_add_plug(s, i, "plug2"); mock_snapd_connect(snapd, p, sl, TRUE, FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) ifaces = snapd_client_get_interfaces2_sync( client, SNAPD_GET_INTERFACES_FLAGS_ONLY_CONNECTED, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(ifaces); g_assert_cmpint(ifaces->len, ==, 1); SnapdInterface *iface = ifaces->pdata[0]; g_assert_cmpstr(snapd_interface_get_name(iface), ==, "interface1"); GPtrArray *plugs = snapd_interface_get_plugs(iface); g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 0); GPtrArray *slots = snapd_interface_get_slots(iface); g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 0); } static void test_get_interfaces2_slots(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_add_slot(s, i, "slot1"); mock_snap_add_plug(s, i, "plug1"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) ifaces = snapd_client_get_interfaces2_sync( client, SNAPD_GET_INTERFACES_FLAGS_INCLUDE_SLOTS, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(ifaces); g_assert_cmpint(ifaces->len, ==, 1); SnapdInterface *iface = ifaces->pdata[0]; GPtrArray *plugs = snapd_interface_get_plugs(iface); g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 0); GPtrArray *slots = snapd_interface_get_slots(iface); g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 1); SnapdSlot *slot = slots->pdata[0]; g_assert_cmpstr(snapd_slot_get_name(slot), ==, "slot1"); g_assert_cmpstr(snapd_slot_get_snap(slot), ==, "snap1"); } static void test_get_interfaces2_plugs(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_add_slot(s, i, "slot1"); mock_snap_add_plug(s, i, "plug1"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) ifaces = snapd_client_get_interfaces2_sync( client, SNAPD_GET_INTERFACES_FLAGS_INCLUDE_PLUGS, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(ifaces); g_assert_cmpint(ifaces->len, ==, 1); SnapdInterface *iface = ifaces->pdata[0]; GPtrArray *plugs = snapd_interface_get_plugs(iface); g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 1); SnapdPlug *plug = plugs->pdata[0]; g_assert_cmpstr(snapd_plug_get_name(plug), ==, "plug1"); g_assert_cmpstr(snapd_plug_get_snap(plug), ==, "snap1"); GPtrArray *slots = snapd_interface_get_slots(iface); g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 0); } static void test_get_interfaces2_filter(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_interface(snapd, "interface1"); mock_snapd_add_interface(snapd, "interface2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gchar *filter_names[] = {"interface2", NULL}; g_autoptr(GPtrArray) ifaces = snapd_client_get_interfaces2_sync( client, SNAPD_GET_INTERFACES_FLAGS_NONE, filter_names, NULL, &error); g_assert_no_error(error); g_assert_nonnull(ifaces); g_assert_cmpint(ifaces->len, ==, 1); SnapdInterface *iface = ifaces->pdata[0]; g_assert_cmpstr(snapd_interface_get_name(iface), ==, "interface2"); GPtrArray *plugs = snapd_interface_get_plugs(iface); g_assert_nonnull(plugs); g_assert_cmpint(plugs->len, ==, 0); GPtrArray *slots = snapd_interface_get_slots(iface); g_assert_nonnull(slots); g_assert_cmpint(slots->len, ==, 0); } static void test_get_interfaces2_make_label(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_interface(snapd, "camera"); MockInterface *i = mock_snapd_add_interface(snapd, "interface-without-translation"); mock_interface_set_summary(i, "SUMMARY"); mock_snapd_add_interface(snapd, "interface-without-summary"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gchar *filter1[] = {"camera", NULL}; g_autoptr(GPtrArray) ifaces1 = snapd_client_get_interfaces2_sync( client, SNAPD_GET_INTERFACES_FLAGS_NONE, filter1, NULL, &error); g_assert_no_error(error); g_assert_nonnull(ifaces1); g_assert_cmpint(ifaces1->len, ==, 1); SnapdInterface *iface1 = ifaces1->pdata[0]; g_autofree gchar *label1 = snapd_interface_make_label(iface1); g_assert_cmpstr(label1, ==, "Use your camera"); // FIXME: Won't work if translated gchar *filter2[] = {"interface-without-translation", NULL}; g_autoptr(GPtrArray) ifaces2 = snapd_client_get_interfaces2_sync( client, SNAPD_GET_INTERFACES_FLAGS_NONE, filter2, NULL, &error); g_assert_no_error(error); g_assert_nonnull(ifaces2); g_assert_cmpint(ifaces2->len, ==, 1); SnapdInterface *iface2 = ifaces2->pdata[0]; g_autofree gchar *label2 = snapd_interface_make_label(iface2); g_assert_cmpstr(label2, ==, "interface-without-translation: SUMMARY"); gchar *filter3[] = {"interface-without-summary", NULL}; g_autoptr(GPtrArray) ifaces3 = snapd_client_get_interfaces2_sync( client, SNAPD_GET_INTERFACES_FLAGS_NONE, filter3, NULL, &error); g_assert_no_error(error); g_assert_nonnull(ifaces3); g_assert_cmpint(ifaces3->len, ==, 1); SnapdInterface *iface3 = ifaces3->pdata[0]; g_autofree gchar *label3 = snapd_interface_make_label(iface3); g_assert_cmpstr(label3, ==, "interface-without-summary"); } static void test_connect_interface_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); MockSlot *slot = mock_snap_add_slot(s, i, "slot"); s = mock_snapd_add_snap(snapd, "snap2"); MockPlug *plug = mock_snap_add_plug(s, i, "plug"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_connect_interface_sync( client, "snap2", "plug", "snap1", "slot", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_true(mock_snapd_find_plug_connection(snapd, plug) == slot); } static void connect_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; MockSnap *s = mock_snapd_find_snap(data->snapd, "snap1"); MockSlot *slot = mock_snap_find_slot(s, "slot"); s = mock_snapd_find_snap(data->snapd, "snap2"); MockPlug *plug = mock_snap_find_plug(s, "plug"); g_autoptr(GError) error = NULL; gboolean r = snapd_client_connect_interface_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_assert_true(mock_snapd_find_plug_connection(data->snapd, plug) == slot); g_main_loop_quit(data->loop); } static void test_connect_interface_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_add_slot(s, i, "slot"); s = mock_snapd_add_snap(snapd, "snap2"); mock_snap_add_plug(s, i, "plug"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_connect_interface_async(client, "snap2", "plug", "snap1", "slot", NULL, NULL, NULL, connect_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } typedef struct { int progress_done; } ConnectInterfaceProgressData; static void connect_interface_progress_cb(SnapdClient *client, SnapdChange *change, gpointer deprecated, gpointer user_data) { ConnectInterfaceProgressData *data = user_data; data->progress_done++; } static void test_connect_interface_progress(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); MockSlot *slot = mock_snap_add_slot(s, i, "slot"); s = mock_snapd_add_snap(snapd, "snap2"); MockPlug *plug = mock_snap_add_plug(s, i, "plug"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); ConnectInterfaceProgressData connect_interface_progress_data; connect_interface_progress_data.progress_done = 0; gboolean result = snapd_client_connect_interface_sync( client, "snap2", "plug", "snap1", "slot", connect_interface_progress_cb, &connect_interface_progress_data, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_true(mock_snapd_find_plug_connection(snapd, plug) == slot); g_assert_cmpint(connect_interface_progress_data.progress_done, >, 0); } static void test_connect_interface_invalid(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_connect_interface_sync( client, "snap2", "plug", "snap1", "slot", NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_REQUEST); g_assert_false(result); } static void test_disconnect_interface_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); MockSlot *slot = mock_snap_add_slot(s, i, "slot"); s = mock_snapd_add_snap(snapd, "snap2"); MockPlug *plug = mock_snap_add_plug(s, i, "plug"); mock_snapd_connect(snapd, plug, slot, TRUE, FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_disconnect_interface_sync( client, "snap2", "plug", "snap1", "slot", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_null(mock_snapd_find_plug_connection(snapd, plug)); } static void disconnect_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; MockSnap *s = mock_snapd_find_snap(data->snapd, "snap2"); MockPlug *plug = mock_snap_find_plug(s, "plug"); g_autoptr(GError) error = NULL; gboolean r = snapd_client_connect_interface_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_assert_null(mock_snapd_find_plug_connection(data->snapd, plug)); g_main_loop_quit(data->loop); } static void test_disconnect_interface_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); MockSlot *slot = mock_snap_add_slot(s, i, "slot"); s = mock_snapd_add_snap(snapd, "snap2"); MockPlug *plug = mock_snap_add_plug(s, i, "plug"); mock_snapd_connect(snapd, plug, slot, TRUE, FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_disconnect_interface_async( client, "snap2", "plug", "snap1", "slot", NULL, NULL, NULL, disconnect_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } typedef struct { int progress_done; } DisconnectInterfaceProgressData; static void disconnect_interface_progress_cb(SnapdClient *client, SnapdChange *change, gpointer deprecated, gpointer user_data) { DisconnectInterfaceProgressData *data = user_data; data->progress_done++; } static void test_disconnect_interface_progress(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockInterface *i = mock_snapd_add_interface(snapd, "interface"); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); MockSlot *slot = mock_snap_add_slot(s, i, "slot"); s = mock_snapd_add_snap(snapd, "snap2"); MockPlug *plug = mock_snap_add_plug(s, i, "plug"); mock_snapd_connect(snapd, plug, slot, TRUE, FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); DisconnectInterfaceProgressData disconnect_interface_progress_data; disconnect_interface_progress_data.progress_done = 0; gboolean result = snapd_client_disconnect_interface_sync( client, "snap2", "plug", "snap1", "slot", disconnect_interface_progress_cb, &disconnect_interface_progress_data, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_null(mock_snapd_find_plug_connection(snapd, plug)); g_assert_cmpint(disconnect_interface_progress_data.progress_done, >, 0); } static void test_disconnect_interface_invalid(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_disconnect_interface_sync( client, "snap2", "plug", "snap1", "slot", NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_REQUEST); g_assert_false(result); } static void test_find_query(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_suggested_currency(snapd, "NZD"); mock_snapd_add_store_snap(snapd, "apple"); mock_snapd_add_store_snap(snapd, "banana"); MockSnap *s = mock_snapd_add_store_snap(snapd, "carrot1"); mock_track_add_channel(mock_snap_add_track(s, "latest"), "stable", NULL); s = mock_snapd_add_store_snap(snapd, "carrot2"); mock_track_add_channel(mock_snap_add_track(s, "latest"), "stable", NULL); mock_snap_set_channel(s, "CHANNEL"); mock_snap_set_contact(s, "CONTACT"); mock_snap_set_website(s, "WEBSITE"); mock_snap_set_description(s, "DESCRIPTION"); mock_snap_set_store_url(s, "https://snapcraft.io/snap"); mock_snap_set_summary(s, "SUMMARY"); mock_snap_set_download_size(s, 1024); mock_snap_add_price(s, 1.25, "NZD"); mock_snap_add_price(s, 0.75, "USD"); mock_snap_add_media(s, "screenshot", "screenshot0.png", 0, 0); mock_snap_add_media(s, "screenshot", "screenshot1.png", 1024, 1024); mock_snap_add_media(s, "banner", "banner.png", 0, 0); mock_snap_set_trymode(s, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autofree gchar *suggested_currency = NULL; g_autoptr(GPtrArray) snaps = snapd_client_find_sync(client, SNAPD_FIND_FLAGS_NONE, "carrot", &suggested_currency, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 2); g_assert_cmpstr(suggested_currency, ==, "NZD"); SnapdSnap *snap = snaps->pdata[0]; g_assert_cmpstr(snapd_snap_get_name(snap), ==, "carrot1"); g_assert_null(snapd_snap_get_channel(snap)); GStrv tracks = snapd_snap_get_tracks(snap); g_assert_cmpint(g_strv_length(tracks), ==, 1); g_assert_cmpstr(tracks[0], ==, "latest"); GPtrArray *channels = snapd_snap_get_channels(snap); g_assert_cmpint(channels->len, ==, 1); SnapdChannel *channel = channels->pdata[0]; g_assert_cmpstr(snapd_channel_get_name(channel), ==, "stable"); g_assert_cmpint(snapd_channel_get_confinement(channel), ==, SNAPD_CONFINEMENT_STRICT); g_assert_cmpstr(snapd_channel_get_revision(channel), ==, "REVISION"); g_assert_cmpstr(snapd_channel_get_version(channel), ==, "VERSION"); g_assert_cmpstr(snapd_channel_get_epoch(channel), ==, "0"); g_assert_cmpint(snapd_channel_get_size(channel), ==, 65535); g_assert_null(snapd_snap_get_contact(snap)); g_assert_null(snapd_snap_get_description(snap)); g_assert_null(snapd_snap_get_store_url(snap)); g_assert_null(snapd_snap_get_summary(snap)); snap = snaps->pdata[1]; g_assert_cmpstr(snapd_snap_get_channel(snap), ==, "CHANNEL"); g_assert_cmpint(snapd_snap_get_confinement(snap), ==, SNAPD_CONFINEMENT_STRICT); g_assert_cmpstr(snapd_snap_get_contact(snap), ==, "CONTACT"); g_assert_cmpstr(snapd_snap_get_description(snap), ==, "DESCRIPTION"); g_assert_cmpstr(snapd_snap_get_publisher_display_name(snap), ==, "PUBLISHER-DISPLAY-NAME"); g_assert_cmpstr(snapd_snap_get_publisher_id(snap), ==, "PUBLISHER-ID"); g_assert_cmpstr(snapd_snap_get_publisher_username(snap), ==, "PUBLISHER-USERNAME"); g_assert_cmpint(snapd_snap_get_publisher_validation(snap), ==, SNAPD_PUBLISHER_VALIDATION_UNKNOWN); g_assert_cmpint(snapd_snap_get_download_size(snap), ==, 1024); g_assert_null(snapd_snap_get_hold(snap)); g_assert_cmpstr(snapd_snap_get_icon(snap), ==, "ICON"); g_assert_cmpstr(snapd_snap_get_id(snap), ==, "ID"); g_assert_null(snapd_snap_get_install_date(snap)); g_assert_cmpint(snapd_snap_get_installed_size(snap), ==, 0); GPtrArray *media = snapd_snap_get_media(snap); g_assert_cmpint(media->len, ==, 3); g_assert_cmpstr(snapd_media_get_media_type(media->pdata[0]), ==, "screenshot"); g_assert_cmpstr(snapd_media_get_url(media->pdata[0]), ==, "screenshot0.png"); g_assert_cmpstr(snapd_media_get_media_type(media->pdata[1]), ==, "screenshot"); g_assert_cmpstr(snapd_media_get_url(media->pdata[1]), ==, "screenshot1.png"); g_assert_cmpint(snapd_media_get_width(media->pdata[1]), ==, 1024); g_assert_cmpint(snapd_media_get_height(media->pdata[1]), ==, 1024); g_assert_cmpstr(snapd_media_get_media_type(media->pdata[2]), ==, "banner"); g_assert_cmpstr(snapd_media_get_url(media->pdata[2]), ==, "banner.png"); g_assert_cmpstr(snapd_snap_get_name(snap), ==, "carrot2"); GPtrArray *prices = snapd_snap_get_prices(snap); g_assert_cmpint(prices->len, ==, 2); g_assert_cmpfloat(snapd_price_get_amount(prices->pdata[0]), ==, 1.25); g_assert_cmpstr(snapd_price_get_currency(prices->pdata[0]), ==, "NZD"); g_assert_cmpfloat(snapd_price_get_amount(prices->pdata[1]), ==, 0.75); g_assert_cmpstr(snapd_price_get_currency(prices->pdata[1]), ==, "USD"); g_assert_false(snapd_snap_get_private(snap)); g_assert_cmpstr(snapd_snap_get_revision(snap), ==, "REVISION"); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_assert_cmpint(snapd_snap_get_screenshots(snap)->len, ==, 0); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_cmpint(snapd_snap_get_snap_type(snap), ==, SNAPD_SNAP_TYPE_APP); g_assert_cmpint(snapd_snap_get_status(snap), ==, SNAPD_SNAP_STATUS_ACTIVE); g_assert_cmpstr(snapd_snap_get_store_url(snap), ==, "https://snapcraft.io/snap"); g_assert_cmpstr(snapd_snap_get_summary(snap), ==, "SUMMARY"); g_assert_true(snapd_snap_get_trymode(snap)); g_assert_cmpstr(snapd_snap_get_version(snap), ==, "VERSION"); g_assert_cmpstr(snapd_snap_get_website(snap), ==, "WEBSITE"); } static void test_find_query_private(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_snapd_add_store_snap(snapd, "snap1"); mock_account_add_private_snap(a, "snap2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(user_information); snapd_client_set_auth_data( client, snapd_user_information_get_auth_data(user_information)); g_autoptr(GPtrArray) snaps = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_SELECT_PRIVATE, "snap", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 1); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap2"); g_assert_true(snapd_snap_get_private(snaps->pdata[0])); } static void test_find_query_private_not_logged_in(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_SELECT_PRIVATE, "snap", NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_AUTH_DATA_REQUIRED); g_assert_null(snaps); } static void test_find_bad_query(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); // '?' is not allowed in queries g_autoptr(GPtrArray) snaps = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_NONE, "snap?", NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_QUERY); g_assert_null(snaps); } static void test_find_network_timeout(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_NONE, "network-timeout", NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NETWORK_TIMEOUT); g_assert_null(snaps); } static void test_find_dns_failure(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_NONE, "dns-failure", NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_DNS_FAILURE); g_assert_null(snaps); } static void test_find_name(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); mock_snapd_add_store_snap(snapd, "snap2"); mock_snapd_add_store_snap(snapd, "snap3"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_MATCH_NAME, "snap", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 1); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap"); } static void test_find_name_private(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_account_add_private_snap(a, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(user_information); snapd_client_set_auth_data( client, snapd_user_information_get_auth_data(user_information)); g_autoptr(GPtrArray) snaps = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_MATCH_NAME | SNAPD_FIND_FLAGS_SELECT_PRIVATE, "snap", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 1); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap"); g_assert_true(snapd_snap_get_private(snaps->pdata[0])); } static void test_find_name_private_not_logged_in(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_MATCH_NAME | SNAPD_FIND_FLAGS_SELECT_PRIVATE, "snap", NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_AUTH_DATA_REQUIRED); g_assert_null(snaps); } static void test_find_channels(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); MockTrack *t = mock_snap_add_track(s, "latest"); mock_track_add_channel(t, "stable", NULL); MockChannel *c = mock_track_add_channel(t, "beta", NULL); mock_channel_set_revision(c, "BETA-REVISION"); mock_channel_set_version(c, "BETA-VERSION"); mock_channel_set_epoch(c, "1"); mock_channel_set_confinement(c, "classic"); mock_channel_set_size(c, 10000); mock_channel_set_released_at(c, "2018-01-19T13:14:15Z"); c = mock_track_add_channel(t, "stable", "branch"); t = mock_snap_add_track(s, "insider"); mock_track_add_channel(t, "stable", NULL); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_MATCH_NAME, "snap", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 1); SnapdSnap *snap = snaps->pdata[0]; g_assert_cmpstr(snapd_snap_get_name(snap), ==, "snap"); GStrv tracks = snapd_snap_get_tracks(snap); g_assert_cmpint(g_strv_length(tracks), ==, 2); g_assert_cmpstr(tracks[0], ==, "latest"); g_assert_cmpstr(tracks[1], ==, "insider"); GPtrArray *channels = snapd_snap_get_channels(snap); g_assert_cmpint(channels->len, ==, 4); gboolean matched_stable = FALSE, matched_beta = FALSE, matched_branch = FALSE, matched_track = FALSE; for (guint i = 0; i < channels->len; i++) { SnapdChannel *channel = channels->pdata[i]; if (strcmp(snapd_channel_get_name(channel), "stable") == 0) { g_assert_cmpstr(snapd_channel_get_track(channel), ==, "latest"); g_assert_cmpstr(snapd_channel_get_risk(channel), ==, "stable"); g_assert_null(snapd_channel_get_branch(channel)); g_assert_cmpstr(snapd_channel_get_revision(channel), ==, "REVISION"); g_assert_cmpstr(snapd_channel_get_version(channel), ==, "VERSION"); g_assert_cmpstr(snapd_channel_get_epoch(channel), ==, "0"); g_assert_cmpint(snapd_channel_get_confinement(channel), ==, SNAPD_CONFINEMENT_STRICT); g_assert_cmpint(snapd_channel_get_size(channel), ==, 65535); g_assert_null(snapd_channel_get_released_at(channel)); matched_stable = TRUE; } if (strcmp(snapd_channel_get_name(channel), "beta") == 0) { g_assert_cmpstr(snapd_channel_get_track(channel), ==, "latest"); g_assert_cmpstr(snapd_channel_get_risk(channel), ==, "beta"); g_assert_null(snapd_channel_get_branch(channel)); g_assert_cmpstr(snapd_channel_get_revision(channel), ==, "BETA-REVISION"); g_assert_cmpstr(snapd_channel_get_version(channel), ==, "BETA-VERSION"); g_assert_cmpstr(snapd_channel_get_epoch(channel), ==, "1"); g_assert_cmpint(snapd_channel_get_confinement(channel), ==, SNAPD_CONFINEMENT_CLASSIC); g_assert_cmpint(snapd_channel_get_size(channel), ==, 10000); g_assert_true(date_matches(snapd_channel_get_released_at(channel), 2018, 1, 19, 13, 14, 15)); matched_beta = TRUE; } if (strcmp(snapd_channel_get_name(channel), "stable/branch") == 0) { g_assert_cmpstr(snapd_channel_get_track(channel), ==, "latest"); g_assert_cmpstr(snapd_channel_get_risk(channel), ==, "stable"); g_assert_cmpstr(snapd_channel_get_branch(channel), ==, "branch"); g_assert_null(snapd_channel_get_released_at(channel)); matched_branch = TRUE; } if (strcmp(snapd_channel_get_name(channel), "insider/stable") == 0) { g_assert_cmpstr(snapd_channel_get_track(channel), ==, "insider"); g_assert_cmpstr(snapd_channel_get_risk(channel), ==, "stable"); g_assert_null(snapd_channel_get_branch(channel)); g_assert_null(snapd_channel_get_released_at(channel)); matched_track = TRUE; } } g_assert_true(matched_stable); g_assert_true(matched_beta); g_assert_true(matched_branch); g_assert_true(matched_track); } static void test_find_channels_match(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "stable-snap"); MockTrack *t = mock_snap_add_track(s, "latest"); mock_track_add_channel(t, "stable", NULL); s = mock_snapd_add_store_snap(snapd, "full-snap"); t = mock_snap_add_track(s, "latest"); mock_track_add_channel(t, "stable", NULL); mock_track_add_channel(t, "candidate", NULL); mock_track_add_channel(t, "beta", NULL); mock_track_add_channel(t, "edge", NULL); s = mock_snapd_add_store_snap(snapd, "beta-snap"); t = mock_snap_add_track(s, "latest"); mock_track_add_channel(t, "beta", NULL); s = mock_snapd_add_store_snap(snapd, "branch-snap"); t = mock_snap_add_track(s, "latest"); mock_track_add_channel(t, "stable", NULL); mock_track_add_channel(t, "stable", "branch"); s = mock_snapd_add_store_snap(snapd, "track-snap"); t = mock_snap_add_track(s, "latest"); mock_track_add_channel(t, "stable", NULL); t = mock_snap_add_track(s, "insider"); mock_track_add_channel(t, "stable", NULL); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); /* All channels match to stable if only stable defined */ g_autoptr(GPtrArray) snaps1 = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_MATCH_NAME, "stable-snap", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps1); g_assert_cmpint(snaps1->len, ==, 1); SnapdSnap *snap = snaps1->pdata[0]; g_assert_cmpstr(snapd_snap_get_name(snap), ==, "stable-snap"); SnapdChannel *channel = snapd_snap_match_channel(snap, "stable"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "stable"); channel = snapd_snap_match_channel(snap, "candidate"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "stable"); channel = snapd_snap_match_channel(snap, "beta"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "stable"); channel = snapd_snap_match_channel(snap, "edge"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "stable"); channel = snapd_snap_match_channel(snap, "UNDEFINED"); g_assert_null(channel); /* All channels match if all defined */ g_autoptr(GPtrArray) snaps2 = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_MATCH_NAME, "full-snap", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps2); g_assert_cmpint(snaps2->len, ==, 1); snap = snaps2->pdata[0]; g_assert_cmpstr(snapd_snap_get_name(snap), ==, "full-snap"); channel = snapd_snap_match_channel(snap, "stable"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "stable"); channel = snapd_snap_match_channel(snap, "candidate"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "candidate"); channel = snapd_snap_match_channel(snap, "beta"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "beta"); channel = snapd_snap_match_channel(snap, "edge"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "edge"); channel = snapd_snap_match_channel(snap, "UNDEFINED"); g_assert_null(channel); /* Only match with more stable channels */ g_autoptr(GPtrArray) snaps3 = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_MATCH_NAME, "beta-snap", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps3); g_assert_cmpint(snaps3->len, ==, 1); snap = snaps3->pdata[0]; g_assert_cmpstr(snapd_snap_get_name(snap), ==, "beta-snap"); channel = snapd_snap_match_channel(snap, "stable"); g_assert_null(channel); channel = snapd_snap_match_channel(snap, "candidate"); g_assert_null(channel); channel = snapd_snap_match_channel(snap, "beta"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "beta"); channel = snapd_snap_match_channel(snap, "edge"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "beta"); channel = snapd_snap_match_channel(snap, "UNDEFINED"); g_assert_null(channel); /* Match branches */ g_autoptr(GPtrArray) snaps4 = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_MATCH_NAME, "branch-snap", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps4); g_assert_cmpint(snaps4->len, ==, 1); snap = snaps4->pdata[0]; g_assert_cmpstr(snapd_snap_get_name(snap), ==, "branch-snap"); channel = snapd_snap_match_channel(snap, "stable"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "stable"); channel = snapd_snap_match_channel(snap, "stable/branch"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "stable/branch"); channel = snapd_snap_match_channel(snap, "candidate"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "stable"); channel = snapd_snap_match_channel(snap, "beta"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "stable"); channel = snapd_snap_match_channel(snap, "edge"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "stable"); channel = snapd_snap_match_channel(snap, "UNDEFINED"); g_assert_null(channel); /* Match correct tracks */ g_autoptr(GPtrArray) snaps5 = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_MATCH_NAME, "track-snap", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps5); g_assert_cmpint(snaps5->len, ==, 1); snap = snaps5->pdata[0]; g_assert_cmpstr(snapd_snap_get_name(snap), ==, "track-snap"); channel = snapd_snap_match_channel(snap, "stable"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "stable"); g_assert_cmpstr(snapd_channel_get_track(channel), ==, "latest"); g_assert_cmpstr(snapd_channel_get_risk(channel), ==, "stable"); channel = snapd_snap_match_channel(snap, "latest/stable"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "stable"); g_assert_cmpstr(snapd_channel_get_track(channel), ==, "latest"); g_assert_cmpstr(snapd_channel_get_risk(channel), ==, "stable"); channel = snapd_snap_match_channel(snap, "insider/stable"); g_assert_nonnull(channel); g_assert_cmpstr(snapd_channel_get_name(channel), ==, "insider/stable"); g_assert_cmpstr(snapd_channel_get_track(channel), ==, "insider"); g_assert_cmpstr(snapd_channel_get_risk(channel), ==, "stable"); } static gboolean cancel_cb(gpointer user_data) { GCancellable *cancellable = user_data; g_cancellable_cancel(cancellable); return G_SOURCE_REMOVE; } static void find_cancel_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) snaps = snapd_client_find_finish(SNAPD_CLIENT(object), result, NULL, &error); g_assert_error(error, G_IO_ERROR, G_IO_ERROR_CANCELLED); g_assert_null(snaps); g_main_loop_quit(data->loop); } static void test_find_cancel(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); /* Use a special query that never responds */ g_autoptr(GCancellable) cancellable = g_cancellable_new(); snapd_client_find_async(client, SNAPD_FIND_FLAGS_NONE, "do-not-respond", cancellable, find_cancel_cb, async_data_new(loop, snapd)); g_idle_add(cancel_cb, cancellable); g_main_loop_run(loop); } static void test_find_section(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "apple"); mock_snap_add_store_category(s, "section", FALSE); mock_snapd_add_store_snap(snapd, "banana"); s = mock_snapd_add_store_snap(snapd, "carrot1"); mock_snap_add_store_category(s, "section", FALSE); mock_snapd_add_store_snap(snapd, "carrot2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_autoptr(GPtrArray) snaps = snapd_client_find_section_sync( client, SNAPD_FIND_FLAGS_NONE, "section", NULL, NULL, NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 2); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "apple"); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[1]), ==, "carrot1"); } static void test_find_section_query(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "apple"); mock_snap_add_store_category(s, "section", FALSE); mock_snapd_add_store_snap(snapd, "banana"); s = mock_snapd_add_store_snap(snapd, "carrot1"); mock_snap_add_store_category(s, "section", FALSE); mock_snapd_add_store_snap(snapd, "carrot2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_autoptr(GPtrArray) snaps = snapd_client_find_section_sync( client, SNAPD_FIND_FLAGS_NONE, "section", "carrot", NULL, NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 1); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "carrot1"); } static void test_find_section_name(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "apple"); mock_snap_add_store_category(s, "section", FALSE); mock_snapd_add_store_snap(snapd, "banana"); s = mock_snapd_add_store_snap(snapd, "carrot1"); mock_snap_add_store_category(s, "section", FALSE); s = mock_snapd_add_store_snap(snapd, "carrot2"); mock_snap_add_store_category(s, "section", FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_autoptr(GPtrArray) snaps = snapd_client_find_section_sync(client, SNAPD_FIND_FLAGS_MATCH_NAME, "section", "carrot1", NULL, NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 1); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "carrot1"); } static void test_find_category(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "apple"); mock_snap_add_store_category(s, "category", FALSE); mock_snapd_add_store_snap(snapd, "banana"); s = mock_snapd_add_store_snap(snapd, "carrot1"); mock_snap_add_store_category(s, "category", FALSE); mock_snapd_add_store_snap(snapd, "carrot2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_category_sync( client, SNAPD_FIND_FLAGS_NONE, "category", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 2); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "apple"); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[1]), ==, "carrot1"); } static void test_find_category_query(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "apple"); mock_snap_add_store_category(s, "category", FALSE); mock_snapd_add_store_snap(snapd, "banana"); s = mock_snapd_add_store_snap(snapd, "carrot1"); mock_snap_add_store_category(s, "category", FALSE); mock_snapd_add_store_snap(snapd, "carrot2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_category_sync( client, SNAPD_FIND_FLAGS_NONE, "category", "carrot", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 1); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "carrot1"); } static void test_find_category_name(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "apple"); mock_snap_add_store_category(s, "category", FALSE); mock_snapd_add_store_snap(snapd, "banana"); s = mock_snapd_add_store_snap(snapd, "carrot1"); mock_snap_add_store_category(s, "category", FALSE); s = mock_snapd_add_store_snap(snapd, "carrot2"); mock_snap_add_store_category(s, "category", FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_category_sync( client, SNAPD_FIND_FLAGS_MATCH_NAME, "category", "carrot1", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 1); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "carrot1"); } static void test_find_scope_narrow(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap1"); s = mock_snapd_add_store_snap(snapd, "snap2"); mock_snap_set_scope_is_wide(s, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_NONE, "snap", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 1); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap1"); } static void test_find_scope_wide(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap1"); s = mock_snapd_add_store_snap(snapd, "snap2"); mock_snap_set_scope_is_wide(s, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_SCOPE_WIDE, "snap", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 2); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap1"); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[1]), ==, "snap2"); } static void test_find_common_id(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap1"); MockApp *a = mock_snap_add_app(s, "snap1"); mock_app_set_common_id(a, "com.example.snap1"); s = mock_snapd_add_store_snap(snapd, "snap2"); a = mock_snap_add_app(s, "snap2"); mock_app_set_common_id(a, "com.example.snap2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_sync(client, SNAPD_FIND_FLAGS_MATCH_COMMON_ID, "com.example.snap2", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 1); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap2"); } static void test_find_categories(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "apple"); mock_snap_add_category(s, "fruit", TRUE); mock_snap_add_category(s, "food", FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_sync( client, SNAPD_FIND_FLAGS_MATCH_NAME, "apple", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 1); SnapdSnap *snap = snaps->pdata[0]; g_assert_cmpint(snapd_snap_get_categories(snap)->len, ==, 2); SnapdCategory *category = snapd_snap_get_categories(snap)->pdata[0]; g_assert_cmpstr(snapd_category_get_name(category), ==, "fruit"); g_assert_true(snapd_category_get_featured(category)); category = snapd_snap_get_categories(snap)->pdata[1]; g_assert_cmpstr(snapd_category_get_name(category), ==, "food"); g_assert_false(snapd_category_get_featured(category)); } static void test_find_refreshable_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_snap(snapd, "snap2"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_snap(snapd, "snap3"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_store_snap(snapd, "snap1"); mock_snap_set_revision(s, "1"); s = mock_snapd_add_store_snap(snapd, "snap3"); mock_snap_set_revision(s, "1"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_refreshable_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 2); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap1"); g_assert_cmpstr(snapd_snap_get_revision(snaps->pdata[0]), ==, "1"); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[1]), ==, "snap3"); g_assert_cmpstr(snapd_snap_get_revision(snaps->pdata[1]), ==, "1"); } static void find_refreshable_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) snaps = snapd_client_find_refreshable_finish( SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 2); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[0]), ==, "snap1"); g_assert_cmpstr(snapd_snap_get_revision(snaps->pdata[0]), ==, "1"); g_assert_cmpstr(snapd_snap_get_name(snaps->pdata[1]), ==, "snap3"); g_assert_cmpstr(snapd_snap_get_revision(snaps->pdata[1]), ==, "1"); g_main_loop_quit(data->loop); } static void test_find_refreshable_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_snap(snapd, "snap2"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_snap(snapd, "snap3"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_store_snap(snapd, "snap1"); mock_snap_set_revision(s, "1"); s = mock_snapd_add_store_snap(snapd, "snap3"); mock_snap_set_revision(s, "1"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_find_refreshable_async(client, NULL, find_refreshable_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_find_refreshable_no_updates(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) snaps = snapd_client_find_refreshable_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snaps); g_assert_cmpint(snaps->len, ==, 0); } static void test_install_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_NONE, "snap", NULL, NULL, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap")); g_assert_cmpstr( mock_snap_get_confinement(mock_snapd_find_snap(snapd, "snap")), ==, "strict"); g_assert_false(mock_snap_get_devmode(mock_snapd_find_snap(snapd, "snap"))); g_assert_false(mock_snap_get_dangerous(mock_snapd_find_snap(snapd, "snap"))); g_assert_false(mock_snap_get_jailmode(mock_snapd_find_snap(snapd, "snap"))); } static void test_install_sync_multiple(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap1"); mock_snapd_add_store_snap(snapd, "snap2"); mock_snapd_add_store_snap(snapd, "snap3"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap1")); g_assert_null(mock_snapd_find_snap(snapd, "snap2")); g_assert_null(mock_snapd_find_snap(snapd, "snap3")); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_NONE, "snap1", NULL, NULL, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_NONE, "snap2", NULL, NULL, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_NONE, "snap3", NULL, NULL, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap1")); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap2")); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap3")); } static void install_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_install2_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_assert_nonnull(mock_snapd_find_snap(data->snapd, "snap")); g_assert_cmpstr( mock_snap_get_confinement(mock_snapd_find_snap(data->snapd, "snap")), ==, "strict"); g_assert_false( mock_snap_get_devmode(mock_snapd_find_snap(data->snapd, "snap"))); g_assert_false( mock_snap_get_dangerous(mock_snapd_find_snap(data->snapd, "snap"))); g_assert_false( mock_snap_get_jailmode(mock_snapd_find_snap(data->snapd, "snap"))); g_main_loop_quit(data->loop); } static void test_install_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); snapd_client_install2_async(client, SNAPD_INSTALL_FLAGS_NONE, "snap", NULL, NULL, NULL, NULL, NULL, install_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void install_multiple_cb(GObject *object, GAsyncResult *result, gpointer user_data) { AsyncData *data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_install2_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); data->counter--; if (data->counter == 0) { g_assert_nonnull(mock_snapd_find_snap(data->snapd, "snap1")); g_assert_nonnull(mock_snapd_find_snap(data->snapd, "snap2")); g_assert_nonnull(mock_snapd_find_snap(data->snapd, "snap3")); g_main_loop_quit(data->loop); async_data_free(data); } } static void test_install_async_multiple(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap1"); mock_snapd_add_store_snap(snapd, "snap2"); mock_snapd_add_store_snap(snapd, "snap3"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap1")); g_assert_null(mock_snapd_find_snap(snapd, "snap2")); g_assert_null(mock_snapd_find_snap(snapd, "snap3")); AsyncData *data = async_data_new(loop, snapd); data->counter = 3; snapd_client_install2_async(client, SNAPD_INSTALL_FLAGS_NONE, "snap1", NULL, NULL, NULL, NULL, NULL, install_multiple_cb, data); snapd_client_install2_async(client, SNAPD_INSTALL_FLAGS_NONE, "snap2", NULL, NULL, NULL, NULL, NULL, install_multiple_cb, data); snapd_client_install2_async(client, SNAPD_INSTALL_FLAGS_NONE, "snap3", NULL, NULL, NULL, NULL, NULL, install_multiple_cb, data); g_main_loop_run(loop); } static void install_failure_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_install2_finish(SNAPD_CLIENT(object), result, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_FAILED); g_assert_cmpstr(error->message, ==, "ERROR"); g_assert_false(r); g_assert_null(mock_snapd_find_snap(data->snapd, "snap")); g_main_loop_quit(data->loop); } static void test_install_async_failure(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_error(s, "ERROR"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); snapd_client_install2_async(client, SNAPD_INSTALL_FLAGS_NONE, "snap", NULL, NULL, NULL, NULL, NULL, install_failure_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void install_cancel_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_install2_finish(SNAPD_CLIENT(object), result, &error); g_assert_error(error, G_IO_ERROR, G_IO_ERROR_CANCELLED); g_assert_false(r); g_assert_null(mock_snapd_find_snap(data->snapd, "snap")); g_main_loop_quit(data->loop); } static void test_install_async_cancel(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); g_autoptr(GCancellable) cancellable = g_cancellable_new(); snapd_client_install2_async(client, SNAPD_INSTALL_FLAGS_NONE, "snap", NULL, NULL, NULL, NULL, cancellable, install_cancel_cb, async_data_new(loop, snapd)); g_idle_add(cancel_cb, cancellable); g_main_loop_run(loop); } static void complete_async_multiple_cancel_first(AsyncData *data) { data->counter--; if (data->counter == 0) { g_assert_null(mock_snapd_find_snap(data->snapd, "snap1")); g_assert_nonnull(mock_snapd_find_snap(data->snapd, "snap2")); g_assert_nonnull(mock_snapd_find_snap(data->snapd, "snap3")); g_main_loop_quit(data->loop); async_data_free(data); } } static void install_multiple_cancel_first_snap1_cb(GObject *object, GAsyncResult *result, gpointer user_data) { AsyncData *data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_install2_finish(SNAPD_CLIENT(object), result, &error); g_assert_error(error, G_IO_ERROR, G_IO_ERROR_CANCELLED); g_assert_false(r); g_assert_null(mock_snapd_find_snap(data->snapd, "snap1")); complete_async_multiple_cancel_first(data); } static void install_multiple_cancel_first_cb(GObject *object, GAsyncResult *result, gpointer user_data) { AsyncData *data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_install2_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); complete_async_multiple_cancel_first(data); } static void test_install_async_multiple_cancel_first(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap1"); mock_snapd_add_store_snap(snapd, "snap2"); mock_snapd_add_store_snap(snapd, "snap3"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap1")); g_assert_null(mock_snapd_find_snap(snapd, "snap2")); g_assert_null(mock_snapd_find_snap(snapd, "snap3")); g_autoptr(GCancellable) cancellable = g_cancellable_new(); AsyncData *data = async_data_new(loop, snapd); data->counter = 3; snapd_client_install2_async(client, SNAPD_INSTALL_FLAGS_NONE, "snap1", NULL, NULL, NULL, NULL, cancellable, install_multiple_cancel_first_snap1_cb, data); snapd_client_install2_async(client, SNAPD_INSTALL_FLAGS_NONE, "snap2", NULL, NULL, NULL, NULL, NULL, install_multiple_cancel_first_cb, data); snapd_client_install2_async(client, SNAPD_INSTALL_FLAGS_NONE, "snap3", NULL, NULL, NULL, NULL, NULL, install_multiple_cancel_first_cb, data); g_idle_add(cancel_cb, cancellable); g_main_loop_run(loop); } static void complete_async_multiple_cancel_last(AsyncData *data) { data->counter--; if (data->counter == 0) { g_assert_nonnull(mock_snapd_find_snap(data->snapd, "snap1")); g_assert_nonnull(mock_snapd_find_snap(data->snapd, "snap2")); g_assert_null(mock_snapd_find_snap(data->snapd, "snap3")); g_main_loop_quit(data->loop); async_data_free(data); } } static void install_multiple_cancel_last_snap3_cb(GObject *object, GAsyncResult *result, gpointer user_data) { AsyncData *data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_install2_finish(SNAPD_CLIENT(object), result, &error); g_assert_error(error, G_IO_ERROR, G_IO_ERROR_CANCELLED); g_assert_false(r); g_assert_null(mock_snapd_find_snap(data->snapd, "snap3")); complete_async_multiple_cancel_last(data); } static void install_multiple_cancel_last_cb(GObject *object, GAsyncResult *result, gpointer user_data) { AsyncData *data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_install2_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); complete_async_multiple_cancel_last(data); } static void test_install_async_multiple_cancel_last(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap1"); mock_snapd_add_store_snap(snapd, "snap2"); mock_snapd_add_store_snap(snapd, "snap3"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap1")); g_assert_null(mock_snapd_find_snap(snapd, "snap2")); g_assert_null(mock_snapd_find_snap(snapd, "snap3")); g_autoptr(GCancellable) cancellable = g_cancellable_new(); AsyncData *data = async_data_new(loop, snapd); data->counter = 3; snapd_client_install2_async(client, SNAPD_INSTALL_FLAGS_NONE, "snap1", NULL, NULL, NULL, NULL, NULL, install_multiple_cancel_last_cb, data); snapd_client_install2_async(client, SNAPD_INSTALL_FLAGS_NONE, "snap2", NULL, NULL, NULL, NULL, NULL, install_multiple_cancel_last_cb, data); snapd_client_install2_async(client, SNAPD_INSTALL_FLAGS_NONE, "snap3", NULL, NULL, NULL, NULL, cancellable, install_multiple_cancel_last_snap3_cb, data); g_idle_add(cancel_cb, cancellable); g_main_loop_run(loop); } typedef struct { int progress_done; const gchar *spawn_time; const gchar *ready_time; } InstallProgressData; static gchar *time_to_string(GDateTime *time) { if (time == NULL) return NULL; return g_date_time_format(time, "%FT%H:%M:%S%Z"); } static void install_progress_cb(SnapdClient *client, SnapdChange *change, gpointer deprecated, gpointer user_data) { InstallProgressData *data = user_data; data->progress_done++; // Check we've been notified of all tasks GPtrArray *tasks = snapd_change_get_tasks(change); int progress_done = 0, progress_total = 0; for (guint i = 0; i < tasks->len; i++) { SnapdTask *task = tasks->pdata[i]; progress_done += snapd_task_get_progress_done(task); progress_total += snapd_task_get_progress_total(task); } g_assert_cmpint(data->progress_done, ==, progress_done); g_autofree gchar *spawn_time = time_to_string(snapd_change_get_spawn_time(change)); g_autofree gchar *ready_time = time_to_string(snapd_change_get_ready_time(change)); g_assert_cmpstr(snapd_change_get_kind(change), ==, "KIND"); g_assert_cmpstr(snapd_change_get_summary(change), ==, "SUMMARY"); if (progress_done == progress_total) { g_assert_cmpstr(snapd_change_get_status(change), ==, "Done"); g_assert_true(snapd_change_get_ready(change)); } else { g_assert_cmpstr(snapd_change_get_status(change), ==, "Do"); g_assert_false(snapd_change_get_ready(change)); } g_assert_cmpstr(spawn_time, ==, data->spawn_time); if (snapd_change_get_ready(change)) g_assert_cmpstr(ready_time, ==, data->ready_time); else g_assert_null(ready_time); } static void test_install_progress(void) { InstallProgressData install_progress_data; install_progress_data.progress_done = 0; install_progress_data.spawn_time = "2017-01-02T11:23:58Z"; install_progress_data.ready_time = "2017-01-03T00:00:00Z"; g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_spawn_time(snapd, install_progress_data.spawn_time); mock_snapd_set_ready_time(snapd, install_progress_data.ready_time); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_install2_sync( client, SNAPD_INSTALL_FLAGS_NONE, "snap", NULL, NULL, install_progress_cb, &install_progress_data, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_cmpint(install_progress_data.progress_done, >, 0); } static void test_install_needs_classic(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_confinement(s, "classic"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_NONE, "snap", NULL, NULL, NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NEEDS_CLASSIC); g_assert_false(result); } static void test_install_classic(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_on_classic(snapd, TRUE); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_confinement(s, "classic"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_CLASSIC, "snap", NULL, NULL, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap")); g_assert_cmpstr( mock_snap_get_confinement(mock_snapd_find_snap(snapd, "snap")), ==, "classic"); } static void test_install_not_classic(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_on_classic(snapd, TRUE); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_CLASSIC, "snap", NULL, NULL, NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_CLASSIC); g_assert_false(result); } static void test_install_needs_classic_system(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_confinement(s, "classic"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_CLASSIC, "snap", NULL, NULL, NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NEEDS_CLASSIC_SYSTEM); g_assert_false(result); } static void test_install_needs_devmode(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_confinement(s, "devmode"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_NONE, "snap", NULL, NULL, NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NEEDS_DEVMODE); g_assert_false(result); } static void test_install_devmode(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_confinement(s, "devmode"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_DEVMODE, "snap", NULL, NULL, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap")); g_assert_true(mock_snap_get_devmode(mock_snapd_find_snap(snapd, "snap"))); } static void test_install_dangerous(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_DANGEROUS, "snap", NULL, NULL, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap")); g_assert_true(mock_snap_get_dangerous(mock_snapd_find_snap(snapd, "snap"))); } static void test_install_jailmode(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_JAILMODE, "snap", NULL, NULL, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap")); g_assert_true(mock_snap_get_jailmode(mock_snapd_find_snap(snapd, "snap"))); } static void test_install_channel(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_channel(s, "channel1"); s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_channel(s, "channel2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_NONE, "snap", "channel2", NULL, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap")); g_assert_cmpstr(mock_snap_get_channel(mock_snapd_find_snap(snapd, "snap")), ==, "channel2"); } static void test_install_revision(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_revision(s, "1.2"); s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_revision(s, "1.1"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_NONE, "snap", NULL, "1.1", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap")); g_assert_cmpstr(mock_snap_get_revision(mock_snapd_find_snap(snapd, "snap")), ==, "1.1"); } static void test_install_not_available(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_NONE, "snap", NULL, NULL, NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_FOUND); g_assert_false(result); } static void test_install_channel_not_available(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_NONE, "snap", "channel", NULL, NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_CHANNEL_NOT_AVAILABLE); g_assert_false(result); } static void test_install_revision_not_available(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_NONE, "snap", NULL, "1.1", NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_REVISION_NOT_AVAILABLE); g_assert_false(result); } static void test_install_snapd_restart(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_restart_required(s, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_NONE, "snap", NULL, NULL, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); } static void test_install_async_snapd_restart(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_restart_required(s, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "snap")); snapd_client_install2_async(client, SNAPD_INSTALL_FLAGS_NONE, "snap", NULL, NULL, NULL, NULL, NULL, install_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_install_auth_cancelled(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); mock_snapd_set_decline_auth(snapd, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_install2_sync(client, SNAPD_INSTALL_FLAGS_NONE, "snap", NULL, NULL, NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_AUTH_CANCELLED); g_assert_false(result); } static void test_install_stream_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "sideload")); g_autoptr(GInputStream) stream = g_memory_input_stream_new_from_data("SNAP", 4, NULL); gboolean result = snapd_client_install_stream_sync( client, SNAPD_INSTALL_FLAGS_NONE, stream, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); MockSnap *snap = mock_snapd_find_snap(snapd, "sideload"); g_assert_nonnull(snap); g_assert_cmpstr(mock_snap_get_data(snap), ==, "SNAP"); g_assert_cmpstr(mock_snap_get_confinement(snap), ==, "strict"); g_assert_false(mock_snap_get_dangerous(snap)); g_assert_false(mock_snap_get_devmode(snap)); g_assert_false(mock_snap_get_jailmode(snap)); } static void install_stream_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_install_stream_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); MockSnap *snap = mock_snapd_find_snap(data->snapd, "sideload"); g_assert_nonnull(snap); g_assert_cmpstr(mock_snap_get_data(snap), ==, "SNAP"); g_assert_cmpstr(mock_snap_get_confinement(snap), ==, "strict"); g_assert_false(mock_snap_get_dangerous(snap)); g_assert_false(mock_snap_get_devmode(snap)); g_assert_false(mock_snap_get_jailmode(snap)); g_main_loop_quit(data->loop); } static void test_install_stream_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "sideload")); g_autoptr(GInputStream) stream = g_memory_input_stream_new_from_data("SNAP", 4, NULL); snapd_client_install_stream_async(client, SNAPD_INSTALL_FLAGS_NONE, stream, NULL, NULL, NULL, install_stream_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } typedef struct { int progress_done; } InstallStreamProgressData; static void install_stream_progress_cb(SnapdClient *client, SnapdChange *change, gpointer deprecated, gpointer user_data) { InstallStreamProgressData *data = user_data; data->progress_done++; } static void test_install_stream_progress(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "sideload")); g_autoptr(GInputStream) stream = g_memory_input_stream_new_from_data("SNAP", 4, NULL); InstallStreamProgressData install_stream_progress_data; install_stream_progress_data.progress_done = 0; gboolean result = snapd_client_install_stream_sync( client, SNAPD_INSTALL_FLAGS_NONE, stream, install_stream_progress_cb, &install_stream_progress_data, NULL, &error); g_assert_no_error(error); g_assert_true(result); MockSnap *snap = mock_snapd_find_snap(snapd, "sideload"); g_assert_nonnull(snap); g_assert_cmpstr(mock_snap_get_data(snap), ==, "SNAP"); g_assert_cmpint(install_stream_progress_data.progress_done, >, 0); } static void test_install_stream_classic(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "sideload")); g_autoptr(GInputStream) stream = g_memory_input_stream_new_from_data("SNAP", 4, NULL); gboolean result = snapd_client_install_stream_sync( client, SNAPD_INSTALL_FLAGS_CLASSIC, stream, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); MockSnap *snap = mock_snapd_find_snap(snapd, "sideload"); g_assert_nonnull(snap); g_assert_cmpstr(mock_snap_get_data(snap), ==, "SNAP"); g_assert_cmpstr(mock_snap_get_confinement(snap), ==, "classic"); g_assert_false(mock_snap_get_dangerous(snap)); g_assert_false(mock_snap_get_devmode(snap)); g_assert_false(mock_snap_get_jailmode(snap)); } static void test_install_stream_dangerous(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "sideload")); g_autoptr(GInputStream) stream = g_memory_input_stream_new_from_data("SNAP", 4, NULL); gboolean result = snapd_client_install_stream_sync( client, SNAPD_INSTALL_FLAGS_DANGEROUS, stream, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); MockSnap *snap = mock_snapd_find_snap(snapd, "sideload"); g_assert_nonnull(snap); g_assert_cmpstr(mock_snap_get_data(snap), ==, "SNAP"); g_assert_cmpstr(mock_snap_get_confinement(snap), ==, "strict"); g_assert_true(mock_snap_get_dangerous(snap)); g_assert_false(mock_snap_get_devmode(snap)); g_assert_false(mock_snap_get_jailmode(snap)); } static void test_install_stream_devmode(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "sideload")); g_autoptr(GInputStream) stream = g_memory_input_stream_new_from_data("SNAP", 4, NULL); gboolean result = snapd_client_install_stream_sync( client, SNAPD_INSTALL_FLAGS_DEVMODE, stream, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); MockSnap *snap = mock_snapd_find_snap(snapd, "sideload"); g_assert_nonnull(snap); g_assert_cmpstr(mock_snap_get_data(snap), ==, "SNAP"); g_assert_cmpstr(mock_snap_get_confinement(snap), ==, "strict"); g_assert_false(mock_snap_get_dangerous(snap)); g_assert_true(mock_snap_get_devmode(snap)); g_assert_false(mock_snap_get_jailmode(snap)); } static void test_install_stream_jailmode(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_snap(snapd, "sideload")); g_autoptr(GInputStream) stream = g_memory_input_stream_new_from_data("SNAP", 4, NULL); gboolean result = snapd_client_install_stream_sync( client, SNAPD_INSTALL_FLAGS_JAILMODE, stream, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); MockSnap *snap = mock_snapd_find_snap(snapd, "sideload"); g_assert_nonnull(snap); g_assert_cmpstr(mock_snap_get_data(snap), ==, "SNAP"); g_assert_cmpstr(mock_snap_get_confinement(snap), ==, "strict"); g_assert_false(mock_snap_get_dangerous(snap)); g_assert_false(mock_snap_get_devmode(snap)); g_assert_true(mock_snap_get_jailmode(snap)); } static void test_try_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_try_sync(client, "/path/to/snap", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); MockSnap *snap = mock_snapd_find_snap(snapd, "try"); g_assert_nonnull(snap); g_assert_cmpstr(mock_snap_get_path(snap), ==, "/path/to/snap"); } static void try_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_try_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); MockSnap *snap = mock_snapd_find_snap(data->snapd, "try"); g_assert_nonnull(snap); g_assert_cmpstr(mock_snap_get_path(snap), ==, "/path/to/snap"); g_main_loop_quit(data->loop); } static void test_try_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_try_async(client, "/path/to/snap", NULL, NULL, NULL, try_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } typedef struct { int progress_done; } TryProgressData; static void try_progress_cb(SnapdClient *client, SnapdChange *change, gpointer deprecated, gpointer user_data) { TryProgressData *data = user_data; data->progress_done++; } static void test_try_progress(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); TryProgressData try_progress_data; try_progress_data.progress_done = 0; gboolean result = snapd_client_try_sync(client, "/path/to/snap", try_progress_cb, &try_progress_data, NULL, &error); g_assert_no_error(error); g_assert_true(result); MockSnap *snap = mock_snapd_find_snap(snapd, "try"); g_assert_nonnull(snap); g_assert_cmpstr(mock_snap_get_path(snap), ==, "/path/to/snap"); g_assert_cmpint(try_progress_data.progress_done, >, 0); } static void test_try_not_a_snap(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_try_sync(client, "*", NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_A_SNAP); g_assert_false(result); } static void test_refresh_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_revision(s, "1"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_refresh_sync(client, "snap", NULL, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); } static void refresh_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_refresh_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_main_loop_quit(data->loop); } static void test_refresh_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_revision(s, "1"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_refresh_async(client, "snap", NULL, NULL, NULL, NULL, refresh_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } typedef struct { int progress_done; } RefreshProgressData; static void refresh_progress_cb(SnapdClient *client, SnapdChange *change, gpointer deprecated, gpointer user_data) { RefreshProgressData *data = user_data; data->progress_done++; } static void test_refresh_progress(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_revision(s, "1"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); RefreshProgressData refresh_progress_data; refresh_progress_data.progress_done = 0; gboolean result = snapd_client_refresh_sync(client, "snap", NULL, refresh_progress_cb, &refresh_progress_data, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_cmpint(refresh_progress_data.progress_done, >, 0); } static void test_refresh_channel(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_revision(s, "1"); mock_snap_set_channel(s, "channel1"); s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_revision(s, "1"); mock_snap_set_channel(s, "channel2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_refresh_sync(client, "snap", "channel2", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_cmpstr(mock_snap_get_channel(mock_snapd_find_snap(snapd, "snap")), ==, "channel2"); } static void test_refresh_no_updates(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_revision(s, "0"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_refresh_sync(client, "snap", NULL, NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NO_UPDATE_AVAILABLE); g_assert_false(result); } static void test_refresh_not_installed(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_refresh_sync(client, "snap", NULL, NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_INSTALLED); g_assert_false(result); } static void test_refresh_not_in_store(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_revision(s, "0"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_refresh_sync(client, "snap", NULL, NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_IN_STORE); g_assert_false(result); } static void test_refresh_all_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_snap(snapd, "snap2"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_snap(snapd, "snap3"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_store_snap(snapd, "snap1"); mock_snap_set_revision(s, "1"); s = mock_snapd_add_store_snap(snapd, "snap3"); mock_snap_set_revision(s, "1"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_auto(GStrv) snap_names = snapd_client_refresh_all_sync(client, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_cmpint(g_strv_length(snap_names), ==, 2); g_assert_cmpstr(snap_names[0], ==, "snap1"); g_assert_cmpstr(snap_names[1], ==, "snap3"); } static void refresh_all_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_auto(GStrv) snap_names = snapd_client_refresh_all_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_cmpint(g_strv_length(snap_names), ==, 2); g_assert_cmpstr(snap_names[0], ==, "snap1"); g_assert_cmpstr(snap_names[1], ==, "snap3"); g_main_loop_quit(data->loop); } static void test_refresh_all_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_snap(snapd, "snap2"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_snap(snapd, "snap3"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_store_snap(snapd, "snap1"); mock_snap_set_revision(s, "1"); s = mock_snapd_add_store_snap(snapd, "snap3"); mock_snap_set_revision(s, "1"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_refresh_all_async(client, NULL, NULL, NULL, refresh_all_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } typedef struct { int progress_done; } RefreshAllProgressData; static void refresh_all_progress_cb(SnapdClient *client, SnapdChange *change, gpointer deprecated, gpointer user_data) { RefreshAllProgressData *data = user_data; data->progress_done++; } static void test_refresh_all_progress(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap1"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_snap(snapd, "snap2"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_snap(snapd, "snap3"); mock_snap_set_revision(s, "0"); s = mock_snapd_add_store_snap(snapd, "snap1"); mock_snap_set_revision(s, "1"); s = mock_snapd_add_store_snap(snapd, "snap3"); mock_snap_set_revision(s, "1"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); RefreshAllProgressData refresh_all_progress_data; refresh_all_progress_data.progress_done = 0; g_auto(GStrv) snap_names = snapd_client_refresh_all_sync(client, refresh_all_progress_cb, &refresh_all_progress_data, NULL, &error); g_assert_no_error(error); g_assert_cmpint(g_strv_length(snap_names), ==, 2); g_assert_cmpstr(snap_names[0], ==, "snap1"); g_assert_cmpstr(snap_names[1], ==, "snap3"); g_assert_cmpint(refresh_all_progress_data.progress_done, >, 0); } static void test_refresh_all_no_updates(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_auto(GStrv) snap_names = snapd_client_refresh_all_sync(client, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_cmpint(g_strv_length(snap_names), ==, 0); } static void test_remove_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap")); gboolean result = snapd_client_remove2_sync(client, SNAPD_REMOVE_FLAGS_NONE, "snap", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_null(mock_snapd_find_snap(snapd, "snap")); g_assert_nonnull(mock_snapd_find_snapshot(snapd, "snap")); } static void remove_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_remove2_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_assert_null(mock_snapd_find_snap(data->snapd, "snap")); g_assert_nonnull(mock_snapd_find_snapshot(data->snapd, "snap")); g_main_loop_quit(data->loop); } static void test_remove_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap")); snapd_client_remove2_async(client, SNAPD_REMOVE_FLAGS_NONE, "snap", NULL, NULL, NULL, remove_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void remove_failure_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_remove2_finish(SNAPD_CLIENT(object), result, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_FAILED); g_assert_cmpstr(error->message, ==, "ERROR"); g_assert_false(r); g_assert_nonnull(mock_snapd_find_snap(data->snapd, "snap")); g_main_loop_quit(data->loop); } static void test_remove_async_failure(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_error(s, "ERROR"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap")); snapd_client_remove2_async(client, SNAPD_REMOVE_FLAGS_NONE, "snap", NULL, NULL, NULL, remove_failure_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void remove_cancel_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_remove2_finish(SNAPD_CLIENT(object), result, &error); g_assert_error(error, G_IO_ERROR, G_IO_ERROR_CANCELLED); g_assert_false(r); g_assert_nonnull(mock_snapd_find_snap(data->snapd, "snap")); g_main_loop_quit(data->loop); } static void test_remove_async_cancel(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap")); g_autoptr(GCancellable) cancellable = g_cancellable_new(); snapd_client_remove2_async(client, SNAPD_REMOVE_FLAGS_NONE, "snap", NULL, NULL, cancellable, remove_cancel_cb, async_data_new(loop, snapd)); g_idle_add(cancel_cb, cancellable); g_main_loop_run(loop); } typedef struct { int progress_done; } RemoveProgressData; static void remove_progress_cb(SnapdClient *client, SnapdChange *change, gpointer deprecated, gpointer user_data) { RemoveProgressData *data = user_data; data->progress_done++; } static void test_remove_progress(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_nonnull(mock_snapd_find_snap(snapd, "snap")); RemoveProgressData remove_progress_data; remove_progress_data.progress_done = 0; gboolean result = snapd_client_remove2_sync( client, SNAPD_REMOVE_FLAGS_NONE, "snap", remove_progress_cb, &remove_progress_data, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_null(mock_snapd_find_snap(snapd, "snap")); g_assert_cmpint(remove_progress_data.progress_done, >, 0); } static void test_remove_not_installed(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_remove2_sync(client, SNAPD_REMOVE_FLAGS_NONE, "snap", NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_INSTALLED); g_assert_false(result); } static void test_remove_purge(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_remove2_sync(client, SNAPD_REMOVE_FLAGS_PURGE, "snap", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_null(mock_snapd_find_snap(snapd, "snap")); g_assert_null(mock_snapd_find_snapshot(snapd, "snap")); } static void test_enable_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_disabled(s, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_enable_sync(client, "snap", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_false(mock_snap_get_disabled(mock_snapd_find_snap(snapd, "snap"))); } static void enable_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_enable_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_assert_false( mock_snap_get_disabled(mock_snapd_find_snap(data->snapd, "snap"))); g_main_loop_quit(data->loop); } static void test_enable_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_disabled(s, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_enable_async(client, "snap", NULL, NULL, NULL, enable_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } typedef struct { int progress_done; } EnableProgressData; static void enable_progress_cb(SnapdClient *client, SnapdChange *change, gpointer deprecated, gpointer user_data) { EnableProgressData *data = user_data; data->progress_done++; } static void test_enable_progress(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_disabled(s, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); EnableProgressData enable_progress_data; enable_progress_data.progress_done = 0; gboolean result = snapd_client_enable_sync( client, "snap", enable_progress_cb, &enable_progress_data, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_false(mock_snap_get_disabled(mock_snapd_find_snap(snapd, "snap"))); g_assert_cmpint(enable_progress_data.progress_done, >, 0); } static void test_enable_already_enabled(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_disabled(s, FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_enable_sync(client, "snap", NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_REQUEST); g_assert_false(result); } static void test_enable_not_installed(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_enable_sync(client, "snap", NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_INSTALLED); g_assert_false(result); } static void test_disable_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_disabled(s, FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_disable_sync(client, "snap", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_true(mock_snap_get_disabled(mock_snapd_find_snap(snapd, "snap"))); } static void disable_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_disable_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_assert_true( mock_snap_get_disabled(mock_snapd_find_snap(data->snapd, "snap"))); g_main_loop_quit(data->loop); } static void test_disable_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_disabled(s, FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_disable_async(client, "snap", NULL, NULL, NULL, disable_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } typedef struct { int progress_done; } DisableProgressData; static void disable_progress_cb(SnapdClient *client, SnapdChange *change, gpointer deprecated, gpointer user_data) { DisableProgressData *data = user_data; data->progress_done++; } static void test_disable_progress(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_disabled(s, FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); DisableProgressData disable_progress_data; disable_progress_data.progress_done = 0; gboolean result = snapd_client_disable_sync(client, "snap", disable_progress_cb, &disable_progress_data, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_true(mock_snap_get_disabled(mock_snapd_find_snap(snapd, "snap"))); g_assert_cmpint(disable_progress_data.progress_done, >, 0); } static void test_disable_already_disabled(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_disabled(s, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_disable_sync(client, "snap", NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_REQUEST); g_assert_false(result); } static void test_disable_not_installed(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_disable_sync(client, "snap", NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_INSTALLED); g_assert_false(result); } static void test_switch_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_tracking_channel(s, "stable"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_switch_sync(client, "snap", "beta", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_cmpstr( mock_snap_get_tracking_channel(mock_snapd_find_snap(snapd, "snap")), ==, "beta"); } static void switch_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_switch_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_assert_cmpstr( mock_snap_get_tracking_channel(mock_snapd_find_snap(data->snapd, "snap")), ==, "beta"); g_main_loop_quit(data->loop); } static void test_switch_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_tracking_channel(s, "stable"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_switch_async(client, "snap", "beta", NULL, NULL, NULL, switch_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } typedef struct { int progress_done; } SwitchProgressData; static void switch_progress_cb(SnapdClient *client, SnapdChange *change, gpointer deprecated, gpointer user_data) { SwitchProgressData *data = user_data; data->progress_done++; } static void test_switch_progress(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_set_tracking_channel(s, "stable"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); SwitchProgressData switch_progress_data; switch_progress_data.progress_done = 0; gboolean result = snapd_client_switch_sync(client, "snap", "beta", switch_progress_cb, &switch_progress_data, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_cmpstr( mock_snap_get_tracking_channel(mock_snapd_find_snap(snapd, "snap")), ==, "beta"); g_assert_cmpint(switch_progress_data.progress_done, >, 0); } static void test_switch_not_installed(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_switch_sync(client, "snap", "beta", NULL, NULL, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_INSTALLED); g_assert_false(result); } static void test_check_buy_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_account_set_terms_accepted(a, TRUE); mock_account_set_has_payment_methods(a, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(user_information); snapd_client_set_auth_data( client, snapd_user_information_get_auth_data(user_information)); gboolean result = snapd_client_check_buy_sync(client, NULL, &error); g_assert_no_error(error); g_assert_true(result); } static void check_buy_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_check_buy_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_main_loop_quit(data->loop); } static void test_check_buy_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_account_set_terms_accepted(a, TRUE); mock_account_set_has_payment_methods(a, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(user_information); snapd_client_set_auth_data( client, snapd_user_information_get_auth_data(user_information)); snapd_client_check_buy_async(client, NULL, check_buy_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_check_buy_terms_not_accepted(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_account_set_terms_accepted(a, FALSE); mock_account_set_has_payment_methods(a, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(user_information); snapd_client_set_auth_data( client, snapd_user_information_get_auth_data(user_information)); gboolean result = snapd_client_check_buy_sync(client, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_TERMS_NOT_ACCEPTED); g_assert_false(result); } static void test_check_buy_no_payment_methods(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_account_set_terms_accepted(a, TRUE); mock_account_set_has_payment_methods(a, FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(user_information); snapd_client_set_auth_data( client, snapd_user_information_get_auth_data(user_information)); gboolean result = snapd_client_check_buy_sync(client, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_PAYMENT_NOT_SETUP); g_assert_false(result); } static void test_check_buy_not_logged_in(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_check_buy_sync(client, NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_AUTH_DATA_REQUIRED); g_assert_false(result); } static void test_buy_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_account_set_terms_accepted(a, TRUE); mock_account_set_has_payment_methods(a, TRUE); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_id(s, "ABCDEF"); mock_snap_add_price(s, 1.25, "NZD"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(user_information); snapd_client_set_auth_data( client, snapd_user_information_get_auth_data(user_information)); gboolean result = snapd_client_buy_sync(client, "ABCDEF", 1.25, "NZD", NULL, &error); g_assert_no_error(error); g_assert_true(result); } static void buy_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_buy_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_main_loop_quit(data->loop); } static void test_buy_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_account_set_terms_accepted(a, TRUE); mock_account_set_has_payment_methods(a, TRUE); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_id(s, "ABCDEF"); mock_snap_add_price(s, 1.25, "NZD"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(user_information); snapd_client_set_auth_data( client, snapd_user_information_get_auth_data(user_information)); snapd_client_buy_async(client, "ABCDEF", 1.25, "NZD", NULL, buy_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_buy_not_logged_in(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_id(s, "ABCDEF"); mock_snap_add_price(s, 1.25, "NZD"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_buy_sync(client, "ABCDEF", 1.25, "NZD", NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_AUTH_DATA_REQUIRED); g_assert_false(result); } static void test_buy_not_available(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_account_set_terms_accepted(a, TRUE); mock_account_set_has_payment_methods(a, TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(user_information); snapd_client_set_auth_data( client, snapd_user_information_get_auth_data(user_information)); gboolean result = snapd_client_buy_sync(client, "ABCDEF", 1.25, "NZD", NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_NOT_FOUND); g_assert_false(result); } static void test_buy_terms_not_accepted(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_account_set_terms_accepted(a, FALSE); mock_account_set_has_payment_methods(a, FALSE); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_id(s, "ABCDEF"); mock_snap_add_price(s, 1.25, "NZD"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(user_information); snapd_client_set_auth_data( client, snapd_user_information_get_auth_data(user_information)); gboolean result = snapd_client_buy_sync(client, "ABCDEF", 1.25, "NZD", NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_TERMS_NOT_ACCEPTED); g_assert_false(result); } static void test_buy_no_payment_methods(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_account_set_terms_accepted(a, TRUE); mock_account_set_has_payment_methods(a, FALSE); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_id(s, "ABCDEF"); mock_snap_add_price(s, 1.25, "NZD"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(user_information); snapd_client_set_auth_data( client, snapd_user_information_get_auth_data(user_information)); gboolean result = snapd_client_buy_sync(client, "ABCDEF", 1.25, "NZD", NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_PAYMENT_NOT_SETUP); g_assert_false(result); } static void test_buy_invalid_price(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockAccount *a = mock_snapd_add_account(snapd, "test@example.com", "test", "secret"); mock_account_set_terms_accepted(a, TRUE); mock_account_set_has_payment_methods(a, TRUE); MockSnap *s = mock_snapd_add_store_snap(snapd, "snap"); mock_snap_set_id(s, "ABCDEF"); mock_snap_add_price(s, 1.25, "NZD"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdUserInformation) user_information = snapd_client_login2_sync( client, "test@example.com", "secret", NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(user_information); snapd_client_set_auth_data( client, snapd_user_information_get_auth_data(user_information)); gboolean result = snapd_client_buy_sync(client, "ABCDEF", 0.75, "NZD", NULL, &error); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_PAYMENT_DECLINED); g_assert_false(result); } static void test_create_user_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_account_by_username(snapd, "user")); g_autoptr(SnapdUserInformation) info = snapd_client_create_user_sync( client, "user@example.com", SNAPD_CREATE_USER_FLAGS_NONE, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpstr(snapd_user_information_get_username(info), ==, "user"); GStrv ssh_keys = snapd_user_information_get_ssh_keys(info); g_assert_nonnull(ssh_keys); g_assert_cmpint(g_strv_length(ssh_keys), ==, 2); g_assert_cmpstr(ssh_keys[0], ==, "KEY1"); g_assert_cmpstr(ssh_keys[1], ==, "KEY2"); MockAccount *account = mock_snapd_find_account_by_username(snapd, "user"); g_assert_nonnull(account); g_assert_false(mock_account_get_sudoer(account)); g_assert_false(mock_account_get_known(account)); } static void test_create_user_sudo(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_account_by_username(snapd, "user")); g_autoptr(SnapdUserInformation) info = snapd_client_create_user_sync( client, "user@example.com", SNAPD_CREATE_USER_FLAGS_SUDO, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); MockAccount *account = mock_snapd_find_account_by_username(snapd, "user"); g_assert_nonnull(account); g_assert_true(mock_account_get_sudoer(account)); } static void test_create_user_known(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_snapd_find_account_by_username(snapd, "user")); g_autoptr(SnapdUserInformation) info = snapd_client_create_user_sync( client, "user@example.com", SNAPD_CREATE_USER_FLAGS_KNOWN, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); MockAccount *account = mock_snapd_find_account_by_username(snapd, "user"); g_assert_nonnull(account); g_assert_true(mock_account_get_known(account)); } static void test_create_users_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) users_info = snapd_client_create_users_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(users_info); g_assert_cmpint(users_info->len, ==, 3); SnapdUserInformation *info = users_info->pdata[0]; g_assert_cmpstr(snapd_user_information_get_username(info), ==, "admin"); GStrv ssh_keys = snapd_user_information_get_ssh_keys(info); g_assert_nonnull(ssh_keys); g_assert_cmpint(g_strv_length(ssh_keys), ==, 2); g_assert_cmpstr(ssh_keys[0], ==, "KEY1"); g_assert_cmpstr(ssh_keys[1], ==, "KEY2"); info = users_info->pdata[1]; g_assert_cmpstr(snapd_user_information_get_username(info), ==, "alice"); info = users_info->pdata[2]; g_assert_cmpstr(snapd_user_information_get_username(info), ==, "bob"); g_assert_nonnull(mock_snapd_find_account_by_username(snapd, "admin")); g_assert_nonnull(mock_snapd_find_account_by_username(snapd, "alice")); g_assert_nonnull(mock_snapd_find_account_by_username(snapd, "bob")); } static void test_get_users_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_account(snapd, "alice@example.com", "alice", "secret"); mock_snapd_add_account(snapd, "bob@example.com", "bob", "secret"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) users_info = snapd_client_get_users_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(users_info); g_assert_cmpint(users_info->len, ==, 2); SnapdUserInformation *info = users_info->pdata[0]; g_assert_cmpint(snapd_user_information_get_id(info), ==, 1); g_assert_cmpstr(snapd_user_information_get_username(info), ==, "alice"); g_assert_cmpstr(snapd_user_information_get_email(info), ==, "alice@example.com"); info = users_info->pdata[1]; g_assert_cmpint(snapd_user_information_get_id(info), ==, 2); g_assert_cmpstr(snapd_user_information_get_username(info), ==, "bob"); g_assert_cmpstr(snapd_user_information_get_email(info), ==, "bob@example.com"); } static void get_users_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) users_info = snapd_client_get_users_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(users_info); g_assert_cmpint(users_info->len, ==, 2); SnapdUserInformation *info = users_info->pdata[0]; g_assert_cmpint(snapd_user_information_get_id(info), ==, 1); g_assert_cmpstr(snapd_user_information_get_username(info), ==, "alice"); g_assert_cmpstr(snapd_user_information_get_email(info), ==, "alice@example.com"); info = users_info->pdata[1]; g_assert_cmpint(snapd_user_information_get_id(info), ==, 2); g_assert_cmpstr(snapd_user_information_get_username(info), ==, "bob"); g_assert_cmpstr(snapd_user_information_get_email(info), ==, "bob@example.com"); g_main_loop_quit(data->loop); } static void test_get_users_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_account(snapd, "alice@example.com", "alice", "secret"); mock_snapd_add_account(snapd, "bob@example.com", "bob", "secret"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_users_async(client, NULL, get_users_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_get_sections_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_category(snapd, "SECTION1"); mock_snapd_add_store_category(snapd, "SECTION2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_auto(GStrv) sections = snapd_client_get_sections_sync(client, NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_nonnull(sections); g_assert_cmpint(g_strv_length(sections), ==, 2); g_assert_cmpstr(sections[0], ==, "SECTION1"); g_assert_cmpstr(sections[1], ==, "SECTION2"); } static void get_sections_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_auto(GStrv) sections = snapd_client_get_sections_finish(SNAPD_CLIENT(object), result, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_nonnull(sections); g_assert_cmpint(g_strv_length(sections), ==, 2); g_assert_cmpstr(sections[0], ==, "SECTION1"); g_assert_cmpstr(sections[1], ==, "SECTION2"); g_main_loop_quit(data->loop); } static void test_get_sections_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_category(snapd, "SECTION1"); mock_snapd_add_store_category(snapd, "SECTION2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_get_sections_async(client, NULL, get_sections_cb, async_data_new(loop, snapd)); G_GNUC_END_IGNORE_DEPRECATIONS g_main_loop_run(loop); } static void test_get_categories_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_category(snapd, "CATEGORY1"); mock_snapd_add_store_category(snapd, "CATEGORY2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_autoptr(GPtrArray) categories = snapd_client_get_categories_sync(client, NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_nonnull(categories); g_assert_cmpint(categories->len, ==, 2); SnapdCategoryDetails *category_details = categories->pdata[0]; g_assert_cmpstr(snapd_category_details_get_name(category_details), ==, "CATEGORY1"); category_details = categories->pdata[1]; g_assert_cmpstr(snapd_category_details_get_name(category_details), ==, "CATEGORY2"); } static void get_categories_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_autoptr(GPtrArray) categories = snapd_client_get_categories_finish(SNAPD_CLIENT(object), result, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_nonnull(categories); g_assert_cmpint(categories->len, ==, 2); SnapdCategoryDetails *category_details = categories->pdata[0]; g_assert_cmpstr(snapd_category_details_get_name(category_details), ==, "CATEGORY1"); category_details = categories->pdata[1]; g_assert_cmpstr(snapd_category_details_get_name(category_details), ==, "CATEGORY2"); g_main_loop_quit(data->loop); } static void test_get_categories_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_store_category(snapd, "CATEGORY1"); mock_snapd_add_store_category(snapd, "CATEGORY2"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS snapd_client_get_categories_async(client, NULL, get_categories_cb, async_data_new(loop, snapd)); G_GNUC_END_IGNORE_DEPRECATIONS g_main_loop_run(loop); } static gint compare_alias_name(gconstpointer a, gconstpointer b) { SnapdAlias *alias_a = *((SnapdAlias **)a); SnapdAlias *alias_b = *((SnapdAlias **)b); return strcmp(snapd_alias_get_name(alias_a), snapd_alias_get_name(alias_b)); } static void test_aliases_get_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); MockApp *a = mock_snap_add_app(s, "app"); mock_app_add_auto_alias(a, "alias1"); mock_app_add_manual_alias(a, "alias2", TRUE); mock_app_add_auto_alias(a, "alias3"); mock_app_add_manual_alias(a, "alias3", FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) aliases = snapd_client_get_aliases_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(aliases); g_assert_cmpint(aliases->len, ==, 3); g_ptr_array_sort(aliases, compare_alias_name); SnapdAlias *alias = aliases->pdata[0]; g_assert_cmpstr(snapd_alias_get_name(alias), ==, "alias1"); g_assert_cmpstr(snapd_alias_get_snap(alias), ==, "snap"); g_assert_cmpstr(snapd_alias_get_command(alias), ==, "snap.app"); g_assert_cmpint(snapd_alias_get_status(alias), ==, SNAPD_ALIAS_STATUS_AUTO); g_assert_cmpstr(snapd_alias_get_app_auto(alias), ==, "app"); g_assert_null(snapd_alias_get_app_manual(alias)); alias = aliases->pdata[1]; g_assert_cmpstr(snapd_alias_get_name(alias), ==, "alias2"); g_assert_cmpstr(snapd_alias_get_snap(alias), ==, "snap"); g_assert_cmpstr(snapd_alias_get_command(alias), ==, "snap.app"); g_assert_cmpint(snapd_alias_get_status(alias), ==, SNAPD_ALIAS_STATUS_MANUAL); g_assert_null(snapd_alias_get_app_auto(alias)); g_assert_cmpstr(snapd_alias_get_app_manual(alias), ==, "app"); alias = aliases->pdata[2]; g_assert_cmpstr(snapd_alias_get_name(alias), ==, "alias3"); g_assert_cmpstr(snapd_alias_get_snap(alias), ==, "snap"); g_assert_cmpstr(snapd_alias_get_command(alias), ==, "snap.app"); g_assert_cmpint(snapd_alias_get_status(alias), ==, SNAPD_ALIAS_STATUS_DISABLED); g_assert_cmpstr(snapd_alias_get_app_auto(alias), ==, "app"); g_assert_null(snapd_alias_get_app_manual(alias)); } static void get_aliases_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) aliases = snapd_client_get_aliases_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(aliases); g_assert_cmpint(aliases->len, ==, 3); g_ptr_array_sort(aliases, compare_alias_name); SnapdAlias *alias = aliases->pdata[0]; g_assert_cmpstr(snapd_alias_get_name(alias), ==, "alias1"); g_assert_cmpstr(snapd_alias_get_snap(alias), ==, "snap"); g_assert_cmpstr(snapd_alias_get_command(alias), ==, "snap.app"); g_assert_cmpint(snapd_alias_get_status(alias), ==, SNAPD_ALIAS_STATUS_AUTO); g_assert_cmpstr(snapd_alias_get_app_auto(alias), ==, "app"); g_assert_null(snapd_alias_get_app_manual(alias)); alias = aliases->pdata[1]; g_assert_cmpstr(snapd_alias_get_name(alias), ==, "alias2"); g_assert_cmpstr(snapd_alias_get_snap(alias), ==, "snap"); g_assert_cmpstr(snapd_alias_get_command(alias), ==, "snap.app"); g_assert_cmpint(snapd_alias_get_status(alias), ==, SNAPD_ALIAS_STATUS_MANUAL); g_assert_null(snapd_alias_get_app_auto(alias)); g_assert_cmpstr(snapd_alias_get_app_manual(alias), ==, "app"); alias = aliases->pdata[2]; g_assert_cmpstr(snapd_alias_get_name(alias), ==, "alias3"); g_assert_cmpstr(snapd_alias_get_snap(alias), ==, "snap"); g_assert_cmpstr(snapd_alias_get_command(alias), ==, "snap.app"); g_assert_cmpint(snapd_alias_get_status(alias), ==, SNAPD_ALIAS_STATUS_DISABLED); g_assert_cmpstr(snapd_alias_get_app_auto(alias), ==, "app"); g_assert_null(snapd_alias_get_app_manual(alias)); g_main_loop_quit(data->loop); } static void test_aliases_get_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); MockApp *a = mock_snap_add_app(s, "app"); mock_app_add_auto_alias(a, "alias1"); mock_app_add_manual_alias(a, "alias2", TRUE); mock_app_add_auto_alias(a, "alias3"); mock_app_add_manual_alias(a, "alias3", FALSE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_aliases_async(client, NULL, get_aliases_cb, async_data_new(loop, snapd)); } static void test_aliases_get_empty(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) aliases = snapd_client_get_aliases_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(aliases); g_assert_cmpint(aliases->len, ==, 0); } static void test_aliases_alias_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); MockApp *a = mock_snap_add_app(s, "app"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_app_find_alias(a, "foo")); gboolean result = snapd_client_alias_sync(client, "snap", "app", "foo", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(mock_app_find_alias(a, "foo")); } static void alias_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; MockSnap *s = mock_snapd_find_snap(data->snapd, "snap"); MockApp *a = mock_snap_find_app(s, "app"); g_autoptr(GError) error = NULL; gboolean r = snapd_client_alias_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_assert_nonnull(mock_app_find_alias(a, "foo")); g_main_loop_quit(data->loop); } static void test_aliases_alias_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); MockApp *a = mock_snap_add_app(s, "app"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_null(mock_app_find_alias(a, "foo")); snapd_client_alias_async(client, "snap", "app", "foo", NULL, NULL, NULL, alias_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_aliases_unalias_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); MockApp *a = mock_snap_add_app(s, "app"); mock_app_add_manual_alias(a, "foo", TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_unalias_sync(client, "snap", "foo", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_null(mock_app_find_alias(a, "foo")); } static void unalias_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; MockSnap *s = mock_snapd_find_snap(data->snapd, "snap"); MockApp *a = mock_snap_find_app(s, "app"); g_autoptr(GError) error = NULL; gboolean r = snapd_client_unalias_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_assert_null(mock_app_find_alias(a, "foo")); g_main_loop_quit(data->loop); } static void test_aliases_unalias_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); mock_snap_add_app(s, "app"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_unalias_async(client, "snap", "foo", NULL, NULL, NULL, unalias_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_aliases_unalias_no_snap_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); MockApp *a = mock_snap_add_app(s, "app"); mock_app_add_manual_alias(a, "foo", TRUE); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); gboolean result = snapd_client_unalias_sync(client, NULL, "foo", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_null(mock_app_find_alias(a, "foo")); } static void test_aliases_prefer_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_false(mock_snap_get_preferred(s)); gboolean result = snapd_client_prefer_sync(client, "snap", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_true(mock_snap_get_preferred(s)); } static void prefer_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; MockSnap *s = mock_snapd_find_snap(data->snapd, "snap"); g_autoptr(GError) error = NULL; gboolean r = snapd_client_prefer_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_assert_true(mock_snap_get_preferred(s)); g_main_loop_quit(data->loop); } static void test_aliases_prefer_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockSnap *s = mock_snapd_add_snap(snapd, "snap"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_assert_false(mock_snap_get_preferred(s)); snapd_client_prefer_async(client, "snap", NULL, NULL, NULL, prefer_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_run_snapctl_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_auto(GStrv) args = g_strsplit("arg1;arg2", ";", -1); g_autofree gchar *stdout_output = NULL; g_autofree gchar *stderr_output = NULL; int exit_code = 0; gboolean result = snapd_client_run_snapctl2_sync(client, "ABC", args, &stdout_output, &stderr_output, &exit_code, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_cmpstr(stdout_output, ==, "STDOUT:ABC:arg1:arg2"); g_assert_cmpstr(stderr_output, ==, "STDERR"); g_assert_cmpint(exit_code, ==, 0); } static void snapctl_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autofree gchar *stdout_output = NULL; g_autofree gchar *stderr_output = NULL; int exit_code = 0; g_autoptr(GError) error = NULL; gboolean r = snapd_client_run_snapctl2_finish(SNAPD_CLIENT(object), result, &stdout_output, &stderr_output, &exit_code, &error); g_assert_no_error(error); g_assert_true(r); g_assert_cmpstr(stdout_output, ==, "STDOUT:ABC:arg1:arg2"); g_assert_cmpstr(stderr_output, ==, "STDERR"); g_assert_cmpint(exit_code, ==, 0); g_main_loop_quit(data->loop); } static void test_run_snapctl_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_auto(GStrv) args = g_strsplit("arg1;arg2", ";", -1); snapd_client_run_snapctl2_async(client, "ABC", args, NULL, snapctl_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_run_snapctl_unsuccessful(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_auto(GStrv) args = g_strsplit("arg1;arg2", ";", -1); g_autofree gchar *stdout_output = NULL; g_autofree gchar *stderr_output = NULL; int exit_code = 0; gboolean result = snapd_client_run_snapctl2_sync( client, "return-error", args, &stdout_output, &stderr_output, &exit_code, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_cmpstr(stdout_output, ==, "STDOUT:return-error:arg1:arg2"); g_assert_cmpstr(stderr_output, ==, "STDERR"); g_assert_cmpint(exit_code, ==, 1); } static void test_run_snapctl_legacy(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_auto(GStrv) args = g_strsplit("arg1;arg2", ";", -1); g_autofree gchar *stdout_output = NULL; g_autofree gchar *stderr_output = NULL; G_GNUC_BEGIN_IGNORE_DEPRECATIONS gboolean result = snapd_client_run_snapctl_sync( client, "ABC", args, &stdout_output, &stderr_output, NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_no_error(error); g_assert_true(result); g_assert_cmpstr(stdout_output, ==, "STDOUT:ABC:arg1:arg2"); g_assert_cmpstr(stderr_output, ==, "STDERR"); /* Unsuccessful exit codes are still reported as errors by the old API */ g_clear_pointer(&stdout_output, g_free); g_clear_pointer(&stderr_output, g_free); G_GNUC_BEGIN_IGNORE_DEPRECATIONS result = snapd_client_run_snapctl_sync(client, "return-error", args, &stdout_output, &stderr_output, NULL, &error); G_GNUC_END_IGNORE_DEPRECATIONS g_assert_false(result); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_UNSUCCESSFUL); } static void test_download_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GBytes) snap_data = snapd_client_download_sync(client, "test", NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(snap_data); g_assert_cmpmem(g_bytes_get_data(snap_data, NULL), g_bytes_get_size(snap_data), "SNAP:name=test", 14); } static void download_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GBytes) snap_data = snapd_client_download_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(snap_data); g_assert_cmpmem(g_bytes_get_data(snap_data, NULL), g_bytes_get_size(snap_data), "SNAP:name=test", 14); g_main_loop_quit(data->loop); } static void test_download_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_download_async(client, "test", NULL, NULL, NULL, download_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_download_channel_revision(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GBytes) snap_data = snapd_client_download_sync( client, "test", "CHANNEL", "REVISION", NULL, &error); g_assert_no_error(error); g_assert_nonnull(snap_data); g_assert_cmpmem(g_bytes_get_data(snap_data, NULL), g_bytes_get_size(snap_data), "SNAP:name=test:channel=CHANNEL:revision=REVISION", 48); } static void test_themes_check_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); mock_snapd_set_gtk_theme_status(snapd, "gtktheme1", "installed"); mock_snapd_set_gtk_theme_status(snapd, "gtktheme2", "available"); mock_snapd_set_gtk_theme_status(snapd, "gtktheme3", "unavailable"); mock_snapd_set_icon_theme_status(snapd, "icontheme1", "installed"); mock_snapd_set_icon_theme_status(snapd, "icontheme2", "available"); mock_snapd_set_icon_theme_status(snapd, "icontheme3", "unavailable"); mock_snapd_set_sound_theme_status(snapd, "soundtheme1", "installed"); mock_snapd_set_sound_theme_status(snapd, "soundtheme2", "available"); mock_snapd_set_sound_theme_status(snapd, "soundtheme3", "unavailable"); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); char *gtk_themes[] = {"gtktheme1", "gtktheme2", "gtktheme3", NULL}; char *icon_themes[] = {"icontheme1", "icontheme2", "icontheme3", NULL}; char *sound_themes[] = {"soundtheme1", "soundtheme2", "soundtheme3", NULL}; g_autoptr(GHashTable) gtk_status = NULL; g_autoptr(GHashTable) icon_status = NULL; g_autoptr(GHashTable) sound_status = NULL; gboolean result = snapd_client_check_themes_sync( client, gtk_themes, icon_themes, sound_themes, >k_status, &icon_status, &sound_status, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_nonnull(gtk_status); g_assert_nonnull(icon_status); g_assert_nonnull(sound_status); g_assert_cmpint(g_hash_table_size(gtk_status), ==, 3); g_assert_cmpint(GPOINTER_TO_INT(g_hash_table_lookup(gtk_status, "gtktheme1")), ==, SNAPD_THEME_STATUS_INSTALLED); g_assert_cmpint(GPOINTER_TO_INT(g_hash_table_lookup(gtk_status, "gtktheme2")), ==, SNAPD_THEME_STATUS_AVAILABLE); g_assert_cmpint(GPOINTER_TO_INT(g_hash_table_lookup(gtk_status, "gtktheme3")), ==, SNAPD_THEME_STATUS_UNAVAILABLE); g_assert_cmpint(g_hash_table_size(icon_status), ==, 3); g_assert_cmpint( GPOINTER_TO_INT(g_hash_table_lookup(icon_status, "icontheme1")), ==, SNAPD_THEME_STATUS_INSTALLED); g_assert_cmpint( GPOINTER_TO_INT(g_hash_table_lookup(icon_status, "icontheme2")), ==, SNAPD_THEME_STATUS_AVAILABLE); g_assert_cmpint( GPOINTER_TO_INT(g_hash_table_lookup(icon_status, "icontheme3")), ==, SNAPD_THEME_STATUS_UNAVAILABLE); g_assert_cmpint(g_hash_table_size(sound_status), ==, 3); g_assert_cmpint( GPOINTER_TO_INT(g_hash_table_lookup(sound_status, "soundtheme1")), ==, SNAPD_THEME_STATUS_INSTALLED); g_assert_cmpint( GPOINTER_TO_INT(g_hash_table_lookup(sound_status, "soundtheme2")), ==, SNAPD_THEME_STATUS_AVAILABLE); g_assert_cmpint( GPOINTER_TO_INT(g_hash_table_lookup(sound_status, "soundtheme3")), ==, SNAPD_THEME_STATUS_UNAVAILABLE); } static void check_themes_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GHashTable) gtk_status = NULL; g_autoptr(GHashTable) icon_status = NULL; g_autoptr(GHashTable) sound_status = NULL; gboolean res = snapd_client_check_themes_finish(SNAPD_CLIENT(object), result, >k_status, &icon_status, &sound_status, &error); g_assert_no_error(error); g_assert_true(res); g_assert_nonnull(gtk_status); g_assert_nonnull(icon_status); g_assert_nonnull(sound_status); g_assert_cmpint(g_hash_table_size(gtk_status), ==, 3); g_assert_cmpint(GPOINTER_TO_INT(g_hash_table_lookup(gtk_status, "gtktheme1")), ==, SNAPD_THEME_STATUS_INSTALLED); g_assert_cmpint(GPOINTER_TO_INT(g_hash_table_lookup(gtk_status, "gtktheme2")), ==, SNAPD_THEME_STATUS_AVAILABLE); g_assert_cmpint(GPOINTER_TO_INT(g_hash_table_lookup(gtk_status, "gtktheme3")), ==, SNAPD_THEME_STATUS_UNAVAILABLE); g_assert_cmpint(g_hash_table_size(icon_status), ==, 3); g_assert_cmpint( GPOINTER_TO_INT(g_hash_table_lookup(icon_status, "icontheme1")), ==, SNAPD_THEME_STATUS_INSTALLED); g_assert_cmpint( GPOINTER_TO_INT(g_hash_table_lookup(icon_status, "icontheme2")), ==, SNAPD_THEME_STATUS_AVAILABLE); g_assert_cmpint( GPOINTER_TO_INT(g_hash_table_lookup(icon_status, "icontheme3")), ==, SNAPD_THEME_STATUS_UNAVAILABLE); g_assert_cmpint(g_hash_table_size(sound_status), ==, 3); g_assert_cmpint( GPOINTER_TO_INT(g_hash_table_lookup(sound_status, "soundtheme1")), ==, SNAPD_THEME_STATUS_INSTALLED); g_assert_cmpint( GPOINTER_TO_INT(g_hash_table_lookup(sound_status, "soundtheme2")), ==, SNAPD_THEME_STATUS_AVAILABLE); g_assert_cmpint( GPOINTER_TO_INT(g_hash_table_lookup(sound_status, "soundtheme3")), ==, SNAPD_THEME_STATUS_UNAVAILABLE); g_main_loop_quit(data->loop); } static void test_themes_check_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_gtk_theme_status(snapd, "gtktheme1", "installed"); mock_snapd_set_gtk_theme_status(snapd, "gtktheme2", "available"); mock_snapd_set_gtk_theme_status(snapd, "gtktheme3", "unavailable"); mock_snapd_set_icon_theme_status(snapd, "icontheme1", "installed"); mock_snapd_set_icon_theme_status(snapd, "icontheme2", "available"); mock_snapd_set_icon_theme_status(snapd, "icontheme3", "unavailable"); mock_snapd_set_sound_theme_status(snapd, "soundtheme1", "installed"); mock_snapd_set_sound_theme_status(snapd, "soundtheme2", "available"); mock_snapd_set_sound_theme_status(snapd, "soundtheme3", "unavailable"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); char *gtk_themes[] = {"gtktheme1", "gtktheme2", "gtktheme3", NULL}; char *icon_themes[] = {"icontheme1", "icontheme2", "icontheme3", NULL}; char *sound_themes[] = {"soundtheme1", "soundtheme2", "soundtheme3", NULL}; snapd_client_check_themes_async(client, gtk_themes, icon_themes, sound_themes, NULL, check_themes_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_themes_install_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); mock_snapd_set_gtk_theme_status(snapd, "gtktheme1", "available"); mock_snapd_set_icon_theme_status(snapd, "icontheme1", "available"); mock_snapd_set_sound_theme_status(snapd, "soundtheme1", "available"); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); char *gtk_themes[] = {"gtktheme1", NULL}; char *icon_themes[] = {"icontheme1", NULL}; char *sound_themes[] = {"soundtheme1", NULL}; gboolean result = snapd_client_install_themes_sync( client, gtk_themes, icon_themes, sound_themes, NULL, NULL, NULL, &error); g_assert_no_error(error); g_assert_true(result); } static void install_themes_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean res = snapd_client_install_themes_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(res); g_main_loop_quit(data->loop); } static void test_themes_install_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_gtk_theme_status(snapd, "gtktheme1", "available"); mock_snapd_set_icon_theme_status(snapd, "icontheme1", "available"); mock_snapd_set_sound_theme_status(snapd, "soundtheme1", "available"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); char *gtk_themes[] = {"gtktheme1", NULL}; char *icon_themes[] = {"icontheme1", NULL}; char *sound_themes[] = {"soundtheme1", NULL}; snapd_client_install_themes_async( client, gtk_themes, icon_themes, sound_themes, NULL, NULL, NULL, install_themes_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_themes_install_no_snaps(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); mock_snapd_set_gtk_theme_status(snapd, "gtktheme1", "installed"); mock_snapd_set_icon_theme_status(snapd, "icontheme1", "unavailable"); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); char *gtk_themes[] = {"gtktheme1", NULL}; char *icon_themes[] = {"icontheme1", NULL}; char *sound_themes[] = {NULL}; gboolean result = snapd_client_install_themes_sync( client, gtk_themes, icon_themes, sound_themes, NULL, NULL, NULL, &error); g_assert_false(result); g_assert_error(error, SNAPD_ERROR, SNAPD_ERROR_BAD_REQUEST); } static void test_themes_install_progress(void) { InstallProgressData install_progress_data; install_progress_data.progress_done = 0; install_progress_data.spawn_time = "2017-01-02T11:23:58Z"; install_progress_data.ready_time = "2017-01-03T00:00:00Z"; g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_set_spawn_time(snapd, install_progress_data.spawn_time); mock_snapd_set_ready_time(snapd, install_progress_data.ready_time); mock_snapd_set_gtk_theme_status(snapd, "gtktheme1", "available"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); char *gtk_themes[] = {"gtktheme1", NULL}; char *icon_themes[] = {"icontheme1", NULL}; char *sound_themes[] = {NULL}; gboolean result = snapd_client_install_themes_sync( client, gtk_themes, icon_themes, sound_themes, install_progress_cb, &install_progress_data, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_cmpint(install_progress_data.progress_done, >, 0); } static void test_get_logs_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_log(snapd, "2023-06-15T23:20:40Z", "first", "cups.cups-browsed", "1234"); mock_snapd_add_log(snapd, "2023-06-16T00:20:40Z", "second", "cups.cups-browsed", "1234"); mock_snapd_add_log(snapd, "2023-06-16T03:20:40Z", "third", "cups.cups-browsed", "1234"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) logs = snapd_client_get_logs_sync(client, NULL, 0, NULL, &error); g_assert_no_error(error); g_assert_nonnull(logs); g_assert_cmpint(logs->len, ==, 3); SnapdLog *log = logs->pdata[0]; g_assert_true( date_matches(snapd_log_get_timestamp(log), 2023, 6, 15, 23, 20, 40)); g_assert_cmpstr(snapd_log_get_message(log), ==, "first"); g_assert_cmpstr(snapd_log_get_sid(log), ==, "cups.cups-browsed"); g_assert_cmpstr(snapd_log_get_pid(log), ==, "1234"); log = logs->pdata[1]; g_assert_true( date_matches(snapd_log_get_timestamp(log), 2023, 6, 16, 0, 20, 40)); g_assert_cmpstr(snapd_log_get_message(log), ==, "second"); g_assert_cmpstr(snapd_log_get_sid(log), ==, "cups.cups-browsed"); g_assert_cmpstr(snapd_log_get_pid(log), ==, "1234"); log = logs->pdata[2]; g_assert_true( date_matches(snapd_log_get_timestamp(log), 2023, 6, 16, 3, 20, 40)); g_assert_cmpstr(snapd_log_get_message(log), ==, "third"); g_assert_cmpstr(snapd_log_get_sid(log), ==, "cups.cups-browsed"); g_assert_cmpstr(snapd_log_get_pid(log), ==, "1234"); } static void get_logs_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) logs = snapd_client_get_logs_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(logs); g_assert_cmpint(logs->len, ==, 3); SnapdLog *log = logs->pdata[0]; g_assert_true( date_matches(snapd_log_get_timestamp(log), 2023, 6, 15, 23, 20, 40)); g_assert_cmpstr(snapd_log_get_message(log), ==, "first"); g_assert_cmpstr(snapd_log_get_sid(log), ==, "cups.cups-browsed"); g_assert_cmpstr(snapd_log_get_pid(log), ==, "1234"); log = logs->pdata[1]; g_assert_true( date_matches(snapd_log_get_timestamp(log), 2023, 6, 16, 0, 20, 40)); g_assert_cmpstr(snapd_log_get_message(log), ==, "second"); g_assert_cmpstr(snapd_log_get_sid(log), ==, "cups.cups-browsed"); g_assert_cmpstr(snapd_log_get_pid(log), ==, "1234"); log = logs->pdata[2]; g_assert_true( date_matches(snapd_log_get_timestamp(log), 2023, 6, 16, 3, 20, 40)); g_assert_cmpstr(snapd_log_get_message(log), ==, "third"); g_assert_cmpstr(snapd_log_get_sid(log), ==, "cups.cups-browsed"); g_assert_cmpstr(snapd_log_get_pid(log), ==, "1234"); g_main_loop_quit(data->loop); } static void test_get_logs_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_log(snapd, "2023-06-15T23:20:40Z", "first", "cups.cups-browsed", "1234"); mock_snapd_add_log(snapd, "2023-06-16T00:20:40Z", "second", "cups.cups-browsed", "1234"); mock_snapd_add_log(snapd, "2023-06-16T03:20:40Z", "third", "cups.cups-browsed", "1234"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_logs_async(client, NULL, 0, NULL, get_logs_cb, async_data_new(loop, snapd)); g_main_loop_run(loop); } static void test_get_logs_names(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_log(snapd, "2023-06-15T23:20:40Z", "first", "snap1.app1", "1234"); mock_snapd_add_log(snapd, "2023-06-16T00:20:40Z", "second", "snap2.app2", "1234"); mock_snapd_add_log(snapd, "2023-06-16T03:20:40Z", "third", "snap3.app3", "1234"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_auto(GStrv) names = g_strsplit("snap1.app1;snap3.app3", ";", -1); g_autoptr(GPtrArray) logs = snapd_client_get_logs_sync(client, names, 0, NULL, &error); g_assert_no_error(error); g_assert_nonnull(logs); g_assert_cmpint(logs->len, ==, 2); g_assert_cmpstr(snapd_log_get_sid(logs->pdata[0]), ==, "snap1.app1"); g_assert_cmpstr(snapd_log_get_sid(logs->pdata[1]), ==, "snap3.app3"); } static void test_get_logs_limit(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_log(snapd, "2023-06-15T23:20:40Z", "first", "cups.cups-browsed", "1234"); mock_snapd_add_log(snapd, "2023-06-16T00:20:40Z", "second", "cups.cups-browsed", "1234"); mock_snapd_add_log(snapd, "2023-06-16T03:20:40Z", "third", "cups.cups-browsed", "1234"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) logs = snapd_client_get_logs_sync(client, NULL, 1, NULL, &error); g_assert_no_error(error); g_assert_nonnull(logs); g_assert_cmpint(logs->len, ==, 1); } static void test_stress(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); for (gint i = 0; i < 10000; i++) { g_autoptr(GError) error = NULL; g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(info); g_assert_cmpstr(snapd_system_information_get_version(info), ==, "VERSION"); } } static void sync_log_cb(SnapdClient *client, SnapdLog *log, gpointer user_data) { int *counter = user_data; (*counter)++; } static void test_follow_logs_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_log(snapd, "2023-06-15T23:20:40Z", "first", "cups.cups-browsed", "1234"); mock_snapd_add_log(snapd, "2023-06-16T00:20:40Z", "second", "cups.cups-browsed", "1234"); mock_snapd_add_log(snapd, "2023-06-16T03:20:40Z", "third", "cups.cups-browsed", "1234"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); int counter = 0; gboolean result = snapd_client_follow_logs_sync(client, NULL, sync_log_cb, &counter, NULL, &error); g_assert_no_error(error); g_assert_true(result); g_assert_cmpint(counter, ==, 3); } static void async_log_cb(SnapdClient *client, SnapdLog *log, gpointer user_data) { // This callback is called several times. Also, the same data // memory block is used in the `follow_logs_cb()` callback. // This is why it must not be freed here. AsyncData *data = user_data; data->counter++; } static void follow_logs_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; gboolean r = snapd_client_follow_logs_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_true(r); g_assert_cmpint(data->counter, ==, 3); g_main_loop_quit(data->loop); } static void test_follow_logs_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); mock_snapd_add_log(snapd, "2023-06-15T23:20:40Z", "first", "cups.cups-browsed", "1234"); mock_snapd_add_log(snapd, "2023-06-16T00:20:40Z", "second", "cups.cups-browsed", "1234"); mock_snapd_add_log(snapd, "2023-06-16T03:20:40Z", "third", "cups.cups-browsed", "1234"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); AsyncData *data = async_data_new(loop, snapd); snapd_client_follow_logs_async(client, NULL, async_log_cb, data, NULL, follow_logs_cb, data); g_main_loop_run(loop); } static void test_get_changes_data(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); MockChange *c = mock_snapd_add_change(snapd); g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); json_builder_set_member_name(builder, "snap-names"); json_builder_begin_array(builder); json_builder_add_string_value(builder, "snap1"); json_builder_add_string_value(builder, "snap2"); json_builder_add_string_value(builder, "snap3"); json_builder_end_array(builder); json_builder_set_member_name(builder, "refresh-forced"); json_builder_begin_array(builder); json_builder_add_string_value(builder, "snap_forced1"); json_builder_add_string_value(builder, "snap_forced2"); json_builder_end_array(builder); json_builder_end_object(builder); JsonNode *node = json_builder_get_root(builder); mock_change_add_data(c, node); mock_change_set_kind(c, "auto-refresh"); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(GPtrArray) changes = snapd_client_get_changes_sync( client, SNAPD_CHANGE_FILTER_ALL, NULL, NULL, &error); g_assert_no_error(error); g_assert_nonnull(changes); g_assert_cmpint(changes->len, ==, 1); SnapdAutorefreshChangeData *data = SNAPD_AUTOREFRESH_CHANGE_DATA( snapd_change_get_data(SNAPD_CHANGE(changes->pdata[0]))); g_assert_nonnull(data); GStrv snap_names = snapd_autorefresh_change_data_get_snap_names(data); g_assert_nonnull(snap_names); g_assert_cmpint(g_strv_length(snap_names), ==, 3); g_assert_true(g_str_equal(snap_names[0], "snap1")); g_assert_true(g_str_equal(snap_names[1], "snap2")); g_assert_true(g_str_equal(snap_names[2], "snap3")); GStrv refresh_forced = snapd_autorefresh_change_data_get_refresh_forced(data); g_assert_nonnull(refresh_forced); g_assert_cmpint(g_strv_length(refresh_forced), ==, 2); g_assert_true(g_str_equal(refresh_forced[0], "snap_forced1")); g_assert_true(g_str_equal(refresh_forced[1], "snap_forced2")); json_node_unref(node); } /* Notices example { "type":"sync", "status-code":200, "status":"OK", "result":[ { "id":"1", "user-id":null, "type":"change-update", "key":"8473", "first-occurred":"2024-03-27T11:34:53.34609455Z", "last-occurred":"2024-03-27T11:34:54.847953897Z", "last-repeated":"2024-03-27T11:34:54.847953897Z", "occurrences":3, "last-data":{ "kind":"install-snap" }, "expire-after":"168h0m0s" },{ "id":"2", "user-id":null, "type":"change-update", "key":"8474", "first-occurred":"2024-03-27T16:15:09.871332485Z", "last-occurred":"2024-03-27T16:15:43.702284133Z", "last-repeated":"2024-03-27T16:15:43.702284133Z", "occurrences":3, "last-data":{ "kind":"refresh-snap" }, "expire-after":"168h0m0s" } ] } */ void test_notices_events_cb(GObject *object, GAsyncResult *result, gpointer user_data) { AsyncData *data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) notices = snapd_client_get_notices_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(notices); g_autoptr(SnapdNotice) notice1 = g_object_ref(notices->pdata[0]); g_autoptr(SnapdNotice) notice2 = NULL; g_autoptr(GTimeZone) timezone = g_time_zone_new_utc(); g_assert_cmpstr(snapd_notice_get_id(notice1), ==, "1"); g_assert_null(snapd_notice_get_user_id(notice1)); g_assert_cmpint(snapd_notice_get_expire_after(notice1), ==, 382 * G_TIME_SPAN_DAY + 4 * G_TIME_SPAN_HOUR + 5 * G_TIME_SPAN_MINUTE + 6 * G_TIME_SPAN_SECOND + 7 * G_TIME_SPAN_MILLISECOND + 8); g_assert_cmpint(snapd_notice_get_repeat_after(notice1), ==, -(382 * G_TIME_SPAN_DAY + 4 * G_TIME_SPAN_HOUR + 5 * G_TIME_SPAN_MINUTE + 6 * G_TIME_SPAN_SECOND + 7 * G_TIME_SPAN_MILLISECOND + 8)); g_autoptr(GDateTime) date1 = g_date_time_new(timezone, 2024, 3, 1, 20, 29, 58); g_autoptr(GDateTime) date2 = g_date_time_new(timezone, 2025, 4, 2, 23, 28, 8); g_autoptr(GDateTime) date3 = g_date_time_new(timezone, 2026, 5, 3, 22, 20, 7); g_assert_true( g_date_time_equal(snapd_notice_get_first_occurred2(notice1), date1)); g_assert_true( g_date_time_equal(snapd_notice_get_last_occurred2(notice1), date2)); g_assert_true( g_date_time_equal(snapd_notice_get_last_repeated2(notice1), date3)); g_assert_true(snapd_notice_get_notice_type(notice1) == SNAPD_NOTICE_TYPE_UNKNOWN); g_assert_cmpint(snapd_notice_get_occurrences(notice1), ==, 5); GHashTable *notice_data1 = snapd_notice_get_last_data2(notice1); g_assert_nonnull(notice_data1); g_assert_cmpint(g_hash_table_size(notice_data1), ==, 0); if (data->counter == 0) { g_assert_cmpint(notices->len, ==, 2); notice2 = g_object_ref(notices->pdata[1]); g_assert_cmpstr(snapd_notice_get_id(notice2), ==, "2"); g_assert_cmpstr(snapd_notice_get_user_id(notice2), ==, "67"); #if GLIB_CHECK_VERSION(2, 68, 0) g_autoptr(GTimeZone) timezone2 = g_time_zone_new_identifier("01:32"); #else g_autoptr(GTimeZone) timezone2 = g_time_zone_new("01:32"); #endif g_autoptr(GDateTime) date4 = g_date_time_new(timezone2, 2023, 2, 5, 21, 23, 3); g_autoptr(GDateTime) date5 = g_date_time_new(timezone2, 2023, 2, 5, 21, 23, 3.000123); g_assert_true( g_date_time_equal(snapd_notice_get_first_occurred2(notice2), date4)); g_assert_true( g_date_time_equal(snapd_notice_get_last_occurred2(notice2), date5)); g_assert_true( g_date_time_equal(snapd_notice_get_last_repeated2(notice2), date4)); g_assert_cmpint(snapd_notice_get_occurrences(notice2), ==, 1); g_assert_true(snapd_notice_get_notice_type(notice2) == SNAPD_NOTICE_TYPE_REFRESH_INHIBIT); GHashTable *notice_data2 = snapd_notice_get_last_data2(notice2); g_assert_nonnull(notice_data2); g_assert_cmpint(g_hash_table_size(notice_data2), ==, 1); g_assert_true(g_hash_table_contains(notice_data2, "kind")); g_assert_cmpstr(g_hash_table_lookup(notice_data2, "kind"), ==, "change-kind"); } else { g_assert_cmpint(notices->len, ==, 1); } // Test it twice, to ensure that multiple calls do work if (data->counter == 0) { // this was done without parameters gchar *parameters = mock_snapd_get_notices_parameters(data->snapd); g_assert_null(parameters); data->counter++; g_autoptr(GDateTime) date5 = g_date_time_new(timezone, 2023, 2, 5, 21, 23, 58.123456789); snapd_client_get_notices_with_filters_async( SNAPD_CLIENT(object), "an_user_id", "id1, id2, an_utf8_íd", "type1,type2", "key1,key2", date5, 20000, NULL, test_notices_events_cb, data); } else { // and this one with parameters g_autoptr(GHashTable) parameters = g_uri_parse_params(mock_snapd_get_notices_parameters(data->snapd), -1, "&", G_URI_PARAMS_NONE, NULL); g_assert_nonnull(parameters); g_assert_cmpint(g_hash_table_size(parameters), ==, 6); g_assert_true(g_hash_table_contains(parameters, "user-id")); g_assert_cmpstr(g_hash_table_lookup(parameters, "user-id"), ==, "an_user_id"); g_assert_true(g_hash_table_contains(parameters, "users")); g_assert_cmpstr(g_hash_table_lookup(parameters, "users"), ==, "id1, id2, an_utf8_íd"); g_assert_true(g_hash_table_contains(parameters, "types")); g_assert_cmpstr(g_hash_table_lookup(parameters, "types"), ==, "type1,type2"); g_assert_true(g_hash_table_contains(parameters, "keys")); g_assert_cmpstr(g_hash_table_lookup(parameters, "keys"), ==, "key1,key2"); g_assert_true(g_hash_table_contains(parameters, "after")); g_assert_cmpstr(g_hash_table_lookup(parameters, "after"), ==, "2023-02-05T21:23:58.123456+00:00"); g_assert_true(g_hash_table_contains(parameters, "timeout")); g_assert_cmpstr(g_hash_table_lookup(parameters, "timeout"), ==, "20000us"); g_main_loop_quit(data->loop); } } static void test_notices_events(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); // In this case, we define the `data` struct with g_autoptr // because the callback can be called several times, so this // ensures that it is freed only when no more callbacks will be // serviced. We can do this because in this tests we are // using a new mainloop, which only returns after g_main_loop_quit() // has been called. g_autoptr(AsyncData) data = async_data_new(loop, snapd); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); MockNotice *notice = mock_snapd_add_notice(snapd, "1", "8473", "refresh-snap"); mock_notice_set_expire_after(notice, "1y2w3d4h5m6s7ms8us9ns"); mock_notice_set_repeat_after(notice, "-1y2w3d4h5m6s7ms8µs9ns"); g_autoptr(GTimeZone) timezone = g_time_zone_new_utc(); g_autoptr(GDateTime) date1 = g_date_time_new(timezone, 2024, 3, 1, 20, 29, 58); g_autoptr(GDateTime) date2 = g_date_time_new(timezone, 2025, 4, 2, 23, 28, 8); g_autoptr(GDateTime) date3 = g_date_time_new(timezone, 2026, 5, 3, 22, 20, 7); mock_notice_set_dates(notice, date1, date2, date3, 5); notice = mock_snapd_add_notice(snapd, "2", "8474", "refresh-inhibit"); mock_notice_set_nanoseconds(notice, 123456); mock_notice_set_user_id(notice, "67"); #if GLIB_CHECK_VERSION(2, 68, 0) g_autoptr(GTimeZone) timezone2 = g_time_zone_new_identifier("01:32"); #else g_autoptr(GTimeZone) timezone2 = g_time_zone_new("01:32"); #endif g_autoptr(GDateTime) date4 = g_date_time_new(timezone2, 2023, 2, 5, 21, 23, 3); mock_notice_set_dates(notice, date4, date4, date4, 1); mock_notice_add_data_pair(notice, "kind", "change-kind"); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_notices_async(client, NULL, 0, NULL, test_notices_events_cb, data); g_main_loop_run(loop); } void test_notices_minimal_data_events_cb(GObject *object, GAsyncResult *result, gpointer user_data) { AsyncData *data = user_data; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) notices = snapd_client_get_notices_finish(SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(notices); g_assert_cmpint(notices->len, ==, 1); g_autoptr(SnapdNotice) notice1 = g_object_ref(notices->pdata[0]); g_assert_cmpstr(snapd_notice_get_id(notice1), ==, "1"); g_assert_null(snapd_notice_get_user_id(notice1)); g_assert_cmpint(snapd_notice_get_expire_after(notice1), ==, 0); g_assert_cmpint(snapd_notice_get_repeat_after(notice1), ==, 0); g_assert_null(snapd_notice_get_first_occurred2(notice1)); g_assert_null(snapd_notice_get_last_occurred2(notice1)); g_assert_null(snapd_notice_get_last_repeated2(notice1)); g_assert_true(snapd_notice_get_notice_type(notice1) == SNAPD_NOTICE_TYPE_UNKNOWN); g_assert_cmpint(snapd_notice_get_occurrences(notice1), ==, -1); GHashTable *notice_data = snapd_notice_get_last_data2(notice1); g_assert_nonnull(notice_data); g_assert_cmpint(g_hash_table_size(notice_data), ==, 0); // Test it twice, to ensure that multiple calls do work if (data->counter == 0) { data->counter++; g_autoptr(GTimeZone) timezone = g_time_zone_new_utc(); g_autoptr(GDateTime) date5 = g_date_time_new(timezone, 2029, 3, 1, 20, 29, 58.123456789); g_autoptr(SnapdNotice) noticeTest = g_object_new(SNAPD_TYPE_NOTICE, "id", "an-id", "last-occurred-nanoseconds", 12345678, NULL); snapd_client_notices_set_after_notice(SNAPD_CLIENT(object), noticeTest); snapd_client_get_notices_async(SNAPD_CLIENT(object), date5, 0, NULL, test_notices_minimal_data_events_cb, data); } else { g_autoptr(GHashTable) parameters = g_uri_parse_params(mock_snapd_get_notices_parameters(data->snapd), -1, "&", G_URI_PARAMS_NONE, NULL); g_assert_nonnull(parameters); g_assert_cmpint(g_hash_table_size(parameters), ==, 1); g_assert_true(g_hash_table_contains(parameters, "after")); g_assert_cmpstr(g_hash_table_lookup(parameters, "after"), ==, "2029-03-01T20:29:58.012345678+00:00"); g_main_loop_quit(data->loop); } } static void test_notices_events_with_minimal_data(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); // In this case, we define the `data` struct with g_autoptr // because the callback can be called several times, so this // ensures that it is freed only when no more callbacks will be // serviced. We can do this because in this tests we are // using a new mainloop, which only returns after g_main_loop_quit() // has been called. g_autoptr(AsyncData) data = async_data_new(loop, snapd); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); mock_snapd_add_notice(snapd, "1", "8473", "refresh-snap"); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); snapd_client_get_notices_async(client, NULL, 0, NULL, test_notices_minimal_data_events_cb, data); g_main_loop_run(loop); } static void test_notice_comparison(void) { g_autoptr(GTimeZone) timezone = g_time_zone_new_utc(); g_autoptr(GDateTime) date0 = g_date_time_new(timezone, 2023, 5, 3, 22, 20, 7); g_autoptr(GDateTime) date1 = g_date_time_new(timezone, 2024, 3, 1, 20, 29, 58.45); g_autoptr(GDateTime) date2 = g_date_time_new(timezone, 2025, 4, 2, 23, 28, 8); g_autoptr(SnapdNotice) notice0 = g_object_new(SNAPD_TYPE_NOTICE, "id", "id1", "last-occurred", date1, "last-occurred-nanoseconds", 123456788, NULL); g_autoptr(SnapdNotice) notice1 = g_object_new(SNAPD_TYPE_NOTICE, "id", "id1", "last-occurred", date1, "last-occurred-nanoseconds", 123456789, NULL); g_autoptr(SnapdNotice) notice2 = g_object_new(SNAPD_TYPE_NOTICE, "id", "id2", "last-occurred", date1, "last-occurred-nanoseconds", 123456789, NULL); g_autoptr(SnapdNotice) notice3 = g_object_new(SNAPD_TYPE_NOTICE, "id", "id3", "last-occurred", date1, "last-occurred-nanoseconds", 123456790, NULL); g_autoptr(SnapdNotice) notice4 = g_object_new(SNAPD_TYPE_NOTICE, "id", "id4", "last-occurred", date0, "last-occurred-nanoseconds", 123456789, NULL); g_autoptr(SnapdNotice) notice5 = g_object_new(SNAPD_TYPE_NOTICE, "id", "id5", "last-occurred", date2, "last-occurred-nanoseconds", 123456789, NULL); g_assert_true(snapd_notice_compare_last_occurred(notice1, notice0) == 1); g_assert_true(snapd_notice_compare_last_occurred(notice1, notice2) == 0); g_assert_true(snapd_notice_compare_last_occurred(notice1, notice3) == -1); g_assert_true(snapd_notice_compare_last_occurred(notice1, notice4) == 1); g_assert_true(snapd_notice_compare_last_occurred(notice1, notice5) == -1); } static void test_error_get_change(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); MockChange *change = mock_snapd_add_change(snapd); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); error = NULL; g_autoptr(SnapdChange) change1 = snapd_client_get_change_sync( client, mock_change_get_id(change), NULL, &error); g_assert_nonnull(change1); g_assert_null(error); g_autoptr(SnapdChange) change2 = snapd_client_get_change_sync(client, "aninexistentID", NULL, &error); g_assert_null(change2); g_assert_nonnull(error); } static void test_task_data_field(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); MockChange *change = mock_snapd_add_change(snapd); MockTask *task1 = mock_change_add_task(change, "task1"); mock_task_add_affected_snap(task1, "telegram-desktop"); mock_task_add_affected_snap(task1, "cups"); MockTask *task2 = mock_change_add_task(change, "task2"); mock_task_add_affected_snap(task2, "cups"); mock_change_add_task(change, "task3"); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autoptr(SnapdChange) change1 = snapd_client_get_change_sync( client, mock_change_get_id(change), NULL, &error); g_assert_nonnull(change1); g_assert_null(error); GPtrArray *tasks = snapd_change_get_tasks(change1); g_assert_nonnull(tasks); g_assert_cmpint(tasks->len, ==, 3); SnapdTask *task_1 = tasks->pdata[0]; g_assert_nonnull(task_1); SnapdTask *task_2 = tasks->pdata[1]; g_assert_nonnull(task_2); SnapdTask *task_3 = tasks->pdata[2]; g_assert_nonnull(task_3); SnapdTaskData *data1 = snapd_task_get_data(task_1); g_assert_nonnull(data1); GStrv affected_snaps1 = snapd_task_data_get_affected_snaps(data1); g_assert_nonnull(affected_snaps1); g_assert_cmpint(g_strv_length(affected_snaps1), ==, 2); g_assert_true(g_str_equal(affected_snaps1[0], "telegram-desktop")); g_assert_true(g_str_equal(affected_snaps1[1], "cups")); SnapdTaskData *data2 = snapd_task_get_data(task_2); g_assert_nonnull(data2); GStrv affected_snaps2 = snapd_task_data_get_affected_snaps(data2); g_assert_nonnull(affected_snaps2); g_assert_cmpint(g_strv_length(affected_snaps2), ==, 1); g_assert_true(g_str_equal(affected_snaps2[0], "cups")); SnapdTaskData *data3 = snapd_task_get_data(task_3); g_assert_null(data3); } static void test_get_model_assertion_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autofree gchar *model_assertion = snapd_client_get_model_assertion_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(model_assertion); g_assert_cmpstr(model_assertion, ==, "type: model\n\nSIGNATURE"); } static void get_model_assertion_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autofree gchar *model_assertion = snapd_client_get_model_assertion_finish( SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(model_assertion); g_assert_cmpstr(model_assertion, ==, "type: model\n\nSIGNATURE"); g_main_loop_quit(data->loop); } static void test_get_model_assertion_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); AsyncData *data = async_data_new(loop, snapd); snapd_client_get_model_assertion_async(client, NULL, get_model_assertion_cb, data); g_main_loop_run(loop); } static void test_get_serial_assertion_sync(void) { g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); g_autofree gchar *serial_assertion = snapd_client_get_serial_assertion_sync(client, NULL, &error); g_assert_no_error(error); g_assert_nonnull(serial_assertion); g_assert_cmpstr(serial_assertion, ==, "type: serial\n\nSIGNATURE"); } static void get_serial_assertion_cb(GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(AsyncData) data = user_data; g_autoptr(GError) error = NULL; g_autofree gchar *serial_assertion = snapd_client_get_serial_assertion_finish( SNAPD_CLIENT(object), result, &error); g_assert_no_error(error); g_assert_nonnull(serial_assertion); g_assert_cmpstr(serial_assertion, ==, "type: serial\n\nSIGNATURE"); g_main_loop_quit(data->loop); } static void test_get_serial_assertion_async(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, mock_snapd_get_socket_path(snapd)); AsyncData *data = async_data_new(loop, snapd); snapd_client_get_serial_assertion_async(client, NULL, get_serial_assertion_cb, data); g_main_loop_run(loop); } static void test_abstract_socket(void) { g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); g_autoptr(MockSnapd) snapd = mock_snapd_new(); g_assert_nonnull(snapd); mock_snapd_use_abstract_socket(snapd); g_autoptr(GError) error = NULL; g_assert_true(mock_snapd_start(snapd, &error)); g_assert_null(error); const gchar *socket_path = mock_snapd_get_socket_path(snapd); g_assert_nonnull(socket_path); g_assert_cmpint(socket_path[0], ==, '@'); g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, socket_path); g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_nonnull(info); g_assert_null(error); } static void test_non_existent_abstract_socket(void) { g_autoptr(SnapdClient) client = snapd_client_new(); snapd_client_set_socket_path(client, "@/snapd/this-socket-doesn-t-exist"); g_autoptr(GError) error = NULL; g_autoptr(SnapdSystemInformation) info = snapd_client_get_system_information_sync(client, NULL, &error); g_assert_null(info); g_assert_nonnull(error); g_assert_cmpstr(error->message, ==, "Unable to connect snapd socket: Connection refused"); } int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); g_test_add_func("/socket/test_abstract_socket", test_abstract_socket); g_test_add_func("/socket/test_not_existing_abstract_socket", test_non_existent_abstract_socket); g_test_add_func("/notices/test_task_data_field", test_task_data_field); g_test_add_func("/errors/test_error_get_change", test_error_get_change); g_test_add_func("/notices/test_notices", test_notices_events); g_test_add_func("/notices/test_minimal_data", test_notices_events_with_minimal_data); g_test_add_func("/notices/test_notice_comparison", test_notice_comparison); g_test_add_func("/socket-closed/before-request", test_socket_closed_before_request); g_test_add_func("/socket-closed/after-request", test_socket_closed_after_request); g_test_add_func("/socket-closed/reconnect", test_socket_closed_reconnect); g_test_add_func("/socket-closed/reconnect-after-failure", test_socket_closed_reconnect_after_failure); g_test_add_func("/client/set-socket-path", test_client_set_socket_path); g_test_add_func("/user-agent/default", test_user_agent_default); g_test_add_func("/user-agent/custom", test_user_agent_custom); g_test_add_func("/user-agent/null", test_user_agent_null); g_test_add_func("/accept-language/basic", test_accept_language); g_test_add_func("/accept-language/empty", test_accept_language_empty); g_test_add_func("/allow-interaction/basic", test_allow_interaction); g_test_add_func("/maintenance/none", test_maintenance_none); g_test_add_func("/maintenance/daemon-restart", test_maintenance_daemon_restart); g_test_add_func("/maintenance/system-restart", test_maintenance_system_restart); g_test_add_func("/maintenance/unknown", test_maintenance_unknown); g_test_add_func("/get-system-information/sync", test_get_system_information_sync); g_test_add_func("/get-system-information/async", test_get_system_information_async); g_test_add_func("/get-system-information/store", test_get_system_information_store); g_test_add_func("/get-system-information/refresh", test_get_system_information_refresh); g_test_add_func("/get-system-information/refresh_schedule", test_get_system_information_refresh_schedule); g_test_add_func("/get-system-information/confinement_strict", test_get_system_information_confinement_strict); g_test_add_func("/get-system-information/confinement_none", test_get_system_information_confinement_none); g_test_add_func("/get-system-information/confinement_unknown", test_get_system_information_confinement_unknown); g_test_add_func("/login/sync", test_login_sync); g_test_add_func("/login/async", test_login_async); g_test_add_func("/login/invalid-email", test_login_invalid_email); g_test_add_func("/login/invalid-password", test_login_invalid_password); g_test_add_func("/login/otp-missing", test_login_otp_missing); g_test_add_func("/login/otp-invalid", test_login_otp_invalid); g_test_add_func("/login/legacy", test_login_legacy); g_test_add_func("/logout/sync", test_logout_sync); g_test_add_func("/logout/async", test_logout_async); g_test_add_func("/logout/no-auth", test_logout_no_auth); g_test_add_func("/get-changes/sync", test_get_changes_sync); g_test_add_func("/get-changes/async", test_get_changes_async); g_test_add_func("/get-changes/filter-in-progress", test_get_changes_filter_in_progress); g_test_add_func("/get-changes/filter-ready", test_get_changes_filter_ready); g_test_add_func("/get-changes/filter-snap", test_get_changes_filter_snap); g_test_add_func("/get-changes/filter-ready-snap", test_get_changes_filter_ready_snap); g_test_add_func("/get-changes/data", test_get_changes_data); g_test_add_func("/get-change/sync", test_get_change_sync); g_test_add_func("/get-change/async", test_get_change_async); g_test_add_func("/abort-change/sync", test_abort_change_sync); g_test_add_func("/abort-change/async", test_abort_change_async); g_test_add_func("/list/sync", test_list_sync); g_test_add_func("/list/async", test_list_async); g_test_add_func("/get-snaps/sync", test_get_snaps_sync); g_test_add_func("/get_snaps/inhibited", test_get_snaps_inhibited); g_test_add_func("/get-snaps/async", test_get_snaps_async); g_test_add_func("/get-snaps/filter", test_get_snaps_filter); g_test_add_func("/list-one/sync", test_list_one_sync); g_test_add_func("/list-one/async", test_list_one_async); g_test_add_func("/get-snap/sync", test_get_snap_sync); g_test_add_func("/get-snap/async", test_get_snap_async); g_test_add_func("/get-snap/types", test_get_snap_types); g_test_add_func("/get-snap/optional-fields", test_get_snap_optional_fields); g_test_add_func("/get-snap/deprecated-fields", test_get_snap_deprecated_fields); g_test_add_func("/get-snap/common-ids", test_get_snap_common_ids); g_test_add_func("/get-snap/not-installed", test_get_snap_not_installed); g_test_add_func("/get-snap/classic-confinement", test_get_snap_classic_confinement); g_test_add_func("/get-snap/devmode-confinement", test_get_snap_devmode_confinement); g_test_add_func("/get-snap/daemons", test_get_snap_daemons); g_test_add_func("/get-snap/publisher-starred", test_get_snap_publisher_starred); g_test_add_func("/get-snap/publisher-verified", test_get_snap_publisher_verified); g_test_add_func("/get-snap/publisher-unproven", test_get_snap_publisher_unproven); g_test_add_func("/get-snap/publisher-unknown-validation", test_get_snap_publisher_unknown_validation); g_test_add_func("/get-snap-conf/sync", test_get_snap_conf_sync); g_test_add_func("/get-snap-conf/async", test_get_snap_conf_async); g_test_add_func("/get-snap-conf/key-filter", test_get_snap_conf_key_filter); g_test_add_func("/get-snap-conf/invalid-key", test_get_snap_conf_invalid_key); g_test_add_func("/set-snap-conf/sync", test_set_snap_conf_sync); g_test_add_func("/set-snap-conf/async", test_set_snap_conf_async); g_test_add_func("/set-snap-conf/invalid", test_set_snap_conf_invalid); g_test_add_func("/get-apps/sync", test_get_apps_sync); g_test_add_func("/get-apps/async", test_get_apps_async); g_test_add_func("/get-apps/services", test_get_apps_services); g_test_add_func("/get-apps/filter", test_get_apps_filter); g_test_add_func("/icon/sync", test_icon_sync); g_test_add_func("/icon/async", test_icon_async); g_test_add_func("/icon/not-installed", test_icon_not_installed); g_test_add_func("/icon/large", test_icon_large); g_test_add_func("/get-assertions/sync", test_get_assertions_sync); // g_test_add_func ("/get-assertions/async", test_get_assertions_async); g_test_add_func("/get-assertions/body", test_get_assertions_body); g_test_add_func("/get-assertions/multiple", test_get_assertions_multiple); g_test_add_func("/get-assertions/invalid", test_get_assertions_invalid); g_test_add_func("/add-assertions/sync", test_add_assertions_sync); // g_test_add_func ("/add-assertions/async", test_add_assertions_async); g_test_add_func("/assertions/sync", test_assertions_sync); // g_test_add_func ("/assertions/async", test_assertions_async); g_test_add_func("/assertions/body", test_assertions_body); g_test_add_func("/get-connections/sync", test_get_connections_sync); g_test_add_func("/get-connections/async", test_get_connections_async); g_test_add_func("/get-connections/empty", test_get_connections_empty); g_test_add_func("/get-connections/filter-all", test_get_connections_filter_all); g_test_add_func("/get-connections/filter-snap", test_get_connections_filter_snap); g_test_add_func("/get-connections/filter-interface", test_get_connections_filter_interface); g_test_add_func("/get-connections/attributes", test_get_connections_attributes); g_test_add_func("/get-interfaces/sync", test_get_interfaces_sync); g_test_add_func("/get-interfaces/async", test_get_interfaces_async); g_test_add_func("/get-interfaces/no-snaps", test_get_interfaces_no_snaps); g_test_add_func("/get-interfaces/attributes", test_get_interfaces_attributes); g_test_add_func("/get-interfaces/legacy", test_get_interfaces_legacy); g_test_add_func("/get-interfaces2/sync", test_get_interfaces2_sync); g_test_add_func("/get-interfaces2/async", test_get_interfaces2_async); g_test_add_func("/get-interfaces2/only-connected", test_get_interfaces2_only_connected); g_test_add_func("/get-interfaces2/slots", test_get_interfaces2_slots); g_test_add_func("/get-interfaces2/plugs", test_get_interfaces2_plugs); g_test_add_func("/get-interfaces2/filter", test_get_interfaces2_filter); g_test_add_func("/get-interfaces2/make-label", test_get_interfaces2_make_label); g_test_add_func("/connect-interface/sync", test_connect_interface_sync); g_test_add_func("/connect-interface/async", test_connect_interface_async); g_test_add_func("/connect-interface/progress", test_connect_interface_progress); g_test_add_func("/connect-interface/invalid", test_connect_interface_invalid); g_test_add_func("/disconnect-interface/sync", test_disconnect_interface_sync); g_test_add_func("/disconnect-interface/async", test_disconnect_interface_async); g_test_add_func("/disconnect-interface/progress", test_disconnect_interface_progress); g_test_add_func("/disconnect-interface/invalid", test_disconnect_interface_invalid); g_test_add_func("/find/query", test_find_query); g_test_add_func("/find/query-private", test_find_query_private); g_test_add_func("/find/query-private/not-logged-in", test_find_query_private_not_logged_in); g_test_add_func("/find/bad-query", test_find_bad_query); g_test_add_func("/find/network-timeout", test_find_network_timeout); g_test_add_func("/find/dns-failure", test_find_dns_failure); g_test_add_func("/find/name", test_find_name); g_test_add_func("/find/name-private", test_find_name_private); g_test_add_func("/find/name-private/not-logged-in", test_find_name_private_not_logged_in); g_test_add_func("/find/channels", test_find_channels); g_test_add_func("/find/channels-match", test_find_channels_match); g_test_add_func("/find/cancel", test_find_cancel); g_test_add_func("/find/section", test_find_section); g_test_add_func("/find/section-query", test_find_section_query); g_test_add_func("/find/section-name", test_find_section_name); g_test_add_func("/find/category", test_find_category); g_test_add_func("/find/category-query", test_find_category_query); g_test_add_func("/find/category-name", test_find_category_name); g_test_add_func("/find/scope-narrow", test_find_scope_narrow); g_test_add_func("/find/scope-wide", test_find_scope_wide); g_test_add_func("/find/common-id", test_find_common_id); g_test_add_func("/find/categories", test_find_categories); g_test_add_func("/find-refreshable/sync", test_find_refreshable_sync); g_test_add_func("/find-refreshable/async", test_find_refreshable_async); g_test_add_func("/find-refreshable/no-updates", test_find_refreshable_no_updates); g_test_add_func("/install/sync", test_install_sync); g_test_add_func("/install/sync-multiple", test_install_sync_multiple); g_test_add_func("/install/async", test_install_async); g_test_add_func("/install/async-multiple", test_install_async_multiple); g_test_add_func("/install/async-failure", test_install_async_failure); g_test_add_func("/install/async-cancel", test_install_async_cancel); g_test_add_func("/install/async-multiple-cancel-first", test_install_async_multiple_cancel_first); g_test_add_func("/install/async-multiple-cancel-last", test_install_async_multiple_cancel_last); g_test_add_func("/install/progress", test_install_progress); g_test_add_func("/install/needs-classic", test_install_needs_classic); g_test_add_func("/install/classic", test_install_classic); g_test_add_func("/install/not-classic", test_install_not_classic); g_test_add_func("/install/needs-classic-system", test_install_needs_classic_system); g_test_add_func("/install/needs-devmode", test_install_needs_devmode); g_test_add_func("/install/devmode", test_install_devmode); g_test_add_func("/install/dangerous", test_install_dangerous); g_test_add_func("/install/jailmode", test_install_jailmode); g_test_add_func("/install/channel", test_install_channel); g_test_add_func("/install/revision", test_install_revision); g_test_add_func("/install/not-available", test_install_not_available); g_test_add_func("/install/channel-not-available", test_install_channel_not_available); g_test_add_func("/install/revision-not-available", test_install_revision_not_available); g_test_add_func("/install/snapd-restart", test_install_snapd_restart); g_test_add_func("/install/async-snapd-restart", test_install_async_snapd_restart); g_test_add_func("/install/auth-cancelled", test_install_auth_cancelled); g_test_add_func("/install-stream/sync", test_install_stream_sync); g_test_add_func("/install-stream/async", test_install_stream_async); g_test_add_func("/install-stream/progress", test_install_stream_progress); g_test_add_func("/install-stream/classic", test_install_stream_classic); g_test_add_func("/install-stream/dangerous", test_install_stream_dangerous); g_test_add_func("/install-stream/devmode", test_install_stream_devmode); g_test_add_func("/install-stream/jailmode", test_install_stream_jailmode); g_test_add_func("/try/sync", test_try_sync); g_test_add_func("/try/async", test_try_async); g_test_add_func("/try/progress", test_try_progress); g_test_add_func("/try/not-a-snap", test_try_not_a_snap); g_test_add_func("/refresh/sync", test_refresh_sync); g_test_add_func("/refresh/async", test_refresh_async); g_test_add_func("/refresh/progress", test_refresh_progress); g_test_add_func("/refresh/channel", test_refresh_channel); g_test_add_func("/refresh/no-updates", test_refresh_no_updates); g_test_add_func("/refresh/not-installed", test_refresh_not_installed); g_test_add_func("/refresh/not-in-store", test_refresh_not_in_store); g_test_add_func("/refresh-all/sync", test_refresh_all_sync); g_test_add_func("/refresh-all/async", test_refresh_all_async); g_test_add_func("/refresh-all/progress", test_refresh_all_progress); g_test_add_func("/refresh-all/no-updates", test_refresh_all_no_updates); g_test_add_func("/remove/sync", test_remove_sync); g_test_add_func("/remove/async", test_remove_async); g_test_add_func("/remove/async-failure", test_remove_async_failure); g_test_add_func("/remove/async-cancel", test_remove_async_cancel); g_test_add_func("/remove/progress", test_remove_progress); g_test_add_func("/remove/not-installed", test_remove_not_installed); g_test_add_func("/remove/purge", test_remove_purge); g_test_add_func("/enable/sync", test_enable_sync); g_test_add_func("/enable/async", test_enable_async); g_test_add_func("/enable/progress", test_enable_progress); g_test_add_func("/enable/already-enabled", test_enable_already_enabled); g_test_add_func("/enable/not-installed", test_enable_not_installed); g_test_add_func("/disable/sync", test_disable_sync); g_test_add_func("/disable/async", test_disable_async); g_test_add_func("/disable/progress", test_disable_progress); g_test_add_func("/disable/already-disabled", test_disable_already_disabled); g_test_add_func("/disable/not-installed", test_disable_not_installed); g_test_add_func("/switch/sync", test_switch_sync); g_test_add_func("/switch/async", test_switch_async); g_test_add_func("/switch/progress", test_switch_progress); g_test_add_func("/switch/not-installed", test_switch_not_installed); g_test_add_func("/check-buy/sync", test_check_buy_sync); g_test_add_func("/check-buy/async", test_check_buy_async); g_test_add_func("/check-buy/no-terms-not-accepted", test_check_buy_terms_not_accepted); g_test_add_func("/check-buy/no-payment-methods", test_check_buy_no_payment_methods); g_test_add_func("/check-buy/not-logged-in", test_check_buy_not_logged_in); g_test_add_func("/buy/sync", test_buy_sync); g_test_add_func("/buy/async", test_buy_async); g_test_add_func("/buy/not-logged-in", test_buy_not_logged_in); g_test_add_func("/buy/not-available", test_buy_not_available); g_test_add_func("/buy/terms-not-accepted", test_buy_terms_not_accepted); g_test_add_func("/buy/no-payment-methods", test_buy_no_payment_methods); g_test_add_func("/buy/invalid-price", test_buy_invalid_price); g_test_add_func("/create-user/sync", test_create_user_sync); // g_test_add_func ("/create-user/async", test_create_user_async); g_test_add_func("/create-user/sudo", test_create_user_sudo); g_test_add_func("/create-user/known", test_create_user_known); g_test_add_func("/create-users/sync", test_create_users_sync); // g_test_add_func ("/create-users/async", test_create_users_async); g_test_add_func("/get-users/sync", test_get_users_sync); g_test_add_func("/get-users/async", test_get_users_async); g_test_add_func("/get-sections/sync", test_get_sections_sync); g_test_add_func("/get-sections/async", test_get_sections_async); g_test_add_func("/get-categories/sync", test_get_categories_sync); g_test_add_func("/get-categories/async", test_get_categories_async); g_test_add_func("/aliases/get-sync", test_aliases_get_sync); g_test_add_func("/aliases/get-async", test_aliases_get_async); g_test_add_func("/aliases/get-empty", test_aliases_get_empty); g_test_add_func("/aliases/alias-sync", test_aliases_alias_sync); g_test_add_func("/aliases/alias-async", test_aliases_alias_async); g_test_add_func("/aliases/unalias-sync", test_aliases_unalias_sync); g_test_add_func("/aliases/unalias-async", test_aliases_unalias_async); g_test_add_func("/aliases/unalias-no-snap-sync", test_aliases_unalias_no_snap_sync); g_test_add_func("/aliases/prefer-sync", test_aliases_prefer_sync); g_test_add_func("/aliases/prefer-async", test_aliases_prefer_async); g_test_add_func("/run-snapctl/sync", test_run_snapctl_sync); g_test_add_func("/run-snapctl/async", test_run_snapctl_async); g_test_add_func("/run-snapctl/unsuccessful", test_run_snapctl_unsuccessful); g_test_add_func("/run-snapctl/legacy", test_run_snapctl_legacy); g_test_add_func("/download/sync", test_download_sync); g_test_add_func("/download/async", test_download_async); g_test_add_func("/download/channel-revision", test_download_channel_revision); g_test_add_func("/themes/check/sync", test_themes_check_sync); g_test_add_func("/themes/check/async", test_themes_check_async); g_test_add_func("/themes/install/sync", test_themes_install_sync); g_test_add_func("/themes/install/async", test_themes_install_async); g_test_add_func("/themes/install/no-snaps", test_themes_install_no_snaps); g_test_add_func("/themes/install/progress", test_themes_install_progress); g_test_add_func("/get-logs/sync", test_get_logs_sync); g_test_add_func("/get-logs/async", test_get_logs_async); g_test_add_func("/get-logs/names", test_get_logs_names); g_test_add_func("/get-logs/limit", test_get_logs_limit); g_test_add_func("/follow-logs/sync", test_follow_logs_sync); g_test_add_func("/follow-logs/async", test_follow_logs_async); g_test_add_func("/get-model-assertion/sync", test_get_model_assertion_sync); g_test_add_func("/get-model-assertion/async", test_get_model_assertion_async); g_test_add_func("/get-serial-assertion/sync", test_get_serial_assertion_sync); g_test_add_func("/get-serial-assertion/async", test_get_serial_assertion_async); g_test_add_func("/stress/basic", test_stress); return g_test_run(); } snapd-glib-1.67/tests/test-glib.test.in000066400000000000000000000000761477073115000200410ustar00rootroot00000000000000[Test] Type=session Exec=@installed_tests_exec_dir@/test-glib snapd-glib-1.67/tests/test-markdown-glib.c000066400000000000000000001142501477073115000205170ustar00rootroot00000000000000/* * Copyright (C) 2019 Canonical Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2 or version 3 of the License. * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include #include static gchar *escape_text(const gchar *text) { g_autoptr(GString) escaped_text = g_string_new(""); for (const gchar *c = text; *c != '\0'; c++) { if (*c == '&') g_string_append(escaped_text, "&"); else if (*c == '<') g_string_append(escaped_text, "<"); else if (*c == '>') g_string_append(escaped_text, ">"); else if (*c == '"') g_string_append(escaped_text, """); else g_string_append_c(escaped_text, *c); } return g_steal_pointer(&escaped_text->str); } static gchar *serialize_node(SnapdMarkdownNode *node); static gchar *serialize_nodes(GPtrArray *nodes) { g_autoptr(GString) text = g_string_new(""); for (int i = 0; i < nodes->len; i++) { SnapdMarkdownNode *node = g_ptr_array_index(nodes, i); g_autofree gchar *node_text = serialize_node(node); g_string_append(text, node_text); } return g_steal_pointer(&text->str); } static gchar *serialize_node(SnapdMarkdownNode *node) { GPtrArray *children = snapd_markdown_node_get_children(node); g_autofree gchar *contents = NULL; switch (snapd_markdown_node_get_node_type(node)) { case SNAPD_MARKDOWN_NODE_TYPE_TEXT: return escape_text(snapd_markdown_node_get_text(node)); case SNAPD_MARKDOWN_NODE_TYPE_PARAGRAPH: contents = serialize_nodes(children); return g_strdup_printf("

%s

\n", contents); case SNAPD_MARKDOWN_NODE_TYPE_UNORDERED_LIST: contents = serialize_nodes(children); return g_strdup_printf("
    \n%s
\n", contents); case SNAPD_MARKDOWN_NODE_TYPE_LIST_ITEM: if (children->len == 0) return g_strdup("
  • \n"); if (children->len == 1) { SnapdMarkdownNode *child = g_ptr_array_index(children, 0); if (snapd_markdown_node_get_node_type(child) == SNAPD_MARKDOWN_NODE_TYPE_PARAGRAPH) { contents = serialize_nodes(snapd_markdown_node_get_children(child)); return g_strdup_printf("
  • %s
  • \n", contents); } } contents = serialize_nodes(children); return g_strdup_printf("
  • \n%s
  • \n", contents); case SNAPD_MARKDOWN_NODE_TYPE_CODE_BLOCK: contents = serialize_nodes(children); return g_strdup_printf("
    %s
    \n", contents); case SNAPD_MARKDOWN_NODE_TYPE_CODE_SPAN: contents = serialize_nodes(children); return g_strdup_printf("%s", contents); case SNAPD_MARKDOWN_NODE_TYPE_EMPHASIS: contents = serialize_nodes(children); return g_strdup_printf("%s", contents); case SNAPD_MARKDOWN_NODE_TYPE_STRONG_EMPHASIS: contents = serialize_nodes(children); return g_strdup_printf("%s", contents); case SNAPD_MARKDOWN_NODE_TYPE_URL: return serialize_nodes(children); default: g_assert_not_reached(); return g_strdup(""); } } static gchar *parse(const gchar *text) { g_autoptr(SnapdMarkdownParser) parser = snapd_markdown_parser_new(SNAPD_MARKDOWN_VERSION_0); snapd_markdown_parser_set_preserve_whitespace(parser, TRUE); g_autoptr(GPtrArray) nodes = snapd_markdown_parser_parse(parser, text); return serialize_nodes(nodes); } static void test_markdown_empty(void) { g_autofree gchar *markup = parse(""); g_assert_cmpstr(markup, ==, ""); } static void test_markdown_single_character(void) { g_autofree gchar *markup = parse("a"); g_assert_cmpstr(markup, ==, "

    a

    \n"); } /* The following tests are a subset of those in the CommonMark spec * (https://spec.commonmark.org/0.28). Some tests are modified to match the * expected snap behaviour */ static void test_markdown_precedence(void) { g_autofree gchar *example12 = parse("- `one\n- two`\n"); g_assert_cmpstr(example12, ==, "
      \n
    • `one
    • \n
    • two`
    • \n
    \n"); } static void test_markdown_indented_code(void) { g_autofree gchar *example76 = parse(" a simple\n indented code block\n"); g_assert_cmpstr( example76, ==, "
    a simple\n  indented code block\n
    \n"); g_autofree gchar *example77 = parse(" - foo\n\n bar\n"); g_assert_cmpstr(example77, ==, "
      \n
    • \n

      foo

      \n

      bar

      \n
    • \n
    \n"); g_autofree gchar *example79 = parse(" \n *hi*\n\n - one\n"); g_assert_cmpstr(example79, ==, "
    <a/>\n*hi*\n\n- one\n
    \n"); g_autofree gchar *example80 = parse(" chunk1\n\n chunk2\n \n \n \n chunk3\n"); g_assert_cmpstr(example80, ==, "
    chunk1\n\nchunk2\n\n\n\nchunk3\n
    \n"); g_autofree gchar *example81 = parse(" chunk1\n \n chunk2\n"); g_assert_cmpstr(example81, ==, "
    chunk1\n  \n  chunk2\n
    \n"); g_autofree gchar *example82 = parse("Foo\n bar\n\n"); g_assert_cmpstr(example82, ==, "

    Foo\nbar

    \n"); g_autofree gchar *example83 = parse(" foo\nbar\n"); g_assert_cmpstr(example83, ==, "
    foo\n
    \n

    bar

    \n"); g_autofree gchar *example85 = parse(" foo\n bar\n"); g_assert_cmpstr(example85, ==, "
        foo\nbar\n
    \n"); g_autofree gchar *example86 = parse("\n \n foo\n \n\n"); g_assert_cmpstr(example86, ==, "
    foo\n
    \n"); g_autofree gchar *example87 = parse(" foo \n"); g_assert_cmpstr(example87, ==, "
    foo  \n
    \n"); } static void test_markdown_paragraphs(void) { g_autofree gchar *example182 = parse("aaa\n\nbbb\n"); g_assert_cmpstr(example182, ==, "

    aaa

    \n

    bbb

    \n"); g_autofree gchar *example183 = parse("aaa\nbbb\n\nccc\nddd\n"); g_assert_cmpstr(example183, ==, "

    aaa\nbbb

    \n

    ccc\nddd

    \n"); g_autofree gchar *example184 = parse("aaa\n\n\nbbb\n"); g_assert_cmpstr(example184, ==, "

    aaa

    \n

    bbb

    \n"); g_autofree gchar *example185 = parse(" aaa\n bbb\n"); g_assert_cmpstr(example185, ==, "

    aaa\nbbb

    \n"); g_autofree gchar *example186 = parse( "aaa\n bbb\n ccc\n"); g_assert_cmpstr(example186, ==, "

    aaa\nbbb\nccc

    \n"); g_autofree gchar *example187 = parse(" aaa\nbbb\n"); g_assert_cmpstr(example187, ==, "

    aaa\nbbb

    \n"); g_autofree gchar *example188 = parse(" aaa\nbbb\n"); g_assert_cmpstr(example188, ==, "
    aaa\n
    \n

    bbb

    \n"); } static void test_markdown_list_items(void) { g_autofree gchar *example218 = parse("- one\n\n two\n"); g_assert_cmpstr(example218, ==, "
      \n
    • one
    • \n
    \n

    two

    \n"); g_autofree gchar *example219 = parse("- one\n\n two\n"); g_assert_cmpstr(example219, ==, "
      \n
    • \n

      one

      \n

      two

      \n
    • \n
    \n"); g_autofree gchar *example220 = parse(" - one\n\n two\n"); g_assert_cmpstr( example220, ==, "
      \n
    • one
    • \n
    \n
     two\n
    \n"); g_autofree gchar *example221 = parse(" - one\n\n two\n"); g_assert_cmpstr(example221, ==, "
      \n
    • \n

      one

      \n

      two

      \n
    • \n
    \n"); g_autofree gchar *example224 = parse("-one\n\n2.two\n"); g_assert_cmpstr(example224, ==, "

    -one

    \n

    2.two

    \n"); g_autofree gchar *example225 = parse("- foo\n\n\n bar\n"); g_assert_cmpstr(example225, ==, "
      \n
    • \n

      foo

      \n

      bar

      \n
    • \n
    \n"); g_autofree gchar *example227 = parse("- Foo\n\n bar\n\n\n baz\n"); g_assert_cmpstr(example227, ==, "
      \n
    • \n

      Foo

      \n
      bar\n\n\nbaz\n\n
    • \n
    \n"); g_autofree gchar *example229 = parse("1234567890. not ok\n"); g_assert_cmpstr(example229, ==, "

    1234567890. not ok

    \n"); g_autofree gchar *example232 = parse("-1. not ok\n"); g_assert_cmpstr(example232, ==, "

    -1. not ok

    \n"); g_autofree gchar *example233 = parse("- foo\n\n bar\n"); g_assert_cmpstr( example233, ==, "
      \n
    • \n

      foo

      \n
      bar\n
      \n
    • \n
    \n"); g_autofree gchar *example235 = parse(" indented code\n\nparagraph\n\n more code\n"); g_assert_cmpstr(example235, ==, "
    indented "
                      "code\n
    \n

    paragraph

    \n
    more "
                      "code\n
    \n"); g_autofree gchar *example238 = parse(" foo\n\nbar\n"); g_assert_cmpstr(example238, ==, "

    foo

    \n

    bar

    \n"); g_autofree gchar *example239 = parse("- foo\n\n bar\n"); g_assert_cmpstr(example239, ==, "
      \n
    • foo
    • \n
    \n

    bar

    \n"); g_autofree gchar *example240 = parse("- foo\n\n bar\n"); g_assert_cmpstr(example240, ==, "
      \n
    • \n

      foo

      \n

      bar

      \n
    • \n
    \n"); g_autofree gchar *example242 = parse("- \n foo\n"); g_assert_cmpstr(example242, ==, "
      \n
    • foo
    • \n
    \n"); g_autofree gchar *example243 = parse("-\n\n foo\n"); g_assert_cmpstr(example243, ==, "
      \n
    • \n
    \n

    foo

    \n"); g_autofree gchar *example244 = parse("- foo\n-\n- bar\n"); g_assert_cmpstr(example244, ==, "
      \n
    • foo
    • \n
    • \n
    • bar
    • \n
    \n"); g_autofree gchar *example245 = parse("- foo\n- \n- bar\n"); g_assert_cmpstr(example245, ==, "
      \n
    • foo
    • \n
    • \n
    • bar
    • \n
    \n"); g_autofree gchar *example247 = parse("*\n"); g_assert_cmpstr(example247, ==, "
      \n
    • \n
    \n"); g_autofree gchar *example248 = parse("foo\n*\n\nfoo\n1.\n"); g_assert_cmpstr(example248, ==, "

    foo\n*

    \n

    foo\n1.

    \n"); g_autofree gchar *example252 = parse(" 1. A paragraph\n with two lines.\n\n " "indented code\n\n > A block quote.\n"); g_assert_cmpstr(example252, ==, "
    1.  A paragraph\n    with two lines.\n\n        "
                      "indented code\n\n    > A block quote.\n
    \n"); g_autofree gchar *example257 = parse("- foo\n - bar\n - baz\n - boo\n"); g_assert_cmpstr(example257, ==, "
      \n
    • \n

      foo

      \n
        \n
      • \n

        bar\n

          \n
        • \n

          baz

          \n
            \n
          • boo
          • \n
          \n\n
        \n
      • \n
      \n
    • \n
    \n"); g_autofree gchar *example258 = parse("- foo\n - bar\n - baz\n - boo\n"); g_assert_cmpstr( example258, ==, "
      \n
    • foo
    • \n
    • bar
    • \n
    • baz
    • \n
    • boo
    • \n
    \n"); g_autofree gchar *example261 = parse("- - foo\n"); g_assert_cmpstr(example261, ==, "
      \n
    • \n
        \n
      • foo
      • \n
      \n
    • \n
    \n"); } static void test_markdown_lists(void) { g_autofree gchar *example264 = parse("- foo\n- bar\n+ baz\n"); g_assert_cmpstr( example264, ==, "
      \n
    • foo
    • \n
    • bar
    • \n
    \n
      \n
    • baz
    • \n
    \n"); g_autofree gchar *example266 = parse("Foo\n- bar\n- baz\n"); g_assert_cmpstr(example266, ==, "

    Foo

    \n
      \n
    • bar
    • \n
    • baz
    • \n
    \n"); g_autofree gchar *example267 = parse( "The number of windows in my house is\n14. The number of doors is 6.\n"); g_assert_cmpstr(example267, ==, "

    The number of windows in my house is\n14. The number of " "doors is 6.

    \n"); g_autofree gchar *example269 = parse("- foo\n\n- bar\n\n\n- baz\n"); g_assert_cmpstr(example269, ==, "
      \n
    • foo
    • \n
    • bar
    • \n
    • baz
    • \n
    \n"); g_autofree gchar *example270 = parse("- foo\n - bar\n - baz\n\n\n bim\n"); g_assert_cmpstr( example270, ==, "
      \n
    • \n

      foo

      \n
        \n
      • \n

        bar

        \n
          \n
        • \n

          baz\n

          bim

          \n
        • \n
        \n
      • \n
      \n
    • \n
    \n"); g_autofree gchar *example273 = parse("- a\n - b\n - c\n - d\n - e\n - f\n - g\n - h\n- i\n"); g_assert_cmpstr( example273, ==, "
      \n
    • a
    • \n
    • b
    • \n
    • c
    • \n
    • d
    • \n
    • e\n
    • f
    • \n
    • g
    • \n
    • h
    • \n
    • i
    • \n
    \n"); g_autofree gchar *example275 = parse("- a\n- b\n\n- c\n"); g_assert_cmpstr(example275, ==, "
      \n
    • a
    • \n
    • b
    • \n
    • c
    • \n
    \n"); g_autofree gchar *example276 = parse("* a\n*\n\n* c\n"); g_assert_cmpstr(example276, ==, "
      \n
    • a
    • \n
    • \n
    • c
    • \n
    \n"); g_autofree gchar *example277 = parse("- a\n- b\n\n c\n- d\n"); g_assert_cmpstr( example277, ==, "
      \n
    • a
    • \n
    • \n

      b

      \n

      c

      \n
    • \n
    • d
    • \n
    \n"); g_autofree gchar *example280 = parse("- a\n - b\n\n c\n- d\n"); g_assert_cmpstr(example280, ==, "
      \n
    • \n

      a

      \n
        \n
      • \n

        b

        \n

        c

        \n\n
      \n
    • \n
    • d
    • \n
    \n"); g_autofree gchar *example283 = parse("- a\n"); g_assert_cmpstr(example283, ==, "
      \n
    • a
    • \n
    \n"); g_autofree gchar *example284 = parse("- a\n - b\n"); g_assert_cmpstr( example284, ==, "
      \n
    • \n

      a

      \n
        \n
      • b
      • \n
      \n
    • \n
    \n"); g_autofree gchar *example286 = parse("* foo\n * bar\n\n baz\n"); g_assert_cmpstr(example286, ==, "
      \n
    • \n

      foo

      \n
        \n
      • bar
      • \n
      \n

      baz\n

    • \n
    \n"); g_autofree gchar *example287 = parse("- a\n - b\n - c\n\n- d\n - e\n - f\n"); g_assert_cmpstr(example287, ==, "