├── .gitignore
├── .gitmodules
├── demos
├── CMakeLists.txt
├── simple
│ ├── CMakeLists.txt
│ └── simple.cpp
├── resource
│ ├── CMakeLists.txt
│ └── resource.cpp
├── simple-headless
│ ├── CMakeLists.txt
│ └── simple-headless.cpp
├── cefsimple
│ ├── README.md
│ ├── simple_handler_win.cc
│ ├── CMakeLists.txt
│ ├── simple_app.h
│ ├── LICENSE.txt
│ ├── simple_handler_linux.cc
│ ├── cefsimple_linux.cc
│ ├── simple_handler.h
│ ├── cefsimple_win.cc
│ ├── simple_app.cc
│ └── simple_handler.cc
└── file-manager
│ ├── CMakeLists.txt
│ ├── FileManager.hpp
│ ├── FileManager.cpp
│ ├── file-manager-main.cpp
│ └── win_dirent.h
├── index.html
├── html
├── hello-demos.html
└── file-manager.html
├── common
├── CMakeLists.txt
└── common
│ ├── Resources.hpp
│ ├── Resources.cpp
│ ├── PlatformUtil.hpp
│ └── PlatformUtil.cpp
├── README.md
├── CMakeLists.txt
├── LICENSE.txt
└── cmake
└── src_group.cmake
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 |
3 | # IDEs and editors
4 | .vscode/
5 |
6 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "cef-cmake"]
2 | path = cef-cmake
3 | url = https://github.com/iboB/cef-cmake.git
4 |
--------------------------------------------------------------------------------
/demos/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_subdirectory(simple)
2 | add_subdirectory(cefsimple)
3 | add_subdirectory(simple-headless)
4 | add_subdirectory(resource)
5 | add_subdirectory(file-manager)
6 |
--------------------------------------------------------------------------------
/demos/simple/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_executable(simple
2 | simple.cpp
3 | ${CEF_CMAKE_EXECUTABLE_RESOURCES}
4 | )
5 |
6 | target_link_libraries(simple
7 | cefdll_wrapper
8 | )
9 |
--------------------------------------------------------------------------------
/demos/resource/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_executable(resource
2 | resource.cpp
3 | ${CEF_CMAKE_EXECUTABLE_RESOURCES}
4 | )
5 |
6 | target_link_libraries(resource
7 | demos-common
8 | )
9 |
--------------------------------------------------------------------------------
/demos/simple-headless/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_executable(simple-headless
2 | simple-headless.cpp
3 | ${CEF_CMAKE_EXECUTABLE_RESOURCES}
4 | )
5 |
6 | target_link_libraries(simple-headless
7 | cefdll_wrapper
8 | )
9 |
--------------------------------------------------------------------------------
/demos/cefsimple/README.md:
--------------------------------------------------------------------------------
1 | # cefsimple
2 |
3 | A copy of the cefsimple test from the CEF project. Here to make sure everything is backwards compatible.
4 |
5 | Note that it has a different license than the rest. This demo in under the BSD 3-Clause License, while the rest are under MIT.
6 |
7 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CEF Demos
5 |
6 |
7 | CEF Demos
8 | This page serves as a holder for demo html files for CEF-Demos.
9 |
10 |
11 |
--------------------------------------------------------------------------------
/html/hello-demos.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello CEF Demos
5 |
6 |
7 | Hello CEF Demos
8 | This is a simple html file
9 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/demos/file-manager/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_executable(file-manager
2 | file-manager-main.cpp
3 | FileManager.cpp
4 | FileManager.hpp
5 | ${CEF_CMAKE_EXECUTABLE_RESOURCES}
6 | )
7 |
8 | target_link_libraries(file-manager
9 | demos-common
10 | )
11 |
12 | if(MSVC)
13 | target_compile_definitions(file-manager PRIVATE
14 | -D_CRT_SECURE_NO_WARNINGS
15 | )
16 | endif()
17 |
--------------------------------------------------------------------------------
/common/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(srcs)
2 | src_group(resource srcs
3 | common/Resources.hpp
4 | common/Resources.cpp
5 | )
6 |
7 | src_group(platform srcs
8 | common/PlatformUtil.hpp
9 | common/PlatformUtil.cpp
10 | )
11 |
12 | add_library(demos-common STATIC
13 | ${srcs}
14 | )
15 |
16 | target_include_directories(demos-common PUBLIC .)
17 |
18 | target_link_libraries(demos-common PUBLIC
19 | cefdll_wrapper
20 | )
21 |
--------------------------------------------------------------------------------
/demos/cefsimple/simple_handler_win.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
2 | // reserved. Use of this source code is governed by a BSD-style license that
3 | // can be found in the LICENSE file.
4 |
5 | #include "tests/cefsimple/simple_handler.h"
6 |
7 | #include
8 | #include
9 |
10 | #include "include/cef_browser.h"
11 |
12 | void SimpleHandler::PlatformTitleChange(CefRefPtr browser,
13 | const CefString& title) {
14 | CefWindowHandle hwnd = browser->GetHost()->GetWindowHandle();
15 | SetWindowText(hwnd, std::wstring(title).c_str());
16 | }
17 |
--------------------------------------------------------------------------------
/common/common/Resources.hpp:
--------------------------------------------------------------------------------
1 | // CEF-Demos
2 | // Copyright (c) 2019 Borislav Stanimirov
3 | //
4 | // Distributed under the MIT Software License
5 | // See accompanying file LICENSE.txt or copy at
6 | // http://opensource.org/licenses/MIT
7 | //
8 | #pragma once
9 |
10 | #include
11 | #include
12 |
13 |
14 | namespace cefdemos
15 | {
16 |
17 | class Resources
18 | {
19 | public:
20 | // setup a resource manager to associate uris below `uri` to point to files below the directory `dir`
21 | static void setupResourceManagerDirectoryProvider(CefRefPtr resource_manager, std::string uri, std::string dir);
22 | };
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/common/common/Resources.cpp:
--------------------------------------------------------------------------------
1 | // CEF-Demos
2 | // Copyright (c) 2019 Borislav Stanimirov
3 | //
4 | // Distributed under the MIT Software License
5 | // See accompanying file LICENSE.txt or copy at
6 | // http://opensource.org/licenses/MIT
7 | //
8 | #include "Resources.hpp"
9 |
10 | namespace cefdemos
11 | {
12 |
13 | void Resources::setupResourceManagerDirectoryProvider(CefRefPtr resource_manager, std::string uri, std::string dir)
14 | {
15 | if (!CefCurrentlyOn(TID_IO)) {
16 | // Execute on the browser IO thread.
17 | CefPostTask(TID_IO, base::Bind(&Resources::setupResourceManagerDirectoryProvider, resource_manager, uri, dir));
18 | return;
19 | }
20 |
21 | resource_manager->AddDirectoryProvider(uri, dir, 1, dir);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/demos/file-manager/FileManager.hpp:
--------------------------------------------------------------------------------
1 | // CEF-Demos
2 | // Copyright (c) 2019 Borislav Stanimirov
3 | //
4 | // Distributed under the MIT Software License
5 | // See accompanying file LICENSE.txt or copy at
6 | // http://opensource.org/licenses/MIT
7 | //
8 | // GUI-agnostic file manager code
9 | #pragma once
10 |
11 | #include
12 | #include
13 |
14 | namespace fileman
15 | {
16 |
17 | class FileManager
18 | {
19 | public:
20 | FileManager();
21 | ~FileManager();
22 |
23 | struct DirectoryContents
24 | {
25 | std::vector files;
26 | std::vector dirs;
27 | };
28 |
29 | // path will be interpreted as relative to inner path
30 | DirectoryContents getDirectoryContents(const char* path);
31 |
32 | private:
33 | std::string m_path;
34 | };
35 |
36 | }
--------------------------------------------------------------------------------
/common/common/PlatformUtil.hpp:
--------------------------------------------------------------------------------
1 | // CEF-Demos
2 | // Copyright (c) 2019 Borislav Stanimirov
3 | //
4 | // Distributed under the MIT Software License
5 | // See accompanying file LICENSE.txt or copy at
6 | // http://opensource.org/licenses/MIT
7 | //
8 | #pragma once
9 |
10 | #include
11 |
12 | namespace cefdemos
13 | {
14 |
15 | class PlatformUtil
16 | {
17 | public:
18 | // get the full path to the current executable
19 | static std::string getCurrentExecutablePath();
20 |
21 | // starts looking from the current directory upwards until it discovers a valid subdirectory described by assetDir
22 | // for example
23 | // getAssetPath("/home/someuser/projects/xxx/build/bin", "assets"); will return /home/someuser/projects/xxx/assests if this directory exists
24 | static std::string getAssetPath(std::string baseDir, const std::string& assetDir);
25 |
26 | };
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/demos/cefsimple/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(srcs)
2 |
3 | src_group(sources srcs
4 | simple_app.cc
5 | simple_app.h
6 | simple_handler.cc
7 | simple_handler.h
8 | )
9 |
10 | if(CEFDEMOS_OS_LINUX)
11 | src_group(sources srcs
12 | cefsimple_linux.cc
13 | simple_handler_linux.cc
14 | )
15 | elseif(CEFDEMOS_OS_MACOSX)
16 | src_group(sources srcs
17 | cefsimple_mac.mm
18 | simple_handler_mac.mm
19 | )
20 | elseif(CEFDEMOS_OS_WINDOWS)
21 | src_group(sources srcs
22 | cefsimple_win.cc
23 | simple_handler_win.cc
24 | )
25 | endif()
26 |
27 | add_executable(cefsimple
28 | ${srcs}
29 | ${CEF_CMAKE_EXECUTABLE_RESOURCES}
30 | )
31 |
32 | if(CEFDEMOS_OS_WINDOWS)
33 | set_target_properties(cefsimple PROPERTIES WIN32_EXECUTABLE 1)
34 | endif()
35 |
36 | target_link_libraries(cefsimple
37 | cefdll_wrapper
38 | )
39 |
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CEF Demos
2 |
3 | Small CEF Demos
4 |
5 | *More docs to come*
6 |
7 | ## Demos
8 |
9 | The simple demos have no external dependencies other than CEF and the cef.dll wrapper.
10 |
11 | * **cefsimple** - A copy of the cefsimple test from the CEF project. Here to make sure everything is backwards compatible.
12 | * **simple** - A bare-bones minimal example which launches a browser.
13 | * **simple-headless** - A minimal headless browser example
14 |
15 | The other demos depend on the `demos-common` library defined [here](common).
16 |
17 | * **resource** - Uses a resource manager to load files from the `html` subdirectory
18 | * **file-manager** - A file manager demo with HTML GUI
19 |
20 | ## License and copyright
21 |
22 | This software is distributed under the MIT Software License.
23 |
24 | See accompanying file LICENSE.txt or copy [here](https://opensource.org/licenses/MIT).
25 |
26 | Copyright © 2019 [Borislav Stanimirov](http://github.com/iboB)
27 |
--------------------------------------------------------------------------------
/demos/cefsimple/simple_app.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
2 | // reserved. Use of this source code is governed by a BSD-style license that
3 | // can be found in the LICENSE file.
4 |
5 | #ifndef CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_
6 | #define CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_
7 |
8 | #include "include/cef_app.h"
9 |
10 | // Implement application-level callbacks for the browser process.
11 | class SimpleApp : public CefApp, public CefBrowserProcessHandler {
12 | public:
13 | SimpleApp();
14 |
15 | // CefApp methods:
16 | virtual CefRefPtr GetBrowserProcessHandler()
17 | OVERRIDE {
18 | return this;
19 | }
20 |
21 | // CefBrowserProcessHandler methods:
22 | virtual void OnContextInitialized() OVERRIDE;
23 |
24 | private:
25 | // Include the default reference counting implementation.
26 | IMPLEMENT_REFCOUNTING(SimpleApp);
27 | };
28 |
29 | #endif // CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_
30 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.10)
2 |
3 | set_property(GLOBAL PROPERTY USE_FOLDERS ON)
4 |
5 | project(cef-demos)
6 |
7 | set(CMAKE_CXX_STANDARD 17)
8 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
9 |
10 | set(CMAKE_MODULE_PATH
11 | ${CMAKE_MODULE_PATH}
12 | ${CMAKE_CURRENT_SOURCE_DIR}/cmake
13 | ${CMAKE_CURRENT_SOURCE_DIR}/cef-cmake/cmake
14 | )
15 |
16 | if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
17 | set(CEFDEMOS_OS_MACOSX 1)
18 | set(CEFDEMOS_OS_POSIX 1)
19 | elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
20 | set(CEFDEMOS_OS_LINUX 1)
21 | set(CEFDEMOS_OS_POSIX 1)
22 | elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
23 | set(CEFDEMOS_OS_WINDOWS 1)
24 | else()
25 | message(FATAL_ERROR "CEF-Demos: Unsupported target platform")
26 | endif()
27 |
28 | include(src_group)
29 |
30 | # configure
31 | set(CEF_USE_SANDBOX OFF CACHE BOOL "Force turning off of sandbox")
32 | include(cef_cmake)
33 | add_subdirectory(cef-cmake)
34 |
35 | add_subdirectory(common)
36 |
37 | add_subdirectory(demos)
38 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Borislav Stanimirov
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/cmake/src_group.cmake:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2015 Borislav Stanimirov
2 | #
3 | # Distributed under the MIT Software License
4 | # See accompanying file LICENSE.txt or copy at
5 | # http://opensource.org/licenses/MIT
6 | #
7 | # src_group
8 | #
9 | # Defines a group of source files, while also appending them to a list
10 | # (to be used with add_executable or add_library)
11 | # Args:
12 | # GROUP_NAME - name of the group. Subroups are separated by "~"
13 | # SRC_LIST - list of sources to append to
14 | # ... the other arguments are a list of files
15 | #
16 | # Example Usage
17 | # set(mySources)
18 | # src_group("Group~Subgroup" mySources file1 file2 ... fileN)
19 | # add_executable(myexe mySources)
20 | #
21 | macro(src_group GROUP_NAME SRC_LIST)
22 | # In order to work CMake's source_group macro requiers backslashes between
23 | # groups and subgroups. However this leads to escape hell. That's why we
24 | # use tildes and then replace them with backslashes at the very end
25 | set(DEMANGLED_GROUP)
26 | string(REPLACE "~" "\\\\" DEMANGLED_GROUP ${GROUP_NAME})
27 |
28 | source_group(${DEMANGLED_GROUP} FILES ${ARGN})
29 |
30 | foreach(filename ${ARGN})
31 | list(APPEND ${SRC_LIST} ${filename})
32 | endforeach()
33 | endmacro(src_group)
34 |
--------------------------------------------------------------------------------
/demos/cefsimple/LICENSE.txt:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2008-2014 Marshall A. Greenblatt. Portions Copyright (c)
2 | // 2006-2009 Google Inc. All rights reserved.
3 | //
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are
6 | // met:
7 | //
8 | // * Redistributions of source code must retain the above copyright
9 | // notice, this list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above
11 | // copyright notice, this list of conditions and the following disclaimer
12 | // in the documentation and/or other materials provided with the
13 | // distribution.
14 | // * Neither the name of Google Inc. nor the name Chromium Embedded
15 | // Framework nor the names of its contributors may be used to endorse
16 | // or promote products derived from this software without specific prior
17 | // written permission.
18 | //
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/demos/file-manager/FileManager.cpp:
--------------------------------------------------------------------------------
1 | // CEF-Demos
2 | // Copyright (c) 2019 Borislav Stanimirov
3 | //
4 | // Distributed under the MIT Software License
5 | // See accompanying file LICENSE.txt or copy at
6 | // http://opensource.org/licenses/MIT
7 | //
8 | #include "FileManager.hpp"
9 |
10 | #if defined(_WIN32)
11 | # include
12 | # include "win_dirent.h"
13 | #else
14 | # include
15 | #endif
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | namespace fileman
22 | {
23 |
24 | namespace
25 | {
26 | void normalizePath(std::string& path)
27 | {
28 | for (auto& c : path)
29 | if (c == '\\')
30 | c = '/';
31 | }
32 | }
33 |
34 | FileManager::FileManager()
35 | {
36 | #if defined(_WIN32)
37 | m_path = getenv("homedrive");
38 | m_path += getenv("homepath");
39 | normalizePath(m_path);
40 | #else
41 | m_path = getenv("HOME");
42 | #endif
43 | }
44 |
45 | FileManager::~FileManager() = default;
46 |
47 | FileManager::DirectoryContents FileManager::getDirectoryContents(const char* path)
48 | {
49 | DirectoryContents ret;
50 |
51 | auto dir = m_path + path;
52 | auto dp = opendir(dir.c_str());
53 |
54 | dirent* entry;
55 | while ((entry = readdir(dp)) != nullptr)
56 | {
57 | if (strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0) continue; // don't care for this
58 | auto fullPath = dir + "/" + entry->d_name;
59 | struct stat info;
60 | if (stat(fullPath.c_str(), &info) == 0 && (info.st_mode & S_IFDIR))
61 | {
62 | ret.dirs.emplace_back(entry->d_name);
63 | }
64 | else
65 | {
66 | ret.files.emplace_back(entry->d_name);
67 | }
68 | }
69 |
70 | closedir(dp);
71 |
72 | return ret;
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/demos/cefsimple/simple_handler_linux.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
2 | // reserved. Use of this source code is governed by a BSD-style license that
3 | // can be found in the LICENSE file.
4 |
5 | #include "tests/cefsimple/simple_handler.h"
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | #include "include/base/cef_logging.h"
12 | #include "include/cef_browser.h"
13 |
14 | void SimpleHandler::PlatformTitleChange(CefRefPtr browser,
15 | const CefString& title) {
16 | std::string titleStr(title);
17 |
18 | // Retrieve the X11 display shared with Chromium.
19 | ::Display* display = cef_get_xdisplay();
20 | DCHECK(display);
21 |
22 | // Retrieve the X11 window handle for the browser.
23 | ::Window window = browser->GetHost()->GetWindowHandle();
24 | DCHECK(window != kNullWindowHandle);
25 |
26 | // Retrieve the atoms required by the below XChangeProperty call.
27 | const char* kAtoms[] = {"_NET_WM_NAME", "UTF8_STRING"};
28 | Atom atoms[2];
29 | int result =
30 | XInternAtoms(display, const_cast(kAtoms), 2, false, atoms);
31 | if (!result)
32 | NOTREACHED();
33 |
34 | // Set the window title.
35 | XChangeProperty(display, window, atoms[0], atoms[1], 8, PropModeReplace,
36 | reinterpret_cast(titleStr.c_str()),
37 | titleStr.size());
38 |
39 | // TODO(erg): This is technically wrong. So XStoreName and friends expect
40 | // this in Host Portable Character Encoding instead of UTF-8, which I believe
41 | // is Compound Text. This shouldn't matter 90% of the time since this is the
42 | // fallback to the UTF8 property above.
43 | XStoreName(display, browser->GetHost()->GetWindowHandle(), titleStr.c_str());
44 | }
45 |
--------------------------------------------------------------------------------
/demos/simple/simple.cpp:
--------------------------------------------------------------------------------
1 | // CEF-Demos
2 | // Copyright (c) 2019 Borislav Stanimirov
3 | //
4 | // Distributed under the MIT Software License
5 | // See accompanying file LICENSE.txt or copy at
6 | // http://opensource.org/licenses/MIT
7 | //
8 | // Bare-bones minimal demo. Creates a simple Chromium browser.
9 | #include
10 | #include
11 |
12 | // this is only needed so we have a way to break the message loop
13 | class MinimalClient : public CefClient, public CefLifeSpanHandler
14 | {
15 | public:
16 | MinimalClient() = default;
17 |
18 | CefRefPtr GetLifeSpanHandler() override { return this; }
19 | void OnBeforeClose(CefRefPtr browser) override
20 | {
21 | CefQuitMessageLoop();
22 | }
23 |
24 | IMPLEMENT_REFCOUNTING(MinimalClient);
25 | DISALLOW_COPY_AND_ASSIGN(MinimalClient);
26 | };
27 |
28 |
29 | int main(int argc, char* argv[])
30 | {
31 | #if defined(_WIN32)
32 | CefEnableHighDPISupport();
33 | CefMainArgs args(GetModuleHandle(NULL));
34 | #else
35 | CefMainArgs args(argc, argv);
36 | #endif
37 |
38 | void* windowsSandboxInfo = NULL;
39 |
40 | #if defined(CEF_USE_SANDBOX) && defined(_WIN32)
41 | // Manage the life span of the sandbox information object. This is necessary
42 | // for sandbox support on Windows. See cef_sandbox_win.h for complete details.
43 | CefScopedSandboxInfo scopedSandbox;
44 | windowsSandboxInfo = scopedSandbox.sandbox_info();
45 | #endif
46 |
47 | int result = CefExecuteProcess(args, nullptr, windowsSandboxInfo);
48 | if (result >= 0)
49 | {
50 | // child process completed
51 | return result;
52 | }
53 |
54 | CefSettings settings;
55 | #if !defined(CEF_USE_SANDBOX)
56 | settings.no_sandbox = true;
57 | #endif
58 |
59 | CefInitialize(args, settings, nullptr, windowsSandboxInfo);
60 |
61 |
62 | CefWindowInfo windowInfo;
63 |
64 | #if defined(_WIN32)
65 | // On Windows we need to specify certain flags that will be passed to CreateWindowEx().
66 | windowInfo.SetAsPopup(NULL, "simple");
67 | #endif
68 | CefBrowserSettings browserSettings;
69 | CefBrowserHost::CreateBrowser(windowInfo, new MinimalClient, "https://ibob.github.io/cef-demos/html/hello-demos.html", browserSettings, nullptr);
70 |
71 | CefRunMessageLoop();
72 |
73 | CefShutdown();
74 |
75 | return 0;
76 | }
77 |
--------------------------------------------------------------------------------
/common/common/PlatformUtil.cpp:
--------------------------------------------------------------------------------
1 | // CEF-Demos
2 | // Copyright (c) 2019 Borislav Stanimirov
3 | //
4 | // Distributed under the MIT Software License
5 | // See accompanying file LICENSE.txt or copy at
6 | // http://opensource.org/licenses/MIT
7 | //
8 | #include "PlatformUtil.hpp"
9 |
10 | #if defined(_WIN32)
11 | # include
12 | #else
13 | # include
14 | # include
15 | #endif
16 |
17 | #include
18 | #include
19 |
20 | namespace cefdemos
21 | {
22 |
23 | #if defined(_WIN32)
24 | namespace
25 | {
26 | // local function used to identify the current module on Windows
27 | void getAddr() {}
28 | }
29 | #endif
30 |
31 | std::string PlatformUtil::getCurrentExecutablePath()
32 | {
33 | std::string modulePath;
34 | #if defined(_WIN32)
35 | HMODULE engine;
36 | GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
37 | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
38 | (LPCSTR)getAddr,
39 | &engine);
40 |
41 | char path[_MAX_PATH + _MAX_FNAME + 1];
42 | GetModuleFileNameA(engine, path, _MAX_PATH + _MAX_FNAME);
43 |
44 | // normalize path
45 | char* p = path;
46 | while (*p)
47 | {
48 | if (*p == '\\')
49 | {
50 | *p = '/';
51 | }
52 | ++p;
53 | }
54 |
55 | modulePath = path;
56 |
57 | #else
58 | // retrieve the executable path and hope for the best
59 | char buff[2048];
60 | size_t len = readlink("/proc/self/exe", buff, sizeof(buff) - 1);
61 | if (len > 0)
62 | {
63 | buff[len] = 0;
64 | modulePath = buff;
65 | }
66 |
67 | #endif
68 |
69 | return modulePath;
70 | }
71 |
72 | std::string PlatformUtil::getAssetPath(std::string baseDir, const std::string& assetDir)
73 | {
74 | while (true)
75 | {
76 | auto slash = baseDir.rfind('/');
77 | if (slash == std::string::npos)
78 | {
79 | baseDir = assetDir;
80 | break;
81 | }
82 |
83 | baseDir.erase(slash + 1);
84 |
85 | baseDir += assetDir;
86 |
87 | struct stat info;
88 | if (stat(baseDir.c_str(), &info) == 0 && (info.st_mode & S_IFDIR))
89 | {
90 | break;
91 | }
92 |
93 | baseDir.erase(slash);
94 | }
95 |
96 | return baseDir;
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/demos/cefsimple/cefsimple_linux.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
2 | // reserved. Use of this source code is governed by a BSD-style license that
3 | // can be found in the LICENSE file.
4 |
5 | #include "tests/cefsimple/simple_app.h"
6 |
7 | #include
8 |
9 | #include "include/base/cef_logging.h"
10 |
11 | namespace {
12 |
13 | int XErrorHandlerImpl(Display* display, XErrorEvent* event) {
14 | LOG(WARNING) << "X error received: "
15 | << "type " << event->type << ", "
16 | << "serial " << event->serial << ", "
17 | << "error_code " << static_cast(event->error_code) << ", "
18 | << "request_code " << static_cast(event->request_code)
19 | << ", "
20 | << "minor_code " << static_cast(event->minor_code);
21 | return 0;
22 | }
23 |
24 | int XIOErrorHandlerImpl(Display* display) {
25 | return 0;
26 | }
27 |
28 | } // namespace
29 |
30 | // Entry point function for all processes.
31 | int main(int argc, char* argv[]) {
32 | // Provide CEF with command-line arguments.
33 | CefMainArgs main_args(argc, argv);
34 |
35 | // CEF applications have multiple sub-processes (render, plugin, GPU, etc)
36 | // that share the same executable. This function checks the command-line and,
37 | // if this is a sub-process, executes the appropriate logic.
38 | int exit_code = CefExecuteProcess(main_args, NULL, NULL);
39 | if (exit_code >= 0) {
40 | // The sub-process has completed so return here.
41 | return exit_code;
42 | }
43 |
44 | // Install xlib error handlers so that the application won't be terminated
45 | // on non-fatal errors.
46 | XSetErrorHandler(XErrorHandlerImpl);
47 | XSetIOErrorHandler(XIOErrorHandlerImpl);
48 |
49 | // Specify CEF global settings here.
50 | CefSettings settings;
51 |
52 | // When generating projects with CMake the CEF_USE_SANDBOX value will be defined
53 | // automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line to disable
54 | // use of the sandbox.
55 | #if !defined(CEF_USE_SANDBOX)
56 | settings.no_sandbox = true;
57 | #endif
58 |
59 | // SimpleApp implements application-level callbacks for the browser process.
60 | // It will create the first browser instance in OnContextInitialized() after
61 | // CEF has initialized.
62 | CefRefPtr app(new SimpleApp);
63 |
64 | // Initialize CEF for the browser process.
65 | CefInitialize(main_args, settings, app.get(), NULL);
66 |
67 | // Run the CEF message loop. This will block until CefQuitMessageLoop() is
68 | // called.
69 | CefRunMessageLoop();
70 |
71 | // Shut down CEF.
72 | CefShutdown();
73 |
74 | return 0;
75 | }
76 |
--------------------------------------------------------------------------------
/demos/cefsimple/simple_handler.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
2 | // reserved. Use of this source code is governed by a BSD-style license that
3 | // can be found in the LICENSE file.
4 |
5 | #ifndef CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_
6 | #define CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_
7 |
8 | #include "include/cef_client.h"
9 |
10 | #include
11 |
12 | class SimpleHandler : public CefClient,
13 | public CefDisplayHandler,
14 | public CefLifeSpanHandler,
15 | public CefLoadHandler {
16 | public:
17 | explicit SimpleHandler(bool use_views);
18 | ~SimpleHandler();
19 |
20 | // Provide access to the single global instance of this object.
21 | static SimpleHandler* GetInstance();
22 |
23 | // CefClient methods:
24 | virtual CefRefPtr GetDisplayHandler() OVERRIDE {
25 | return this;
26 | }
27 | virtual CefRefPtr GetLifeSpanHandler() OVERRIDE {
28 | return this;
29 | }
30 | virtual CefRefPtr GetLoadHandler() OVERRIDE { return this; }
31 |
32 | // CefDisplayHandler methods:
33 | virtual void OnTitleChange(CefRefPtr browser,
34 | const CefString& title) OVERRIDE;
35 |
36 | // CefLifeSpanHandler methods:
37 | virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE;
38 | virtual bool DoClose(CefRefPtr browser) OVERRIDE;
39 | virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE;
40 |
41 | // CefLoadHandler methods:
42 | virtual void OnLoadError(CefRefPtr browser,
43 | CefRefPtr frame,
44 | ErrorCode errorCode,
45 | const CefString& errorText,
46 | const CefString& failedUrl) OVERRIDE;
47 |
48 | // Request that all existing browser windows close.
49 | void CloseAllBrowsers(bool force_close);
50 |
51 | bool IsClosing() const { return is_closing_; }
52 |
53 | private:
54 | // Platform-specific implementation.
55 | void PlatformTitleChange(CefRefPtr browser,
56 | const CefString& title);
57 |
58 | // True if the application is using the Views framework.
59 | const bool use_views_;
60 |
61 | // List of existing browser windows. Only accessed on the CEF UI thread.
62 | typedef std::list> BrowserList;
63 | BrowserList browser_list_;
64 |
65 | bool is_closing_;
66 |
67 | // Include the default reference counting implementation.
68 | IMPLEMENT_REFCOUNTING(SimpleHandler);
69 | };
70 |
71 | #endif // CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_
72 |
--------------------------------------------------------------------------------
/demos/cefsimple/cefsimple_win.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
2 | // reserved. Use of this source code is governed by a BSD-style license that
3 | // can be found in the LICENSE file.
4 |
5 | #include
6 |
7 | #include "include/cef_sandbox_win.h"
8 | #include "tests/cefsimple/simple_app.h"
9 |
10 | // When generating projects with CMake the CEF_USE_SANDBOX value will be defined
11 | // automatically if using the required compiler version. Pass -DUSE_SANDBOX=OFF
12 | // to the CMake command-line to disable use of the sandbox.
13 | // Uncomment this line to manually enable sandbox support.
14 | // #define CEF_USE_SANDBOX 1
15 |
16 | #if defined(CEF_USE_SANDBOX)
17 | // The cef_sandbox.lib static library may not link successfully with all VS
18 | // versions.
19 | #pragma comment(lib, "cef_sandbox.lib")
20 | #endif
21 |
22 | // Entry point function for all processes.
23 | int APIENTRY wWinMain(HINSTANCE hInstance,
24 | HINSTANCE hPrevInstance,
25 | LPTSTR lpCmdLine,
26 | int nCmdShow) {
27 | UNREFERENCED_PARAMETER(hPrevInstance);
28 | UNREFERENCED_PARAMETER(lpCmdLine);
29 |
30 | // Enable High-DPI support on Windows 7 or newer.
31 | CefEnableHighDPISupport();
32 |
33 | void* sandbox_info = NULL;
34 |
35 | #if defined(CEF_USE_SANDBOX)
36 | // Manage the life span of the sandbox information object. This is necessary
37 | // for sandbox support on Windows. See cef_sandbox_win.h for complete details.
38 | CefScopedSandboxInfo scoped_sandbox;
39 | sandbox_info = scoped_sandbox.sandbox_info();
40 | #endif
41 |
42 | // Provide CEF with command-line arguments.
43 | CefMainArgs main_args(hInstance);
44 |
45 | // CEF applications have multiple sub-processes (render, plugin, GPU, etc)
46 | // that share the same executable. This function checks the command-line and,
47 | // if this is a sub-process, executes the appropriate logic.
48 | int exit_code = CefExecuteProcess(main_args, NULL, sandbox_info);
49 | if (exit_code >= 0) {
50 | // The sub-process has completed so return here.
51 | return exit_code;
52 | }
53 |
54 | // Specify CEF global settings here.
55 | CefSettings settings;
56 |
57 | #if !defined(CEF_USE_SANDBOX)
58 | settings.no_sandbox = true;
59 | #endif
60 |
61 | // SimpleApp implements application-level callbacks for the browser process.
62 | // It will create the first browser instance in OnContextInitialized() after
63 | // CEF has initialized.
64 | CefRefPtr app(new SimpleApp);
65 |
66 | // Initialize CEF.
67 | CefInitialize(main_args, settings, app.get(), sandbox_info);
68 |
69 | // Run the CEF message loop. This will block until CefQuitMessageLoop() is
70 | // called.
71 | CefRunMessageLoop();
72 |
73 | // Shut down CEF.
74 | CefShutdown();
75 |
76 | return 0;
77 | }
78 |
--------------------------------------------------------------------------------
/html/file-manager.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | File Manager :: CEF Demos
6 |
7 |
42 |
43 |
44 |
45 |
46 | Path:
47 |
48 |
49 |
50 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/demos/resource/resource.cpp:
--------------------------------------------------------------------------------
1 | // CEF-Demos
2 | // Copyright (c) 2019 Borislav Stanimirov
3 | //
4 | // Distributed under the MIT Software License
5 | // See accompanying file LICENSE.txt or copy at
6 | // http://opensource.org/licenses/MIT
7 | //
8 | #include
9 |
10 | #include
11 | #include
12 |
13 | #include
14 | #include
15 |
16 | #define URI_ROOT "https://cefdemos"
17 | const char* URL = URI_ROOT "/hello-demos.html";
18 |
19 | class ResourceClient : public CefClient, public CefLifeSpanHandler, public CefRequestHandler
20 | {
21 | public:
22 | ResourceClient()
23 | : m_resourceManager(new CefResourceManager)
24 | {
25 | auto exePath = cefdemos::PlatformUtil::getCurrentExecutablePath();
26 | auto assetPath = cefdemos::PlatformUtil::getAssetPath(exePath, "html");
27 | cefdemos::Resources::setupResourceManagerDirectoryProvider(m_resourceManager, URI_ROOT, assetPath);
28 | }
29 |
30 | CefRefPtr GetLifeSpanHandler() override { return this; }
31 | virtual CefRefPtr GetRequestHandler() override { return this; }
32 |
33 | void OnBeforeClose(CefRefPtr browser) override
34 | {
35 | CefQuitMessageLoop();
36 | }
37 |
38 | virtual cef_return_value_t OnBeforeResourceLoad(
39 | CefRefPtr browser,
40 | CefRefPtr frame,
41 | CefRefPtr request,
42 | CefRefPtr callback) override
43 | {
44 | return m_resourceManager->OnBeforeResourceLoad(browser, frame, request, callback);
45 | }
46 |
47 | virtual CefRefPtr GetResourceHandler(
48 | CefRefPtr browser,
49 | CefRefPtr frame,
50 | CefRefPtr request) override
51 | {
52 | return m_resourceManager->GetResourceHandler(browser, frame, request);
53 | }
54 |
55 | private:
56 | CefRefPtr m_resourceManager;
57 |
58 | IMPLEMENT_REFCOUNTING(ResourceClient);
59 | DISALLOW_COPY_AND_ASSIGN(ResourceClient);
60 | };
61 |
62 | int main(int argc, char* argv[])
63 | {
64 | #if defined(_WIN32)
65 | CefEnableHighDPISupport();
66 | CefMainArgs args(GetModuleHandle(NULL));
67 | #else
68 | CefMainArgs args(argc, argv);
69 | #endif
70 |
71 | void* windowsSandboxInfo = NULL;
72 |
73 | #if defined(CEF_USE_SANDBOX) && defined(_WIN32)
74 | // Manage the life span of the sandbox information object. This is necessary
75 | // for sandbox support on Windows. See cef_sandbox_win.h for complete details.
76 | CefScopedSandboxInfo scopedSandbox;
77 | windowsSandboxInfo = scopedSandbox.sandbox_info();
78 | #endif
79 |
80 | int result = CefExecuteProcess(args, nullptr, windowsSandboxInfo);
81 | if (result >= 0)
82 | {
83 | // child process completed
84 | return result;
85 | }
86 |
87 | CefSettings settings;
88 | #if !defined(CEF_USE_SANDBOX)
89 | settings.no_sandbox = true;
90 | #endif
91 |
92 | CefInitialize(args, settings, nullptr, windowsSandboxInfo);
93 |
94 | CefWindowInfo windowInfo;
95 |
96 | #if defined(_WIN32)
97 | // On Windows we need to specify certain flags that will be passed to CreateWindowEx().
98 | windowInfo.SetAsPopup(NULL, "Resource");
99 | #endif
100 | CefBrowserSettings browserSettings;
101 | CefBrowserHost::CreateBrowser(windowInfo, new ResourceClient, URL, browserSettings, nullptr);
102 |
103 | CefRunMessageLoop();
104 |
105 | CefShutdown();
106 |
107 | return 0;
108 | }
109 |
--------------------------------------------------------------------------------
/demos/cefsimple/simple_app.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
2 | // reserved. Use of this source code is governed by a BSD-style license that
3 | // can be found in the LICENSE file.
4 |
5 | #include "tests/cefsimple/simple_app.h"
6 |
7 | #include
8 |
9 | #include "include/cef_browser.h"
10 | #include "include/cef_command_line.h"
11 | #include "include/views/cef_browser_view.h"
12 | #include "include/views/cef_window.h"
13 | #include "include/wrapper/cef_helpers.h"
14 | #include "tests/cefsimple/simple_handler.h"
15 |
16 | namespace {
17 |
18 | // When using the Views framework this object provides the delegate
19 | // implementation for the CefWindow that hosts the Views-based browser.
20 | class SimpleWindowDelegate : public CefWindowDelegate {
21 | public:
22 | explicit SimpleWindowDelegate(CefRefPtr browser_view)
23 | : browser_view_(browser_view) {}
24 |
25 | void OnWindowCreated(CefRefPtr window) OVERRIDE {
26 | // Add the browser view and show the window.
27 | window->AddChildView(browser_view_);
28 | window->Show();
29 |
30 | // Give keyboard focus to the browser view.
31 | browser_view_->RequestFocus();
32 | }
33 |
34 | void OnWindowDestroyed(CefRefPtr window) OVERRIDE {
35 | browser_view_ = NULL;
36 | }
37 |
38 | bool CanClose(CefRefPtr window) OVERRIDE {
39 | // Allow the window to close if the browser says it's OK.
40 | CefRefPtr browser = browser_view_->GetBrowser();
41 | if (browser)
42 | return browser->GetHost()->TryCloseBrowser();
43 | return true;
44 | }
45 |
46 | private:
47 | CefRefPtr browser_view_;
48 |
49 | IMPLEMENT_REFCOUNTING(SimpleWindowDelegate);
50 | DISALLOW_COPY_AND_ASSIGN(SimpleWindowDelegate);
51 | };
52 |
53 | } // namespace
54 |
55 | SimpleApp::SimpleApp() {}
56 |
57 | void SimpleApp::OnContextInitialized() {
58 | CEF_REQUIRE_UI_THREAD();
59 |
60 | CefRefPtr command_line =
61 | CefCommandLine::GetGlobalCommandLine();
62 |
63 | #if defined(OS_WIN) || defined(OS_LINUX)
64 | // Create the browser using the Views framework if "--use-views" is specified
65 | // via the command-line. Otherwise, create the browser using the native
66 | // platform framework. The Views framework is currently only supported on
67 | // Windows and Linux.
68 | const bool use_views = command_line->HasSwitch("use-views");
69 | #else
70 | const bool use_views = false;
71 | #endif
72 |
73 | // SimpleHandler implements browser-level callbacks.
74 | CefRefPtr handler(new SimpleHandler(use_views));
75 |
76 | // Specify CEF browser settings here.
77 | CefBrowserSettings browser_settings;
78 |
79 | std::string url;
80 |
81 | // Check if a "--url=" value was provided via the command-line. If so, use
82 | // that instead of the default URL.
83 | url = command_line->GetSwitchValue("url");
84 | if (url.empty())
85 | url = "http://www.google.com";
86 |
87 | if (use_views) {
88 | // Create the BrowserView.
89 | CefRefPtr browser_view = CefBrowserView::CreateBrowserView(
90 | handler, url, browser_settings, NULL, NULL);
91 |
92 | // Create the Window. It will show itself after creation.
93 | CefWindow::CreateTopLevelWindow(new SimpleWindowDelegate(browser_view));
94 | } else {
95 | // Information used when creating the native window.
96 | CefWindowInfo window_info;
97 |
98 | #if defined(OS_WIN)
99 | // On Windows we need to specify certain flags that will be passed to
100 | // CreateWindowEx().
101 | window_info.SetAsPopup(NULL, "cefsimple");
102 | #endif
103 |
104 | // Create the first browser window.
105 | CefBrowserHost::CreateBrowser(window_info, handler, url, browser_settings,
106 | NULL);
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/demos/cefsimple/simple_handler.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
2 | // reserved. Use of this source code is governed by a BSD-style license that
3 | // can be found in the LICENSE file.
4 |
5 | #include "tests/cefsimple/simple_handler.h"
6 |
7 | #include
8 | #include
9 |
10 | #include "include/base/cef_bind.h"
11 | #include "include/cef_app.h"
12 | #include "include/views/cef_browser_view.h"
13 | #include "include/views/cef_window.h"
14 | #include "include/wrapper/cef_closure_task.h"
15 | #include "include/wrapper/cef_helpers.h"
16 |
17 | namespace {
18 |
19 | SimpleHandler* g_instance = NULL;
20 |
21 | } // namespace
22 |
23 | SimpleHandler::SimpleHandler(bool use_views)
24 | : use_views_(use_views), is_closing_(false) {
25 | DCHECK(!g_instance);
26 | g_instance = this;
27 | }
28 |
29 | SimpleHandler::~SimpleHandler() {
30 | g_instance = NULL;
31 | }
32 |
33 | // static
34 | SimpleHandler* SimpleHandler::GetInstance() {
35 | return g_instance;
36 | }
37 |
38 | void SimpleHandler::OnTitleChange(CefRefPtr browser,
39 | const CefString& title) {
40 | CEF_REQUIRE_UI_THREAD();
41 |
42 | if (use_views_) {
43 | // Set the title of the window using the Views framework.
44 | CefRefPtr browser_view =
45 | CefBrowserView::GetForBrowser(browser);
46 | if (browser_view) {
47 | CefRefPtr window = browser_view->GetWindow();
48 | if (window)
49 | window->SetTitle(title);
50 | }
51 | } else {
52 | // Set the title of the window using platform APIs.
53 | PlatformTitleChange(browser, title);
54 | }
55 | }
56 |
57 | void SimpleHandler::OnAfterCreated(CefRefPtr browser) {
58 | CEF_REQUIRE_UI_THREAD();
59 |
60 | // Add to the list of existing browsers.
61 | browser_list_.push_back(browser);
62 | }
63 |
64 | bool SimpleHandler::DoClose(CefRefPtr browser) {
65 | CEF_REQUIRE_UI_THREAD();
66 |
67 | // Closing the main window requires special handling. See the DoClose()
68 | // documentation in the CEF header for a detailed destription of this
69 | // process.
70 | if (browser_list_.size() == 1) {
71 | // Set a flag to indicate that the window close should be allowed.
72 | is_closing_ = true;
73 | }
74 |
75 | // Allow the close. For windowed browsers this will result in the OS close
76 | // event being sent.
77 | return false;
78 | }
79 |
80 | void SimpleHandler::OnBeforeClose(CefRefPtr browser) {
81 | CEF_REQUIRE_UI_THREAD();
82 |
83 | // Remove from the list of existing browsers.
84 | BrowserList::iterator bit = browser_list_.begin();
85 | for (; bit != browser_list_.end(); ++bit) {
86 | if ((*bit)->IsSame(browser)) {
87 | browser_list_.erase(bit);
88 | break;
89 | }
90 | }
91 |
92 | if (browser_list_.empty()) {
93 | // All browser windows have closed. Quit the application message loop.
94 | CefQuitMessageLoop();
95 | }
96 | }
97 |
98 | void SimpleHandler::OnLoadError(CefRefPtr browser,
99 | CefRefPtr frame,
100 | ErrorCode errorCode,
101 | const CefString& errorText,
102 | const CefString& failedUrl) {
103 | CEF_REQUIRE_UI_THREAD();
104 |
105 | // Don't display an error for downloaded files.
106 | if (errorCode == ERR_ABORTED)
107 | return;
108 |
109 | // Display a load error message.
110 | std::stringstream ss;
111 | ss << ""
112 | "Failed to load URL "
113 | << std::string(failedUrl) << " with error " << std::string(errorText)
114 | << " (" << errorCode << ").
";
115 | frame->LoadString(ss.str(), failedUrl);
116 | }
117 |
118 | void SimpleHandler::CloseAllBrowsers(bool force_close) {
119 | if (!CefCurrentlyOn(TID_UI)) {
120 | // Execute on the UI thread.
121 | CefPostTask(TID_UI, base::Bind(&SimpleHandler::CloseAllBrowsers, this,
122 | force_close));
123 | return;
124 | }
125 |
126 | if (browser_list_.empty())
127 | return;
128 |
129 | BrowserList::const_iterator it = browser_list_.begin();
130 | for (; it != browser_list_.end(); ++it)
131 | (*it)->GetHost()->CloseBrowser(force_close);
132 | }
133 |
--------------------------------------------------------------------------------
/demos/file-manager/file-manager-main.cpp:
--------------------------------------------------------------------------------
1 | // CEF-Demos
2 | // Copyright (c) 2019 Borislav Stanimirov
3 | //
4 | // Distributed under the MIT Software License
5 | // See accompanying file LICENSE.txt or copy at
6 | // http://opensource.org/licenses/MIT
7 | //
8 | #include
9 | #include
10 | #include
11 |
12 | #include
13 | #include
14 |
15 | #include "FileManager.hpp"
16 |
17 | #include
18 | #include
19 |
20 | #define URI_ROOT "https://cefdemos"
21 | const char* URL = URI_ROOT "/file-manager.html";
22 |
23 | class MessageHandler : public CefMessageRouterBrowserSide::Handler
24 | {
25 | public:
26 | MessageHandler(fileman::FileManager& f)
27 | : m_fileManager(f)
28 | {}
29 |
30 | bool OnQuery(CefRefPtr browser,
31 | CefRefPtr frame,
32 | int64 query_id,
33 | const CefString& request,
34 | bool persistent,
35 | CefRefPtr callback) override
36 | {
37 | std::string r = request;
38 | auto f = r.find(':');
39 | if (f == std::string::npos) return false;
40 | auto rtype = r.substr(0, f);
41 | if (rtype != "contents") return false;
42 | auto rarg = r.substr(f+1);
43 | auto contents = m_fileManager.getDirectoryContents(rarg.c_str());
44 |
45 | std::ostringstream json;
46 | json << R"json({"dirs":[)json";
47 | for(size_t i=0; iSuccess(json.str());
61 | return true;
62 | }
63 |
64 | private:
65 | fileman::FileManager& m_fileManager;
66 | };
67 |
68 | class FileManagerClient : public CefClient, public CefLifeSpanHandler, public CefRequestHandler
69 | {
70 | public:
71 | FileManagerClient()
72 | : m_resourceManager(new CefResourceManager)
73 | , m_fileManager(new fileman::FileManager)
74 | {
75 | auto exePath = cefdemos::PlatformUtil::getCurrentExecutablePath();
76 | auto assetPath = cefdemos::PlatformUtil::getAssetPath(exePath, "html");
77 | cefdemos::Resources::setupResourceManagerDirectoryProvider(m_resourceManager, URI_ROOT, assetPath);
78 | }
79 |
80 | virtual CefRefPtr GetLifeSpanHandler() override { return this; }
81 | virtual CefRefPtr GetRequestHandler() override { return this; }
82 |
83 | virtual bool OnProcessMessageReceived(CefRefPtr browser,
84 | CefProcessId source_process,
85 | CefRefPtr message) override
86 | {
87 | return m_messageRouter->OnProcessMessageReceived(browser, source_process, message);
88 | }
89 |
90 | /////////////////////////////////////
91 | // lifespan handler
92 | virtual void OnAfterCreated(CefRefPtr browser) override
93 | {
94 | CefMessageRouterConfig mrconfig;
95 | m_messageRouter = CefMessageRouterBrowserSide::Create(mrconfig);
96 | m_messageHandler.reset(new MessageHandler(*m_fileManager));
97 | m_messageRouter->AddHandler(m_messageHandler.get(), false);
98 | }
99 |
100 | void OnBeforeClose(CefRefPtr browser) override
101 | {
102 | m_messageRouter->RemoveHandler(m_messageHandler.get());
103 | m_messageHandler.reset();
104 | m_messageRouter = nullptr;
105 |
106 | CefQuitMessageLoop();
107 | }
108 |
109 |
110 | /////////////////////////////////////
111 | // request handler
112 |
113 | virtual bool OnBeforeBrowse(CefRefPtr browser,
114 | CefRefPtr frame,
115 | CefRefPtr request,
116 | bool user_gesture,
117 | bool is_redirect) override
118 | {
119 | m_messageRouter->OnBeforeBrowse(browser, frame);
120 | return false;
121 | }
122 |
123 | virtual void OnRenderProcessTerminated(CefRefPtr browser, TerminationStatus status) override
124 | {
125 | m_messageRouter->OnRenderProcessTerminated(browser);
126 | }
127 |
128 | virtual cef_return_value_t OnBeforeResourceLoad(
129 | CefRefPtr browser,
130 | CefRefPtr frame,
131 | CefRefPtr request,
132 | CefRefPtr callback) override
133 | {
134 | return m_resourceManager->OnBeforeResourceLoad(browser, frame, request, callback);
135 | }
136 |
137 | virtual CefRefPtr GetResourceHandler(
138 | CefRefPtr browser,
139 | CefRefPtr frame,
140 | CefRefPtr request) override
141 | {
142 | return m_resourceManager->GetResourceHandler(browser, frame, request);
143 | }
144 |
145 | private:
146 | std::unique_ptr m_fileManager;
147 |
148 | CefRefPtr m_resourceManager;
149 |
150 | CefRefPtr m_messageRouter;
151 | scoped_ptr m_messageHandler;
152 |
153 | IMPLEMENT_REFCOUNTING(FileManagerClient);
154 | DISALLOW_COPY_AND_ASSIGN(FileManagerClient);
155 | };
156 |
157 | ////////////////////////////////////////
158 | // renderer process handling
159 | class RendererApp : public CefApp, public CefRenderProcessHandler
160 | {
161 | public:
162 | RendererApp() = default;
163 |
164 | CefRefPtr GetRenderProcessHandler() override {
165 | return this;
166 | }
167 |
168 | void OnWebKitInitialized() override
169 | {
170 | CefMessageRouterConfig config;
171 | m_messageRouter = CefMessageRouterRendererSide::Create(config);
172 | }
173 |
174 | virtual void OnContextCreated(CefRefPtr browser,
175 | CefRefPtr frame, CefRefPtr context) override
176 | {
177 | m_messageRouter->OnContextCreated(browser, frame, context);
178 | }
179 |
180 | virtual void OnContextReleased(CefRefPtr browser,
181 | CefRefPtr frame, CefRefPtr context) override
182 | {
183 | m_messageRouter->OnContextReleased(browser, frame, context);
184 | }
185 |
186 | virtual bool OnProcessMessageReceived(CefRefPtr browser,
187 | CefProcessId source_process, CefRefPtr message) override
188 | {
189 | return m_messageRouter->OnProcessMessageReceived(browser, source_process, message);
190 | }
191 |
192 | private:
193 | CefRefPtr m_messageRouter;
194 |
195 | IMPLEMENT_REFCOUNTING(RendererApp);
196 | DISALLOW_COPY_AND_ASSIGN(RendererApp);
197 | };
198 | ////////////////////////////////////////
199 |
200 | int main(int argc, char* argv[])
201 | {
202 | CefRefPtr commandLine = CefCommandLine::CreateCommandLine();
203 | #if defined(_WIN32)
204 | CefEnableHighDPISupport();
205 | CefMainArgs args(GetModuleHandle(NULL));
206 | commandLine->InitFromString(GetCommandLineW());
207 | #else
208 | CefMainArgs args(argc, argv);
209 | commandLine->InitFromArgv(argc, argv);
210 | #endif
211 |
212 | void* windowsSandboxInfo = NULL;
213 |
214 | #if defined(CEF_USE_SANDBOX) && defined(_WIN32)
215 | // Manage the life span of the sandbox information object. This is necessary
216 | // for sandbox support on Windows. See cef_sandbox_win.h for complete details.
217 | CefScopedSandboxInfo scopedSandbox;
218 | windowsSandboxInfo = scopedSandbox.sandbox_info();
219 | #endif
220 |
221 | CefRefPtr app = nullptr;
222 | std::string appType = commandLine->GetSwitchValue("type");
223 | if (appType == "renderer" || appType == "zygote") {
224 | app = new RendererApp;
225 | }
226 | int result = CefExecuteProcess(args, app, windowsSandboxInfo);
227 | if (result >= 0)
228 | {
229 | // child process completed
230 | return result;
231 | }
232 |
233 | CefSettings settings;
234 | #if !defined(CEF_USE_SANDBOX)
235 | settings.no_sandbox = true;
236 | #endif
237 |
238 | CefInitialize(args, settings, nullptr, windowsSandboxInfo);
239 |
240 | CefWindowInfo windowInfo;
241 |
242 | #if defined(_WIN32)
243 | // On Windows we need to specify certain flags that will be passed to CreateWindowEx().
244 | windowInfo.SetAsPopup(NULL, "Resource");
245 | #endif
246 | CefBrowserSettings browserSettings;
247 | CefBrowserHost::CreateBrowser(windowInfo, new FileManagerClient, URL, browserSettings, nullptr);
248 |
249 | CefRunMessageLoop();
250 |
251 | CefShutdown();
252 |
253 | return 0;
254 | }
--------------------------------------------------------------------------------
/demos/simple-headless/simple-headless.cpp:
--------------------------------------------------------------------------------
1 | // CEF-Demos
2 | // Copyright (c) 2019 Borislav Stanimirov
3 | //
4 | // Distributed under the MIT Software License
5 | // See accompanying file LICENSE.txt or copy at
6 | // http://opensource.org/licenses/MIT
7 | //
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #include // so we can sleep in the main loop
14 | #include
15 |
16 | const char* HTML = R"demohtml(
17 |
18 |
19 |
26 |
27 | )demohtml";
28 |
29 | const char* URL = "https://cef-demos/headless";
30 |
31 | std::atomic_bool HTML_LoadingDone;
32 |
33 | class MessageHandler : public CefMessageRouterBrowserSide::Handler
34 | {
35 | public:
36 | MessageHandler() = default;
37 |
38 | bool OnQuery(CefRefPtr browser,
39 | CefRefPtr frame,
40 | int64 query_id,
41 | const CefString& request,
42 | bool persistent,
43 | CefRefPtr callback) override
44 | {
45 | if (request == "done") {
46 | HTML_LoadingDone = true;
47 | return true;
48 | }
49 | return false;
50 | }
51 | };
52 |
53 | void SetupResourceManagerOnIOThread(CefRefPtr resourceManager)
54 | {
55 | if (!CefCurrentlyOn(TID_IO))
56 | {
57 | CefPostTask(TID_IO, base::Bind(SetupResourceManagerOnIOThread, resourceManager));
58 | return;
59 | }
60 |
61 | resourceManager->AddContentProvider(URL, HTML, "text/html", 10, std::string());
62 | }
63 |
64 | class HeadlessClient : public CefClient, public CefLifeSpanHandler, public CefRequestHandler, public CefRenderHandler
65 | {
66 | public:
67 | HeadlessClient()
68 | : m_resourceManager(new CefResourceManager)
69 | {
70 | SetupResourceManagerOnIOThread(m_resourceManager);
71 | }
72 |
73 | virtual CefRefPtr GetLifeSpanHandler() override { return this; }
74 | virtual CefRefPtr GetRequestHandler() override { return this; }
75 | virtual CefRefPtr GetRenderHandler() override { return this; }
76 |
77 | virtual bool OnProcessMessageReceived(CefRefPtr browser,
78 | CefProcessId source_process,
79 | CefRefPtr message) override
80 | {
81 | return m_messageRouter->OnProcessMessageReceived(browser, source_process, message);
82 | }
83 |
84 | /////////////////////////////////////
85 | // lifespan handler
86 | virtual void OnAfterCreated(CefRefPtr browser) override
87 | {
88 | CefMessageRouterConfig mrconfig;
89 | m_messageRouter = CefMessageRouterBrowserSide::Create(mrconfig);
90 | m_messageHandler.reset(new MessageHandler);
91 | m_messageRouter->AddHandler(m_messageHandler.get(), false);
92 | }
93 |
94 | void OnBeforeClose(CefRefPtr browser) override
95 | {
96 | m_messageRouter->RemoveHandler(m_messageHandler.get());
97 | m_messageHandler.reset();
98 | m_messageRouter = nullptr;
99 | }
100 |
101 |
102 | /////////////////////////////////////
103 | // request handler
104 |
105 | virtual bool OnBeforeBrowse(CefRefPtr browser,
106 | CefRefPtr frame,
107 | CefRefPtr request,
108 | bool user_gesture,
109 | bool is_redirect) override
110 | {
111 | m_messageRouter->OnBeforeBrowse(browser, frame);
112 | return false;
113 | }
114 |
115 | virtual void OnRenderProcessTerminated(CefRefPtr browser, TerminationStatus status) override
116 | {
117 | m_messageRouter->OnRenderProcessTerminated(browser);
118 | }
119 |
120 | virtual cef_return_value_t OnBeforeResourceLoad(
121 | CefRefPtr browser,
122 | CefRefPtr frame,
123 | CefRefPtr request,
124 | CefRefPtr callback) override
125 | {
126 | return m_resourceManager->OnBeforeResourceLoad(browser, frame, request, callback);
127 | }
128 |
129 | virtual CefRefPtr GetResourceHandler(
130 | CefRefPtr browser,
131 | CefRefPtr frame,
132 | CefRefPtr request) override
133 | {
134 | return m_resourceManager->GetResourceHandler(browser, frame, request);
135 | }
136 |
137 | /////////////////////////////////////
138 | // render handler
139 | virtual void GetViewRect(CefRefPtr browser, CefRect &rect) override
140 | {
141 | rect = CefRect(0, 0, 200, 200); // some random rect
142 | }
143 |
144 | virtual void OnPaint(CefRefPtr browser,
145 | PaintElementType type,
146 | const RectList& dirtyRects,
147 | const void* buffer,
148 | int width,
149 | int height) override
150 | {} // noop. nothing to do
151 |
152 |
153 | private:
154 | CefRefPtr m_resourceManager;
155 |
156 | CefRefPtr m_messageRouter;
157 | scoped_ptr m_messageHandler;
158 |
159 | IMPLEMENT_REFCOUNTING(HeadlessClient);
160 | DISALLOW_COPY_AND_ASSIGN(HeadlessClient);
161 | };
162 |
163 | ////////////////////////////////////////
164 | // renderer process handling
165 | class RendererApp : public CefApp, public CefRenderProcessHandler
166 | {
167 | public:
168 | RendererApp() = default;
169 |
170 | CefRefPtr GetRenderProcessHandler() override {
171 | return this;
172 | }
173 |
174 | void OnWebKitInitialized() override
175 | {
176 | puts("WEBKIG!!!");
177 | CefMessageRouterConfig config;
178 | m_messageRouter = CefMessageRouterRendererSide::Create(config);
179 | }
180 |
181 | virtual void OnContextCreated(CefRefPtr browser,
182 | CefRefPtr frame, CefRefPtr context) override
183 | {
184 | m_messageRouter->OnContextCreated(browser, frame, context);
185 | }
186 |
187 | virtual void OnContextReleased(CefRefPtr browser,
188 | CefRefPtr frame, CefRefPtr context) override
189 | {
190 | m_messageRouter->OnContextReleased(browser, frame, context);
191 | }
192 |
193 | virtual bool OnProcessMessageReceived(CefRefPtr browser,
194 | CefProcessId source_process, CefRefPtr message) override
195 | {
196 | return m_messageRouter->OnProcessMessageReceived(browser, source_process, message);
197 | }
198 |
199 | private:
200 | CefRefPtr m_messageRouter;
201 |
202 | IMPLEMENT_REFCOUNTING(RendererApp);
203 | DISALLOW_COPY_AND_ASSIGN(RendererApp);
204 | };
205 | ////////////////////////////////////////
206 |
207 | int main(int argc, char* argv[])
208 | {
209 | CefRefPtr commandLine = CefCommandLine::CreateCommandLine();
210 | #if defined(_WIN32)
211 | CefEnableHighDPISupport();
212 | CefMainArgs args(GetModuleHandle(NULL));
213 | commandLine->InitFromString(GetCommandLineW());
214 | #else
215 | CefMainArgs args(argc, argv);
216 | commandLine->InitFromArgv(argc, argv);
217 | #endif
218 |
219 | void* windowsSandboxInfo = NULL;
220 |
221 | #if defined(CEF_USE_SANDBOX) && defined(_WIN32)
222 | // Manage the life span of the sandbox information object. This is necessary
223 | // for sandbox support on Windows. See cef_sandbox_win.h for complete details.
224 | CefScopedSandboxInfo scopedSandbox;
225 | windowsSandboxInfo = scopedSandbox.sandbox_info();
226 | #endif
227 |
228 | CefRefPtr app = nullptr;
229 | std::string appType = commandLine->GetSwitchValue("type");
230 | if (appType == "renderer" || appType == "zygote") {
231 | app = new RendererApp;
232 | }
233 | int result = CefExecuteProcess(args, app, windowsSandboxInfo);
234 | if (result >= 0)
235 | {
236 | // child process completed
237 | return result;
238 | }
239 |
240 | CefSettings settings;
241 | settings.windowless_rendering_enabled = 1;
242 | #if !defined(CEF_USE_SANDBOX)
243 | settings.no_sandbox = true;
244 | #endif
245 |
246 | CefInitialize(args, settings, nullptr, windowsSandboxInfo);
247 |
248 | CefWindowInfo windowInfo;
249 | windowInfo.SetAsWindowless(0);
250 |
251 | CefBrowserSettings browserSettings;
252 | auto browser = CefBrowserHost::CreateBrowserSync(windowInfo, new HeadlessClient, URL, browserSettings, nullptr);
253 |
254 | // main loop
255 | while (!HTML_LoadingDone)
256 | {
257 | CefDoMessageLoopWork();
258 | std::this_thread::sleep_for(std::chrono::milliseconds(15));
259 | }
260 |
261 | browser = nullptr;
262 | CefShutdown();
263 |
264 | return 0;
265 | }
--------------------------------------------------------------------------------
/demos/file-manager/win_dirent.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Dirent interface for Microsoft Visual Studio
3 | *
4 | * Copyright (C) 1998-2019 Toni Ronkko
5 | * This file is part of dirent. Dirent may be freely distributed
6 | * under the MIT license. For all details and documentation, see
7 | * https://github.com/tronkko/dirent
8 | */
9 | #ifndef DIRENT_H
10 | #define DIRENT_H
11 |
12 | /* Hide warnings about unreferenced local functions */
13 | #if defined(__clang__)
14 | # pragma clang diagnostic ignored "-Wunused-function"
15 | #elif defined(_MSC_VER)
16 | # pragma warning(disable:4505)
17 | #elif defined(__GNUC__)
18 | # pragma GCC diagnostic ignored "-Wunused-function"
19 | #endif
20 |
21 | /*
22 | * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
23 | * Windows Sockets 2.0.
24 | */
25 | #ifndef WIN32_LEAN_AND_MEAN
26 | # define WIN32_LEAN_AND_MEAN
27 | #endif
28 | #include
29 |
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 |
40 | /* Indicates that d_type field is available in dirent structure */
41 | #define _DIRENT_HAVE_D_TYPE
42 |
43 | /* Indicates that d_namlen field is available in dirent structure */
44 | #define _DIRENT_HAVE_D_NAMLEN
45 |
46 | /* Entries missing from MSVC 6.0 */
47 | #if !defined(FILE_ATTRIBUTE_DEVICE)
48 | # define FILE_ATTRIBUTE_DEVICE 0x40
49 | #endif
50 |
51 | /* File type and permission flags for stat(), general mask */
52 | #if !defined(S_IFMT)
53 | # define S_IFMT _S_IFMT
54 | #endif
55 |
56 | /* Directory bit */
57 | #if !defined(S_IFDIR)
58 | # define S_IFDIR _S_IFDIR
59 | #endif
60 |
61 | /* Character device bit */
62 | #if !defined(S_IFCHR)
63 | # define S_IFCHR _S_IFCHR
64 | #endif
65 |
66 | /* Pipe bit */
67 | #if !defined(S_IFFIFO)
68 | # define S_IFFIFO _S_IFFIFO
69 | #endif
70 |
71 | /* Regular file bit */
72 | #if !defined(S_IFREG)
73 | # define S_IFREG _S_IFREG
74 | #endif
75 |
76 | /* Read permission */
77 | #if !defined(S_IREAD)
78 | # define S_IREAD _S_IREAD
79 | #endif
80 |
81 | /* Write permission */
82 | #if !defined(S_IWRITE)
83 | # define S_IWRITE _S_IWRITE
84 | #endif
85 |
86 | /* Execute permission */
87 | #if !defined(S_IEXEC)
88 | # define S_IEXEC _S_IEXEC
89 | #endif
90 |
91 | /* Pipe */
92 | #if !defined(S_IFIFO)
93 | # define S_IFIFO _S_IFIFO
94 | #endif
95 |
96 | /* Block device */
97 | #if !defined(S_IFBLK)
98 | # define S_IFBLK 0
99 | #endif
100 |
101 | /* Link */
102 | #if !defined(S_IFLNK)
103 | # define S_IFLNK 0
104 | #endif
105 |
106 | /* Socket */
107 | #if !defined(S_IFSOCK)
108 | # define S_IFSOCK 0
109 | #endif
110 |
111 | /* Read user permission */
112 | #if !defined(S_IRUSR)
113 | # define S_IRUSR S_IREAD
114 | #endif
115 |
116 | /* Write user permission */
117 | #if !defined(S_IWUSR)
118 | # define S_IWUSR S_IWRITE
119 | #endif
120 |
121 | /* Execute user permission */
122 | #if !defined(S_IXUSR)
123 | # define S_IXUSR 0
124 | #endif
125 |
126 | /* Read group permission */
127 | #if !defined(S_IRGRP)
128 | # define S_IRGRP 0
129 | #endif
130 |
131 | /* Write group permission */
132 | #if !defined(S_IWGRP)
133 | # define S_IWGRP 0
134 | #endif
135 |
136 | /* Execute group permission */
137 | #if !defined(S_IXGRP)
138 | # define S_IXGRP 0
139 | #endif
140 |
141 | /* Read others permission */
142 | #if !defined(S_IROTH)
143 | # define S_IROTH 0
144 | #endif
145 |
146 | /* Write others permission */
147 | #if !defined(S_IWOTH)
148 | # define S_IWOTH 0
149 | #endif
150 |
151 | /* Execute others permission */
152 | #if !defined(S_IXOTH)
153 | # define S_IXOTH 0
154 | #endif
155 |
156 | /* Maximum length of file name */
157 | #if !defined(PATH_MAX)
158 | # define PATH_MAX MAX_PATH
159 | #endif
160 | #if !defined(FILENAME_MAX)
161 | # define FILENAME_MAX MAX_PATH
162 | #endif
163 | #if !defined(NAME_MAX)
164 | # define NAME_MAX FILENAME_MAX
165 | #endif
166 |
167 | /* File type flags for d_type */
168 | #define DT_UNKNOWN 0
169 | #define DT_REG S_IFREG
170 | #define DT_DIR S_IFDIR
171 | #define DT_FIFO S_IFIFO
172 | #define DT_SOCK S_IFSOCK
173 | #define DT_CHR S_IFCHR
174 | #define DT_BLK S_IFBLK
175 | #define DT_LNK S_IFLNK
176 |
177 | /* Macros for converting between st_mode and d_type */
178 | #define IFTODT(mode) ((mode) & S_IFMT)
179 | #define DTTOIF(type) (type)
180 |
181 | /*
182 | * File type macros. Note that block devices, sockets and links cannot be
183 | * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
184 | * only defined for compatibility. These macros should always return false
185 | * on Windows.
186 | */
187 | #if !defined(S_ISFIFO)
188 | # define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
189 | #endif
190 | #if !defined(S_ISDIR)
191 | # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
192 | #endif
193 | #if !defined(S_ISREG)
194 | # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
195 | #endif
196 | #if !defined(S_ISLNK)
197 | # define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
198 | #endif
199 | #if !defined(S_ISSOCK)
200 | # define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
201 | #endif
202 | #if !defined(S_ISCHR)
203 | # define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
204 | #endif
205 | #if !defined(S_ISBLK)
206 | # define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
207 | #endif
208 |
209 | /* Return the exact length of the file name without zero terminator */
210 | #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
211 |
212 | /* Return the maximum size of a file name */
213 | #define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1)
214 |
215 |
216 | #ifdef __cplusplus
217 | extern "C" {
218 | #endif
219 |
220 |
221 | /* Wide-character version */
222 | struct _wdirent {
223 | /* Always zero */
224 | long d_ino;
225 |
226 | /* File position within stream */
227 | long d_off;
228 |
229 | /* Structure size */
230 | unsigned short d_reclen;
231 |
232 | /* Length of name without \0 */
233 | size_t d_namlen;
234 |
235 | /* File type */
236 | int d_type;
237 |
238 | /* File name */
239 | wchar_t d_name[PATH_MAX + 1];
240 | };
241 | typedef struct _wdirent _wdirent;
242 |
243 | struct _WDIR {
244 | /* Current directory entry */
245 | struct _wdirent ent;
246 |
247 | /* Private file data */
248 | WIN32_FIND_DATAW data;
249 |
250 | /* True if data is valid */
251 | int cached;
252 |
253 | /* Win32 search handle */
254 | HANDLE handle;
255 |
256 | /* Initial directory name */
257 | wchar_t *patt;
258 | };
259 | typedef struct _WDIR _WDIR;
260 |
261 | /* Multi-byte character version */
262 | struct dirent {
263 | /* Always zero */
264 | long d_ino;
265 |
266 | /* File position within stream */
267 | long d_off;
268 |
269 | /* Structure size */
270 | unsigned short d_reclen;
271 |
272 | /* Length of name without \0 */
273 | size_t d_namlen;
274 |
275 | /* File type */
276 | int d_type;
277 |
278 | /* File name */
279 | char d_name[PATH_MAX + 1];
280 | };
281 | typedef struct dirent dirent;
282 |
283 | struct DIR {
284 | struct dirent ent;
285 | struct _WDIR *wdirp;
286 | };
287 | typedef struct DIR DIR;
288 |
289 |
290 | /* Dirent functions */
291 | static DIR *opendir(const char *dirname);
292 | static _WDIR *_wopendir(const wchar_t *dirname);
293 |
294 | static struct dirent *readdir(DIR *dirp);
295 | static struct _wdirent *_wreaddir(_WDIR *dirp);
296 |
297 | static int readdir_r(
298 | DIR *dirp, struct dirent *entry, struct dirent **result);
299 | static int _wreaddir_r(
300 | _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result);
301 |
302 | static int closedir(DIR *dirp);
303 | static int _wclosedir(_WDIR *dirp);
304 |
305 | static void rewinddir(DIR* dirp);
306 | static void _wrewinddir(_WDIR* dirp);
307 |
308 | static int scandir(const char *dirname, struct dirent ***namelist,
309 | int(*filter)(const struct dirent*),
310 | int(*compare)(const struct dirent**, const struct dirent**));
311 |
312 | static int alphasort(const struct dirent **a, const struct dirent **b);
313 |
314 | static int versionsort(const struct dirent **a, const struct dirent **b);
315 |
316 |
317 | /* For compatibility with Symbian */
318 | #define wdirent _wdirent
319 | #define WDIR _WDIR
320 | #define wopendir _wopendir
321 | #define wreaddir _wreaddir
322 | #define wclosedir _wclosedir
323 | #define wrewinddir _wrewinddir
324 |
325 |
326 | /* Internal utility functions */
327 | static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp);
328 | static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp);
329 |
330 | static int dirent_mbstowcs_s(
331 | size_t *pReturnValue,
332 | wchar_t *wcstr,
333 | size_t sizeInWords,
334 | const char *mbstr,
335 | size_t count);
336 |
337 | static int dirent_wcstombs_s(
338 | size_t *pReturnValue,
339 | char *mbstr,
340 | size_t sizeInBytes,
341 | const wchar_t *wcstr,
342 | size_t count);
343 |
344 | static void dirent_set_errno(int error);
345 |
346 |
347 | /*
348 | * Open directory stream DIRNAME for read and return a pointer to the
349 | * internal working area that is used to retrieve individual directory
350 | * entries.
351 | */
352 | static _WDIR*
353 | _wopendir(
354 | const wchar_t *dirname)
355 | {
356 | _WDIR *dirp;
357 | DWORD n;
358 | wchar_t *p;
359 |
360 | /* Must have directory name */
361 | if (dirname == NULL || dirname[0] == '\0') {
362 | dirent_set_errno(ENOENT);
363 | return NULL;
364 | }
365 |
366 | /* Allocate new _WDIR structure */
367 | dirp = (_WDIR*)malloc(sizeof(struct _WDIR));
368 | if (!dirp) {
369 | return NULL;
370 | }
371 |
372 | /* Reset _WDIR structure */
373 | dirp->handle = INVALID_HANDLE_VALUE;
374 | dirp->patt = NULL;
375 | dirp->cached = 0;
376 |
377 | /*
378 | * Compute the length of full path plus zero terminator
379 | *
380 | * Note that on WinRT there's no way to convert relative paths
381 | * into absolute paths, so just assume it is an absolute path.
382 | */
383 | #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
384 | /* Desktop */
385 | n = GetFullPathNameW(dirname, 0, NULL, NULL);
386 | #else
387 | /* WinRT */
388 | n = wcslen(dirname);
389 | #endif
390 |
391 | /* Allocate room for absolute directory name and search pattern */
392 | dirp->patt = (wchar_t*)malloc(sizeof(wchar_t) * n + 16);
393 | if (dirp->patt == NULL) {
394 | goto exit_closedir;
395 | }
396 |
397 | /*
398 | * Convert relative directory name to an absolute one. This
399 | * allows rewinddir() to function correctly even when current
400 | * working directory is changed between opendir() and rewinddir().
401 | *
402 | * Note that on WinRT there's no way to convert relative paths
403 | * into absolute paths, so just assume it is an absolute path.
404 | */
405 | #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
406 | /* Desktop */
407 | n = GetFullPathNameW(dirname, n, dirp->patt, NULL);
408 | if (n <= 0) {
409 | goto exit_closedir;
410 | }
411 | #else
412 | /* WinRT */
413 | wcsncpy_s(dirp->patt, n + 1, dirname, n);
414 | #endif
415 |
416 | /* Append search pattern \* to the directory name */
417 | p = dirp->patt + n;
418 | switch (p[-1]) {
419 | case '\\':
420 | case '/':
421 | case ':':
422 | /* Directory ends in path separator, e.g. c:\temp\ */
423 | /*NOP*/;
424 | break;
425 |
426 | default:
427 | /* Directory name doesn't end in path separator */
428 | *p++ = '\\';
429 | }
430 | *p++ = '*';
431 | *p = '\0';
432 |
433 | /* Open directory stream and retrieve the first entry */
434 | if (!dirent_first(dirp)) {
435 | goto exit_closedir;
436 | }
437 |
438 | /* Success */
439 | return dirp;
440 |
441 | /* Failure */
442 | exit_closedir:
443 | _wclosedir(dirp);
444 | return NULL;
445 | }
446 |
447 | /*
448 | * Read next directory entry.
449 | *
450 | * Returns pointer to static directory entry which may be overwritten by
451 | * subsequent calls to _wreaddir().
452 | */
453 | static struct _wdirent*
454 | _wreaddir(
455 | _WDIR *dirp)
456 | {
457 | struct _wdirent *entry;
458 |
459 | /*
460 | * Read directory entry to buffer. We can safely ignore the return value
461 | * as entry will be set to NULL in case of error.
462 | */
463 | (void)_wreaddir_r(dirp, &dirp->ent, &entry);
464 |
465 | /* Return pointer to statically allocated directory entry */
466 | return entry;
467 | }
468 |
469 | /*
470 | * Read next directory entry.
471 | *
472 | * Returns zero on success. If end of directory stream is reached, then sets
473 | * result to NULL and returns zero.
474 | */
475 | static int
476 | _wreaddir_r(
477 | _WDIR *dirp,
478 | struct _wdirent *entry,
479 | struct _wdirent **result)
480 | {
481 | WIN32_FIND_DATAW *datap;
482 |
483 | /* Read next directory entry */
484 | datap = dirent_next(dirp);
485 | if (datap) {
486 | size_t n;
487 | DWORD attr;
488 |
489 | /*
490 | * Copy file name as wide-character string. If the file name is too
491 | * long to fit in to the destination buffer, then truncate file name
492 | * to PATH_MAX characters and zero-terminate the buffer.
493 | */
494 | n = 0;
495 | while (n < PATH_MAX && datap->cFileName[n] != 0) {
496 | entry->d_name[n] = datap->cFileName[n];
497 | n++;
498 | }
499 | entry->d_name[n] = 0;
500 |
501 | /* Length of file name excluding zero terminator */
502 | entry->d_namlen = n;
503 |
504 | /* File type */
505 | attr = datap->dwFileAttributes;
506 | if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
507 | entry->d_type = DT_CHR;
508 | }
509 | else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
510 | entry->d_type = DT_DIR;
511 | }
512 | else {
513 | entry->d_type = DT_REG;
514 | }
515 |
516 | /* Reset dummy fields */
517 | entry->d_ino = 0;
518 | entry->d_off = 0;
519 | entry->d_reclen = sizeof(struct _wdirent);
520 |
521 | /* Set result address */
522 | *result = entry;
523 |
524 | }
525 | else {
526 |
527 | /* Return NULL to indicate end of directory */
528 | *result = NULL;
529 |
530 | }
531 |
532 | return /*OK*/0;
533 | }
534 |
535 | /*
536 | * Close directory stream opened by opendir() function. This invalidates the
537 | * DIR structure as well as any directory entry read previously by
538 | * _wreaddir().
539 | */
540 | static int
541 | _wclosedir(
542 | _WDIR *dirp)
543 | {
544 | int ok;
545 | if (dirp) {
546 |
547 | /* Release search handle */
548 | if (dirp->handle != INVALID_HANDLE_VALUE) {
549 | FindClose(dirp->handle);
550 | }
551 |
552 | /* Release search pattern */
553 | free(dirp->patt);
554 |
555 | /* Release directory structure */
556 | free(dirp);
557 | ok = /*success*/0;
558 |
559 | }
560 | else {
561 |
562 | /* Invalid directory stream */
563 | dirent_set_errno(EBADF);
564 | ok = /*failure*/-1;
565 |
566 | }
567 | return ok;
568 | }
569 |
570 | /*
571 | * Rewind directory stream such that _wreaddir() returns the very first
572 | * file name again.
573 | */
574 | static void
575 | _wrewinddir(
576 | _WDIR* dirp)
577 | {
578 | if (dirp) {
579 | /* Release existing search handle */
580 | if (dirp->handle != INVALID_HANDLE_VALUE) {
581 | FindClose(dirp->handle);
582 | }
583 |
584 | /* Open new search handle */
585 | dirent_first(dirp);
586 | }
587 | }
588 |
589 | /* Get first directory entry (internal) */
590 | static WIN32_FIND_DATAW*
591 | dirent_first(
592 | _WDIR *dirp)
593 | {
594 | WIN32_FIND_DATAW *datap;
595 | DWORD error;
596 |
597 | /* Open directory and retrieve the first entry */
598 | dirp->handle = FindFirstFileExW(
599 | dirp->patt, FindExInfoStandard, &dirp->data,
600 | FindExSearchNameMatch, NULL, 0);
601 | if (dirp->handle != INVALID_HANDLE_VALUE) {
602 |
603 | /* a directory entry is now waiting in memory */
604 | datap = &dirp->data;
605 | dirp->cached = 1;
606 |
607 | }
608 | else {
609 |
610 | /* Failed to open directory: no directory entry in memory */
611 | dirp->cached = 0;
612 | datap = NULL;
613 |
614 | /* Set error code */
615 | error = GetLastError();
616 | switch (error) {
617 | case ERROR_ACCESS_DENIED:
618 | /* No read access to directory */
619 | dirent_set_errno(EACCES);
620 | break;
621 |
622 | case ERROR_DIRECTORY:
623 | /* Directory name is invalid */
624 | dirent_set_errno(ENOTDIR);
625 | break;
626 |
627 | case ERROR_PATH_NOT_FOUND:
628 | default:
629 | /* Cannot find the file */
630 | dirent_set_errno(ENOENT);
631 | }
632 |
633 | }
634 | return datap;
635 | }
636 |
637 | /*
638 | * Get next directory entry (internal).
639 | *
640 | * Returns
641 | */
642 | static WIN32_FIND_DATAW*
643 | dirent_next(
644 | _WDIR *dirp)
645 | {
646 | WIN32_FIND_DATAW *p;
647 |
648 | /* Get next directory entry */
649 | if (dirp->cached != 0) {
650 |
651 | /* A valid directory entry already in memory */
652 | p = &dirp->data;
653 | dirp->cached = 0;
654 |
655 | }
656 | else if (dirp->handle != INVALID_HANDLE_VALUE) {
657 |
658 | /* Get the next directory entry from stream */
659 | if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) {
660 | /* Got a file */
661 | p = &dirp->data;
662 | }
663 | else {
664 | /* The very last entry has been processed or an error occurred */
665 | FindClose(dirp->handle);
666 | dirp->handle = INVALID_HANDLE_VALUE;
667 | p = NULL;
668 | }
669 |
670 | }
671 | else {
672 |
673 | /* End of directory stream reached */
674 | p = NULL;
675 |
676 | }
677 |
678 | return p;
679 | }
680 |
681 | /*
682 | * Open directory stream using plain old C-string.
683 | */
684 | static DIR*
685 | opendir(
686 | const char *dirname)
687 | {
688 | struct DIR *dirp;
689 |
690 | /* Must have directory name */
691 | if (dirname == NULL || dirname[0] == '\0') {
692 | dirent_set_errno(ENOENT);
693 | return NULL;
694 | }
695 |
696 | /* Allocate memory for DIR structure */
697 | dirp = (DIR*)malloc(sizeof(struct DIR));
698 | if (!dirp) {
699 | return NULL;
700 | }
701 | {
702 | int error;
703 | wchar_t wname[PATH_MAX + 1];
704 | size_t n;
705 |
706 | /* Convert directory name to wide-character string */
707 | error = dirent_mbstowcs_s(
708 | &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
709 | if (error) {
710 | /*
711 | * Cannot convert file name to wide-character string. This
712 | * occurs if the string contains invalid multi-byte sequences or
713 | * the output buffer is too small to contain the resulting
714 | * string.
715 | */
716 | goto exit_free;
717 | }
718 |
719 |
720 | /* Open directory stream using wide-character name */
721 | dirp->wdirp = _wopendir(wname);
722 | if (!dirp->wdirp) {
723 | goto exit_free;
724 | }
725 |
726 | }
727 |
728 | /* Success */
729 | return dirp;
730 |
731 | /* Failure */
732 | exit_free:
733 | free(dirp);
734 | return NULL;
735 | }
736 |
737 | /*
738 | * Read next directory entry.
739 | */
740 | static struct dirent*
741 | readdir(
742 | DIR *dirp)
743 | {
744 | struct dirent *entry;
745 |
746 | /*
747 | * Read directory entry to buffer. We can safely ignore the return value
748 | * as entry will be set to NULL in case of error.
749 | */
750 | (void)readdir_r(dirp, &dirp->ent, &entry);
751 |
752 | /* Return pointer to statically allocated directory entry */
753 | return entry;
754 | }
755 |
756 | /*
757 | * Read next directory entry into called-allocated buffer.
758 | *
759 | * Returns zero on success. If the end of directory stream is reached, then
760 | * sets result to NULL and returns zero.
761 | */
762 | static int
763 | readdir_r(
764 | DIR *dirp,
765 | struct dirent *entry,
766 | struct dirent **result)
767 | {
768 | WIN32_FIND_DATAW *datap;
769 |
770 | /* Read next directory entry */
771 | datap = dirent_next(dirp->wdirp);
772 | if (datap) {
773 | size_t n;
774 | int error;
775 |
776 | /* Attempt to convert file name to multi-byte string */
777 | error = dirent_wcstombs_s(
778 | &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1);
779 |
780 | /*
781 | * If the file name cannot be represented by a multi-byte string,
782 | * then attempt to use old 8+3 file name. This allows traditional
783 | * Unix-code to access some file names despite of unicode
784 | * characters, although file names may seem unfamiliar to the user.
785 | *
786 | * Be ware that the code below cannot come up with a short file
787 | * name unless the file system provides one. At least
788 | * VirtualBox shared folders fail to do this.
789 | */
790 | if (error && datap->cAlternateFileName[0] != '\0') {
791 | error = dirent_wcstombs_s(
792 | &n, entry->d_name, PATH_MAX + 1,
793 | datap->cAlternateFileName, PATH_MAX + 1);
794 | }
795 |
796 | if (!error) {
797 | DWORD attr;
798 |
799 | /* Length of file name excluding zero terminator */
800 | entry->d_namlen = n - 1;
801 |
802 | /* File attributes */
803 | attr = datap->dwFileAttributes;
804 | if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
805 | entry->d_type = DT_CHR;
806 | }
807 | else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
808 | entry->d_type = DT_DIR;
809 | }
810 | else {
811 | entry->d_type = DT_REG;
812 | }
813 |
814 | /* Reset dummy fields */
815 | entry->d_ino = 0;
816 | entry->d_off = 0;
817 | entry->d_reclen = sizeof(struct dirent);
818 |
819 | }
820 | else {
821 |
822 | /*
823 | * Cannot convert file name to multi-byte string so construct
824 | * an erroneous directory entry and return that. Note that
825 | * we cannot return NULL as that would stop the processing
826 | * of directory entries completely.
827 | */
828 | entry->d_name[0] = '?';
829 | entry->d_name[1] = '\0';
830 | entry->d_namlen = 1;
831 | entry->d_type = DT_UNKNOWN;
832 | entry->d_ino = 0;
833 | entry->d_off = -1;
834 | entry->d_reclen = 0;
835 |
836 | }
837 |
838 | /* Return pointer to directory entry */
839 | *result = entry;
840 |
841 | }
842 | else {
843 |
844 | /* No more directory entries */
845 | *result = NULL;
846 |
847 | }
848 |
849 | return /*OK*/0;
850 | }
851 |
852 | /*
853 | * Close directory stream.
854 | */
855 | static int
856 | closedir(
857 | DIR *dirp)
858 | {
859 | int ok;
860 | if (dirp) {
861 |
862 | /* Close wide-character directory stream */
863 | ok = _wclosedir(dirp->wdirp);
864 | dirp->wdirp = NULL;
865 |
866 | /* Release multi-byte character version */
867 | free(dirp);
868 |
869 | }
870 | else {
871 |
872 | /* Invalid directory stream */
873 | dirent_set_errno(EBADF);
874 | ok = /*failure*/-1;
875 |
876 | }
877 | return ok;
878 | }
879 |
880 | /*
881 | * Rewind directory stream to beginning.
882 | */
883 | static void
884 | rewinddir(
885 | DIR* dirp)
886 | {
887 | /* Rewind wide-character string directory stream */
888 | _wrewinddir(dirp->wdirp);
889 | }
890 |
891 | /*
892 | * Scan directory for entries.
893 | */
894 | static int
895 | scandir(
896 | const char *dirname,
897 | struct dirent ***namelist,
898 | int(*filter)(const struct dirent*),
899 | int(*compare)(const struct dirent**, const struct dirent**))
900 | {
901 | struct dirent **files = NULL;
902 | size_t size = 0;
903 | size_t allocated = 0;
904 | const size_t init_size = 1;
905 | DIR *dir = NULL;
906 | struct dirent *entry;
907 | struct dirent *tmp = NULL;
908 | size_t i;
909 | int result = 0;
910 |
911 | /* Open directory stream */
912 | dir = opendir(dirname);
913 | if (dir) {
914 |
915 | /* Read directory entries to memory */
916 | while (1) {
917 |
918 | /* Enlarge pointer table to make room for another pointer */
919 | if (size >= allocated) {
920 | void *p;
921 | size_t num_entries;
922 |
923 | /* Compute number of entries in the enlarged pointer table */
924 | if (size < init_size) {
925 | /* Allocate initial pointer table */
926 | num_entries = init_size;
927 | }
928 | else {
929 | /* Double the size */
930 | num_entries = size * 2;
931 | }
932 |
933 | /* Allocate first pointer table or enlarge existing table */
934 | p = realloc(files, sizeof(void*) * num_entries);
935 | if (p != NULL) {
936 | /* Got the memory */
937 | files = (dirent**)p;
938 | allocated = num_entries;
939 | }
940 | else {
941 | /* Out of memory */
942 | result = -1;
943 | break;
944 | }
945 |
946 | }
947 |
948 | /* Allocate room for temporary directory entry */
949 | if (tmp == NULL) {
950 | tmp = (struct dirent*) malloc(sizeof(struct dirent));
951 | if (tmp == NULL) {
952 | /* Cannot allocate temporary directory entry */
953 | result = -1;
954 | break;
955 | }
956 | }
957 |
958 | /* Read directory entry to temporary area */
959 | if (readdir_r(dir, tmp, &entry) == /*OK*/0) {
960 |
961 | /* Did we get an entry? */
962 | if (entry != NULL) {
963 | int pass;
964 |
965 | /* Determine whether to include the entry in result */
966 | if (filter) {
967 | /* Let the filter function decide */
968 | pass = filter(tmp);
969 | }
970 | else {
971 | /* No filter function, include everything */
972 | pass = 1;
973 | }
974 |
975 | if (pass) {
976 | /* Store the temporary entry to pointer table */
977 | files[size++] = tmp;
978 | tmp = NULL;
979 |
980 | /* Keep up with the number of files */
981 | result++;
982 | }
983 |
984 | }
985 | else {
986 |
987 | /*
988 | * End of directory stream reached => sort entries and
989 | * exit.
990 | */
991 | qsort(files, size, sizeof(void*),
992 | (int(*) (const void*, const void*)) compare);
993 | break;
994 |
995 | }
996 |
997 | }
998 | else {
999 | /* Error reading directory entry */
1000 | result = /*Error*/ -1;
1001 | break;
1002 | }
1003 |
1004 | }
1005 |
1006 | }
1007 | else {
1008 | /* Cannot open directory */
1009 | result = /*Error*/ -1;
1010 | }
1011 |
1012 | /* Release temporary directory entry */
1013 | free(tmp);
1014 |
1015 | /* Release allocated memory on error */
1016 | if (result < 0) {
1017 | for (i = 0; i < size; i++) {
1018 | free(files[i]);
1019 | }
1020 | free(files);
1021 | files = NULL;
1022 | }
1023 |
1024 | /* Close directory stream */
1025 | if (dir) {
1026 | closedir(dir);
1027 | }
1028 |
1029 | /* Pass pointer table to caller */
1030 | if (namelist) {
1031 | *namelist = files;
1032 | }
1033 | return result;
1034 | }
1035 |
1036 | /* Alphabetical sorting */
1037 | static int
1038 | alphasort(
1039 | const struct dirent **a, const struct dirent **b)
1040 | {
1041 | return strcoll((*a)->d_name, (*b)->d_name);
1042 | }
1043 |
1044 | /* Sort versions */
1045 | static int
1046 | versionsort(
1047 | const struct dirent **a, const struct dirent **b)
1048 | {
1049 | /* FIXME: implement strverscmp and use that */
1050 | return alphasort(a, b);
1051 | }
1052 |
1053 | /* Convert multi-byte string to wide character string */
1054 | static int
1055 | dirent_mbstowcs_s(
1056 | size_t *pReturnValue,
1057 | wchar_t *wcstr,
1058 | size_t sizeInWords,
1059 | const char *mbstr,
1060 | size_t count)
1061 | {
1062 | int error;
1063 |
1064 | #if defined(_MSC_VER) && _MSC_VER >= 1400
1065 |
1066 | /* Microsoft Visual Studio 2005 or later */
1067 | error = mbstowcs_s(pReturnValue, wcstr, sizeInWords, mbstr, count);
1068 |
1069 | #else
1070 |
1071 | /* Older Visual Studio or non-Microsoft compiler */
1072 | size_t n;
1073 |
1074 | /* Convert to wide-character string (or count characters) */
1075 | n = mbstowcs(wcstr, mbstr, sizeInWords);
1076 | if (!wcstr || n < count) {
1077 |
1078 | /* Zero-terminate output buffer */
1079 | if (wcstr && sizeInWords) {
1080 | if (n >= sizeInWords) {
1081 | n = sizeInWords - 1;
1082 | }
1083 | wcstr[n] = 0;
1084 | }
1085 |
1086 | /* Length of resulting multi-byte string WITH zero terminator */
1087 | if (pReturnValue) {
1088 | *pReturnValue = n + 1;
1089 | }
1090 |
1091 | /* Success */
1092 | error = 0;
1093 |
1094 | }
1095 | else {
1096 |
1097 | /* Could not convert string */
1098 | error = 1;
1099 |
1100 | }
1101 |
1102 | #endif
1103 | return error;
1104 | }
1105 |
1106 | /* Convert wide-character string to multi-byte string */
1107 | static int
1108 | dirent_wcstombs_s(
1109 | size_t *pReturnValue,
1110 | char *mbstr,
1111 | size_t sizeInBytes, /* max size of mbstr */
1112 | const wchar_t *wcstr,
1113 | size_t count)
1114 | {
1115 | int error;
1116 |
1117 | #if defined(_MSC_VER) && _MSC_VER >= 1400
1118 |
1119 | /* Microsoft Visual Studio 2005 or later */
1120 | error = wcstombs_s(pReturnValue, mbstr, sizeInBytes, wcstr, count);
1121 |
1122 | #else
1123 |
1124 | /* Older Visual Studio or non-Microsoft compiler */
1125 | size_t n;
1126 |
1127 | /* Convert to multi-byte string (or count the number of bytes needed) */
1128 | n = wcstombs(mbstr, wcstr, sizeInBytes);
1129 | if (!mbstr || n < count) {
1130 |
1131 | /* Zero-terminate output buffer */
1132 | if (mbstr && sizeInBytes) {
1133 | if (n >= sizeInBytes) {
1134 | n = sizeInBytes - 1;
1135 | }
1136 | mbstr[n] = '\0';
1137 | }
1138 |
1139 | /* Length of resulting multi-bytes string WITH zero-terminator */
1140 | if (pReturnValue) {
1141 | *pReturnValue = n + 1;
1142 | }
1143 |
1144 | /* Success */
1145 | error = 0;
1146 |
1147 | }
1148 | else {
1149 |
1150 | /* Cannot convert string */
1151 | error = 1;
1152 |
1153 | }
1154 |
1155 | #endif
1156 | return error;
1157 | }
1158 |
1159 | /* Set errno variable */
1160 | static void
1161 | dirent_set_errno(
1162 | int error)
1163 | {
1164 | #if defined(_MSC_VER) && _MSC_VER >= 1400
1165 |
1166 | /* Microsoft Visual Studio 2005 and later */
1167 | _set_errno(error);
1168 |
1169 | #else
1170 |
1171 | /* Non-Microsoft compiler or older Microsoft compiler */
1172 | errno = error;
1173 |
1174 | #endif
1175 | }
1176 |
1177 |
1178 | #ifdef __cplusplus
1179 | }
1180 | #endif
1181 | #endif /*DIRENT_H*/
1182 |
--------------------------------------------------------------------------------