mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Add support for loading extensions (issue #1947)
- Add CefRequestContext::LoadExtension, CefExtension, CefExtensionHandler and related methods/interfaces. - Add chrome://extensions-support that lists supported Chrome APIs. - Add CefBrowserHost::SetAutoResizeEnabled and CefDisplayHandler::OnAutoResize to support browser resize based on preferred web contents size. - views: Add support for custom CefMenuButton popups. - cefclient: Run with `--load-extension=set_page_color` command-line flag for an extension loading example. Add `--use-views` on Windows and Linux for an even better example.
This commit is contained in:
@@ -73,6 +73,11 @@ void BrowserWindow::OnSetFullscreen(bool fullscreen) {
|
||||
delegate_->OnSetFullscreen(fullscreen);
|
||||
}
|
||||
|
||||
void BrowserWindow::OnAutoResize(const CefSize& new_size) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
delegate_->OnAutoResize(new_size);
|
||||
}
|
||||
|
||||
void BrowserWindow::OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) {
|
||||
|
@@ -37,6 +37,9 @@ class BrowserWindow : public ClientHandler::Delegate {
|
||||
// Set fullscreen mode.
|
||||
virtual void OnSetFullscreen(bool fullscreen) = 0;
|
||||
|
||||
// Auto-resize contents.
|
||||
virtual void OnAutoResize(const CefSize& new_size) = 0;
|
||||
|
||||
// Set the loading state.
|
||||
virtual void OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
@@ -117,6 +120,7 @@ class BrowserWindow : public ClientHandler::Delegate {
|
||||
void OnSetAddress(const std::string& url) OVERRIDE;
|
||||
void OnSetTitle(const std::string& title) OVERRIDE;
|
||||
void OnSetFullscreen(bool fullscreen) OVERRIDE;
|
||||
void OnAutoResize(const CefSize& new_size) OVERRIDE;
|
||||
void OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) OVERRIDE;
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include "tests/cefclient/browser/main_context.h"
|
||||
#include "tests/cefclient/browser/root_window_manager.h"
|
||||
#include "tests/cefclient/browser/test_runner.h"
|
||||
#include "tests/shared/browser/extension_util.h"
|
||||
#include "tests/shared/browser/resource_util.h"
|
||||
#include "tests/shared/common/client_switches.h"
|
||||
|
||||
@@ -417,6 +418,14 @@ bool ClientHandler::OnConsoleMessage(CefRefPtr<CefBrowser> browser,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClientHandler::OnAutoResize(CefRefPtr<CefBrowser> browser,
|
||||
const CefSize& new_size) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
NotifyAutoResize(new_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientHandler::OnBeforeDownload(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDownloadItem> download_item,
|
||||
@@ -541,6 +550,19 @@ void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
|
||||
if (mouse_cursor_change_disabled_)
|
||||
browser->GetHost()->SetMouseCursorChangeDisabled(true);
|
||||
|
||||
if (browser->GetHost()->GetExtension()) {
|
||||
// Browsers hosting extension apps should auto-resize.
|
||||
browser->GetHost()->SetAutoResizeEnabled(true, CefSize(20, 20),
|
||||
CefSize(1000, 1000));
|
||||
|
||||
CefRefPtr<CefExtension> extension = browser->GetHost()->GetExtension();
|
||||
if (extension_util::IsInternalExtension(extension->GetPath())) {
|
||||
// Register the internal handler for extension resources.
|
||||
extension_util::AddInternalExtensionToResourceManager(extension,
|
||||
resource_manager_);
|
||||
}
|
||||
}
|
||||
|
||||
NotifyBrowserCreated(browser);
|
||||
}
|
||||
|
||||
@@ -623,8 +645,11 @@ bool ClientHandler::OnOpenURLFromTab(
|
||||
target_disposition == WOD_NEW_FOREGROUND_TAB) {
|
||||
// Handle middle-click and ctrl + left-click by opening the URL in a new
|
||||
// browser window.
|
||||
MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
|
||||
true, is_osr(), CefRect(), target_url);
|
||||
RootWindowConfig config;
|
||||
config.with_controls = true;
|
||||
config.with_osr = is_osr();
|
||||
config.url = target_url;
|
||||
MainContext::Get()->GetRootWindowManager()->CreateRootWindow(config);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -867,9 +892,11 @@ void ClientHandler::ShowSSLInformation(CefRefPtr<CefBrowser> browser) {
|
||||
|
||||
ss << "</body></html>";
|
||||
|
||||
MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
|
||||
false, is_osr(), CefRect(),
|
||||
test_runner::GetDataURI(ss.str(), "text/html"));
|
||||
RootWindowConfig config;
|
||||
config.with_controls = false;
|
||||
config.with_osr = is_osr();
|
||||
config.url = test_runner::GetDataURI(ss.str(), "text/html");
|
||||
MainContext::Get()->GetRootWindowManager()->CreateRootWindow(config);
|
||||
}
|
||||
|
||||
bool ClientHandler::CreatePopupWindow(CefRefPtr<CefBrowser> browser,
|
||||
@@ -969,6 +996,18 @@ void ClientHandler::NotifyFullscreen(bool fullscreen) {
|
||||
delegate_->OnSetFullscreen(fullscreen);
|
||||
}
|
||||
|
||||
void ClientHandler::NotifyAutoResize(const CefSize& new_size) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&ClientHandler::NotifyAutoResize, this, new_size));
|
||||
return;
|
||||
}
|
||||
|
||||
if (delegate_)
|
||||
delegate_->OnAutoResize(new_size);
|
||||
}
|
||||
|
||||
void ClientHandler::NotifyLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) {
|
||||
|
@@ -58,11 +58,14 @@ class ClientHandler : public CefClient,
|
||||
virtual void OnSetTitle(const std::string& title) = 0;
|
||||
|
||||
// Set the Favicon image.
|
||||
virtual void OnSetFavicon(CefRefPtr<CefImage> image){};
|
||||
virtual void OnSetFavicon(CefRefPtr<CefImage> image) {}
|
||||
|
||||
// Set fullscreen mode.
|
||||
virtual void OnSetFullscreen(bool fullscreen) = 0;
|
||||
|
||||
// Auto-resize contents.
|
||||
virtual void OnAutoResize(const CefSize& new_size) = 0;
|
||||
|
||||
// Set the loading state.
|
||||
virtual void OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
@@ -147,6 +150,8 @@ class ClientHandler : public CefClient,
|
||||
const CefString& message,
|
||||
const CefString& source,
|
||||
int line) OVERRIDE;
|
||||
bool OnAutoResize(CefRefPtr<CefBrowser> browser,
|
||||
const CefSize& new_size) OVERRIDE;
|
||||
|
||||
// CefDownloadHandler methods
|
||||
void OnBeforeDownload(CefRefPtr<CefBrowser> browser,
|
||||
@@ -311,6 +316,7 @@ class ClientHandler : public CefClient,
|
||||
void NotifyTitle(const CefString& title);
|
||||
void NotifyFavicon(CefRefPtr<CefImage> image);
|
||||
void NotifyFullscreen(bool fullscreen);
|
||||
void NotifyAutoResize(const CefSize& new_size);
|
||||
void NotifyLoadingState(bool isLoading, bool canGoBack, bool canGoForward);
|
||||
void NotifyDraggableRegions(const std::vector<CefDraggableRegion>& regions);
|
||||
void NotifyTakeFocus(bool next);
|
||||
|
306
tests/cefclient/browser/image_cache.cc
Normal file
306
tests/cefclient/browser/image_cache.cc
Normal file
@@ -0,0 +1,306 @@
|
||||
// Copyright (c) 2017 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include "tests/cefclient/browser/image_cache.h"
|
||||
|
||||
#include "tests/shared/browser/file_util.h"
|
||||
#include "tests/shared/browser/resource_util.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kEmptyId[] = "__empty";
|
||||
|
||||
} // namespace
|
||||
|
||||
ImageCache::ImageCache() {}
|
||||
|
||||
ImageCache::~ImageCache() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
}
|
||||
|
||||
ImageCache::ImageRep::ImageRep(const std::string& path, float scale_factor)
|
||||
: path_(path), scale_factor_(scale_factor) {
|
||||
DCHECK(!path_.empty());
|
||||
DCHECK_GT(scale_factor_, 0.0f);
|
||||
}
|
||||
|
||||
ImageCache::ImageInfo::ImageInfo(const std::string& id,
|
||||
const ImageRepSet& reps,
|
||||
bool internal,
|
||||
bool force_reload)
|
||||
: id_(id), reps_(reps), internal_(internal), force_reload_(force_reload) {
|
||||
#ifndef NDEBUG
|
||||
DCHECK(!id_.empty());
|
||||
if (id_ != kEmptyId)
|
||||
DCHECK(!reps_.empty());
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
ImageCache::ImageInfo ImageCache::ImageInfo::Empty() {
|
||||
return ImageInfo(kEmptyId, ImageRepSet(), true, false);
|
||||
}
|
||||
|
||||
// static
|
||||
ImageCache::ImageInfo ImageCache::ImageInfo::Create1x(
|
||||
const std::string& id,
|
||||
const std::string& path_1x,
|
||||
bool internal) {
|
||||
ImageRepSet reps;
|
||||
reps.push_back(ImageRep(path_1x, 1.0f));
|
||||
return ImageInfo(id, reps, internal, false);
|
||||
}
|
||||
|
||||
// static
|
||||
ImageCache::ImageInfo ImageCache::ImageInfo::Create2x(
|
||||
const std::string& id,
|
||||
const std::string& path_1x,
|
||||
const std::string& path_2x,
|
||||
bool internal) {
|
||||
ImageRepSet reps;
|
||||
reps.push_back(ImageRep(path_1x, 1.0f));
|
||||
reps.push_back(ImageRep(path_2x, 2.0f));
|
||||
return ImageInfo(id, reps, internal, false);
|
||||
}
|
||||
|
||||
// static
|
||||
ImageCache::ImageInfo ImageCache::ImageInfo::Create2x(const std::string& id) {
|
||||
return Create2x(id, id + ".1x.png", id + ".2x.png", true);
|
||||
}
|
||||
|
||||
struct ImageCache::ImageContent {
|
||||
ImageContent() {}
|
||||
|
||||
struct RepContent {
|
||||
RepContent(ImageType type, float scale_factor, const std::string& contents)
|
||||
: type_(type), scale_factor_(scale_factor), contents_(contents) {}
|
||||
|
||||
ImageType type_;
|
||||
float scale_factor_;
|
||||
std::string contents_;
|
||||
};
|
||||
typedef std::vector<RepContent> RepContentSet;
|
||||
RepContentSet contents_;
|
||||
|
||||
CefRefPtr<CefImage> image_;
|
||||
};
|
||||
|
||||
void ImageCache::LoadImages(const ImageInfoSet& image_info,
|
||||
const LoadImagesCallback& callback) {
|
||||
DCHECK(!image_info.empty());
|
||||
DCHECK(!callback.is_null());
|
||||
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI, base::Bind(&ImageCache::LoadImages, this, image_info,
|
||||
callback));
|
||||
return;
|
||||
}
|
||||
|
||||
ImageSet images;
|
||||
bool missing_images = false;
|
||||
|
||||
ImageInfoSet::const_iterator it = image_info.begin();
|
||||
for (; it != image_info.end(); ++it) {
|
||||
const ImageInfo& info = *it;
|
||||
|
||||
if (info.id_ == kEmptyId) {
|
||||
// Image intentionally left empty.
|
||||
images.push_back(NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
ImageMap::iterator it2 = image_map_.find(info.id_);
|
||||
if (it2 != image_map_.end()) {
|
||||
if (!info.force_reload_) {
|
||||
// Image already exists.
|
||||
images.push_back(it2->second);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove the existing image from the map.
|
||||
image_map_.erase(it2);
|
||||
}
|
||||
|
||||
// Load the image.
|
||||
images.push_back(NULL);
|
||||
if (!missing_images)
|
||||
missing_images = true;
|
||||
}
|
||||
|
||||
if (missing_images) {
|
||||
CefPostTask(TID_FILE, base::Bind(&ImageCache::LoadMissing, this, image_info,
|
||||
images, callback));
|
||||
} else {
|
||||
callback.Run(images);
|
||||
}
|
||||
}
|
||||
|
||||
CefRefPtr<CefImage> ImageCache::GetCachedImage(const std::string& image_id) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
DCHECK(!image_id.empty());
|
||||
|
||||
ImageMap::const_iterator it = image_map_.find(image_id);
|
||||
if (it != image_map_.end())
|
||||
return it->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// static
|
||||
ImageCache::ImageType ImageCache::GetImageType(const std::string& path) {
|
||||
std::string ext = file_util::GetFileExtension(path);
|
||||
if (ext.empty())
|
||||
return TYPE_NONE;
|
||||
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(), tolower);
|
||||
if (ext == "png")
|
||||
return TYPE_PNG;
|
||||
if (ext == "jpg" || ext == "jpeg")
|
||||
return TYPE_JPEG;
|
||||
|
||||
return TYPE_NONE;
|
||||
}
|
||||
|
||||
void ImageCache::LoadMissing(const ImageInfoSet& image_info,
|
||||
const ImageSet& images,
|
||||
const LoadImagesCallback& callback) {
|
||||
CEF_REQUIRE_FILE_THREAD();
|
||||
|
||||
DCHECK_EQ(image_info.size(), images.size());
|
||||
|
||||
ImageContentSet contents;
|
||||
|
||||
ImageInfoSet::const_iterator it1 = image_info.begin();
|
||||
ImageSet::const_iterator it2 = images.begin();
|
||||
for (; it1 != image_info.end() && it2 != images.end(); ++it1, ++it2) {
|
||||
const ImageInfo& info = *it1;
|
||||
ImageContent content;
|
||||
if (*it2 || info.id_ == kEmptyId) {
|
||||
// Image already exists or is intentionally empty.
|
||||
content.image_ = *it2;
|
||||
} else {
|
||||
LoadImageContents(info, &content);
|
||||
}
|
||||
contents.push_back(content);
|
||||
}
|
||||
|
||||
CefPostTask(TID_UI, base::Bind(&ImageCache::UpdateCache, this, image_info,
|
||||
contents, callback));
|
||||
}
|
||||
|
||||
// static
|
||||
bool ImageCache::LoadImageContents(const ImageInfo& info,
|
||||
ImageContent* content) {
|
||||
CEF_REQUIRE_FILE_THREAD();
|
||||
|
||||
ImageRepSet::const_iterator it = info.reps_.begin();
|
||||
for (; it != info.reps_.end(); ++it) {
|
||||
const ImageRep& rep = *it;
|
||||
ImageType rep_type;
|
||||
std::string rep_contents;
|
||||
if (!LoadImageContents(rep.path_, info.internal_, &rep_type,
|
||||
&rep_contents)) {
|
||||
LOG(ERROR) << "Failed to load image " << info.id_ << " from path "
|
||||
<< rep.path_;
|
||||
return false;
|
||||
}
|
||||
content->contents_.push_back(
|
||||
ImageContent::RepContent(rep_type, rep.scale_factor_, rep_contents));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool ImageCache::LoadImageContents(const std::string& path,
|
||||
bool internal,
|
||||
ImageType* type,
|
||||
std::string* contents) {
|
||||
CEF_REQUIRE_FILE_THREAD();
|
||||
|
||||
*type = GetImageType(path);
|
||||
if (*type == TYPE_NONE)
|
||||
return false;
|
||||
|
||||
if (internal) {
|
||||
if (!LoadBinaryResource(path.c_str(), *contents))
|
||||
return false;
|
||||
} else if (!file_util::ReadFileToString(path, contents)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !contents->empty();
|
||||
}
|
||||
|
||||
void ImageCache::UpdateCache(const ImageInfoSet& image_info,
|
||||
const ImageContentSet& contents,
|
||||
const LoadImagesCallback& callback) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
DCHECK_EQ(image_info.size(), contents.size());
|
||||
|
||||
ImageSet images;
|
||||
|
||||
ImageInfoSet::const_iterator it1 = image_info.begin();
|
||||
ImageContentSet::const_iterator it2 = contents.begin();
|
||||
for (; it1 != image_info.end() && it2 != contents.end(); ++it1, ++it2) {
|
||||
const ImageInfo& info = *it1;
|
||||
const ImageContent& content = *it2;
|
||||
if (content.image_ || info.id_ == kEmptyId) {
|
||||
// Image already exists or is intentionally empty.
|
||||
images.push_back(content.image_);
|
||||
} else {
|
||||
CefRefPtr<CefImage> image = CreateImage(info.id_, content);
|
||||
images.push_back(image);
|
||||
|
||||
// Add the image to the map.
|
||||
image_map_.insert(std::make_pair(info.id_, image));
|
||||
}
|
||||
}
|
||||
|
||||
callback.Run(images);
|
||||
}
|
||||
|
||||
// static
|
||||
CefRefPtr<CefImage> ImageCache::CreateImage(const std::string& image_id,
|
||||
const ImageContent& content) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Shouldn't be creating an image if one already exists.
|
||||
DCHECK(!content.image_);
|
||||
|
||||
if (content.contents_.empty())
|
||||
return NULL;
|
||||
|
||||
CefRefPtr<CefImage> image = CefImage::CreateImage();
|
||||
|
||||
ImageContent::RepContentSet::const_iterator it = content.contents_.begin();
|
||||
for (; it != content.contents_.end(); ++it) {
|
||||
const ImageContent::RepContent& rep = *it;
|
||||
if (rep.type_ == TYPE_PNG) {
|
||||
if (!image->AddPNG(rep.scale_factor_, rep.contents_.c_str(),
|
||||
rep.contents_.size())) {
|
||||
LOG(ERROR) << "Failed to create image " << image_id << " for PNG@"
|
||||
<< rep.scale_factor_;
|
||||
return NULL;
|
||||
}
|
||||
} else if (rep.type_ == TYPE_JPEG) {
|
||||
if (!image->AddJPEG(rep.scale_factor_, rep.contents_.c_str(),
|
||||
rep.contents_.size())) {
|
||||
LOG(ERROR) << "Failed to create image " << image_id << " for JPG@"
|
||||
<< rep.scale_factor_;
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
NOTREACHED();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
} // namespace client
|
127
tests/cefclient/browser/image_cache.h
Normal file
127
tests/cefclient/browser/image_cache.h
Normal file
@@ -0,0 +1,127 @@
|
||||
// Copyright (c) 2017 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_IMAGE_CACHE_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_IMAGE_CACHE_H_
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/base/cef_ref_counted.h"
|
||||
#include "include/cef_image.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Simple image caching implementation.
|
||||
class ImageCache
|
||||
: public base::RefCountedThreadSafe<ImageCache, CefDeleteOnUIThread> {
|
||||
public:
|
||||
ImageCache();
|
||||
|
||||
// Image representation at a specific scale factor.
|
||||
struct ImageRep {
|
||||
ImageRep(const std::string& path, float scale_factor);
|
||||
|
||||
// Full file system path.
|
||||
std::string path_;
|
||||
|
||||
// Image scale factor (usually 1.0f or 2.0f).
|
||||
float scale_factor_;
|
||||
};
|
||||
typedef std::vector<ImageRep> ImageRepSet;
|
||||
|
||||
// Unique image that may have multiple representations.
|
||||
struct ImageInfo {
|
||||
ImageInfo(const std::string& id,
|
||||
const ImageRepSet& reps,
|
||||
bool internal,
|
||||
bool force_reload);
|
||||
|
||||
// Helper for returning an empty image.
|
||||
static ImageInfo Empty();
|
||||
|
||||
// Helpers for creating common representations.
|
||||
static ImageInfo Create1x(const std::string& id,
|
||||
const std::string& path_1x,
|
||||
bool internal);
|
||||
static ImageInfo Create2x(const std::string& id,
|
||||
const std::string& path_1x,
|
||||
const std::string& path_2x,
|
||||
bool internal);
|
||||
static ImageInfo Create2x(const std::string& id);
|
||||
|
||||
// Image unique ID.
|
||||
std::string id_;
|
||||
|
||||
// Image representations to load.
|
||||
ImageRepSet reps_;
|
||||
|
||||
// True if the image is internal (loaded via LoadBinaryResource).
|
||||
bool internal_;
|
||||
|
||||
// True to force reload.
|
||||
bool force_reload_;
|
||||
};
|
||||
typedef std::vector<ImageInfo> ImageInfoSet;
|
||||
|
||||
typedef std::vector<CefRefPtr<CefImage>> ImageSet;
|
||||
|
||||
typedef base::Callback<void(const ImageSet& /*images*/)> LoadImagesCallback;
|
||||
|
||||
// Loads the images represented by |image_info|. Executes |callback|
|
||||
// either synchronously or asychronously on the UI thread after completion.
|
||||
void LoadImages(const ImageInfoSet& image_info,
|
||||
const LoadImagesCallback& callback);
|
||||
|
||||
// Returns an image that has already been cached. Must be called on the
|
||||
// UI thread.
|
||||
CefRefPtr<CefImage> GetCachedImage(const std::string& image_id);
|
||||
|
||||
private:
|
||||
// Only allow deletion via scoped_refptr.
|
||||
friend struct CefDeleteOnThread<TID_UI>;
|
||||
friend class base::RefCountedThreadSafe<ImageCache, CefDeleteOnUIThread>;
|
||||
|
||||
~ImageCache();
|
||||
|
||||
enum ImageType {
|
||||
TYPE_NONE,
|
||||
TYPE_PNG,
|
||||
TYPE_JPEG,
|
||||
};
|
||||
|
||||
static ImageType GetImageType(const std::string& path);
|
||||
|
||||
struct ImageContent;
|
||||
typedef std::vector<ImageContent> ImageContentSet;
|
||||
|
||||
// Load missing image contents on the FILE thread.
|
||||
void LoadMissing(const ImageInfoSet& image_info,
|
||||
const ImageSet& images,
|
||||
const LoadImagesCallback& callback);
|
||||
static bool LoadImageContents(const ImageInfo& info, ImageContent* content);
|
||||
static bool LoadImageContents(const std::string& path,
|
||||
bool internal,
|
||||
ImageType* type,
|
||||
std::string* contents);
|
||||
|
||||
// Create missing CefImage representations on the UI thread.
|
||||
void UpdateCache(const ImageInfoSet& image_info,
|
||||
const ImageContentSet& contents,
|
||||
const LoadImagesCallback& callback);
|
||||
static CefRefPtr<CefImage> CreateImage(const std::string& image_id,
|
||||
const ImageContent& content);
|
||||
|
||||
// Map image ID to image representation. Only accessed on the UI thread.
|
||||
typedef std::map<std::string, CefRefPtr<CefImage>> ImageMap;
|
||||
ImageMap image_map_;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_IMAGE_CACHE_H_
|
@@ -65,6 +65,11 @@
|
||||
#define IDS_WINDOW_ICON_2X_PNG 1020
|
||||
#define IDS_XMLHTTPREQUEST_HTML 1021
|
||||
|
||||
#define IDS_EXTENSIONS_SET_PAGE_COLOR_ICON_PNG 1030
|
||||
#define IDS_EXTENSIONS_SET_PAGE_COLOR_MANIFEST_JSON 1031
|
||||
#define IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_HTML 1032
|
||||
#define IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_JS 1033
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
|
@@ -18,6 +18,14 @@ int GetResourceId(const char* resource_name) {
|
||||
{"dialogs.html", IDS_DIALOGS_HTML},
|
||||
{"draggable.html", IDS_DRAGGABLE_HTML},
|
||||
{"drm.html", IDS_DRM_HTML},
|
||||
{"extensions/set_page_color/icon.png",
|
||||
IDS_EXTENSIONS_SET_PAGE_COLOR_ICON_PNG},
|
||||
{"extensions/set_page_color/manifest.json",
|
||||
IDS_EXTENSIONS_SET_PAGE_COLOR_MANIFEST_JSON},
|
||||
{"extensions/set_page_color/popup.html",
|
||||
IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_HTML},
|
||||
{"extensions/set_page_color/popup.js",
|
||||
IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_JS},
|
||||
{"logo.png", IDS_LOGO_PNG},
|
||||
{"localstorage.html", IDS_LOCALSTORAGE_HTML},
|
||||
{"menu_icon.1x.png", IDS_MENU_ICON_1X_PNG},
|
||||
|
@@ -9,10 +9,36 @@
|
||||
|
||||
namespace client {
|
||||
|
||||
RootWindowConfig::RootWindowConfig()
|
||||
: with_controls(true),
|
||||
with_osr(false),
|
||||
with_extension(false),
|
||||
initially_hidden(false),
|
||||
url(MainContext::Get()->GetMainURL()) {}
|
||||
|
||||
RootWindow::RootWindow() : delegate_(NULL) {}
|
||||
|
||||
RootWindow::~RootWindow() {}
|
||||
|
||||
// static
|
||||
scoped_refptr<RootWindow> RootWindow::GetForBrowser(int browser_id) {
|
||||
return MainContext::Get()->GetRootWindowManager()->GetWindowForBrowser(
|
||||
browser_id);
|
||||
}
|
||||
|
||||
void RootWindow::OnExtensionsChanged(const ExtensionSet& extensions) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK(delegate_);
|
||||
DCHECK(!WithExtension());
|
||||
|
||||
if (extensions.empty())
|
||||
return;
|
||||
|
||||
ExtensionSet::const_iterator it = extensions.begin();
|
||||
for (; it != extensions.end(); ++it) {
|
||||
delegate_->CreateExtensionWindow(*it, CefRect(), NULL, base::Closure(),
|
||||
WithWindowlessRendering());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
@@ -6,15 +6,58 @@
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_H_
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "include/base/cef_callback_forward.h"
|
||||
#include "include/base/cef_ref_counted.h"
|
||||
#include "include/cef_browser.h"
|
||||
#include "include/views/cef_window.h"
|
||||
#include "tests/cefclient/browser/client_types.h"
|
||||
#include "tests/cefclient/browser/image_cache.h"
|
||||
#include "tests/shared/browser/main_message_loop.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Used to configure how a RootWindow is created.
|
||||
struct RootWindowConfig {
|
||||
RootWindowConfig();
|
||||
|
||||
// If true the window will show controls.
|
||||
bool with_controls;
|
||||
|
||||
// If true the window will use off-screen rendering.
|
||||
bool with_osr;
|
||||
|
||||
// If true the window is hosting an extension app.
|
||||
bool with_extension;
|
||||
|
||||
// If true the window will be created initially hidden.
|
||||
bool initially_hidden;
|
||||
|
||||
// Requested window position. If |bounds| and |source_bounds| are empty the
|
||||
// default window size and location will be used.
|
||||
CefRect bounds;
|
||||
|
||||
// Position of the UI element that triggered the window creation. If |bounds|
|
||||
// is empty and |source_bounds| is non-empty the new window will be positioned
|
||||
// relative to |source_bounds|. This is currently only implemented for Views-
|
||||
// based windows when |initially_hidden| is also true.
|
||||
CefRect source_bounds;
|
||||
|
||||
// Parent window. Only used for Views-based windows.
|
||||
CefRefPtr<CefWindow> parent_window;
|
||||
|
||||
// Callback to be executed when the window is closed. Will be executed on the
|
||||
// main thread. This is currently only implemented for Views-based windows.
|
||||
base::Closure close_callback;
|
||||
|
||||
// Initial URL to load.
|
||||
std::string url;
|
||||
};
|
||||
|
||||
typedef std::set<CefRefPtr<CefExtension>> ExtensionSet;
|
||||
|
||||
// Represents a top-level native window in the browser process. While references
|
||||
// to this object are thread-safe the methods must be called on the main thread
|
||||
// unless otherwise indicated.
|
||||
@@ -30,8 +73,8 @@ class RootWindow
|
||||
virtual CefRefPtr<CefRequestContext> GetRequestContext(
|
||||
RootWindow* root_window) = 0;
|
||||
|
||||
// Returns the default window icon.
|
||||
virtual CefRefPtr<CefImage> GetDefaultWindowIcon() = 0;
|
||||
// Returns the ImageCache.
|
||||
virtual scoped_refptr<ImageCache> GetImageCache() = 0;
|
||||
|
||||
// Called to execute a test. See resource.h for |test_id| values.
|
||||
virtual void OnTest(RootWindow* root_window, int test_id) = 0;
|
||||
@@ -42,6 +85,21 @@ class RootWindow
|
||||
// Called when the RootWindow has been destroyed.
|
||||
virtual void OnRootWindowDestroyed(RootWindow* root_window) = 0;
|
||||
|
||||
// Called when the RootWindow is activated (becomes the foreground window).
|
||||
virtual void OnRootWindowActivated(RootWindow* root_window) = 0;
|
||||
|
||||
// Called when the browser is created for the RootWindow.
|
||||
virtual void OnBrowserCreated(RootWindow* root_window,
|
||||
CefRefPtr<CefBrowser> browser) = 0;
|
||||
|
||||
// Create a window for |extension|. |source_bounds| are the bounds of the
|
||||
// UI element, like a button, that triggered the extension.
|
||||
virtual void CreateExtensionWindow(CefRefPtr<CefExtension> extension,
|
||||
const CefRect& source_bounds,
|
||||
CefRefPtr<CefWindow> parent_window,
|
||||
const base::Closure& close_callback,
|
||||
bool with_osr) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~Delegate() {}
|
||||
};
|
||||
@@ -68,11 +126,8 @@ class RootWindow
|
||||
// Use RootWindowManager::CreateRootWindow() instead of calling this method
|
||||
// directly.
|
||||
virtual void Init(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& bounds,
|
||||
const CefBrowserSettings& settings,
|
||||
const std::string& url) = 0;
|
||||
const RootWindowConfig& config,
|
||||
const CefBrowserSettings& settings) = 0;
|
||||
|
||||
// Initialize as a popup window. This is used to attach a new native window to
|
||||
// a single browser instance that will be created later. The native window
|
||||
@@ -121,12 +176,25 @@ class RootWindow
|
||||
// Returns the native handle for this window, if any.
|
||||
virtual ClientWindowHandle GetWindowHandle() const = 0;
|
||||
|
||||
// Returns true if this window is using windowless rendering (osr).
|
||||
virtual bool WithWindowlessRendering() const = 0;
|
||||
|
||||
// Returns true if this window is hosting an extension app.
|
||||
virtual bool WithExtension() const = 0;
|
||||
|
||||
// Called when the set of loaded extensions changes. The default
|
||||
// implementation will create a single window instance for each extension.
|
||||
virtual void OnExtensionsChanged(const ExtensionSet& extensions);
|
||||
|
||||
protected:
|
||||
// Allow deletion via scoped_refptr only.
|
||||
friend struct DeleteOnMainThread;
|
||||
friend class base::RefCountedThreadSafe<RootWindow, DeleteOnMainThread>;
|
||||
|
||||
virtual ~RootWindow() {}
|
||||
RootWindow();
|
||||
virtual ~RootWindow();
|
||||
|
||||
Delegate* delegate_;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
@@ -49,9 +49,9 @@ void MaximizeWindow(GtkWindow* window) {
|
||||
} // namespace
|
||||
|
||||
RootWindowGtk::RootWindowGtk()
|
||||
: delegate_(NULL),
|
||||
with_controls_(false),
|
||||
: with_controls_(false),
|
||||
with_osr_(false),
|
||||
with_extension_(false),
|
||||
is_popup_(false),
|
||||
initialized_(false),
|
||||
window_(NULL),
|
||||
@@ -75,29 +75,27 @@ RootWindowGtk::~RootWindowGtk() {
|
||||
}
|
||||
|
||||
void RootWindowGtk::Init(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& bounds,
|
||||
const CefBrowserSettings& settings,
|
||||
const std::string& url) {
|
||||
const RootWindowConfig& config,
|
||||
const CefBrowserSettings& settings) {
|
||||
DCHECK(delegate);
|
||||
DCHECK(!initialized_);
|
||||
|
||||
delegate_ = delegate;
|
||||
with_controls_ = with_controls;
|
||||
with_osr_ = with_osr;
|
||||
start_rect_ = bounds;
|
||||
with_controls_ = config.with_controls;
|
||||
with_osr_ = config.with_osr;
|
||||
with_extension_ = config.with_extension;
|
||||
start_rect_ = config.bounds;
|
||||
|
||||
CreateBrowserWindow(url);
|
||||
CreateBrowserWindow(config.url);
|
||||
|
||||
initialized_ = true;
|
||||
|
||||
// Create the native root window on the main thread.
|
||||
if (CURRENTLY_ON_MAIN_THREAD()) {
|
||||
CreateRootWindow(settings);
|
||||
CreateRootWindow(settings, config.initially_hidden);
|
||||
} else {
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&RootWindowGtk::CreateRootWindow, this, settings));
|
||||
MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::CreateRootWindow, this,
|
||||
settings, config.initially_hidden));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,13 +177,7 @@ void RootWindowGtk::SetBounds(int x, int y, size_t width, size_t height) {
|
||||
else
|
||||
gtk_window_present(window);
|
||||
|
||||
// Retrieve information about the display that contains the window.
|
||||
GdkScreen* screen = gdk_screen_get_default();
|
||||
const gint monitor = gdk_screen_get_monitor_at_window(screen, gdk_window);
|
||||
GdkRectangle rect;
|
||||
gdk_screen_get_monitor_geometry(screen, monitor, &rect);
|
||||
|
||||
gdk_window_move_resize(gdk_window, rect.x, rect.y, rect.width, rect.height);
|
||||
gdk_window_move_resize(gdk_window, x, y, width, height);
|
||||
}
|
||||
|
||||
void RootWindowGtk::Close(bool force) {
|
||||
@@ -200,16 +192,18 @@ void RootWindowGtk::Close(bool force) {
|
||||
void RootWindowGtk::SetDeviceScaleFactor(float device_scale_factor) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_window_)
|
||||
if (browser_window_ && with_osr_)
|
||||
browser_window_->SetDeviceScaleFactor(device_scale_factor);
|
||||
}
|
||||
|
||||
float RootWindowGtk::GetDeviceScaleFactor() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_window_)
|
||||
if (browser_window_ && with_osr_)
|
||||
return browser_window_->GetDeviceScaleFactor();
|
||||
return 1.0f;
|
||||
|
||||
NOTREACHED();
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> RootWindowGtk::GetBrowser() const {
|
||||
@@ -225,6 +219,16 @@ ClientWindowHandle RootWindowGtk::GetWindowHandle() const {
|
||||
return window_;
|
||||
}
|
||||
|
||||
bool RootWindowGtk::WithWindowlessRendering() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
return with_osr_;
|
||||
}
|
||||
|
||||
bool RootWindowGtk::WithExtension() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
return with_extension_;
|
||||
}
|
||||
|
||||
void RootWindowGtk::CreateBrowserWindow(const std::string& startup_url) {
|
||||
if (with_osr_) {
|
||||
OsrRenderer::Settings settings = {};
|
||||
@@ -235,7 +239,8 @@ void RootWindowGtk::CreateBrowserWindow(const std::string& startup_url) {
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings) {
|
||||
void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings,
|
||||
bool initially_hidden) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK(!window_);
|
||||
|
||||
@@ -358,7 +363,9 @@ void RootWindowGtk::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
|
||||
// For popup browsers create the root window once the browser has been
|
||||
// created.
|
||||
if (is_popup_)
|
||||
CreateRootWindow(CefBrowserSettings());
|
||||
CreateRootWindow(CefBrowserSettings(), false);
|
||||
|
||||
delegate_->OnBrowserCreated(this, browser);
|
||||
}
|
||||
|
||||
void RootWindowGtk::OnBrowserWindowDestroyed() {
|
||||
@@ -409,6 +416,24 @@ void RootWindowGtk::OnSetFullscreen(bool fullscreen) {
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::OnAutoResize(const CefSize& new_size) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (!window_)
|
||||
return;
|
||||
|
||||
GtkWindow* window = GTK_WINDOW(window_);
|
||||
GdkWindow* gdk_window = gtk_widget_get_window(window_);
|
||||
|
||||
// Make sure the window isn't minimized or maximized.
|
||||
if (IsWindowMaximized(window))
|
||||
gtk_window_unmaximize(window);
|
||||
else
|
||||
gtk_window_present(window);
|
||||
|
||||
gdk_window_resize(gdk_window, new_size.width, new_size.height);
|
||||
}
|
||||
|
||||
void RootWindowGtk::OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) {
|
||||
@@ -440,6 +465,7 @@ gboolean RootWindowGtk::WindowFocusIn(GtkWidget* widget,
|
||||
RootWindowGtk* self) {
|
||||
if (event->in && self->browser_window_.get()) {
|
||||
self->browser_window_->SetFocus(true);
|
||||
self->delegate_->OnRootWindowActivated(self);
|
||||
// Return true for a windowed browser so that focus is not passed to GTK.
|
||||
return self->with_osr_ ? FALSE : TRUE;
|
||||
}
|
||||
|
@@ -26,11 +26,8 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate {
|
||||
|
||||
// RootWindow methods.
|
||||
void Init(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& rect,
|
||||
const CefBrowserSettings& settings,
|
||||
const std::string& url) OVERRIDE;
|
||||
const RootWindowConfig& config,
|
||||
const CefBrowserSettings& settings) OVERRIDE;
|
||||
void InitAsPopup(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
@@ -46,10 +43,13 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate {
|
||||
float GetDeviceScaleFactor() const OVERRIDE;
|
||||
CefRefPtr<CefBrowser> GetBrowser() const OVERRIDE;
|
||||
ClientWindowHandle GetWindowHandle() const OVERRIDE;
|
||||
bool WithWindowlessRendering() const OVERRIDE;
|
||||
bool WithExtension() const OVERRIDE;
|
||||
|
||||
private:
|
||||
void CreateBrowserWindow(const std::string& startup_url);
|
||||
void CreateRootWindow(const CefBrowserSettings& settings);
|
||||
void CreateRootWindow(const CefBrowserSettings& settings,
|
||||
bool initially_hidden);
|
||||
|
||||
// BrowserWindow::Delegate methods.
|
||||
void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
@@ -57,6 +57,7 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate {
|
||||
void OnSetAddress(const std::string& url) OVERRIDE;
|
||||
void OnSetTitle(const std::string& title) OVERRIDE;
|
||||
void OnSetFullscreen(bool fullscreen) OVERRIDE;
|
||||
void OnAutoResize(const CefSize& new_size) OVERRIDE;
|
||||
void OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) OVERRIDE;
|
||||
@@ -112,9 +113,9 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate {
|
||||
|
||||
// After initialization all members are only accessed on the main thread.
|
||||
// Members set during initialization.
|
||||
RootWindow::Delegate* delegate_;
|
||||
bool with_controls_;
|
||||
bool with_osr_;
|
||||
bool with_extension_;
|
||||
bool is_popup_;
|
||||
CefRect start_rect_;
|
||||
scoped_ptr<BrowserWindow> browser_window_;
|
||||
|
@@ -35,11 +35,8 @@ class RootWindowMac : public RootWindow, public BrowserWindow::Delegate {
|
||||
|
||||
// RootWindow methods.
|
||||
void Init(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& rect,
|
||||
const CefBrowserSettings& settings,
|
||||
const std::string& url) OVERRIDE;
|
||||
const RootWindowConfig& config,
|
||||
const CefBrowserSettings& settings) OVERRIDE;
|
||||
void InitAsPopup(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
@@ -55,16 +52,20 @@ class RootWindowMac : public RootWindow, public BrowserWindow::Delegate {
|
||||
float GetDeviceScaleFactor() const OVERRIDE;
|
||||
CefRefPtr<CefBrowser> GetBrowser() const OVERRIDE;
|
||||
ClientWindowHandle GetWindowHandle() const OVERRIDE;
|
||||
bool WithWindowlessRendering() const OVERRIDE;
|
||||
bool WithExtension() const OVERRIDE;
|
||||
|
||||
// Called by RootWindowDelegate after the associated NSWindow has been
|
||||
// destroyed.
|
||||
void WindowDestroyed();
|
||||
|
||||
BrowserWindow* browser_window() const { return browser_window_.get(); }
|
||||
RootWindow::Delegate* delegate() const { return delegate_; }
|
||||
|
||||
private:
|
||||
void CreateBrowserWindow(const std::string& startup_url);
|
||||
void CreateRootWindow(const CefBrowserSettings& settings);
|
||||
void CreateRootWindow(const CefBrowserSettings& settings,
|
||||
bool initially_hidden);
|
||||
|
||||
// BrowserWindow::Delegate methods.
|
||||
void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
@@ -72,6 +73,7 @@ class RootWindowMac : public RootWindow, public BrowserWindow::Delegate {
|
||||
void OnSetAddress(const std::string& url) OVERRIDE;
|
||||
void OnSetTitle(const std::string& title) OVERRIDE;
|
||||
void OnSetFullscreen(bool fullscreen) OVERRIDE;
|
||||
void OnAutoResize(const CefSize& new_size) OVERRIDE;
|
||||
void OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) OVERRIDE;
|
||||
@@ -82,9 +84,9 @@ class RootWindowMac : public RootWindow, public BrowserWindow::Delegate {
|
||||
|
||||
// After initialization all members are only accessed on the main thread.
|
||||
// Members set during initialization.
|
||||
RootWindow::Delegate* delegate_;
|
||||
bool with_controls_;
|
||||
bool with_osr_;
|
||||
bool with_extension_;
|
||||
bool is_popup_;
|
||||
CefRect start_rect_;
|
||||
scoped_ptr<BrowserWindow> browser_window_;
|
||||
|
@@ -118,6 +118,7 @@
|
||||
client::BrowserWindow* browser_window = root_window_->browser_window();
|
||||
if (browser_window)
|
||||
browser_window->SetFocus(true);
|
||||
root_window_->delegate()->OnRootWindowActivated(root_window_);
|
||||
}
|
||||
|
||||
// Called when we are deactivated (when we lose focus).
|
||||
@@ -236,8 +237,7 @@ NSRect GetScreenRectForWindow(NSWindow* window) {
|
||||
} // namespace
|
||||
|
||||
RootWindowMac::RootWindowMac()
|
||||
: delegate_(NULL),
|
||||
with_controls_(false),
|
||||
: with_controls_(false),
|
||||
with_osr_(false),
|
||||
is_popup_(false),
|
||||
initialized_(false),
|
||||
@@ -259,29 +259,27 @@ RootWindowMac::~RootWindowMac() {
|
||||
}
|
||||
|
||||
void RootWindowMac::Init(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& bounds,
|
||||
const CefBrowserSettings& settings,
|
||||
const std::string& url) {
|
||||
const RootWindowConfig& config,
|
||||
const CefBrowserSettings& settings) {
|
||||
DCHECK(delegate);
|
||||
DCHECK(!initialized_);
|
||||
|
||||
delegate_ = delegate;
|
||||
with_controls_ = with_controls;
|
||||
with_osr_ = with_osr;
|
||||
start_rect_ = bounds;
|
||||
with_controls_ = config.with_controls;
|
||||
with_osr_ = config.with_osr;
|
||||
with_extension_ = config.with_extension;
|
||||
start_rect_ = config.bounds;
|
||||
|
||||
CreateBrowserWindow(url);
|
||||
CreateBrowserWindow(config.url);
|
||||
|
||||
initialized_ = true;
|
||||
|
||||
// Create the native root window on the main thread.
|
||||
if (CURRENTLY_ON_MAIN_THREAD()) {
|
||||
CreateRootWindow(settings);
|
||||
CreateRootWindow(settings, config.initially_hidden);
|
||||
} else {
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&RootWindowMac::CreateRootWindow, this, settings));
|
||||
MAIN_POST_CLOSURE(base::Bind(&RootWindowMac::CreateRootWindow, this,
|
||||
settings, config.initially_hidden));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,16 +400,18 @@ void RootWindowMac::Close(bool force) {
|
||||
void RootWindowMac::SetDeviceScaleFactor(float device_scale_factor) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_window_)
|
||||
if (browser_window_ && with_osr_)
|
||||
browser_window_->SetDeviceScaleFactor(device_scale_factor);
|
||||
}
|
||||
|
||||
float RootWindowMac::GetDeviceScaleFactor() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_window_)
|
||||
if (browser_window_ && with_osr_)
|
||||
return browser_window_->GetDeviceScaleFactor();
|
||||
return 1.0f;
|
||||
|
||||
NOTREACHED();
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> RootWindowMac::GetBrowser() const {
|
||||
@@ -427,6 +427,16 @@ ClientWindowHandle RootWindowMac::GetWindowHandle() const {
|
||||
return [window_ contentView];
|
||||
}
|
||||
|
||||
bool RootWindowMac::WithWindowlessRendering() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
return with_osr_;
|
||||
}
|
||||
|
||||
bool RootWindowMac::WithExtension() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
return with_extension_;
|
||||
}
|
||||
|
||||
void RootWindowMac::WindowDestroyed() {
|
||||
window_ = nil;
|
||||
window_destroyed_ = true;
|
||||
@@ -443,7 +453,8 @@ void RootWindowMac::CreateBrowserWindow(const std::string& startup_url) {
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowMac::CreateRootWindow(const CefBrowserSettings& settings) {
|
||||
void RootWindowMac::CreateRootWindow(const CefBrowserSettings& settings,
|
||||
bool initially_hidden) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK(!window_);
|
||||
|
||||
@@ -566,11 +577,13 @@ void RootWindowMac::CreateRootWindow(const CefBrowserSettings& settings) {
|
||||
contentBounds.size.height);
|
||||
}
|
||||
|
||||
// Show the window.
|
||||
Show(ShowNormal);
|
||||
if (!initially_hidden) {
|
||||
// Show the window.
|
||||
Show(ShowNormal);
|
||||
|
||||
// Size the window.
|
||||
SetBounds(x, y, width, height);
|
||||
// Size the window.
|
||||
SetBounds(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowMac::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
|
||||
@@ -579,7 +592,9 @@ void RootWindowMac::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
|
||||
// For popup browsers create the root window once the browser has been
|
||||
// created.
|
||||
if (is_popup_)
|
||||
CreateRootWindow(CefBrowserSettings());
|
||||
CreateRootWindow(CefBrowserSettings(), false);
|
||||
|
||||
delegate_->OnBrowserCreated(this, browser);
|
||||
}
|
||||
|
||||
void RootWindowMac::OnBrowserWindowDestroyed() {
|
||||
@@ -638,6 +653,29 @@ void RootWindowMac::OnSetFullscreen(bool fullscreen) {
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowMac::OnAutoResize(const CefSize& new_size) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (!window_)
|
||||
return;
|
||||
|
||||
// Desired content rectangle.
|
||||
NSRect content_rect;
|
||||
content_rect.size.width = static_cast<int>(new_size.width);
|
||||
content_rect.size.height =
|
||||
static_cast<int>(new_size.height) + (with_controls_ ? URLBAR_HEIGHT : 0);
|
||||
|
||||
// Convert to a frame rectangle.
|
||||
NSRect frame_rect = [window_ frameRectForContentRect:content_rect];
|
||||
// Don't change the origin.
|
||||
frame_rect.origin = window_.frame.origin;
|
||||
|
||||
[window_ setFrame:frame_rect display:YES];
|
||||
|
||||
// Make sure the window is visible.
|
||||
Show(ShowNormal);
|
||||
}
|
||||
|
||||
void RootWindowMac::OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) {
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "tests/cefclient/browser/main_context.h"
|
||||
#include "tests/cefclient/browser/test_runner.h"
|
||||
#include "tests/shared/browser/extension_util.h"
|
||||
#include "tests/shared/browser/resource_util.h"
|
||||
#include "tests/shared/common/client_switches.h"
|
||||
|
||||
@@ -18,10 +19,12 @@ namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
class ClientRequestContextHandler : public CefRequestContextHandler {
|
||||
class ClientRequestContextHandler : public CefRequestContextHandler,
|
||||
public CefExtensionHandler {
|
||||
public:
|
||||
ClientRequestContextHandler() {}
|
||||
|
||||
// CefRequestContextHandler methods:
|
||||
bool OnBeforePluginLoad(const CefString& mime_type,
|
||||
const CefString& plugin_url,
|
||||
bool is_main_frame,
|
||||
@@ -38,14 +41,73 @@ class ClientRequestContextHandler : public CefRequestContextHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
void OnRequestContextInitialized(
|
||||
CefRefPtr<CefRequestContext> request_context) OVERRIDE {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
CefRefPtr<CefCommandLine> command_line =
|
||||
CefCommandLine::GetGlobalCommandLine();
|
||||
if (command_line->HasSwitch(switches::kLoadExtension)) {
|
||||
if (MainContext::Get()
|
||||
->GetRootWindowManager()
|
||||
->request_context_per_browser()) {
|
||||
// The example extension loading implementation requires all browsers to
|
||||
// share the same request context.
|
||||
LOG(ERROR)
|
||||
<< "Cannot mix --load-extension and --request-context-per-browser";
|
||||
return;
|
||||
}
|
||||
|
||||
// Load one or more extension paths specified on the command-line and
|
||||
// delimited with semicolon.
|
||||
const std::string& extension_path =
|
||||
command_line->GetSwitchValue(switches::kLoadExtension);
|
||||
if (!extension_path.empty()) {
|
||||
std::string part;
|
||||
std::istringstream f(extension_path);
|
||||
while (getline(f, part, ';')) {
|
||||
if (!part.empty())
|
||||
extension_util::LoadExtension(request_context, part, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CefExtensionHandler methods:
|
||||
void OnExtensionLoaded(CefRefPtr<CefExtension> extension) OVERRIDE {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
MainContext::Get()->GetRootWindowManager()->AddExtension(extension);
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> GetActiveBrowser(CefRefPtr<CefExtension> extension,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
bool include_incognito) OVERRIDE {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Return the browser for the active/foreground window.
|
||||
CefRefPtr<CefBrowser> active_browser =
|
||||
MainContext::Get()->GetRootWindowManager()->GetActiveBrowser();
|
||||
if (!active_browser) {
|
||||
LOG(WARNING)
|
||||
<< "No active browser available for extension "
|
||||
<< browser->GetHost()->GetExtension()->GetIdentifier().ToString();
|
||||
} else {
|
||||
// The active browser should not be hosting an extension.
|
||||
DCHECK(!active_browser->GetHost()->GetExtension());
|
||||
}
|
||||
return active_browser;
|
||||
}
|
||||
|
||||
private:
|
||||
IMPLEMENT_REFCOUNTING(ClientRequestContextHandler);
|
||||
DISALLOW_COPY_AND_ASSIGN(ClientRequestContextHandler);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
RootWindowManager::RootWindowManager(bool terminate_when_all_windows_closed)
|
||||
: terminate_when_all_windows_closed_(terminate_when_all_windows_closed) {
|
||||
: terminate_when_all_windows_closed_(terminate_when_all_windows_closed),
|
||||
image_cache_(new ImageCache) {
|
||||
CefRefPtr<CefCommandLine> command_line =
|
||||
CefCommandLine::GetGlobalCommandLine();
|
||||
DCHECK(command_line.get());
|
||||
@@ -61,17 +123,13 @@ RootWindowManager::~RootWindowManager() {
|
||||
}
|
||||
|
||||
scoped_refptr<RootWindow> RootWindowManager::CreateRootWindow(
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& bounds,
|
||||
const std::string& url) {
|
||||
const RootWindowConfig& config) {
|
||||
CefBrowserSettings settings;
|
||||
MainContext::Get()->PopulateBrowserSettings(&settings);
|
||||
|
||||
scoped_refptr<RootWindow> root_window =
|
||||
RootWindow::Create(MainContext::Get()->UseViews());
|
||||
root_window->Init(this, with_controls, with_osr, bounds, settings,
|
||||
url.empty() ? MainContext::Get()->GetMainURL() : url);
|
||||
root_window->Init(this, config, settings);
|
||||
|
||||
// Store a reference to the root window on the main thread.
|
||||
OnRootWindowCreated(root_window);
|
||||
@@ -101,8 +159,60 @@ scoped_refptr<RootWindow> RootWindowManager::CreateRootWindowAsPopup(
|
||||
return root_window;
|
||||
}
|
||||
|
||||
scoped_refptr<RootWindow> RootWindowManager::CreateRootWindowAsExtension(
|
||||
CefRefPtr<CefExtension> extension,
|
||||
const CefRect& source_bounds,
|
||||
CefRefPtr<CefWindow> parent_window,
|
||||
const base::Closure& close_callback,
|
||||
bool with_controls,
|
||||
bool with_osr) {
|
||||
const std::string& extension_url = extension_util::GetExtensionURL(extension);
|
||||
if (extension_url.empty()) {
|
||||
NOTREACHED() << "Extension cannot be loaded directly.";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create an initially hidden browser window that loads the extension URL.
|
||||
// We'll show the window when the desired size becomes available via
|
||||
// ClientHandler::OnAutoResize.
|
||||
RootWindowConfig config;
|
||||
config.with_controls = with_controls;
|
||||
config.with_osr = with_osr;
|
||||
config.with_extension = true;
|
||||
config.initially_hidden = true;
|
||||
config.source_bounds = source_bounds;
|
||||
config.parent_window = parent_window;
|
||||
config.close_callback = close_callback;
|
||||
config.url = extension_url;
|
||||
return CreateRootWindow(config);
|
||||
}
|
||||
|
||||
bool RootWindowManager::HasRootWindowAsExtension(
|
||||
CefRefPtr<CefExtension> extension) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
RootWindowSet::const_iterator it = root_windows_.begin();
|
||||
for (; it != root_windows_.end(); ++it) {
|
||||
const RootWindow* root_window = (*it);
|
||||
if (!root_window->WithExtension())
|
||||
continue;
|
||||
|
||||
CefRefPtr<CefBrowser> browser = root_window->GetBrowser();
|
||||
if (!browser)
|
||||
continue;
|
||||
|
||||
CefRefPtr<CefExtension> browser_extension =
|
||||
browser->GetHost()->GetExtension();
|
||||
DCHECK(browser_extension);
|
||||
if (browser_extension->GetIdentifier() == extension->GetIdentifier())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
scoped_refptr<RootWindow> RootWindowManager::GetWindowForBrowser(
|
||||
int browser_id) {
|
||||
int browser_id) const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
RootWindowSet::const_iterator it = root_windows_.begin();
|
||||
@@ -114,6 +224,16 @@ scoped_refptr<RootWindow> RootWindowManager::GetWindowForBrowser(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scoped_refptr<RootWindow> RootWindowManager::GetActiveRootWindow() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
return active_root_window_;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> RootWindowManager::GetActiveBrowser() const {
|
||||
base::AutoLock lock_scope(active_browser_lock_);
|
||||
return active_browser_;
|
||||
}
|
||||
|
||||
void RootWindowManager::CloseAllWindows(bool force) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
@@ -130,6 +250,29 @@ void RootWindowManager::CloseAllWindows(bool force) {
|
||||
(*it)->Close(force);
|
||||
}
|
||||
|
||||
void RootWindowManager::AddExtension(CefRefPtr<CefExtension> extension) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(base::Bind(&RootWindowManager::AddExtension,
|
||||
base::Unretained(this), extension));
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't track extensions that can't be loaded directly.
|
||||
if (extension_util::GetExtensionURL(extension).empty())
|
||||
return;
|
||||
|
||||
// Don't add the same extension multiple times.
|
||||
ExtensionSet::const_iterator it = extensions_.begin();
|
||||
for (; it != extensions_.end(); ++it) {
|
||||
if ((*it)->GetIdentifier() == extension->GetIdentifier())
|
||||
return;
|
||||
}
|
||||
|
||||
extensions_.insert(extension);
|
||||
NotifyExtensionsChanged();
|
||||
}
|
||||
|
||||
void RootWindowManager::OnRootWindowCreated(
|
||||
scoped_refptr<RootWindow> root_window) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
@@ -140,6 +283,26 @@ void RootWindowManager::OnRootWindowCreated(
|
||||
}
|
||||
|
||||
root_windows_.insert(root_window);
|
||||
if (!root_window->WithExtension()) {
|
||||
root_window->OnExtensionsChanged(extensions_);
|
||||
|
||||
if (root_windows_.size() == 1U) {
|
||||
// The first non-extension root window should be considered the active
|
||||
// window.
|
||||
OnRootWindowActivated(root_window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowManager::NotifyExtensionsChanged() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
RootWindowSet::const_iterator it = root_windows_.begin();
|
||||
for (; it != root_windows_.end(); ++it) {
|
||||
RootWindow* root_window = *it;
|
||||
if (!root_window->WithExtension())
|
||||
root_window->OnExtensionsChanged(extensions_);
|
||||
}
|
||||
}
|
||||
|
||||
CefRefPtr<CefRequestContext> RootWindowManager::GetRequestContext(
|
||||
@@ -180,14 +343,10 @@ CefRefPtr<CefRequestContext> RootWindowManager::GetRequestContext(
|
||||
return shared_request_context_;
|
||||
}
|
||||
|
||||
CefRefPtr<CefImage> RootWindowManager::GetDefaultWindowIcon() {
|
||||
scoped_refptr<ImageCache> RootWindowManager::GetImageCache() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (!default_window_icon_) {
|
||||
// Create the Image and load resources at different scale factors.
|
||||
default_window_icon_ = LoadImageIcon("window_icon");
|
||||
}
|
||||
return default_window_icon_;
|
||||
return image_cache_;
|
||||
}
|
||||
|
||||
void RootWindowManager::OnTest(RootWindow* root_window, int test_id) {
|
||||
@@ -210,10 +369,62 @@ void RootWindowManager::OnRootWindowDestroyed(RootWindow* root_window) {
|
||||
if (it != root_windows_.end())
|
||||
root_windows_.erase(it);
|
||||
|
||||
if (root_window == active_root_window_) {
|
||||
active_root_window_ = NULL;
|
||||
|
||||
base::AutoLock lock_scope(active_browser_lock_);
|
||||
active_browser_ = NULL;
|
||||
}
|
||||
|
||||
if (terminate_when_all_windows_closed_ && root_windows_.empty()) {
|
||||
// Quit the main message loop after all windows have closed.
|
||||
MainMessageLoop::Get()->Quit();
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowManager::OnRootWindowActivated(RootWindow* root_window) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (root_window->WithExtension()) {
|
||||
// We don't want extension apps to become the active RootWindow.
|
||||
return;
|
||||
}
|
||||
|
||||
if (root_window == active_root_window_)
|
||||
return;
|
||||
|
||||
active_root_window_ = root_window;
|
||||
|
||||
{
|
||||
base::AutoLock lock_scope(active_browser_lock_);
|
||||
// May be NULL at this point, in which case we'll make the association in
|
||||
// OnBrowserCreated.
|
||||
active_browser_ = active_root_window_->GetBrowser();
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowManager::OnBrowserCreated(RootWindow* root_window,
|
||||
CefRefPtr<CefBrowser> browser) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (root_window == active_root_window_) {
|
||||
base::AutoLock lock_scope(active_browser_lock_);
|
||||
active_browser_ = browser;
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowManager::CreateExtensionWindow(
|
||||
CefRefPtr<CefExtension> extension,
|
||||
const CefRect& source_bounds,
|
||||
CefRefPtr<CefWindow> parent_window,
|
||||
const base::Closure& close_callback,
|
||||
bool with_osr) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (!HasRootWindowAsExtension(extension)) {
|
||||
CreateRootWindowAsExtension(extension, source_bounds, parent_window,
|
||||
close_callback, false, with_osr);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "include/base/cef_scoped_ptr.h"
|
||||
#include "include/cef_command_line.h"
|
||||
#include "tests/cefclient/browser/image_cache.h"
|
||||
#include "tests/cefclient/browser/root_window.h"
|
||||
#include "tests/cefclient/browser/temp_window.h"
|
||||
|
||||
@@ -23,15 +24,9 @@ class RootWindowManager : public RootWindow::Delegate {
|
||||
// after all windows have closed.
|
||||
explicit RootWindowManager(bool terminate_when_all_windows_closed);
|
||||
|
||||
// Create a new top-level native window that loads |url|.
|
||||
// If |with_controls| is true the window will show controls.
|
||||
// If |with_osr| is true the window will use off-screen rendering.
|
||||
// If |bounds| is empty the default window size and location will be used.
|
||||
// This method can be called from anywhere to create a new top-level window.
|
||||
scoped_refptr<RootWindow> CreateRootWindow(bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& bounds,
|
||||
const std::string& url);
|
||||
// Create a new top-level native window. This method can be called from
|
||||
// anywhere.
|
||||
scoped_refptr<RootWindow> CreateRootWindow(const RootWindowConfig& config);
|
||||
|
||||
// Create a new native popup window.
|
||||
// If |with_controls| is true the window will show controls.
|
||||
@@ -46,14 +41,46 @@ class RootWindowManager : public RootWindow::Delegate {
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings);
|
||||
|
||||
// Create a new top-level native window to host |extension|.
|
||||
// If |with_controls| is true the window will show controls.
|
||||
// If |with_osr| is true the window will use off-screen rendering.
|
||||
// This method can be called from anywhere.
|
||||
scoped_refptr<RootWindow> CreateRootWindowAsExtension(
|
||||
CefRefPtr<CefExtension> extension,
|
||||
const CefRect& source_bounds,
|
||||
CefRefPtr<CefWindow> parent_window,
|
||||
const base::Closure& close_callback,
|
||||
bool with_controls,
|
||||
bool with_osr);
|
||||
|
||||
// Returns true if a window hosting |extension| currently exists. Must be
|
||||
// called on the main thread.
|
||||
bool HasRootWindowAsExtension(CefRefPtr<CefExtension> extension);
|
||||
|
||||
// Returns the RootWindow associated with the specified browser ID. Must be
|
||||
// called on the main thread.
|
||||
scoped_refptr<RootWindow> GetWindowForBrowser(int browser_id);
|
||||
scoped_refptr<RootWindow> GetWindowForBrowser(int browser_id) const;
|
||||
|
||||
// Returns the currently active/foreground RootWindow. May return NULL. Must
|
||||
// be called on the main thread.
|
||||
scoped_refptr<RootWindow> GetActiveRootWindow() const;
|
||||
|
||||
// Returns the currently active/foreground browser. May return NULL. Safe to
|
||||
// call from any thread.
|
||||
CefRefPtr<CefBrowser> GetActiveBrowser() const;
|
||||
|
||||
// Close all existing windows. If |force| is true onunload handlers will not
|
||||
// be executed.
|
||||
void CloseAllWindows(bool force);
|
||||
|
||||
// Manage the set of loaded extensions. RootWindows will be notified via the
|
||||
// OnExtensionsChanged method.
|
||||
void AddExtension(CefRefPtr<CefExtension> extension);
|
||||
|
||||
bool request_context_per_browser() const {
|
||||
return request_context_per_browser_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Allow deletion via scoped_ptr only.
|
||||
friend struct base::DefaultDeleter<RootWindowManager>;
|
||||
@@ -61,14 +88,23 @@ class RootWindowManager : public RootWindow::Delegate {
|
||||
~RootWindowManager();
|
||||
|
||||
void OnRootWindowCreated(scoped_refptr<RootWindow> root_window);
|
||||
void NotifyExtensionsChanged();
|
||||
|
||||
// RootWindow::Delegate methods.
|
||||
CefRefPtr<CefRequestContext> GetRequestContext(
|
||||
RootWindow* root_window) OVERRIDE;
|
||||
CefRefPtr<CefImage> GetDefaultWindowIcon() OVERRIDE;
|
||||
scoped_refptr<ImageCache> GetImageCache() OVERRIDE;
|
||||
void OnTest(RootWindow* root_window, int test_id) OVERRIDE;
|
||||
void OnExit(RootWindow* root_window) OVERRIDE;
|
||||
void OnRootWindowDestroyed(RootWindow* root_window) OVERRIDE;
|
||||
void OnRootWindowActivated(RootWindow* root_window) OVERRIDE;
|
||||
void OnBrowserCreated(RootWindow* root_window,
|
||||
CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
void CreateExtensionWindow(CefRefPtr<CefExtension> extension,
|
||||
const CefRect& source_bounds,
|
||||
CefRefPtr<CefWindow> parent_window,
|
||||
const base::Closure& close_callback,
|
||||
bool with_osr) OVERRIDE;
|
||||
|
||||
const bool terminate_when_all_windows_closed_;
|
||||
bool request_context_per_browser_;
|
||||
@@ -78,11 +114,24 @@ class RootWindowManager : public RootWindow::Delegate {
|
||||
typedef std::set<scoped_refptr<RootWindow>> RootWindowSet;
|
||||
RootWindowSet root_windows_;
|
||||
|
||||
// The currently active/foreground RootWindow. Only accessed on the main
|
||||
// thread.
|
||||
scoped_refptr<RootWindow> active_root_window_;
|
||||
|
||||
// The currently active/foreground browser. Access is protected by
|
||||
// |active_browser_lock_;
|
||||
mutable base::Lock active_browser_lock_;
|
||||
CefRefPtr<CefBrowser> active_browser_;
|
||||
|
||||
// Singleton window used as the temporary parent for popup browsers.
|
||||
TempWindow temp_window_;
|
||||
|
||||
CefRefPtr<CefRequestContext> shared_request_context_;
|
||||
CefRefPtr<CefImage> default_window_icon_;
|
||||
|
||||
// Loaded extensions. Only accessed on the main thread.
|
||||
ExtensionSet extensions_;
|
||||
|
||||
scoped_refptr<ImageCache> image_cache_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RootWindowManager);
|
||||
};
|
||||
|
@@ -12,10 +12,19 @@
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
// Images that are loaded early and cached.
|
||||
static const char* kDefaultImageCache[] = {"menu_icon", "window_icon"};
|
||||
|
||||
} // namespace
|
||||
|
||||
RootWindowViews::RootWindowViews()
|
||||
: delegate_(NULL),
|
||||
with_controls_(false),
|
||||
: with_controls_(false),
|
||||
with_extension_(false),
|
||||
initially_hidden_(false),
|
||||
is_popup_(false),
|
||||
position_on_resize_(false),
|
||||
initialized_(false),
|
||||
window_destroyed_(false),
|
||||
browser_destroyed_(false) {}
|
||||
@@ -25,23 +34,31 @@ RootWindowViews::~RootWindowViews() {
|
||||
}
|
||||
|
||||
void RootWindowViews::Init(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& bounds,
|
||||
const CefBrowserSettings& settings,
|
||||
const std::string& url) {
|
||||
const RootWindowConfig& config,
|
||||
const CefBrowserSettings& settings) {
|
||||
DCHECK(delegate);
|
||||
DCHECK(!with_osr); // Windowless rendering is not supported.
|
||||
DCHECK(!config.with_osr); // Windowless rendering is not supported.
|
||||
DCHECK(!initialized_);
|
||||
|
||||
delegate_ = delegate;
|
||||
with_controls_ = with_controls;
|
||||
initial_bounds_ = bounds;
|
||||
CreateClientHandler(url);
|
||||
with_controls_ = config.with_controls;
|
||||
with_extension_ = config.with_extension;
|
||||
initially_hidden_ = config.initially_hidden;
|
||||
if (initially_hidden_ && !config.source_bounds.IsEmpty()) {
|
||||
// The window will be sized and positioned in OnAutoResize().
|
||||
initial_bounds_ = config.source_bounds;
|
||||
position_on_resize_ = true;
|
||||
} else {
|
||||
initial_bounds_ = config.bounds;
|
||||
}
|
||||
parent_window_ = config.parent_window;
|
||||
close_callback_ = config.close_callback;
|
||||
|
||||
CreateClientHandler(config.url);
|
||||
initialized_ = true;
|
||||
|
||||
// Continue initialization on the main thread.
|
||||
InitOnMainThread(settings, url);
|
||||
InitOnMainThread(settings, config.url);
|
||||
}
|
||||
|
||||
void RootWindowViews::InitAsPopup(RootWindow::Delegate* delegate,
|
||||
@@ -167,20 +184,66 @@ ClientWindowHandle RootWindowViews::GetWindowHandle() const {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RootWindowViews::WithExtension() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
return with_extension_;
|
||||
}
|
||||
|
||||
bool RootWindowViews::WithControls() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
return with_controls_;
|
||||
}
|
||||
|
||||
bool RootWindowViews::WithExtension() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
return with_extension_;
|
||||
}
|
||||
|
||||
void RootWindowViews::OnExtensionsChanged(const ExtensionSet& extensions) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
// Execute this method on the UI thread.
|
||||
CefPostTask(TID_UI, base::Bind(&RootWindowViews::OnExtensionsChanged, this,
|
||||
extensions));
|
||||
return;
|
||||
}
|
||||
|
||||
if (window_) {
|
||||
window_->OnExtensionsChanged(extensions);
|
||||
} else {
|
||||
// Window may not exist yet for popups.
|
||||
pending_extensions_ = extensions;
|
||||
}
|
||||
}
|
||||
|
||||
bool RootWindowViews::InitiallyHidden() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
return initially_hidden_;
|
||||
}
|
||||
|
||||
CefRefPtr<CefWindow> RootWindowViews::GetParentWindow() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
return parent_window_;
|
||||
}
|
||||
|
||||
CefRect RootWindowViews::GetWindowBounds() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
return initial_bounds_;
|
||||
}
|
||||
|
||||
scoped_refptr<ImageCache> RootWindowViews::GetImageCache() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
return image_cache_;
|
||||
}
|
||||
|
||||
void RootWindowViews::OnViewsWindowCreated(CefRefPtr<ViewsWindow> window) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
DCHECK(!window_);
|
||||
window_ = window;
|
||||
|
||||
if (!pending_extensions_.empty()) {
|
||||
window_->OnExtensionsChanged(pending_extensions_);
|
||||
pending_extensions_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowViews::OnViewsWindowDestroyed(CefRefPtr<ViewsWindow> window) {
|
||||
@@ -192,6 +255,14 @@ void RootWindowViews::OnViewsWindowDestroyed(CefRefPtr<ViewsWindow> window) {
|
||||
base::Bind(&RootWindowViews::NotifyViewsWindowDestroyed, this));
|
||||
}
|
||||
|
||||
void RootWindowViews::OnViewsWindowActivated(CefRefPtr<ViewsWindow> window) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Continue on the main thread.
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&RootWindowViews::NotifyViewsWindowActivated, this));
|
||||
}
|
||||
|
||||
ViewsWindow::Delegate* RootWindowViews::GetDelegateForPopup(
|
||||
CefRefPtr<CefClient> client) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
@@ -199,9 +270,30 @@ ViewsWindow::Delegate* RootWindowViews::GetDelegateForPopup(
|
||||
ClientHandlerStd* handler = static_cast<ClientHandlerStd*>(client.get());
|
||||
RootWindowViews* root_window =
|
||||
static_cast<RootWindowViews*>(handler->delegate());
|
||||
|
||||
// Transfer some state to the child RootWindowViews.
|
||||
root_window->image_cache_ = image_cache_;
|
||||
|
||||
return root_window;
|
||||
}
|
||||
|
||||
void RootWindowViews::CreateExtensionWindow(
|
||||
CefRefPtr<CefExtension> extension,
|
||||
const CefRect& source_bounds,
|
||||
CefRefPtr<CefWindow> parent_window,
|
||||
const base::Closure& close_callback) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(base::Bind(&RootWindowViews::CreateExtensionWindow, this,
|
||||
extension, source_bounds, parent_window,
|
||||
close_callback));
|
||||
return;
|
||||
}
|
||||
|
||||
delegate_->CreateExtensionWindow(extension, source_bounds, parent_window,
|
||||
close_callback, false);
|
||||
}
|
||||
|
||||
void RootWindowViews::OnTest(int test_id) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
@@ -226,6 +318,7 @@ void RootWindowViews::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK(!browser_);
|
||||
browser_ = browser;
|
||||
delegate_->OnBrowserCreated(this, browser);
|
||||
}
|
||||
|
||||
void RootWindowViews::OnBrowserClosing(CefRefPtr<CefBrowser> browser) {
|
||||
@@ -293,6 +386,33 @@ void RootWindowViews::OnSetFullscreen(bool fullscreen) {
|
||||
window_->SetFullscreen(fullscreen);
|
||||
}
|
||||
|
||||
void RootWindowViews::OnAutoResize(const CefSize& new_size) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
// Execute this method on the UI thread.
|
||||
CefPostTask(TID_UI,
|
||||
base::Bind(&RootWindowViews::OnAutoResize, this, new_size));
|
||||
return;
|
||||
}
|
||||
|
||||
bool has_position = false;
|
||||
CefPoint position;
|
||||
if (position_on_resize_) {
|
||||
// Position the window centered on and immediately below the source.
|
||||
const int x_offset = (initial_bounds_.width - new_size.width) / 2;
|
||||
position.Set(initial_bounds_.x + x_offset,
|
||||
initial_bounds_.y + initial_bounds_.height);
|
||||
has_position = true;
|
||||
|
||||
// Don't change the window position on future resizes.
|
||||
position_on_resize_ = false;
|
||||
}
|
||||
|
||||
if (window_) {
|
||||
window_->SetBrowserSize(new_size, has_position, position);
|
||||
window_->Show();
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowViews::OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) {
|
||||
@@ -309,7 +429,8 @@ void RootWindowViews::OnSetLoadingState(bool isLoading,
|
||||
|
||||
if (isLoading) {
|
||||
// Reset to the default window icon when loading begins.
|
||||
window_->SetFavicon(delegate_->GetDefaultWindowIcon());
|
||||
window_->SetFavicon(
|
||||
delegate_->GetImageCache()->GetCachedImage("window_icon"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -360,22 +481,34 @@ void RootWindowViews::InitOnMainThread(const CefBrowserSettings& settings,
|
||||
return;
|
||||
}
|
||||
|
||||
CreateViewsWindow(settings, startup_url, delegate_->GetRequestContext(this));
|
||||
image_cache_ = delegate_->GetImageCache();
|
||||
|
||||
// Populate the default image cache.
|
||||
ImageCache::ImageInfoSet image_set;
|
||||
for (size_t i = 0U; i < arraysize(kDefaultImageCache); ++i)
|
||||
image_set.push_back(ImageCache::ImageInfo::Create2x(kDefaultImageCache[i]));
|
||||
|
||||
image_cache_->LoadImages(
|
||||
image_set, base::Bind(&RootWindowViews::CreateViewsWindow, this, settings,
|
||||
startup_url, delegate_->GetRequestContext(this)));
|
||||
}
|
||||
|
||||
void RootWindowViews::CreateViewsWindow(
|
||||
const CefBrowserSettings& settings,
|
||||
const std::string& startup_url,
|
||||
CefRefPtr<CefRequestContext> request_context) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
// Execute this method on the UI thread.
|
||||
CefPostTask(TID_UI, base::Bind(&RootWindowViews::CreateViewsWindow, this,
|
||||
settings, startup_url, request_context));
|
||||
return;
|
||||
}
|
||||
|
||||
CefRefPtr<CefRequestContext> request_context,
|
||||
const ImageCache::ImageSet& images) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
DCHECK(!window_);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Make sure the default images loaded successfully.
|
||||
DCHECK_EQ(images.size(), arraysize(kDefaultImageCache));
|
||||
for (size_t i = 0U; i < arraysize(kDefaultImageCache); ++i) {
|
||||
DCHECK(images[i]) << "Default image " << i << " failed to load";
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create the ViewsWindow. It will show itself after creation.
|
||||
ViewsWindow::Create(this, client_handler_, startup_url, settings,
|
||||
request_context);
|
||||
@@ -387,10 +520,18 @@ void RootWindowViews::NotifyViewsWindowDestroyed() {
|
||||
NotifyDestroyedIfDone();
|
||||
}
|
||||
|
||||
void RootWindowViews::NotifyViewsWindowActivated() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
delegate_->OnRootWindowActivated(this);
|
||||
}
|
||||
|
||||
void RootWindowViews::NotifyDestroyedIfDone() {
|
||||
// Notify once both the window and the browser have been destroyed.
|
||||
if (window_destroyed_ && browser_destroyed_)
|
||||
if (window_destroyed_ && browser_destroyed_) {
|
||||
delegate_->OnRootWindowDestroyed(this);
|
||||
if (!close_callback_.is_null())
|
||||
close_callback_.Run();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
@@ -28,11 +28,8 @@ class RootWindowViews : public RootWindow,
|
||||
|
||||
// RootWindow methods:
|
||||
void Init(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& rect,
|
||||
const CefBrowserSettings& settings,
|
||||
const std::string& url) OVERRIDE;
|
||||
const RootWindowConfig& config,
|
||||
const CefBrowserSettings& settings) OVERRIDE;
|
||||
void InitAsPopup(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
@@ -48,16 +45,28 @@ class RootWindowViews : public RootWindow,
|
||||
float GetDeviceScaleFactor() const OVERRIDE;
|
||||
CefRefPtr<CefBrowser> GetBrowser() const OVERRIDE;
|
||||
ClientWindowHandle GetWindowHandle() const OVERRIDE;
|
||||
bool WithWindowlessRendering() const OVERRIDE { return false; }
|
||||
bool WithExtension() const OVERRIDE;
|
||||
void OnExtensionsChanged(const ExtensionSet& extensions) OVERRIDE;
|
||||
|
||||
// ViewsWindow::Delegate methods:
|
||||
bool WithControls() OVERRIDE;
|
||||
bool WithExtension() OVERRIDE;
|
||||
bool InitiallyHidden() OVERRIDE;
|
||||
CefRefPtr<CefWindow> GetParentWindow() OVERRIDE;
|
||||
CefRect GetWindowBounds() OVERRIDE;
|
||||
scoped_refptr<ImageCache> GetImageCache() OVERRIDE;
|
||||
void OnViewsWindowCreated(CefRefPtr<ViewsWindow> window) OVERRIDE;
|
||||
void OnViewsWindowDestroyed(CefRefPtr<ViewsWindow> window) OVERRIDE;
|
||||
void OnViewsWindowActivated(CefRefPtr<ViewsWindow> window) OVERRIDE;
|
||||
ViewsWindow::Delegate* GetDelegateForPopup(
|
||||
CefRefPtr<CefClient> client) OVERRIDE;
|
||||
virtual void OnTest(int test_id) OVERRIDE;
|
||||
virtual void OnExit() OVERRIDE;
|
||||
void CreateExtensionWindow(CefRefPtr<CefExtension> extension,
|
||||
const CefRect& source_bounds,
|
||||
CefRefPtr<CefWindow> parent_window,
|
||||
const base::Closure& close_callback) OVERRIDE;
|
||||
void OnTest(int test_id) OVERRIDE;
|
||||
void OnExit() OVERRIDE;
|
||||
|
||||
protected:
|
||||
// ClientHandler::Delegate methods:
|
||||
@@ -68,6 +77,7 @@ class RootWindowViews : public RootWindow,
|
||||
void OnSetTitle(const std::string& title) OVERRIDE;
|
||||
void OnSetFavicon(CefRefPtr<CefImage> image) OVERRIDE;
|
||||
void OnSetFullscreen(bool fullscreen) OVERRIDE;
|
||||
void OnAutoResize(const CefSize& new_size) OVERRIDE;
|
||||
void OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) OVERRIDE;
|
||||
@@ -83,18 +93,24 @@ class RootWindowViews : public RootWindow,
|
||||
const std::string& startup_url);
|
||||
void CreateViewsWindow(const CefBrowserSettings& settings,
|
||||
const std::string& startup_url,
|
||||
CefRefPtr<CefRequestContext> request_context);
|
||||
CefRefPtr<CefRequestContext> request_context,
|
||||
const ImageCache::ImageSet& images);
|
||||
|
||||
void NotifyViewsWindowDestroyed();
|
||||
void NotifyViewsWindowActivated();
|
||||
void NotifyDestroyedIfDone();
|
||||
|
||||
// After initialization all members are only accessed on the main thread
|
||||
// unless otherwise indicated.
|
||||
// Members set during initialization.
|
||||
RootWindow::Delegate* delegate_;
|
||||
bool with_controls_;
|
||||
bool with_extension_;
|
||||
bool initially_hidden_;
|
||||
CefRefPtr<CefWindow> parent_window_;
|
||||
bool is_popup_;
|
||||
CefRect initial_bounds_;
|
||||
base::Closure close_callback_;
|
||||
bool position_on_resize_;
|
||||
CefRefPtr<ClientHandler> client_handler_;
|
||||
|
||||
bool initialized_;
|
||||
@@ -105,6 +121,8 @@ class RootWindowViews : public RootWindow,
|
||||
|
||||
// Only accessed on the browser process UI thread.
|
||||
CefRefPtr<ViewsWindow> window_;
|
||||
ExtensionSet pending_extensions_;
|
||||
scoped_refptr<ImageCache> image_cache_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RootWindowViews);
|
||||
};
|
||||
|
@@ -51,7 +51,8 @@ int GetButtonWidth() {
|
||||
static bool initialized = false;
|
||||
|
||||
if (!initialized) {
|
||||
button_width = LogicalToDevice(BUTTON_WIDTH, GetDeviceScaleFactor());
|
||||
button_width =
|
||||
LogicalToDevice(BUTTON_WIDTH, client::GetDeviceScaleFactor());
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@@ -63,7 +64,8 @@ int GetURLBarHeight() {
|
||||
static bool initialized = false;
|
||||
|
||||
if (!initialized) {
|
||||
urlbar_height = LogicalToDevice(URLBAR_HEIGHT, GetDeviceScaleFactor());
|
||||
urlbar_height =
|
||||
LogicalToDevice(URLBAR_HEIGHT, client::GetDeviceScaleFactor());
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@@ -73,9 +75,9 @@ int GetURLBarHeight() {
|
||||
} // namespace
|
||||
|
||||
RootWindowWin::RootWindowWin()
|
||||
: delegate_(NULL),
|
||||
with_controls_(false),
|
||||
: with_controls_(false),
|
||||
with_osr_(false),
|
||||
with_extension_(false),
|
||||
is_popup_(false),
|
||||
start_rect_(),
|
||||
initialized_(false),
|
||||
@@ -114,33 +116,31 @@ RootWindowWin::~RootWindowWin() {
|
||||
}
|
||||
|
||||
void RootWindowWin::Init(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& bounds,
|
||||
const CefBrowserSettings& settings,
|
||||
const std::string& url) {
|
||||
const RootWindowConfig& config,
|
||||
const CefBrowserSettings& settings) {
|
||||
DCHECK(delegate);
|
||||
DCHECK(!initialized_);
|
||||
|
||||
delegate_ = delegate;
|
||||
with_controls_ = with_controls;
|
||||
with_osr_ = with_osr;
|
||||
with_controls_ = config.with_controls;
|
||||
with_osr_ = config.with_osr;
|
||||
with_extension_ = config.with_extension;
|
||||
|
||||
start_rect_.left = bounds.x;
|
||||
start_rect_.top = bounds.y;
|
||||
start_rect_.right = bounds.x + bounds.width;
|
||||
start_rect_.bottom = bounds.y + bounds.height;
|
||||
start_rect_.left = config.bounds.x;
|
||||
start_rect_.top = config.bounds.y;
|
||||
start_rect_.right = config.bounds.x + config.bounds.width;
|
||||
start_rect_.bottom = config.bounds.y + config.bounds.height;
|
||||
|
||||
CreateBrowserWindow(url);
|
||||
CreateBrowserWindow(config.url);
|
||||
|
||||
initialized_ = true;
|
||||
|
||||
// Create the native root window on the main thread.
|
||||
if (CURRENTLY_ON_MAIN_THREAD()) {
|
||||
CreateRootWindow(settings);
|
||||
CreateRootWindow(settings, config.initially_hidden);
|
||||
} else {
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&RootWindowWin::CreateRootWindow, this, settings));
|
||||
MAIN_POST_CLOSURE(base::Bind(&RootWindowWin::CreateRootWindow, this,
|
||||
settings, config.initially_hidden));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,16 +233,18 @@ void RootWindowWin::Close(bool force) {
|
||||
void RootWindowWin::SetDeviceScaleFactor(float device_scale_factor) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_window_)
|
||||
if (browser_window_ && with_osr_)
|
||||
browser_window_->SetDeviceScaleFactor(device_scale_factor);
|
||||
}
|
||||
|
||||
float RootWindowWin::GetDeviceScaleFactor() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_window_)
|
||||
if (browser_window_ && with_osr_)
|
||||
return browser_window_->GetDeviceScaleFactor();
|
||||
return client::GetDeviceScaleFactor();
|
||||
|
||||
NOTREACHED();
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> RootWindowWin::GetBrowser() const {
|
||||
@@ -258,6 +260,16 @@ ClientWindowHandle RootWindowWin::GetWindowHandle() const {
|
||||
return hwnd_;
|
||||
}
|
||||
|
||||
bool RootWindowWin::WithWindowlessRendering() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
return with_osr_;
|
||||
}
|
||||
|
||||
bool RootWindowWin::WithExtension() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
return with_extension_;
|
||||
}
|
||||
|
||||
void RootWindowWin::CreateBrowserWindow(const std::string& startup_url) {
|
||||
if (with_osr_) {
|
||||
OsrRenderer::Settings settings = {};
|
||||
@@ -268,7 +280,8 @@ void RootWindowWin::CreateBrowserWindow(const std::string& startup_url) {
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowWin::CreateRootWindow(const CefBrowserSettings& settings) {
|
||||
void RootWindowWin::CreateRootWindow(const CefBrowserSettings& settings,
|
||||
bool initially_hidden) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK(!hwnd_);
|
||||
|
||||
@@ -415,8 +428,10 @@ void RootWindowWin::CreateRootWindow(const CefBrowserSettings& settings) {
|
||||
rect.right - rect.left, rect.bottom - rect.top);
|
||||
}
|
||||
|
||||
// Show this window.
|
||||
Show(ShowNormal);
|
||||
if (!initially_hidden) {
|
||||
// Show this window.
|
||||
Show(ShowNormal);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -556,6 +571,11 @@ LRESULT CALLBACK RootWindowWin::RootWndProc(HWND hWnd,
|
||||
self->OnPaint();
|
||||
return 0;
|
||||
|
||||
case WM_ACTIVATE:
|
||||
self->OnActivate(LOWORD(wParam) != WA_INACTIVE);
|
||||
// Allow DefWindowProc to set keyboard focus.
|
||||
break;
|
||||
|
||||
case WM_SETFOCUS:
|
||||
self->OnFocus();
|
||||
return 0;
|
||||
@@ -631,6 +651,11 @@ void RootWindowWin::OnFocus() {
|
||||
browser_window_->SetFocus(true);
|
||||
}
|
||||
|
||||
void RootWindowWin::OnActivate(bool active) {
|
||||
if (active)
|
||||
delegate_->OnRootWindowActivated(this);
|
||||
}
|
||||
|
||||
void RootWindowWin::OnSize(bool minimized) {
|
||||
if (minimized) {
|
||||
// Notify the browser window that it was hidden and do nothing further.
|
||||
@@ -825,11 +850,13 @@ void RootWindowWin::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
|
||||
if (is_popup_) {
|
||||
// For popup browsers create the root window once the browser has been
|
||||
// created.
|
||||
CreateRootWindow(CefBrowserSettings());
|
||||
CreateRootWindow(CefBrowserSettings(), false);
|
||||
} else {
|
||||
// Make sure the browser is sized correctly.
|
||||
OnSize(false);
|
||||
}
|
||||
|
||||
delegate_->OnBrowserCreated(this, browser);
|
||||
}
|
||||
|
||||
void RootWindowWin::OnBrowserWindowDestroyed() {
|
||||
@@ -876,6 +903,36 @@ void RootWindowWin::OnSetFullscreen(bool fullscreen) {
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowWin::OnAutoResize(const CefSize& new_size) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (!hwnd_)
|
||||
return;
|
||||
|
||||
int new_width = new_size.width;
|
||||
|
||||
// Make the window wide enough to drag by the top menu bar.
|
||||
if (new_width < 200)
|
||||
new_width = 200;
|
||||
|
||||
RECT rect = {
|
||||
0, 0, LogicalToDevice(new_width, client::GetDeviceScaleFactor()),
|
||||
LogicalToDevice(new_size.height, client::GetDeviceScaleFactor())};
|
||||
DWORD style = GetWindowLong(hwnd_, GWL_STYLE);
|
||||
DWORD ex_style = GetWindowLong(hwnd_, GWL_EXSTYLE);
|
||||
bool has_menu = !(style & WS_CHILD) && (GetMenu(hwnd_) != NULL);
|
||||
|
||||
// The size value is for the client area. Calculate the whole window size
|
||||
// based on the current style.
|
||||
AdjustWindowRectEx(&rect, style, has_menu, ex_style);
|
||||
|
||||
// Size the window. The left/top values may be negative.
|
||||
// Also show the window if it's not currently visible.
|
||||
SetWindowPos(hwnd_, NULL, 0, 0, rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
|
||||
}
|
||||
|
||||
void RootWindowWin::OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) {
|
||||
|
@@ -29,11 +29,8 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
||||
|
||||
// RootWindow methods.
|
||||
void Init(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& rect,
|
||||
const CefBrowserSettings& settings,
|
||||
const std::string& url) OVERRIDE;
|
||||
const RootWindowConfig& config,
|
||||
const CefBrowserSettings& settings) OVERRIDE;
|
||||
void InitAsPopup(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
@@ -49,10 +46,13 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
||||
float GetDeviceScaleFactor() const OVERRIDE;
|
||||
CefRefPtr<CefBrowser> GetBrowser() const OVERRIDE;
|
||||
ClientWindowHandle GetWindowHandle() const OVERRIDE;
|
||||
bool WithWindowlessRendering() const OVERRIDE;
|
||||
bool WithExtension() const OVERRIDE;
|
||||
|
||||
private:
|
||||
void CreateBrowserWindow(const std::string& startup_url);
|
||||
void CreateRootWindow(const CefBrowserSettings& settings);
|
||||
void CreateRootWindow(const CefBrowserSettings& settings,
|
||||
bool initially_hidden);
|
||||
|
||||
// Register the root window class.
|
||||
static void RegisterRootClass(HINSTANCE hInstance,
|
||||
@@ -80,6 +80,7 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
||||
// Event handlers.
|
||||
void OnPaint();
|
||||
void OnFocus();
|
||||
void OnActivate(bool active);
|
||||
void OnSize(bool minimized);
|
||||
void OnMove();
|
||||
bool OnEraseBkgnd();
|
||||
@@ -96,6 +97,7 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
||||
void OnSetAddress(const std::string& url) OVERRIDE;
|
||||
void OnSetTitle(const std::string& title) OVERRIDE;
|
||||
void OnSetFullscreen(bool fullscreen) OVERRIDE;
|
||||
void OnAutoResize(const CefSize& new_size) OVERRIDE;
|
||||
void OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) OVERRIDE;
|
||||
@@ -106,9 +108,9 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
||||
|
||||
// After initialization all members are only accessed on the main thread.
|
||||
// Members set during initialization.
|
||||
RootWindow::Delegate* delegate_;
|
||||
bool with_controls_;
|
||||
bool with_osr_;
|
||||
bool with_extension_;
|
||||
bool is_popup_;
|
||||
RECT start_rect_;
|
||||
scoped_ptr<BrowserWindow> browser_window_;
|
||||
|
@@ -119,11 +119,10 @@ void RunRequestTest(CefRefPtr<CefBrowser> browser) {
|
||||
}
|
||||
|
||||
void RunNewWindowTest(CefRefPtr<CefBrowser> browser) {
|
||||
MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
|
||||
true, // Show controls.
|
||||
browser->GetHost()->IsWindowRenderingDisabled(),
|
||||
CefRect(), // Use default system size.
|
||||
std::string()); // Use default URL.
|
||||
RootWindowConfig config;
|
||||
config.with_controls = true;
|
||||
config.with_osr = browser->GetHost()->IsWindowRenderingDisabled();
|
||||
MainContext::Get()->GetRootWindowManager()->CreateRootWindow(config);
|
||||
}
|
||||
|
||||
void RunPopupWindowTest(CefRefPtr<CefBrowser> browser) {
|
||||
@@ -680,8 +679,9 @@ void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager) {
|
||||
// Add provider for bundled resource files.
|
||||
#if defined(OS_WIN)
|
||||
// Read resources from the binary.
|
||||
resource_manager->AddProvider(CreateBinaryResourceProvider(test_origin), 100,
|
||||
std::string());
|
||||
resource_manager->AddProvider(
|
||||
CreateBinaryResourceProvider(test_origin, std::string()), 100,
|
||||
std::string());
|
||||
#elif defined(OS_POSIX)
|
||||
// Read resources from a directory on disk.
|
||||
std::string resource_dir;
|
||||
@@ -693,6 +693,14 @@ void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager) {
|
||||
}
|
||||
|
||||
void Alert(CefRefPtr<CefBrowser> browser, const std::string& message) {
|
||||
if (browser->GetHost()->GetExtension()) {
|
||||
// Alerts originating from extension hosts should instead be displayed in
|
||||
// the active browser.
|
||||
browser = MainContext::Get()->GetRootWindowManager()->GetActiveBrowser();
|
||||
if (!browser)
|
||||
return;
|
||||
}
|
||||
|
||||
// Escape special characters in the message.
|
||||
std::string msg = StringReplace(message, "\\", "\\\\");
|
||||
msg = StringReplace(msg, "'", "\\'");
|
||||
|
@@ -147,8 +147,10 @@ void ViewsMenuBar::Reset() {
|
||||
id_next_ = id_start_;
|
||||
}
|
||||
|
||||
void ViewsMenuBar::OnMenuButtonPressed(CefRefPtr<CefMenuButton> menu_button,
|
||||
const CefPoint& screen_point) {
|
||||
void ViewsMenuBar::OnMenuButtonPressed(
|
||||
CefRefPtr<CefMenuButton> menu_button,
|
||||
const CefPoint& screen_point,
|
||||
CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) {
|
||||
CefRefPtr<CefMenuModel> menu_model = GetMenuModel(menu_button->GetID());
|
||||
|
||||
// Adjust menu position left by button width.
|
||||
|
@@ -73,8 +73,10 @@ class ViewsMenuBar : public CefMenuButtonDelegate, public CefMenuModelDelegate {
|
||||
void OnButtonPressed(CefRefPtr<CefButton> button) OVERRIDE {}
|
||||
|
||||
// CefMenuButtonDelegate methods:
|
||||
void OnMenuButtonPressed(CefRefPtr<CefMenuButton> menu_button,
|
||||
const CefPoint& screen_point) OVERRIDE;
|
||||
void OnMenuButtonPressed(
|
||||
CefRefPtr<CefMenuButton> menu_button,
|
||||
const CefPoint& screen_point,
|
||||
CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) OVERRIDE;
|
||||
|
||||
// CefMenuModelDelegate methods:
|
||||
void ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
|
||||
|
@@ -13,10 +13,11 @@
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "tests/cefclient/browser/resource.h"
|
||||
#include "tests/cefclient/browser/views_style.h"
|
||||
#include "tests/shared/browser/resource_util.h"
|
||||
#include "tests/shared/browser/extension_util.h"
|
||||
#include "tests/shared/common/client_switches.h"
|
||||
|
||||
#if !defined(OS_WIN)
|
||||
#define VK_ESCAPE 0x1B
|
||||
#define VK_RETURN 0x0D
|
||||
#define VK_MENU 0x12 // ALT key.
|
||||
#endif
|
||||
@@ -25,6 +26,8 @@ namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kDefaultExtensionIcon[] = "window_icon";
|
||||
|
||||
// Control IDs for Views in the top-level Window.
|
||||
enum ControlIds {
|
||||
ID_WINDOW = 1,
|
||||
@@ -39,6 +42,10 @@ enum ControlIds {
|
||||
// Reserved range of top menu button IDs.
|
||||
ID_TOP_MENU_FIRST,
|
||||
ID_TOP_MENU_LAST = ID_TOP_MENU_FIRST + 10,
|
||||
|
||||
// Reserved range of extension button IDs.
|
||||
ID_EXTENSION_BUTTON_FIRST,
|
||||
ID_EXTENSION_BUTTON_LAST = ID_EXTENSION_BUTTON_FIRST + 10,
|
||||
};
|
||||
|
||||
typedef std::vector<CefRefPtr<CefLabelButton>> LabelButtons;
|
||||
@@ -122,6 +129,10 @@ void ViewsWindow::Show() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (window_)
|
||||
window_->Show();
|
||||
if (browser_view_) {
|
||||
// Give keyboard focus to the BrowserView.
|
||||
browser_view_->RequestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsWindow::Hide() {
|
||||
@@ -148,6 +159,19 @@ void ViewsWindow::SetBounds(const CefRect& bounds) {
|
||||
window_->SetBounds(bounds);
|
||||
}
|
||||
|
||||
void ViewsWindow::SetBrowserSize(const CefSize& size,
|
||||
bool has_position,
|
||||
const CefPoint& position) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (browser_view_)
|
||||
browser_view_->SetSize(size);
|
||||
if (window_) {
|
||||
window_->SizeToPreferredSize();
|
||||
if (has_position)
|
||||
window_->SetPosition(position);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsWindow::Close(bool force) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!browser_view_)
|
||||
@@ -251,21 +275,75 @@ void ViewsWindow::OnBeforeContextMenu(CefRefPtr<CefMenuModel> model) {
|
||||
views_style::ApplyTo(model);
|
||||
}
|
||||
|
||||
bool ViewsWindow::OnPopupBrowserViewCreated(
|
||||
void ViewsWindow::OnExtensionsChanged(const ExtensionSet& extensions) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (extensions.empty()) {
|
||||
if (!extensions_.empty()) {
|
||||
extensions_.clear();
|
||||
UpdateExtensionControls();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ImageCache::ImageInfoSet image_set;
|
||||
|
||||
ExtensionSet::const_iterator it = extensions.begin();
|
||||
for (; it != extensions.end(); ++it) {
|
||||
CefRefPtr<CefExtension> extension = *it;
|
||||
bool internal = false;
|
||||
const std::string& icon_path =
|
||||
extension_util::GetExtensionIconPath(extension, &internal);
|
||||
if (!icon_path.empty()) {
|
||||
// Load the extension icon.
|
||||
image_set.push_back(
|
||||
ImageCache::ImageInfo::Create1x(icon_path, icon_path, internal));
|
||||
} else {
|
||||
// Get a NULL image and use the default icon.
|
||||
image_set.push_back(ImageCache::ImageInfo::Empty());
|
||||
}
|
||||
}
|
||||
|
||||
delegate_->GetImageCache()->LoadImages(
|
||||
image_set,
|
||||
base::Bind(&ViewsWindow::OnExtensionIconsLoaded, this, extensions));
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowserViewDelegate> ViewsWindow::GetDelegateForPopupBrowserView(
|
||||
CefRefPtr<CefBrowserView> browser_view,
|
||||
CefRefPtr<CefBrowserView> popup_browser_view,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefClient> client,
|
||||
bool is_devtools) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// The popup browser client is created in CefLifeSpanHandler::OnBeforePopup()
|
||||
// (e.g. via RootWindowViews::InitAsPopup()). The Delegate (RootWindowViews)
|
||||
// knows the association between |client| and itself.
|
||||
Delegate* popup_delegate = delegate_->GetDelegateForPopup(
|
||||
popup_browser_view->GetBrowser()->GetHost()->GetClient());
|
||||
Delegate* popup_delegate = delegate_->GetDelegateForPopup(client);
|
||||
|
||||
// Should not be the same RootWindowViews that owns |this|.
|
||||
DCHECK(popup_delegate && popup_delegate != delegate_);
|
||||
|
||||
// Create a new ViewsWindow for the popup BrowserView.
|
||||
return new ViewsWindow(popup_delegate, NULL);
|
||||
}
|
||||
|
||||
bool ViewsWindow::OnPopupBrowserViewCreated(
|
||||
CefRefPtr<CefBrowserView> browser_view,
|
||||
CefRefPtr<CefBrowserView> popup_browser_view,
|
||||
bool is_devtools) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Retrieve the ViewsWindow created in GetDelegateForPopupBrowserView.
|
||||
CefRefPtr<ViewsWindow> popup_window =
|
||||
new ViewsWindow(popup_delegate, popup_browser_view);
|
||||
static_cast<ViewsWindow*>(static_cast<CefBrowserViewDelegate*>(
|
||||
popup_browser_view->GetDelegate().get()));
|
||||
|
||||
// Should not be the same ViewsWindow as |this|.
|
||||
DCHECK(popup_window && popup_window != this);
|
||||
|
||||
// Associate the ViewsWindow with the new popup browser.
|
||||
popup_window->SetBrowserView(popup_browser_view);
|
||||
|
||||
// Create a new top-level Window for the popup. It will show itself after
|
||||
// creation.
|
||||
@@ -307,11 +385,32 @@ void ViewsWindow::OnButtonPressed(CefRefPtr<CefButton> button) {
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsWindow::OnMenuButtonPressed(CefRefPtr<CefMenuButton> menu_button,
|
||||
const CefPoint& screen_point) {
|
||||
void ViewsWindow::OnMenuButtonPressed(
|
||||
CefRefPtr<CefMenuButton> menu_button,
|
||||
const CefPoint& screen_point,
|
||||
CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
const int id = menu_button->GetID();
|
||||
if (id >= ID_EXTENSION_BUTTON_FIRST && id <= ID_EXTENSION_BUTTON_LAST) {
|
||||
const size_t extension_idx = id - ID_EXTENSION_BUTTON_FIRST;
|
||||
if (extension_idx >= extensions_.size()) {
|
||||
LOG(ERROR) << "Invalid extension index " << extension_idx;
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep the button pressed until the extension window is closed.
|
||||
extension_button_pressed_lock_ = button_pressed_lock;
|
||||
|
||||
// Create a window for the extension.
|
||||
delegate_->CreateExtensionWindow(
|
||||
extensions_[extension_idx].extension_, menu_button->GetBoundsInScreen(),
|
||||
window_, base::Bind(&ViewsWindow::OnExtensionWindowClosed, this));
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(with_controls_);
|
||||
DCHECK_EQ(ID_MENU_BUTTON, menu_button->GetID());
|
||||
DCHECK_EQ(ID_MENU_BUTTON, id);
|
||||
|
||||
menu_button->ShowMenu(button_menu_model_, screen_point,
|
||||
CEF_MENU_ANCHOR_TOPRIGHT);
|
||||
@@ -399,15 +498,16 @@ void ViewsWindow::OnWindowCreated(CefRefPtr<CefWindow> window) {
|
||||
// Add the BrowserView as the only child of the Window.
|
||||
window_->AddChildView(browser_view_);
|
||||
|
||||
// Choose a reasonable minimum window size.
|
||||
minimum_window_size_ = CefSize(100, 100);
|
||||
if (!delegate_->WithExtension()) {
|
||||
// Choose a reasonable minimum window size.
|
||||
minimum_window_size_ = CefSize(100, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// Show the Window.
|
||||
window_->Show();
|
||||
|
||||
// Give keyboard focus to the BrowserView.
|
||||
browser_view_->RequestFocus();
|
||||
if (!delegate_->InitiallyHidden()) {
|
||||
// Show the Window.
|
||||
Show();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsWindow::OnWindowDestroyed(CefRefPtr<CefWindow> window) {
|
||||
@@ -422,6 +522,7 @@ void ViewsWindow::OnWindowDestroyed(CefRefPtr<CefWindow> window) {
|
||||
top_menu_bar_->Reset();
|
||||
top_menu_bar_ = NULL;
|
||||
}
|
||||
extensions_panel_ = NULL;
|
||||
window_ = NULL;
|
||||
}
|
||||
|
||||
@@ -435,11 +536,32 @@ bool ViewsWindow::CanClose(CefRefPtr<CefWindow> window) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CefRefPtr<CefWindow> ViewsWindow::GetParentWindow(CefRefPtr<CefWindow> window,
|
||||
bool* is_menu,
|
||||
bool* can_activate_menu) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
CefRefPtr<CefWindow> parent_window = delegate_->GetParentWindow();
|
||||
if (parent_window) {
|
||||
// Should be an extension window, in which case we want it to behave as a
|
||||
// menu and allow activation.
|
||||
DCHECK(delegate_->WithExtension());
|
||||
*is_menu = true;
|
||||
*can_activate_menu = true;
|
||||
}
|
||||
return parent_window;
|
||||
}
|
||||
|
||||
bool ViewsWindow::IsFrameless(CefRefPtr<CefWindow> window) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
return frameless_;
|
||||
}
|
||||
|
||||
bool ViewsWindow::CanResize(CefRefPtr<CefWindow> window) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
// Don't allow windows hosting extensions to resize.
|
||||
return !delegate_->WithExtension();
|
||||
}
|
||||
|
||||
bool ViewsWindow::OnAccelerator(CefRefPtr<CefWindow> window, int command_id) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
@@ -455,7 +577,17 @@ bool ViewsWindow::OnKeyEvent(CefRefPtr<CefWindow> window,
|
||||
const CefKeyEvent& event) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!window_ || !with_controls_)
|
||||
if (!window_)
|
||||
return false;
|
||||
|
||||
if (delegate_->WithExtension() && event.type == KEYEVENT_RAWKEYDOWN &&
|
||||
event.windows_key_code == VK_ESCAPE) {
|
||||
// Close the extension window on escape.
|
||||
Close(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!with_controls_)
|
||||
return false;
|
||||
|
||||
if (event.type == KEYEVENT_RAWKEYDOWN && event.windows_key_code == VK_MENU) {
|
||||
@@ -509,6 +641,19 @@ void ViewsWindow::OnFocus(CefRefPtr<CefView> view) {
|
||||
SetMenuFocusable(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (view_id == ID_BROWSER_VIEW)
|
||||
delegate_->OnViewsWindowActivated(this);
|
||||
}
|
||||
|
||||
void ViewsWindow::OnBlur(CefRefPtr<CefView> view) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
const int view_id = view->GetID();
|
||||
if (view_id == ID_BROWSER_VIEW && delegate_->WithExtension()) {
|
||||
// Close windows hosting extensions when the browser loses focus.
|
||||
Close(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsWindow::MenuBarExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
|
||||
@@ -529,7 +674,8 @@ ViewsWindow::ViewsWindow(Delegate* delegate,
|
||||
|
||||
CefRefPtr<CefCommandLine> command_line =
|
||||
CefCommandLine::GetGlobalCommandLine();
|
||||
frameless_ = command_line->HasSwitch(switches::kHideFrame);
|
||||
frameless_ = command_line->HasSwitch(switches::kHideFrame) ||
|
||||
delegate_->WithExtension();
|
||||
|
||||
if (!command_line->HasSwitch(switches::kHideTopMenu)) {
|
||||
top_menu_bar_ = new ViewsMenuBar(this, ID_TOP_MENU_FIRST);
|
||||
@@ -609,7 +755,9 @@ void ViewsWindow::AddControls() {
|
||||
CefRefPtr<CefMenuButton> menu_button =
|
||||
CefMenuButton::CreateMenuButton(this, CefString(), false, false);
|
||||
menu_button->SetID(ID_MENU_BUTTON);
|
||||
menu_button->SetImage(CEF_BUTTON_STATE_NORMAL, LoadImageIcon("menu_icon"));
|
||||
menu_button->SetImage(
|
||||
CEF_BUTTON_STATE_NORMAL,
|
||||
delegate_->GetImageCache()->GetCachedImage("menu_icon"));
|
||||
views_style::ApplyTo(menu_button.get());
|
||||
menu_button->SetInkDropEnabled(true);
|
||||
// Override the default minimum size.
|
||||
@@ -628,6 +776,11 @@ void ViewsWindow::AddControls() {
|
||||
for (size_t i = 0U; i < browse_buttons.size(); ++i)
|
||||
top_panel->AddChildView(browse_buttons[i]);
|
||||
top_panel->AddChildView(url_textfield);
|
||||
|
||||
UpdateExtensionControls();
|
||||
DCHECK(extensions_panel_);
|
||||
top_panel->AddChildView(extensions_panel_);
|
||||
|
||||
top_panel->AddChildView(menu_button);
|
||||
views_style::ApplyTo(top_panel);
|
||||
|
||||
@@ -718,4 +871,84 @@ void ViewsWindow::ShowTopControls(bool show) {
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsWindow::UpdateExtensionControls() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!window_ || !with_controls_)
|
||||
return;
|
||||
|
||||
if (!extensions_panel_) {
|
||||
extensions_panel_ = CefPanel::CreatePanel(NULL);
|
||||
|
||||
// Use a horizontal box layout for |top_panel|.
|
||||
CefBoxLayoutSettings top_panel_layout_settings;
|
||||
top_panel_layout_settings.horizontal = true;
|
||||
CefRefPtr<CefBoxLayout> top_panel_layout =
|
||||
extensions_panel_->SetToBoxLayout(top_panel_layout_settings);
|
||||
} else {
|
||||
extensions_panel_->RemoveAllChildViews();
|
||||
}
|
||||
|
||||
if (extensions_.size() >
|
||||
ID_EXTENSION_BUTTON_LAST - ID_EXTENSION_BUTTON_FIRST) {
|
||||
LOG(WARNING) << "Too many extensions loaded. Some will be ignored.";
|
||||
}
|
||||
|
||||
ExtensionInfoSet::const_iterator it = extensions_.begin();
|
||||
for (int id = ID_EXTENSION_BUTTON_FIRST;
|
||||
it != extensions_.end() && id <= ID_EXTENSION_BUTTON_LAST; ++id, ++it) {
|
||||
CefRefPtr<CefMenuButton> button =
|
||||
CefMenuButton::CreateMenuButton(this, CefString(), false, false);
|
||||
button->SetID(id);
|
||||
button->SetImage(CEF_BUTTON_STATE_NORMAL, (*it).image_);
|
||||
views_style::ApplyTo(button.get());
|
||||
button->SetInkDropEnabled(true);
|
||||
// Override the default minimum size.
|
||||
button->SetMinimumSize(CefSize(0, 0));
|
||||
|
||||
extensions_panel_->AddChildView(button);
|
||||
}
|
||||
|
||||
CefRefPtr<CefView> parent_view = extensions_panel_->GetParentView();
|
||||
if (parent_view)
|
||||
parent_view->InvalidateLayout();
|
||||
}
|
||||
|
||||
void ViewsWindow::OnExtensionIconsLoaded(const ExtensionSet& extensions,
|
||||
const ImageCache::ImageSet& images) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
// Execute this method on the UI thread.
|
||||
CefPostTask(TID_UI, base::Bind(&ViewsWindow::OnExtensionIconsLoaded, this,
|
||||
extensions, images));
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK_EQ(extensions.size(), images.size());
|
||||
|
||||
extensions_.clear();
|
||||
|
||||
ExtensionSet::const_iterator it1 = extensions.begin();
|
||||
ImageCache::ImageSet::const_iterator it2 = images.begin();
|
||||
for (; it1 != extensions.end() && it2 != images.end(); ++it1, ++it2) {
|
||||
CefRefPtr<CefImage> icon = *it2;
|
||||
if (!icon)
|
||||
icon = delegate_->GetImageCache()->GetCachedImage(kDefaultExtensionIcon);
|
||||
extensions_.push_back(ExtensionInfo(*it1, icon));
|
||||
}
|
||||
|
||||
UpdateExtensionControls();
|
||||
}
|
||||
|
||||
void ViewsWindow::OnExtensionWindowClosed() {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
// Execute this method on the UI thread.
|
||||
CefPostTask(TID_UI,
|
||||
base::Bind(&ViewsWindow::OnExtensionWindowClosed, this));
|
||||
return;
|
||||
}
|
||||
|
||||
// Restore the button state.
|
||||
extension_button_pressed_lock_ = NULL;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
@@ -6,8 +6,11 @@
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_WINDOW_H_
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "include/base/cef_callback_forward.h"
|
||||
#include "include/cef_menu_model_delegate.h"
|
||||
#include "include/views/cef_browser_view.h"
|
||||
#include "include/views/cef_browser_view_delegate.h"
|
||||
@@ -19,10 +22,13 @@
|
||||
#include "include/views/cef_textfield_delegate.h"
|
||||
#include "include/views/cef_window.h"
|
||||
#include "include/views/cef_window_delegate.h"
|
||||
#include "tests/cefclient/browser/image_cache.h"
|
||||
#include "tests/cefclient/browser/views_menu_bar.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
typedef std::set<CefRefPtr<CefExtension>> ExtensionSet;
|
||||
|
||||
// Implements a CefWindow that hosts a single CefBrowserView and optional
|
||||
// Views-based controls. All methods must be called on the browser process UI
|
||||
// thread.
|
||||
@@ -39,9 +45,21 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
// Return true if the window should show controls.
|
||||
virtual bool WithControls() = 0;
|
||||
|
||||
// Return true if the window is hosting an extension.
|
||||
virtual bool WithExtension() = 0;
|
||||
|
||||
// Return true if the window should be created initially hidden.
|
||||
virtual bool InitiallyHidden() = 0;
|
||||
|
||||
// Returns the parent for this window.
|
||||
virtual CefRefPtr<CefWindow> GetParentWindow() = 0;
|
||||
|
||||
// Return the initial window bounds.
|
||||
virtual CefRect GetWindowBounds() = 0;
|
||||
|
||||
// Returns the ImageCache.
|
||||
virtual scoped_refptr<ImageCache> GetImageCache() = 0;
|
||||
|
||||
// Called when the ViewsWindow is created.
|
||||
virtual void OnViewsWindowCreated(CefRefPtr<ViewsWindow> window) = 0;
|
||||
|
||||
@@ -49,9 +67,19 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
// should be released in this callback.
|
||||
virtual void OnViewsWindowDestroyed(CefRefPtr<ViewsWindow> window) = 0;
|
||||
|
||||
// Called when the ViewsWindow is activated (becomes the foreground window).
|
||||
virtual void OnViewsWindowActivated(CefRefPtr<ViewsWindow> window) = 0;
|
||||
|
||||
// Return the Delegate for the popup window controlled by |client|.
|
||||
virtual Delegate* GetDelegateForPopup(CefRefPtr<CefClient> client) = 0;
|
||||
|
||||
// Create a window for |extension|. |source_bounds| are the bounds of the
|
||||
// UI element, like a button, that triggered the extension.
|
||||
virtual void CreateExtensionWindow(CefRefPtr<CefExtension> extension,
|
||||
const CefRect& source_bounds,
|
||||
CefRefPtr<CefWindow> parent_window,
|
||||
const base::Closure& close_callback) = 0;
|
||||
|
||||
// Called to execute a test. See resource.h for |test_id| values.
|
||||
virtual void OnTest(int test_id) = 0;
|
||||
|
||||
@@ -76,6 +104,9 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
void Minimize();
|
||||
void Maximize();
|
||||
void SetBounds(const CefRect& bounds);
|
||||
void SetBrowserSize(const CefSize& size,
|
||||
bool has_position,
|
||||
const CefPoint& position);
|
||||
void Close(bool force);
|
||||
void SetAddress(const std::string& url);
|
||||
void SetTitle(const std::string& title);
|
||||
@@ -85,8 +116,14 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
void SetDraggableRegions(const std::vector<CefDraggableRegion>& regions);
|
||||
void TakeFocus(bool next);
|
||||
void OnBeforeContextMenu(CefRefPtr<CefMenuModel> model);
|
||||
void OnExtensionsChanged(const ExtensionSet& extensions);
|
||||
|
||||
// CefBrowserViewDelegate methods:
|
||||
CefRefPtr<CefBrowserViewDelegate> GetDelegateForPopupBrowserView(
|
||||
CefRefPtr<CefBrowserView> browser_view,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefClient> client,
|
||||
bool is_devtools) OVERRIDE;
|
||||
bool OnPopupBrowserViewCreated(CefRefPtr<CefBrowserView> browser_view,
|
||||
CefRefPtr<CefBrowserView> popup_browser_view,
|
||||
bool is_devtools) OVERRIDE;
|
||||
@@ -95,8 +132,10 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
void OnButtonPressed(CefRefPtr<CefButton> button) OVERRIDE;
|
||||
|
||||
// CefMenuButtonDelegate methods:
|
||||
void OnMenuButtonPressed(CefRefPtr<CefMenuButton> menu_button,
|
||||
const CefPoint& screen_point) OVERRIDE;
|
||||
void OnMenuButtonPressed(
|
||||
CefRefPtr<CefMenuButton> menu_button,
|
||||
const CefPoint& screen_point,
|
||||
CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) OVERRIDE;
|
||||
|
||||
// CefMenuModelDelegate methods:
|
||||
void ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
|
||||
@@ -110,7 +149,11 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
// CefWindowDelegate methods:
|
||||
void OnWindowCreated(CefRefPtr<CefWindow> window) OVERRIDE;
|
||||
void OnWindowDestroyed(CefRefPtr<CefWindow> window) OVERRIDE;
|
||||
CefRefPtr<CefWindow> GetParentWindow(CefRefPtr<CefWindow> window,
|
||||
bool* is_menu,
|
||||
bool* can_activate_menu) OVERRIDE;
|
||||
bool IsFrameless(CefRefPtr<CefWindow> window) OVERRIDE;
|
||||
bool CanResize(CefRefPtr<CefWindow> window) OVERRIDE;
|
||||
bool CanClose(CefRefPtr<CefWindow> window) OVERRIDE;
|
||||
bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) OVERRIDE;
|
||||
bool OnKeyEvent(CefRefPtr<CefWindow> window,
|
||||
@@ -119,6 +162,7 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
// CefViewDelegate methods:
|
||||
CefSize GetMinimumSize(CefRefPtr<CefView> view) OVERRIDE;
|
||||
void OnFocus(CefRefPtr<CefView> view) OVERRIDE;
|
||||
void OnBlur(CefRefPtr<CefView> view) OVERRIDE;
|
||||
|
||||
// ViewsMenuBar::Delegate methods:
|
||||
void MenuBarExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
|
||||
@@ -152,6 +196,13 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
// Show/hide top controls on the Window.
|
||||
void ShowTopControls(bool show);
|
||||
|
||||
// Update extension controls on the Window.
|
||||
void UpdateExtensionControls();
|
||||
|
||||
void OnExtensionIconsLoaded(const ExtensionSet& extensions,
|
||||
const ImageCache::ImageSet& images);
|
||||
void OnExtensionWindowClosed();
|
||||
|
||||
Delegate* delegate_; // Not owned by this object.
|
||||
CefRefPtr<CefBrowserView> browser_view_;
|
||||
bool frameless_;
|
||||
@@ -165,6 +216,20 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
|
||||
CefSize minimum_window_size_;
|
||||
|
||||
// Structure representing an extension.
|
||||
struct ExtensionInfo {
|
||||
ExtensionInfo(CefRefPtr<CefExtension> extension, CefRefPtr<CefImage> image)
|
||||
: extension_(extension), image_(image) {}
|
||||
|
||||
CefRefPtr<CefExtension> extension_;
|
||||
CefRefPtr<CefImage> image_;
|
||||
};
|
||||
typedef std::vector<ExtensionInfo> ExtensionInfoSet;
|
||||
|
||||
ExtensionInfoSet extensions_;
|
||||
CefRefPtr<CefPanel> extensions_panel_;
|
||||
CefRefPtr<CefMenuButtonPressedLock> extension_button_pressed_lock_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ViewsWindow);
|
||||
DISALLOW_COPY_AND_ASSIGN(ViewsWindow);
|
||||
};
|
||||
|
Reference in New Issue
Block a user