mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
129 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c07b9c85b | ||
|
|
1199224086 | ||
|
|
add4e3c6f5 | ||
|
|
eb55f1cf47 | ||
|
|
8367071dc6 | ||
|
|
68ac6b0cbb | ||
|
|
7fb1cb5b3d | ||
|
|
19b25c0d83 | ||
|
|
fd806f81ce | ||
|
|
d515404abd | ||
|
|
4509056d5e | ||
|
|
f604525b98 | ||
|
|
3afbb66b92 | ||
|
|
fadfd74923 | ||
|
|
222f8e1028 | ||
|
|
e3b6ea62d6 | ||
|
|
3795cc58b0 | ||
|
|
ed7d430f2b | ||
|
|
20f21b707b | ||
|
|
a584ca3678 | ||
|
|
ca881c5aaf | ||
|
|
2832708618 | ||
|
|
b00e56f587 | ||
|
|
d64f43da65 | ||
|
|
3e6d8ddbbd | ||
|
|
533548fdc7 | ||
|
|
3b95f49a14 | ||
|
|
d9d1d03d4d | ||
|
|
9546120ce4 | ||
|
|
48a5591508 | ||
|
|
a413935e91 | ||
|
|
241b07f763 | ||
|
|
d874ba80db | ||
|
|
3e46363ae1 | ||
|
|
d4a46fa35f | ||
|
|
134f8236cc | ||
|
|
55003716aa | ||
|
|
fe88330e87 | ||
|
|
ed68bd18b8 | ||
|
|
45228493eb | ||
|
|
80fb44b926 | ||
|
|
aa8f5e54df | ||
|
|
8134585578 | ||
|
|
a59388ecdd | ||
|
|
8051ad8b2a | ||
|
|
0a937cd2be | ||
|
|
db11c631f6 | ||
|
|
90bfd4bf0f | ||
|
|
39b98b0e4d | ||
|
|
b6c2e7ef76 | ||
|
|
fe96a9de33 | ||
|
|
b80f109524 | ||
|
|
cd40bdbec8 | ||
|
|
1533600720 | ||
|
|
263c4b9ab4 | ||
|
|
f1e72914f5 | ||
|
|
400d5cef3f | ||
|
|
af531d685e | ||
|
|
eb5f1f78bf | ||
|
|
c81a4bcafc | ||
|
|
1beeda170c | ||
|
|
9ad81c054d | ||
|
|
5604e75886 | ||
|
|
2e7ef7ea44 | ||
|
|
a0867fa7c5 | ||
|
|
31f5855001 | ||
|
|
0b24883649 | ||
|
|
4fda81a0b4 | ||
|
|
17c0888932 | ||
|
|
d20ec6952a | ||
|
|
e43b3309af | ||
|
|
d0c1b63064 | ||
|
|
a98e26a307 | ||
|
|
57d06c5241 | ||
|
|
f28e4574b0 | ||
|
|
c9b284d7f7 | ||
|
|
99a510701d | ||
|
|
eb3ecab6a8 | ||
|
|
11b9a06639 | ||
|
|
87d5b72b76 | ||
|
|
c95869e515 | ||
|
|
c2f7920068 | ||
|
|
cb7196a9c1 | ||
|
|
7de0f71a75 | ||
|
|
8dcb3726f9 | ||
|
|
d934526bb3 | ||
|
|
cab546cbb7 | ||
|
|
058d0bbe19 | ||
|
|
a32669ac0d | ||
|
|
cc4b3e9e6f | ||
|
|
fdcad1066e | ||
|
|
41d43920f9 | ||
|
|
fecc90e67c | ||
|
|
6e3b3fa5a2 | ||
|
|
c12c0363a0 | ||
|
|
1207dfde4c | ||
|
|
0f617c3d3c | ||
|
|
7b71ae6824 | ||
|
|
cfae3cd3af | ||
|
|
f470d21a55 | ||
|
|
af0a5744f2 | ||
|
|
2bcb7393c4 | ||
|
|
60dcb0e67f | ||
|
|
c88b691db7 | ||
|
|
27f07974e0 | ||
|
|
a840799b46 | ||
|
|
c8ef79817a | ||
|
|
29abba824d | ||
|
|
6ccec45c61 | ||
|
|
1dabd20d99 | ||
|
|
fedb08899c | ||
|
|
b8bfe8a9ad | ||
|
|
a230daa998 | ||
|
|
ba41634ad6 | ||
|
|
e9536508a5 | ||
|
|
965f2b1b6b | ||
|
|
e25417ab31 | ||
|
|
48c227c263 | ||
|
|
cbd6541e9a | ||
|
|
2a9f5a5fb8 | ||
|
|
78afa29ade | ||
|
|
73bb05e530 | ||
|
|
8cc23aca8d | ||
|
|
f96c6e4bd7 | ||
|
|
3afb4e017c | ||
|
|
54ee12308d | ||
|
|
e9879a3e4b | ||
|
|
dec05988f4 | ||
|
|
be6599807d |
@@ -10,3 +10,6 @@ notifications:
|
||||
on_failure: change
|
||||
|
||||
script: './script/cibuild'
|
||||
|
||||
git:
|
||||
depth: 10
|
||||
|
||||
45
atom.gyp
45
atom.gyp
@@ -28,6 +28,7 @@
|
||||
'atom/browser/api/lib/protocol.coffee',
|
||||
'atom/browser/api/lib/tray.coffee',
|
||||
'atom/browser/api/lib/web-contents.coffee',
|
||||
'atom/browser/lib/chrome-extension.coffee',
|
||||
'atom/browser/lib/init.coffee',
|
||||
'atom/browser/lib/objects-registry.coffee',
|
||||
'atom/browser/lib/rpc-server.coffee',
|
||||
@@ -38,6 +39,7 @@
|
||||
'atom/common/api/lib/screen.coffee',
|
||||
'atom/common/api/lib/shell.coffee',
|
||||
'atom/common/lib/init.coffee',
|
||||
'atom/renderer/lib/chrome-api.coffee',
|
||||
'atom/renderer/lib/init.coffee',
|
||||
'atom/renderer/lib/inspector.coffee',
|
||||
'atom/renderer/lib/override.coffee',
|
||||
@@ -46,6 +48,8 @@
|
||||
'atom/renderer/api/lib/web-view.coffee',
|
||||
],
|
||||
'lib_sources': [
|
||||
'atom/app/atom_content_client.cc',
|
||||
'atom/app/atom_content_client.h',
|
||||
'atom/app/atom_main_delegate.cc',
|
||||
'atom/app/atom_main_delegate.h',
|
||||
'atom/app/atom_main_delegate_mac.mm',
|
||||
@@ -121,6 +125,8 @@
|
||||
'atom/browser/net/atom_url_request_job_factory.h',
|
||||
'atom/browser/net/url_request_string_job.cc',
|
||||
'atom/browser/net/url_request_string_job.h',
|
||||
'atom/browser/node_debugger.cc',
|
||||
'atom/browser/node_debugger.h',
|
||||
'atom/browser/ui/accelerator_util.cc',
|
||||
'atom/browser/ui/accelerator_util.h',
|
||||
'atom/browser/ui/accelerator_util_mac.mm',
|
||||
@@ -154,16 +160,19 @@
|
||||
'atom/browser/ui/views/menu_delegate.h',
|
||||
'atom/browser/ui/views/menu_layout.cc',
|
||||
'atom/browser/ui/views/menu_layout.h',
|
||||
'atom/browser/ui/views/submenu_button.cc',
|
||||
'atom/browser/ui/views/submenu_button.h',
|
||||
'atom/browser/ui/views/win_frame_view.cc',
|
||||
'atom/browser/ui/views/win_frame_view.h',
|
||||
'atom/browser/ui/win/notify_icon_host.cc',
|
||||
'atom/browser/ui/win/notify_icon_host.h',
|
||||
'atom/browser/ui/win/notify_icon.cc',
|
||||
'atom/browser/ui/win/notify_icon.h',
|
||||
'atom/browser/ui/x/x_window_utils.cc',
|
||||
'atom/browser/ui/x/x_window_utils.h',
|
||||
'atom/browser/window_list.cc',
|
||||
'atom/browser/window_list.h',
|
||||
'atom/browser/window_list_observer.h',
|
||||
'atom/common/api/api_messages.cc',
|
||||
'atom/common/api/api_messages.h',
|
||||
'atom/common/api/atom_api_clipboard.cc',
|
||||
'atom/common/api/atom_api_crash_reporter.cc',
|
||||
@@ -177,6 +186,8 @@
|
||||
'atom/common/api/atom_bindings.h',
|
||||
'atom/common/api/object_life_monitor.cc',
|
||||
'atom/common/api/object_life_monitor.h',
|
||||
'atom/common/common_message_generator.cc',
|
||||
'atom/common/common_message_generator.h',
|
||||
'atom/common/crash_reporter/crash_reporter.cc',
|
||||
'atom/common/crash_reporter/crash_reporter.h',
|
||||
'atom/common/crash_reporter/crash_reporter_linux.cc',
|
||||
@@ -229,6 +240,9 @@
|
||||
'atom/renderer/atom_render_view_observer.h',
|
||||
'atom/renderer/atom_renderer_client.cc',
|
||||
'atom/renderer/atom_renderer_client.h',
|
||||
'chromium_src/chrome/browser/browser_process.cc',
|
||||
'chromium_src/chrome/browser/browser_process.h',
|
||||
'chromium_src/chrome/browser/chrome_notification_types.h',
|
||||
'chromium_src/chrome/browser/extensions/global_shortcut_listener.cc',
|
||||
'chromium_src/chrome/browser/extensions/global_shortcut_listener.h',
|
||||
'chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.mm',
|
||||
@@ -237,6 +251,24 @@
|
||||
'chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.h',
|
||||
'chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc',
|
||||
'chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h',
|
||||
'chromium_src/chrome/browser/printing/print_job.cc',
|
||||
'chromium_src/chrome/browser/printing/print_job.h',
|
||||
'chromium_src/chrome/browser/printing/print_job_manager.cc',
|
||||
'chromium_src/chrome/browser/printing/print_job_manager.h',
|
||||
'chromium_src/chrome/browser/printing/print_job_worker.cc',
|
||||
'chromium_src/chrome/browser/printing/print_job_worker.h',
|
||||
'chromium_src/chrome/browser/printing/print_job_worker_owner.h',
|
||||
'chromium_src/chrome/browser/printing/print_view_manager_base.cc',
|
||||
'chromium_src/chrome/browser/printing/print_view_manager_base.h',
|
||||
'chromium_src/chrome/browser/printing/print_view_manager_basic.cc',
|
||||
'chromium_src/chrome/browser/printing/print_view_manager_basic.h',
|
||||
'chromium_src/chrome/browser/printing/print_view_manager_observer.h',
|
||||
'chromium_src/chrome/browser/printing/printer_query.cc',
|
||||
'chromium_src/chrome/browser/printing/printer_query.h',
|
||||
'chromium_src/chrome/browser/printing/printing_message_filter.cc',
|
||||
'chromium_src/chrome/browser/printing/printing_message_filter.h',
|
||||
'chromium_src/chrome/browser/printing/printing_ui_web_contents_observer.cc',
|
||||
'chromium_src/chrome/browser/printing/printing_ui_web_contents_observer.h',
|
||||
'chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.cc',
|
||||
'chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h',
|
||||
'chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.cc',
|
||||
@@ -245,6 +277,13 @@
|
||||
'chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h',
|
||||
'chromium_src/chrome/browser/ui/views/status_icons/status_tray_state_changer_win.cc',
|
||||
'chromium_src/chrome/browser/ui/views/status_icons/status_tray_state_changer_win.h',
|
||||
'chromium_src/chrome/common/print_messages.cc',
|
||||
'chromium_src/chrome/common/print_messages.h',
|
||||
'chromium_src/chrome/renderer/printing/print_web_view_helper.cc',
|
||||
'chromium_src/chrome/renderer/printing/print_web_view_helper_linux.cc',
|
||||
'chromium_src/chrome/renderer/printing/print_web_view_helper_mac.mm',
|
||||
'chromium_src/chrome/renderer/printing/print_web_view_helper_win.cc',
|
||||
'chromium_src/chrome/renderer/printing/print_web_view_helper.h',
|
||||
'<@(native_mate_files)',
|
||||
],
|
||||
'framework_sources': [
|
||||
@@ -435,6 +474,10 @@
|
||||
'vendor/brightray/brightray.gyp:brightray',
|
||||
'vendor/node/node.gyp:node_lib',
|
||||
],
|
||||
'defines': [
|
||||
# This is defined in skia/skia_common.gypi.
|
||||
'SK_SUPPORT_LEGACY_GETTOPDEVICE',
|
||||
],
|
||||
'sources': [
|
||||
'<@(lib_sources)',
|
||||
],
|
||||
|
||||
24
atom/app/atom_content_client.cc
Normal file
24
atom/app/atom_content_client.cc
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/app/atom_content_client.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace atom {
|
||||
|
||||
AtomContentClient::AtomContentClient() {
|
||||
}
|
||||
|
||||
AtomContentClient::~AtomContentClient() {
|
||||
}
|
||||
|
||||
void AtomContentClient::AddAdditionalSchemes(
|
||||
std::vector<std::string>* standard_schemes,
|
||||
std::vector<std::string>* savable_schemes) {
|
||||
standard_schemes->push_back("chrome-extension");
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
32
atom/app/atom_content_client.h
Normal file
32
atom/app/atom_content_client.h
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_APP_ATOM_CONTENT_CLIENT_H_
|
||||
#define ATOM_APP_ATOM_CONTENT_CLIENT_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "brightray/common/content_client.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomContentClient : public brightray::ContentClient {
|
||||
public:
|
||||
AtomContentClient();
|
||||
virtual ~AtomContentClient();
|
||||
|
||||
protected:
|
||||
// content::ContentClient:
|
||||
virtual void AddAdditionalSchemes(
|
||||
std::vector<std::string>* standard_schemes,
|
||||
std::vector<std::string>* savable_schemes) OVERRIDE;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomContentClient);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_APP_ATOM_CONTENT_CLIENT_H_
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "atom/app/atom_main_delegate.h"
|
||||
#include "atom/common/crash_reporter/win/crash_service_main.h"
|
||||
#include "base/environment.h"
|
||||
#include "base/win/registry.h"
|
||||
#include "content/public/app/startup_helper_win.h"
|
||||
#include "sandbox/win/src/sandbox_types.h"
|
||||
#include "ui/gfx/win/dpi.h"
|
||||
@@ -36,13 +35,6 @@ int Start(int argc, char *argv[]);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
||||
namespace {
|
||||
|
||||
const wchar_t kRegistryProfilePath[] = L"SOFTWARE\\Google\\Chrome\\Profile";
|
||||
const wchar_t kHighDPISupportW[] = L"high-dpi-support";
|
||||
|
||||
} // namespace
|
||||
|
||||
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
int argc = 0;
|
||||
wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||
@@ -109,10 +101,6 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
atom::AtomMainDelegate delegate;
|
||||
|
||||
// Now chrome relies on a regkey to enable high dpi support.
|
||||
base::win::RegKey high_dpi_key(HKEY_CURRENT_USER);
|
||||
high_dpi_key.CreateKey(kRegistryProfilePath, KEY_SET_VALUE);
|
||||
high_dpi_key.WriteValue(kHighDPISupportW, 1);
|
||||
|
||||
gfx::EnableHighDPISupport();
|
||||
|
||||
content::ContentMainParams params(&delegate);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/app/atom_content_client.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/renderer/atom_renderer_client.h"
|
||||
#include "base/command_line.h"
|
||||
@@ -22,18 +23,6 @@ AtomMainDelegate::AtomMainDelegate() {
|
||||
AtomMainDelegate::~AtomMainDelegate() {
|
||||
}
|
||||
|
||||
void AtomMainDelegate::AddDataPackFromPath(
|
||||
ui::ResourceBundle* bundle, const base::FilePath& pak_dir) {
|
||||
#if defined(OS_WIN)
|
||||
bundle->AddDataPackFromPath(
|
||||
pak_dir.Append(FILE_PATH_LITERAL("ui_resources_200_percent.pak")),
|
||||
ui::SCALE_FACTOR_200P);
|
||||
bundle->AddDataPackFromPath(
|
||||
pak_dir.Append(FILE_PATH_LITERAL("webkit_resources_200_percent.pak")),
|
||||
ui::SCALE_FACTOR_200P);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
// Disable logging out to debug.log on Windows
|
||||
#if defined(OS_WIN)
|
||||
@@ -99,4 +88,20 @@ content::ContentRendererClient*
|
||||
return renderer_client_.get();
|
||||
}
|
||||
|
||||
scoped_ptr<brightray::ContentClient> AtomMainDelegate::CreateContentClient() {
|
||||
return scoped_ptr<brightray::ContentClient>(new AtomContentClient).Pass();
|
||||
}
|
||||
|
||||
void AtomMainDelegate::AddDataPackFromPath(
|
||||
ui::ResourceBundle* bundle, const base::FilePath& pak_dir) {
|
||||
#if defined(OS_WIN)
|
||||
bundle->AddDataPackFromPath(
|
||||
pak_dir.Append(FILE_PATH_LITERAL("ui_resources_200_percent.pak")),
|
||||
ui::SCALE_FACTOR_200P);
|
||||
bundle->AddDataPackFromPath(
|
||||
pak_dir.Append(FILE_PATH_LITERAL("webkit_resources_200_percent.pak")),
|
||||
ui::SCALE_FACTOR_200P);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -16,24 +16,23 @@ class AtomMainDelegate : public brightray::MainDelegate {
|
||||
~AtomMainDelegate();
|
||||
|
||||
protected:
|
||||
// brightray::MainDelegate:
|
||||
virtual void AddDataPackFromPath(
|
||||
ui::ResourceBundle* bundle, const base::FilePath& pak_dir) OVERRIDE;
|
||||
|
||||
// content::ContentMainDelegate:
|
||||
virtual bool BasicStartupComplete(int* exit_code) OVERRIDE;
|
||||
virtual void PreSandboxStartup() OVERRIDE;
|
||||
virtual content::ContentBrowserClient* CreateContentBrowserClient() OVERRIDE;
|
||||
virtual content::ContentRendererClient*
|
||||
CreateContentRendererClient() OVERRIDE;
|
||||
|
||||
// brightray::MainDelegate:
|
||||
virtual scoped_ptr<brightray::ContentClient> CreateContentClient() OVERRIDE;
|
||||
virtual void AddDataPackFromPath(
|
||||
ui::ResourceBundle* bundle, const base::FilePath& pak_dir) OVERRIDE;
|
||||
#if defined(OS_MACOSX)
|
||||
virtual void OverrideChildProcessPath() OVERRIDE;
|
||||
virtual void OverrideFrameworkBundlePath() OVERRIDE;
|
||||
#endif
|
||||
|
||||
private:
|
||||
virtual content::ContentBrowserClient* CreateContentBrowserClient() OVERRIDE;
|
||||
virtual content::ContentRendererClient*
|
||||
CreateContentRendererClient() OVERRIDE;
|
||||
|
||||
brightray::ContentClient content_client_;
|
||||
scoped_ptr<content::ContentBrowserClient> browser_client_;
|
||||
scoped_ptr<content::ContentRendererClient> renderer_client_;
|
||||
|
||||
@@ -5,21 +5,76 @@
|
||||
#include "atom/browser/api/atom_api_app.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "base/values.h"
|
||||
#include "base/command_line.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "base/environment.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/path_service.h"
|
||||
#include "native_mate/callback.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "net/proxy/proxy_service.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
#include "base/nix/xdg_util.h"
|
||||
#endif
|
||||
|
||||
using atom::Browser;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
class ResolveProxyHelper {
|
||||
public:
|
||||
ResolveProxyHelper(const GURL& url, App::ResolveProxyCallback callback)
|
||||
: callback_(callback) {
|
||||
net::ProxyService* proxy_service = AtomBrowserContext::Get()->
|
||||
url_request_context_getter()->GetURLRequestContext()->proxy_service();
|
||||
|
||||
// Start the request.
|
||||
int result = proxy_service->ResolveProxy(
|
||||
url, &proxy_info_,
|
||||
base::Bind(&ResolveProxyHelper::OnResolveProxyCompleted,
|
||||
base::Unretained(this)),
|
||||
&pac_req_, net::BoundNetLog());
|
||||
|
||||
// Completed synchronously.
|
||||
if (result != net::ERR_IO_PENDING)
|
||||
OnResolveProxyCompleted(result);
|
||||
}
|
||||
|
||||
void OnResolveProxyCompleted(int result) {
|
||||
std::string proxy;
|
||||
if (result == net::OK)
|
||||
proxy = proxy_info_.ToPacString();
|
||||
callback_.Run(proxy);
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
App::ResolveProxyCallback callback_;
|
||||
net::ProxyInfo proxy_info_;
|
||||
net::ProxyService::PacRequest* pac_req_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ResolveProxyHelper);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
App::App() {
|
||||
Browser::Get()->AddObserver(this);
|
||||
}
|
||||
@@ -60,6 +115,25 @@ void App::OnFinishLaunching() {
|
||||
Emit("ready");
|
||||
}
|
||||
|
||||
base::FilePath App::GetDataPath() {
|
||||
base::FilePath path;
|
||||
#if defined(OS_LINUX)
|
||||
scoped_ptr<base::Environment> env(base::Environment::Create());
|
||||
path = base::nix::GetXDGDirectory(env.get(),
|
||||
base::nix::kXdgConfigHomeEnvVar,
|
||||
base::nix::kDotConfigDir);
|
||||
#else
|
||||
PathService::Get(base::DIR_APP_DATA, &path);
|
||||
#endif
|
||||
|
||||
return path.Append(base::FilePath::FromUTF8Unsafe(
|
||||
Browser::Get()->GetName()));
|
||||
}
|
||||
|
||||
void App::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
|
||||
new ResolveProxyHelper(url, callback);
|
||||
}
|
||||
|
||||
mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
Browser* browser = Browser::Get();
|
||||
@@ -75,7 +149,9 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
|
||||
.SetMethod("getName", base::Bind(&Browser::GetName,
|
||||
base::Unretained(browser)))
|
||||
.SetMethod("setName", base::Bind(&Browser::SetName,
|
||||
base::Unretained(browser)));
|
||||
base::Unretained(browser)))
|
||||
.SetMethod("getDataPath", &App::GetDataPath)
|
||||
.SetMethod("resolveProxy", &App::ResolveProxy);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -7,11 +7,17 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "atom/browser/browser_observer.h"
|
||||
#include "base/callback.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
class GURL;
|
||||
|
||||
namespace base {
|
||||
class FilePath;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
@@ -19,6 +25,8 @@ namespace api {
|
||||
class App : public mate::EventEmitter,
|
||||
public BrowserObserver {
|
||||
public:
|
||||
typedef base::Callback<void(std::string)> ResolveProxyCallback;
|
||||
|
||||
static mate::Handle<App> Create(v8::Isolate* isolate);
|
||||
|
||||
protected:
|
||||
@@ -40,6 +48,9 @@ class App : public mate::EventEmitter,
|
||||
v8::Isolate* isolate);
|
||||
|
||||
private:
|
||||
base::FilePath GetDataPath();
|
||||
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(App);
|
||||
};
|
||||
|
||||
|
||||
@@ -66,22 +66,13 @@ void GlobalShortcut::UnregisterAll() {
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerators(this);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::ObjectTemplateBuilder GlobalShortcut::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("register",
|
||||
base::Bind(&GlobalShortcut::Register,
|
||||
base::Unretained(this)))
|
||||
.SetMethod("isRegistered",
|
||||
base::Bind(&GlobalShortcut::IsRegistered,
|
||||
base::Unretained(this)))
|
||||
.SetMethod("unregister",
|
||||
base::Bind(&GlobalShortcut::Unregister,
|
||||
base::Unretained(this)))
|
||||
.SetMethod("unregisterAll",
|
||||
base::Bind(&GlobalShortcut::UnregisterAll,
|
||||
base::Unretained(this)));
|
||||
.SetMethod("register", &GlobalShortcut::Register)
|
||||
.SetMethod("isRegistered", &GlobalShortcut::IsRegistered)
|
||||
.SetMethod("unregister", &GlobalShortcut::Unregister)
|
||||
.SetMethod("unregisterAll", &GlobalShortcut::UnregisterAll);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -16,8 +16,30 @@
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace {
|
||||
|
||||
struct PrintSettings {
|
||||
bool silent;
|
||||
bool print_backgournd;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<PrintSettings> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
|
||||
PrintSettings* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
dict.Get("silent", &(out->silent));
|
||||
dict.Get("printBackground", &(out->print_backgournd));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<gfx::Rect> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
@@ -303,6 +325,22 @@ bool Window::IsWebViewFocused() {
|
||||
return window_->IsWebViewFocused();
|
||||
}
|
||||
|
||||
void Window::SetRepresentedFilename(const std::string& filename) {
|
||||
window_->SetRepresentedFilename(filename);
|
||||
}
|
||||
|
||||
std::string Window::GetRepresentedFilename() {
|
||||
return window_->GetRepresentedFilename();
|
||||
}
|
||||
|
||||
void Window::SetDocumentEdited(bool edited) {
|
||||
window_->SetDocumentEdited(edited);
|
||||
}
|
||||
|
||||
bool Window::IsDocumentEdited() {
|
||||
return window_->IsDocumentEdited();
|
||||
}
|
||||
|
||||
void Window::CapturePage(mate::Arguments* args) {
|
||||
gfx::Rect rect;
|
||||
base::Callback<void(v8::Handle<v8::Value>)> callback;
|
||||
@@ -318,20 +356,14 @@ void Window::CapturePage(mate::Arguments* args) {
|
||||
rect, base::Bind(&OnCapturePageDone, args->isolate(), callback));
|
||||
}
|
||||
|
||||
void Window::SetRepresentedFilename(const std::string& filename) {
|
||||
window_->SetRepresentedFilename(filename);
|
||||
}
|
||||
void Window::Print(mate::Arguments* args) {
|
||||
PrintSettings settings = { false, false };;
|
||||
if (args->Length() == 1 && !args->GetNext(&settings)) {
|
||||
args->ThrowError();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string Window::GetRepresentedFilename() {
|
||||
return window_->GetRepresentedFilename();
|
||||
}
|
||||
|
||||
void Window::SetDocumentEdited(bool edited) {
|
||||
window_->SetDocumentEdited(edited);
|
||||
}
|
||||
|
||||
bool Window::IsDocumentEdited() {
|
||||
return window_->IsDocumentEdited();
|
||||
window_->Print(settings.silent, settings.print_backgournd);
|
||||
}
|
||||
|
||||
mate::Handle<WebContents> Window::GetWebContents(v8::Isolate* isolate) const {
|
||||
@@ -386,7 +418,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setRepresentedFilename", &Window::SetRepresentedFilename)
|
||||
.SetMethod("getRepresentedFilename", &Window::GetRepresentedFilename)
|
||||
.SetMethod("setDocumentEdited", &Window::SetDocumentEdited)
|
||||
.SetMethod("IsDocumentEdited", &Window::IsDocumentEdited)
|
||||
.SetMethod("isDocumentEdited", &Window::IsDocumentEdited)
|
||||
.SetMethod("_openDevTools", &Window::OpenDevTools)
|
||||
.SetMethod("closeDevTools", &Window::CloseDevTools)
|
||||
.SetMethod("isDevToolsOpened", &Window::IsDevToolsOpened)
|
||||
@@ -395,6 +427,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("blurWebView", &Window::BlurWebView)
|
||||
.SetMethod("isWebViewFocused", &Window::IsWebViewFocused)
|
||||
.SetMethod("capturePage", &Window::CapturePage)
|
||||
.SetMethod("print", &Window::Print)
|
||||
.SetMethod("_getWebContents", &Window::GetWebContents)
|
||||
.SetMethod("_getDevToolsWebContents", &Window::GetDevToolsWebContents);
|
||||
}
|
||||
|
||||
@@ -97,11 +97,12 @@ class Window : public mate::EventEmitter,
|
||||
void FocusOnWebView();
|
||||
void BlurWebView();
|
||||
bool IsWebViewFocused();
|
||||
void CapturePage(mate::Arguments* args);
|
||||
void SetRepresentedFilename(const std::string& filename);
|
||||
std::string GetRepresentedFilename();
|
||||
void SetDocumentEdited(bool edited);
|
||||
bool IsDocumentEdited();
|
||||
void CapturePage(mate::Arguments* args);
|
||||
void Print(mate::Arguments* args);
|
||||
|
||||
// APIs for WebContents.
|
||||
mate::Handle<WebContents> GetWebContents(v8::Isolate* isolate) const;
|
||||
|
||||
@@ -35,6 +35,10 @@ BrowserWindow::openDevTools = ->
|
||||
@devToolsWebContents = @getDevToolsWebContents()
|
||||
@devToolsWebContents.once 'destroyed', => @devToolsWebContents = null
|
||||
|
||||
# Emit devtools events.
|
||||
@devToolsWebContents.once 'did-finish-load', => @emit 'devtools-opened'
|
||||
@devToolsWebContents.once 'destroyed', => @emit 'devtools-closed'
|
||||
|
||||
BrowserWindow::toggleDevTools = ->
|
||||
if @isDevToolsOpened() then @closeDevTools() else @openDevTools()
|
||||
|
||||
|
||||
@@ -10,13 +10,21 @@ fileDialogProperties =
|
||||
|
||||
messageBoxTypes = ['none', 'info', 'warning']
|
||||
|
||||
parseArgs = (window, options, callback) ->
|
||||
unless window is null or window?.constructor is BrowserWindow
|
||||
# Shift.
|
||||
callback = options
|
||||
options = window
|
||||
window = null
|
||||
if not callback? and typeof options is 'function'
|
||||
# Shift.
|
||||
callback = options
|
||||
options = null
|
||||
[window, options, callback]
|
||||
|
||||
module.exports =
|
||||
showOpenDialog: (window, options, callback) ->
|
||||
unless window?.constructor is BrowserWindow
|
||||
# Shift.
|
||||
callback = options
|
||||
options = window
|
||||
window = null
|
||||
showOpenDialog: (args...) ->
|
||||
[window, options, callback] = parseArgs args...
|
||||
|
||||
options ?= title: 'Open', properties: ['openFile']
|
||||
options.properties ?= ['openFile']
|
||||
@@ -43,12 +51,8 @@ module.exports =
|
||||
window,
|
||||
wrappedCallback
|
||||
|
||||
showSaveDialog: (window, options, callback) ->
|
||||
unless window?.constructor is BrowserWindow
|
||||
# Shift.
|
||||
callback = options
|
||||
options = window
|
||||
window = null
|
||||
showSaveDialog: (args...) ->
|
||||
[window, options, callback] = parseArgs args...
|
||||
|
||||
options ?= title: 'Save'
|
||||
options.title ?= ''
|
||||
@@ -67,12 +71,8 @@ module.exports =
|
||||
window,
|
||||
wrappedCallback
|
||||
|
||||
showMessageBox: (window, options, callback) ->
|
||||
unless window?.constructor is BrowserWindow
|
||||
# Shift.
|
||||
callback = options
|
||||
options = window
|
||||
window = null
|
||||
showMessageBox: (args...) ->
|
||||
[window, options, callback] = parseArgs args...
|
||||
|
||||
options ?= type: 'none'
|
||||
options.type ?= 'none'
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "chrome/browser/printing/printing_message_filter.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/resource_dispatcher_host.h"
|
||||
@@ -48,6 +49,11 @@ AtomBrowserClient::AtomBrowserClient()
|
||||
AtomBrowserClient::~AtomBrowserClient() {
|
||||
}
|
||||
|
||||
void AtomBrowserClient::RenderProcessWillLaunch(
|
||||
content::RenderProcessHost* host) {
|
||||
host->AddFilter(new PrintingMessageFilter(host->GetID()));
|
||||
}
|
||||
|
||||
void AtomBrowserClient::ResourceDispatcherHostCreated() {
|
||||
resource_dispatcher_delegate_.reset(new AtomResourceDispatcherHostDelegate);
|
||||
content::ResourceDispatcherHost::Get()->SetDelegate(
|
||||
@@ -79,6 +85,12 @@ void AtomBrowserClient::OverrideWebkitPrefs(
|
||||
prefs->allow_displaying_insecure_content = true;
|
||||
prefs->allow_running_insecure_content = true;
|
||||
|
||||
// Turn off web security for devtools.
|
||||
if (url.SchemeIs("chrome-devtools")) {
|
||||
prefs->web_security_enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
NativeWindow* window = NativeWindow::FromRenderView(
|
||||
render_view_host->GetProcess()->GetID(),
|
||||
render_view_host->GetRoutingID());
|
||||
|
||||
@@ -20,6 +20,8 @@ class AtomBrowserClient : public brightray::BrowserClient {
|
||||
|
||||
protected:
|
||||
// content::ContentBrowserClient:
|
||||
virtual void RenderProcessWillLaunch(
|
||||
content::RenderProcessHost* host) OVERRIDE;
|
||||
virtual void ResourceDispatcherHostCreated() OVERRIDE;
|
||||
virtual content::AccessTokenStore* CreateAccessTokenStore() OVERRIDE;
|
||||
virtual void OverrideWebkitPrefs(content::RenderViewHost* render_view_host,
|
||||
|
||||
@@ -8,27 +8,29 @@
|
||||
#include "atom/browser/net/atom_url_request_job_factory.h"
|
||||
#include "base/threading/sequenced_worker_pool.h"
|
||||
#include "base/threading/worker_pool.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/common/url_constants.h"
|
||||
#include "net/url_request/data_protocol_handler.h"
|
||||
#include "net/url_request/file_protocol_handler.h"
|
||||
#include "net/url_request/protocol_intercept_job_factory.h"
|
||||
#include "net/url_request/url_request_intercepting_job_factory.h"
|
||||
#include "url/url_constants.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
|
||||
AtomBrowserContext::AtomBrowserContext()
|
||||
: job_factory_(new AtomURLRequestJobFactory) {
|
||||
: fake_browser_process_(new BrowserProcess),
|
||||
job_factory_(new AtomURLRequestJobFactory) {
|
||||
}
|
||||
|
||||
AtomBrowserContext::~AtomBrowserContext() {
|
||||
}
|
||||
|
||||
scoped_ptr<net::URLRequestJobFactory>
|
||||
AtomBrowserContext::CreateURLRequestJobFactory(
|
||||
net::URLRequestJobFactory* AtomBrowserContext::CreateURLRequestJobFactory(
|
||||
content::ProtocolHandlerMap* handlers,
|
||||
content::ProtocolHandlerScopedVector* interceptors) {
|
||||
content::URLRequestInterceptorScopedVector* interceptors) {
|
||||
scoped_ptr<AtomURLRequestJobFactory> job_factory(job_factory_);
|
||||
|
||||
for (content::ProtocolHandlerMap::iterator it = handlers->begin();
|
||||
@@ -37,22 +39,22 @@ AtomBrowserContext::CreateURLRequestJobFactory(
|
||||
handlers->clear();
|
||||
|
||||
job_factory->SetProtocolHandler(
|
||||
content::kDataScheme, new net::DataProtocolHandler);
|
||||
url::kDataScheme, new net::DataProtocolHandler);
|
||||
job_factory->SetProtocolHandler(
|
||||
content::kFileScheme, new net::FileProtocolHandler(
|
||||
url::kFileScheme, new net::FileProtocolHandler(
|
||||
BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
|
||||
base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));
|
||||
|
||||
// Set up interceptors in the reverse order.
|
||||
scoped_ptr<net::URLRequestJobFactory> top_job_factory =
|
||||
job_factory.PassAs<net::URLRequestJobFactory>();
|
||||
content::ProtocolHandlerScopedVector::reverse_iterator it;
|
||||
content::URLRequestInterceptorScopedVector::reverse_iterator it;
|
||||
for (it = interceptors->rbegin(); it != interceptors->rend(); ++it)
|
||||
top_job_factory.reset(new net::ProtocolInterceptJobFactory(
|
||||
top_job_factory.reset(new net::URLRequestInterceptingJobFactory(
|
||||
top_job_factory.Pass(), make_scoped_ptr(*it)));
|
||||
interceptors->weak_clear();
|
||||
|
||||
return top_job_factory.Pass();
|
||||
return top_job_factory.release();
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "brightray/browser/browser_context.h"
|
||||
|
||||
class BrowserProcess;
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomURLRequestJobFactory;
|
||||
@@ -22,12 +24,15 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||
AtomURLRequestJobFactory* job_factory() const { return job_factory_; }
|
||||
|
||||
protected:
|
||||
// brightray::BrowserContext:
|
||||
virtual scoped_ptr<net::URLRequestJobFactory> CreateURLRequestJobFactory(
|
||||
// brightray::URLRequestContextGetter::Delegate:
|
||||
virtual net::URLRequestJobFactory* CreateURLRequestJobFactory(
|
||||
content::ProtocolHandlerMap* handlers,
|
||||
content::ProtocolHandlerScopedVector* interceptors) OVERRIDE;
|
||||
content::URLRequestInterceptorScopedVector* interceptors) OVERRIDE;
|
||||
|
||||
private:
|
||||
// A fake BrowserProcess object that used to feed the source code from chrome.
|
||||
scoped_ptr<BrowserProcess> fake_browser_process_;
|
||||
|
||||
AtomURLRequestJobFactory* job_factory_; // Weak reference.
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext);
|
||||
|
||||
@@ -8,13 +8,11 @@
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/javascript_environment.h"
|
||||
#include "atom/browser/node_debugger.h"
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "atom/common/node_bindings.h"
|
||||
#include "base/command_line.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "ui/gfx/win/dpi.h"
|
||||
#endif
|
||||
#include "v8/include/v8-debug.h"
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include "chrome/browser/ui/libgtk2ui/gtk2_util.h"
|
||||
@@ -57,9 +55,16 @@ void AtomBrowserMainParts::PostEarlyInitialization() {
|
||||
|
||||
node_bindings_->Initialize();
|
||||
|
||||
// Support the "--debug" switch.
|
||||
node_debugger_.reset(new NodeDebugger(js_env_->isolate()));
|
||||
|
||||
// Create the global environment.
|
||||
global_env = node_bindings_->CreateEnvironment(js_env_->context());
|
||||
|
||||
// Make sure node can get correct environment when debugging.
|
||||
if (node_debugger_->IsRunning())
|
||||
global_env->AssignToContext(v8::Debug::GetDebugContext());
|
||||
|
||||
// Add atom-shell extended APIs.
|
||||
atom_bindings_->BindTo(js_env_->isolate(), global_env->process_object());
|
||||
}
|
||||
@@ -76,10 +81,6 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() {
|
||||
libgtk2ui::GtkInitFromCommandLine(*CommandLine::ForCurrentProcess());
|
||||
#endif
|
||||
|
||||
// Make sure the url request job factory is created before the ready event.
|
||||
static_cast<content::BrowserContext*>(AtomBrowserContext::Get())->
|
||||
GetRequestContext();
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
// The corresponding call in OS X is in AtomApplicationDelegate.
|
||||
Browser::Get()->WillFinishLaunching();
|
||||
|
||||
@@ -13,6 +13,7 @@ class AtomBindings;
|
||||
class Browser;
|
||||
class JavascriptEnvironment;
|
||||
class NodeBindings;
|
||||
class NodeDebugger;
|
||||
|
||||
class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
||||
public:
|
||||
@@ -40,6 +41,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
||||
scoped_ptr<JavascriptEnvironment> js_env_;
|
||||
scoped_ptr<NodeBindings> node_bindings_;
|
||||
scoped_ptr<AtomBindings> atom_bindings_;
|
||||
scoped_ptr<NodeDebugger> node_debugger_;
|
||||
|
||||
static AtomBrowserMainParts* self_;
|
||||
|
||||
|
||||
@@ -34,6 +34,13 @@ app.on('ready', function() {
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Services',
|
||||
submenu: []
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Hide Atom Shell',
|
||||
accelerator: 'Command+H',
|
||||
|
||||
@@ -2,7 +2,6 @@ var app = require('app');
|
||||
var dialog = require('dialog');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var optimist = require('optimist');
|
||||
|
||||
// Quit when all windows are closed and no other one is listening to this.
|
||||
app.on('window-all-closed', function() {
|
||||
@@ -10,14 +9,27 @@ app.on('window-all-closed', function() {
|
||||
app.quit();
|
||||
});
|
||||
|
||||
var argv = optimist(process.argv.slice(1)).boolean('ci').argv;
|
||||
// Parse command line options.
|
||||
var argv = process.argv.slice(1);
|
||||
var option = { file: null, version: null };
|
||||
for (var i in argv) {
|
||||
if (argv[i] == '--version' || argv[i] == '-v') {
|
||||
option.version = true;
|
||||
break;
|
||||
} else if (argv[i][0] == '-') {
|
||||
continue;
|
||||
} else {
|
||||
option.file = argv[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Start the specified app if there is one specified in command line, otherwise
|
||||
// start the default app.
|
||||
if (argv._.length > 0) {
|
||||
if (option.file) {
|
||||
try {
|
||||
// Override app name and version.
|
||||
var packagePath = path.resolve(argv._[0]);
|
||||
var packagePath = path.resolve(option.file);
|
||||
var packageJsonPath = path.join(packagePath, 'package.json');
|
||||
if (fs.existsSync(packageJsonPath)) {
|
||||
var packageJson = JSON.parse(fs.readFileSync(packageJsonPath));
|
||||
@@ -48,7 +60,7 @@ if (argv._.length > 0) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} else if (argv.version) {
|
||||
} else if (option.version) {
|
||||
console.log('v' + process.versions['atom-shell']);
|
||||
process.exit(0);
|
||||
} else {
|
||||
|
||||
@@ -2,8 +2,5 @@
|
||||
"name": "atom-shell-default-app",
|
||||
"productName": "Atom Shell Default App",
|
||||
"version": "0.1.0",
|
||||
"main": "main.js",
|
||||
"dependencies": {
|
||||
"optimist": "*"
|
||||
}
|
||||
"main": "main.js"
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
namespace atom {
|
||||
|
||||
JavascriptEnvironment::JavascriptEnvironment()
|
||||
: isolate_(v8::Isolate::GetCurrent()),
|
||||
: isolate_holder_(gin::IsolateHolder::kNonStrictMode),
|
||||
isolate_(isolate_holder_.isolate()),
|
||||
isolate_scope_(isolate_),
|
||||
locker_(isolate_),
|
||||
handle_scope_(isolate_),
|
||||
context_(isolate_, v8::Context::New(isolate_)),
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "v8/include/v8.h"
|
||||
#include "gin/public/isolate_holder.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -20,7 +20,9 @@ class JavascriptEnvironment {
|
||||
}
|
||||
|
||||
private:
|
||||
gin::IsolateHolder isolate_holder_;
|
||||
v8::Isolate* isolate_;
|
||||
v8::Isolate::Scope isolate_scope_;
|
||||
v8::Locker locker_;
|
||||
v8::HandleScope handle_scope_;
|
||||
v8::UniquePersistent<v8::Context> context_;
|
||||
|
||||
88
atom/browser/lib/chrome-extension.coffee
Normal file
88
atom/browser/lib/chrome-extension.coffee
Normal file
@@ -0,0 +1,88 @@
|
||||
app = require 'app'
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
url = require 'url'
|
||||
|
||||
# Mapping between hostname and file path.
|
||||
hostPathMap = {}
|
||||
hostPathMapNextKey = 0
|
||||
|
||||
getHostForPath = (path) ->
|
||||
key = "extension-#{++hostPathMapNextKey}"
|
||||
hostPathMap[key] = path
|
||||
key
|
||||
|
||||
getPathForHost = (host) ->
|
||||
hostPathMap[host]
|
||||
|
||||
# Cache extensionInfo.
|
||||
extensionInfoMap = {}
|
||||
|
||||
getExtensionInfoFromPath = (srcDirectory) ->
|
||||
manifest = JSON.parse fs.readFileSync(path.join(srcDirectory, 'manifest.json'))
|
||||
unless extensionInfoMap[manifest.name]?
|
||||
# We can not use 'file://' directly because all resources in the extension
|
||||
# will be treated as relative to the root in Chrome.
|
||||
page = url.format
|
||||
protocol: 'chrome-extension'
|
||||
slashes: true
|
||||
hostname: getHostForPath srcDirectory
|
||||
pathname: manifest.devtools_page
|
||||
extensionInfoMap[manifest.name] =
|
||||
startPage: page
|
||||
name: manifest.name
|
||||
srcDirectory: srcDirectory
|
||||
extensionInfoMap[manifest.name]
|
||||
|
||||
# Load persistented extensions.
|
||||
loadedExtensionsPath = path.join app.getDataPath(), 'DevTools Extensions'
|
||||
|
||||
try
|
||||
loadedExtensions = JSON.parse fs.readFileSync(loadedExtensionsPath)
|
||||
loadedExtensions = [] unless Array.isArray loadedExtensions
|
||||
# Preheat the extensionInfo cache.
|
||||
getExtensionInfoFromPath srcDirectory for srcDirectory in loadedExtensions
|
||||
catch e
|
||||
|
||||
# Persistent loaded extensions.
|
||||
app.on 'will-quit', ->
|
||||
try
|
||||
loadedExtensions = Object.keys(extensionInfoMap).map (key) -> extensionInfoMap[key].srcDirectory
|
||||
try
|
||||
fs.mkdirSync path.dirname(loadedExtensionsPath)
|
||||
catch e
|
||||
fs.writeFileSync loadedExtensionsPath, JSON.stringify(loadedExtensions)
|
||||
catch e
|
||||
|
||||
# We can not use protocol or BrowserWindow until app is ready.
|
||||
app.once 'ready', ->
|
||||
protocol = require 'protocol'
|
||||
BrowserWindow = require 'browser-window'
|
||||
|
||||
# The chrome-extension: can map a extension URL request to real file path.
|
||||
protocol.registerProtocol 'chrome-extension', (request) ->
|
||||
parsed = url.parse request.url
|
||||
return unless parsed.hostname and parsed.path?
|
||||
return unless /extension-\d+/.test parsed.hostname
|
||||
|
||||
directory = getPathForHost parsed.hostname
|
||||
return unless directory?
|
||||
return new protocol.RequestFileJob(path.join(directory, parsed.path))
|
||||
|
||||
BrowserWindow::_loadDevToolsExtensions = (extensionInfoArray) ->
|
||||
@devToolsWebContents?.executeJavaScript "WebInspector.addExtensions(#{JSON.stringify(extensionInfoArray)});"
|
||||
|
||||
BrowserWindow.addDevToolsExtension = (srcDirectory) ->
|
||||
extensionInfo = getExtensionInfoFromPath srcDirectory
|
||||
window._loadDevToolsExtensions [extensionInfo] for window in BrowserWindow.getAllWindows()
|
||||
extensionInfo.name
|
||||
|
||||
BrowserWindow.removeDevToolsExtension = (name) ->
|
||||
delete extensionInfoMap[name]
|
||||
|
||||
# Load persistented extensions when devtools is opened.
|
||||
init = BrowserWindow::_init
|
||||
BrowserWindow::_init = ->
|
||||
init.call this
|
||||
@on 'devtools-opened', ->
|
||||
@_loadDevToolsExtensions Object.keys(extensionInfoMap).map (key) -> extensionInfoMap[key]
|
||||
@@ -47,7 +47,7 @@ setImmediate ->
|
||||
message = error.stack ? "#{error.name}: #{error.message}"
|
||||
require('dialog').showMessageBox
|
||||
type: 'warning'
|
||||
title: 'An javascript error occured in the browser'
|
||||
title: 'A javascript error occured in the browser'
|
||||
message: 'uncaughtException'
|
||||
detail: message
|
||||
buttons: ['OK']
|
||||
@@ -77,5 +77,8 @@ setImmediate ->
|
||||
else if packageJson.name?
|
||||
app.setName packageJson.name
|
||||
|
||||
# Load the chrome extension support.
|
||||
require './chrome-extension.js'
|
||||
|
||||
# Finally load app's main.js and transfer control to C++.
|
||||
module._load path.join(packagePath, packageJson.main), module, true
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
#include "chrome/browser/printing/print_view_manager_basic.h"
|
||||
#include "content/public/browser/devtools_agent_host.h"
|
||||
#include "content/public/browser/invalidate_type.h"
|
||||
#include "content/public/browser/navigation_entry.h"
|
||||
@@ -58,6 +59,7 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
|
||||
const mate::Dictionary& options)
|
||||
: content::WebContentsObserver(web_contents),
|
||||
has_frame_(true),
|
||||
enable_larger_than_screen_(false),
|
||||
is_closed_(false),
|
||||
node_integration_("except-iframe"),
|
||||
has_dialog_attached_(false),
|
||||
@@ -65,7 +67,10 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
|
||||
weak_factory_(this),
|
||||
inspectable_web_contents_(
|
||||
brightray::InspectableWebContents::Create(web_contents)) {
|
||||
printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
|
||||
|
||||
options.Get(switches::kFrame, &has_frame_);
|
||||
options.Get(switches::kEnableLargerThanScreen, &enable_larger_than_screen_);
|
||||
|
||||
// Read icon before window is created.
|
||||
options.Get(switches::kIcon, &icon_);
|
||||
@@ -139,8 +144,8 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
|
||||
} else if (options.Get(switches::kCenter, ¢er) && center) {
|
||||
Center();
|
||||
}
|
||||
int min_height = -1, min_width = -1;
|
||||
if (options.Get(switches::kMinHeight, &min_height) &&
|
||||
int min_height = 0, min_width = 0;
|
||||
if (options.Get(switches::kMinHeight, &min_height) |
|
||||
options.Get(switches::kMinWidth, &min_width)) {
|
||||
SetMinimumSize(gfx::Size(min_width, min_height));
|
||||
}
|
||||
@@ -190,11 +195,16 @@ std::string NativeWindow::GetRepresentedFilename() {
|
||||
void NativeWindow::SetDocumentEdited(bool edited) {
|
||||
}
|
||||
|
||||
bool NativeWindow::IsDocumentEdited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void NativeWindow::SetMenu(ui::MenuModel* menu) {
|
||||
}
|
||||
|
||||
bool NativeWindow::IsDocumentEdited() {
|
||||
return false;
|
||||
void NativeWindow::Print(bool silent, bool print_background) {
|
||||
printing::PrintViewManagerBasic::FromWebContents(GetWebContents())->
|
||||
PrintNow(silent, print_background);
|
||||
}
|
||||
|
||||
bool NativeWindow::HasModalDialog() {
|
||||
@@ -247,18 +257,10 @@ void NativeWindow::CapturePage(const gfx::Rect& rect,
|
||||
return;
|
||||
}
|
||||
|
||||
gfx::Rect flipped_y_rect = rect;
|
||||
flipped_y_rect.set_y(-rect.y());
|
||||
|
||||
gfx::Size size;
|
||||
if (flipped_y_rect.IsEmpty())
|
||||
size = render_widget_host_view->GetViewBounds().size();
|
||||
else
|
||||
size = flipped_y_rect.size();
|
||||
|
||||
GetWebContents()->GetRenderViewHost()->CopyFromBackingStore(
|
||||
flipped_y_rect,
|
||||
size,
|
||||
rect,
|
||||
rect.IsEmpty() ? render_widget_host_view->GetViewBounds().size() :
|
||||
rect.size(),
|
||||
base::Bind(&NativeWindow::OnCapturePageDone,
|
||||
weak_factory_.GetWeakPtr(),
|
||||
callback),
|
||||
|
||||
@@ -136,8 +136,8 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
virtual void SetRepresentedFilename(const std::string& filename);
|
||||
virtual std::string GetRepresentedFilename();
|
||||
virtual void SetDocumentEdited(bool edited);
|
||||
virtual void SetMenu(ui::MenuModel* menu);
|
||||
virtual bool IsDocumentEdited();
|
||||
virtual void SetMenu(ui::MenuModel* menu);
|
||||
virtual bool HasModalDialog();
|
||||
virtual gfx::NativeWindow GetNativeWindow() = 0;
|
||||
|
||||
@@ -156,6 +156,9 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
virtual void CapturePage(const gfx::Rect& rect,
|
||||
const CapturePageCallback& callback);
|
||||
|
||||
// Print current page.
|
||||
virtual void Print(bool silent, bool print_background);
|
||||
|
||||
// The same with closing a tab in a real browser.
|
||||
//
|
||||
// Should be called by platform code when user want to close the window.
|
||||
@@ -251,6 +254,9 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
// Whether window has standard frame.
|
||||
bool has_frame_;
|
||||
|
||||
// Whether window can be resized larger than screen.
|
||||
bool enable_larger_than_screen_;
|
||||
|
||||
// Window icon.
|
||||
gfx::ImageSkia icon_;
|
||||
|
||||
|
||||
@@ -108,10 +108,12 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
|
||||
@end
|
||||
|
||||
@interface AtomNSWindow : EventProcessingWindow {
|
||||
@protected
|
||||
@private
|
||||
atom::NativeWindowMac* shell_;
|
||||
bool enable_larger_than_screen_;
|
||||
}
|
||||
- (void)setShell:(atom::NativeWindowMac*)shell;
|
||||
- (void)setEnableLargerThanScreen:(bool)enable;
|
||||
@end
|
||||
|
||||
@implementation AtomNSWindow
|
||||
@@ -120,9 +122,16 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
|
||||
shell_ = shell;
|
||||
}
|
||||
|
||||
- (void)setEnableLargerThanScreen:(bool)enable {
|
||||
enable_larger_than_screen_ = enable;
|
||||
}
|
||||
|
||||
// Enable the window to be larger than screen.
|
||||
- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen {
|
||||
return frameRect;
|
||||
if (enable_larger_than_screen_)
|
||||
return frameRect;
|
||||
else
|
||||
return [super constrainFrameRect:frameRect toScreen:screen];
|
||||
}
|
||||
|
||||
- (IBAction)reload:(id)sender {
|
||||
@@ -133,6 +142,20 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
|
||||
shell_->OpenDevTools();
|
||||
}
|
||||
|
||||
// Returns an empty array for AXChildren attribute, this will force the
|
||||
// SpeechSynthesisServer to use its classical way of speaking the selected text:
|
||||
// by invoking the "Command+C" for current application and then speak out
|
||||
// what's in the clipboard. Otherwise the "Text to Speech" would always speak
|
||||
// out window's title.
|
||||
// This behavior is taken by both FireFox and Chrome, see also FireFox's bug on
|
||||
// more of how SpeechSynthesisServer chose which text to read:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=674612
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute {
|
||||
if ([attribute isEqualToString:@"AXChildren"])
|
||||
return [NSArray array];
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface ControlRegionView : NSView {
|
||||
@@ -199,6 +222,7 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
|
||||
defer:YES];
|
||||
|
||||
[atomWindow setShell:this];
|
||||
[atomWindow setEnableLargerThanScreen:enable_larger_than_screen_];
|
||||
window_.reset(atomWindow);
|
||||
|
||||
AtomNSWindowDelegate* delegate =
|
||||
|
||||
@@ -8,12 +8,6 @@
|
||||
#include <shobjidl.h>
|
||||
#endif
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -35,11 +29,15 @@
|
||||
#include "ui/views/widget/widget.h"
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/ui/views/global_menu_bar_x11.h"
|
||||
#include "atom/browser/ui/views/frameless_view.h"
|
||||
#include "atom/browser/ui/x/x_window_utils.h"
|
||||
#include "base/environment.h"
|
||||
#include "base/nix/xdg_util.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "chrome/browser/ui/libgtk2ui/unity_service.h"
|
||||
#include "ui/base/x/x11_util.h"
|
||||
#include "ui/gfx/x/x11_types.h"
|
||||
#include "ui/views/window/native_frame_view.h"
|
||||
#elif defined(OS_WIN)
|
||||
@@ -60,6 +58,10 @@ const int kMenuBarHeight = 25;
|
||||
#endif
|
||||
|
||||
#if defined(USE_X11)
|
||||
// Counts how many window has already been created, it will be used to set the
|
||||
// window role for X11.
|
||||
int kWindowsCreated = 0;
|
||||
|
||||
bool ShouldUseGlobalMenuBar() {
|
||||
// Some DE would pretend to be Unity but don't have global application menu,
|
||||
// so we can not trust unity::IsRunning().
|
||||
@@ -114,16 +116,23 @@ NativeWindowViews::NativeWindowViews(content::WebContents* web_contents,
|
||||
menu_bar_alt_pressed_(false),
|
||||
keyboard_event_handler_(new views::UnhandledKeyboardEventHandler),
|
||||
use_content_size_(false),
|
||||
resizable_(true),
|
||||
// We need to set a default maximum window size here otherwise Windows
|
||||
// will not allow us to resize the window larger than scree.
|
||||
// Setting directly to INT_MAX somehow doesn't work, so we just devide
|
||||
// by 10, which should still be large enough.
|
||||
maximum_size_(INT_MAX / 10, INT_MAX / 10) {
|
||||
options.Get(switches::kResizable, &resizable_);
|
||||
resizable_(true) {
|
||||
options.Get(switches::kTitle, &title_);
|
||||
options.Get(switches::kAutoHideMenuBar, &menu_bar_autohide_);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// On Windows we rely on the CanResize() to indicate whether window can be
|
||||
// resized, and it should be set before window is created.
|
||||
options.Get(switches::kResizable, &resizable_);
|
||||
#endif
|
||||
|
||||
if (enable_larger_than_screen_)
|
||||
// We need to set a default maximum window size here otherwise Windows
|
||||
// will not allow us to resize the window larger than scree.
|
||||
// Setting directly to INT_MAX somehow doesn't work, so we just devide
|
||||
// by 10, which should still be large enough.
|
||||
maximum_size_.SetSize(INT_MAX / 10, INT_MAX / 10);
|
||||
|
||||
int width = 800, height = 600;
|
||||
options.Get(switches::kWidth, &width);
|
||||
options.Get(switches::kHeight, &height);
|
||||
@@ -136,18 +145,44 @@ NativeWindowViews::NativeWindowViews(content::WebContents* web_contents,
|
||||
params.bounds = bounds;
|
||||
params.delegate = this;
|
||||
params.type = views::Widget::InitParams::TYPE_WINDOW;
|
||||
params.top_level = true;
|
||||
params.remove_standard_frame = !has_frame_;
|
||||
|
||||
#if defined(USE_X11)
|
||||
// FIXME Find out how to do this dynamically on Linux.
|
||||
bool skip_taskbar = false;
|
||||
if (options.Get(switches::kSkipTaskbar, &skip_taskbar) && skip_taskbar)
|
||||
params.type = views::Widget::InitParams::TYPE_BUBBLE;
|
||||
// Set WM_WINDOW_ROLE.
|
||||
params.wm_role_name = base::StringPrintf(
|
||||
"%s/%s/%d", "Atom Shell", Browser::Get()->GetName().c_str(),
|
||||
++kWindowsCreated);
|
||||
// Set WM_CLASS.
|
||||
params.wm_class_name = "atom-shell";
|
||||
params.wm_class_class = "Atom Shell";
|
||||
#endif
|
||||
|
||||
window_->Init(params);
|
||||
|
||||
#if defined(USE_X11)
|
||||
// Set _GTK_THEME_VARIANT to dark if we have "dark-theme" option set.
|
||||
bool use_dark_theme = false;
|
||||
if (options.Get(switches::kDarkTheme, &use_dark_theme) && use_dark_theme) {
|
||||
XDisplay* xdisplay = gfx::GetXDisplay();
|
||||
XChangeProperty(xdisplay, GetAcceleratedWidget(),
|
||||
XInternAtom(xdisplay, "_GTK_THEME_VARIANT", False),
|
||||
XInternAtom(xdisplay, "UTF8_STRING", False),
|
||||
8, PropModeReplace,
|
||||
reinterpret_cast<const unsigned char*>("dark"),
|
||||
4);
|
||||
}
|
||||
|
||||
// Before the window is mapped the SetWMSpecState can not work, so we have
|
||||
// to manually set the _NET_WM_STATE.
|
||||
bool skip_taskbar = false;
|
||||
if (options.Get(switches::kSkipTaskbar, &skip_taskbar) && skip_taskbar) {
|
||||
std::vector<::Atom> state_atom_list;
|
||||
state_atom_list.push_back(GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
|
||||
ui::SetAtomArrayProperty(GetAcceleratedWidget(), "_NET_WM_STATE", "ATOM",
|
||||
state_atom_list);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Add web view.
|
||||
SetLayoutManager(new MenuLayout(kMenuBarHeight));
|
||||
set_background(views::Background::CreateStandardPanelBackground());
|
||||
@@ -191,7 +226,7 @@ bool NativeWindowViews::IsFocused() {
|
||||
}
|
||||
|
||||
void NativeWindowViews::Show() {
|
||||
window_->Show();
|
||||
window_->ShowInactive();
|
||||
}
|
||||
|
||||
void NativeWindowViews::Hide() {
|
||||
@@ -235,6 +270,15 @@ bool NativeWindowViews::IsFullscreen() {
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetSize(const gfx::Size& size) {
|
||||
#if defined(USE_X11)
|
||||
// On Linux the minimum and maximum size should be updated with window size
|
||||
// when window is not resizable.
|
||||
if (!resizable_) {
|
||||
SetMaximumSize(size);
|
||||
SetMinimumSize(size);
|
||||
}
|
||||
#endif
|
||||
|
||||
window_->SetSize(size);
|
||||
}
|
||||
|
||||
@@ -254,8 +298,7 @@ void NativeWindowViews::SetContentSize(const gfx::Size& size) {
|
||||
}
|
||||
|
||||
gfx::Rect bounds = window_->GetWindowBoundsInScreen();
|
||||
bounds.set_size(size);
|
||||
window_->SetBounds(ContentBoundsToWindowBounds(bounds));
|
||||
SetSize(ContentBoundsToWindowBounds(gfx::Rect(bounds.origin(), size)).size());
|
||||
}
|
||||
|
||||
gfx::Size NativeWindowViews::GetContentSize() {
|
||||
@@ -302,8 +345,6 @@ gfx::Size NativeWindowViews::GetMaximumSize() {
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetResizable(bool resizable) {
|
||||
resizable_ = resizable;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
if (has_frame_) {
|
||||
// WS_MAXIMIZEBOX => Maximize button
|
||||
@@ -316,9 +357,21 @@ void NativeWindowViews::SetResizable(bool resizable) {
|
||||
style = (style & ~(WS_MAXIMIZEBOX | WS_THICKFRAME)) | WS_MINIMIZEBOX;
|
||||
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, style);
|
||||
}
|
||||
#elif defined(USE_X11)
|
||||
if (resizable != resizable_) {
|
||||
// On Linux there is no "resizable" property of a window, we have to set
|
||||
// both the minimum and maximum size to the window size to achieve it.
|
||||
if (resizable) {
|
||||
SetMaximumSize(gfx::Size());
|
||||
SetMinimumSize(gfx::Size());
|
||||
} else {
|
||||
SetMaximumSize(GetSize());
|
||||
SetMinimumSize(GetSize());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// FIXME Implement me for X11.
|
||||
resizable_ = resizable;
|
||||
}
|
||||
|
||||
bool NativeWindowViews::IsResizable() {
|
||||
@@ -374,6 +427,9 @@ void NativeWindowViews::SetSkipTaskbar(bool skip) {
|
||||
taskbar->DeleteTab(GetAcceleratedWidget());
|
||||
else
|
||||
taskbar->AddTab(GetAcceleratedWidget());
|
||||
#elif defined(USE_X11)
|
||||
SetWMSpecState(GetAcceleratedWidget(), skip,
|
||||
GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -570,6 +626,26 @@ void NativeWindowViews::HandleKeyboardEvent(
|
||||
const content::NativeWebKeyboardEvent& event) {
|
||||
keyboard_event_handler_->HandleKeyboardEvent(event, GetFocusManager());
|
||||
|
||||
if (!menu_bar_)
|
||||
return;
|
||||
|
||||
// Show accelerator when "Alt" is pressed.
|
||||
if (menu_bar_visible_ && IsAltKey(event))
|
||||
menu_bar_->SetAcceleratorVisibility(
|
||||
event.type == blink::WebInputEvent::RawKeyDown);
|
||||
|
||||
// Show the submenu when "Alt+Key" is pressed.
|
||||
if (event.type == blink::WebInputEvent::RawKeyDown && !IsAltKey(event) &&
|
||||
IsAltModifier(event)) {
|
||||
if (!menu_bar_visible_ &&
|
||||
(menu_bar_->GetAcceleratorIndex(event.windowsKeyCode) != -1)) {
|
||||
SetMenuBarVisibility(true);
|
||||
Layout();
|
||||
}
|
||||
menu_bar_->ActivateAccelerator(event.windowsKeyCode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!menu_bar_autohide_)
|
||||
return;
|
||||
|
||||
@@ -625,6 +701,10 @@ void NativeWindowViews::SetMenuBarVisibility(bool visible) {
|
||||
if (!menu_bar_)
|
||||
return;
|
||||
|
||||
// Always show the accelerator when the auto-hide menu bar shows.
|
||||
if (menu_bar_autohide_)
|
||||
menu_bar_->SetAcceleratorVisibility(visible);
|
||||
|
||||
menu_bar_visible_ = visible;
|
||||
if (visible) {
|
||||
DCHECK_EQ(child_count(), 1);
|
||||
|
||||
202
atom/browser/node_debugger.cc
Normal file
202
atom/browser/node_debugger.cc
Normal file
@@ -0,0 +1,202 @@
|
||||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/node_debugger.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "net/socket/tcp_listen_socket.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
// NodeDebugger is stored in Isolate's data, slots 0, 1, 3 have already been
|
||||
// taken by gin, blink and node, using 2 is a safe option for now.
|
||||
const int kIsolateSlot = 2;
|
||||
|
||||
const char* kContentLength = "Content-Length";
|
||||
|
||||
} // namespace
|
||||
|
||||
NodeDebugger::NodeDebugger(v8::Isolate* isolate)
|
||||
: isolate_(isolate),
|
||||
thread_("NodeDebugger"),
|
||||
content_length_(-1),
|
||||
weak_factory_(this) {
|
||||
bool use_debug_agent = false;
|
||||
int port = 5858;
|
||||
bool wait_for_connection = false;
|
||||
|
||||
std::string port_str;
|
||||
base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
|
||||
if (cmd->HasSwitch("debug")) {
|
||||
use_debug_agent = true;
|
||||
port_str = cmd->GetSwitchValueASCII("debug");
|
||||
}
|
||||
if (cmd->HasSwitch("debug-brk")) {
|
||||
use_debug_agent = true;
|
||||
wait_for_connection = true;
|
||||
port_str = cmd->GetSwitchValueASCII("debug-brk");
|
||||
}
|
||||
|
||||
if (use_debug_agent) {
|
||||
if (!port_str.empty())
|
||||
base::StringToInt(port_str, &port);
|
||||
|
||||
isolate_->SetData(kIsolateSlot, this);
|
||||
v8::Debug::SetMessageHandler(DebugMessageHandler);
|
||||
|
||||
if (wait_for_connection)
|
||||
v8::Debug::DebugBreak(isolate_);
|
||||
|
||||
// Start a new IO thread.
|
||||
base::Thread::Options options;
|
||||
options.message_loop_type = base::MessageLoop::TYPE_IO;
|
||||
if (!thread_.StartWithOptions(options)) {
|
||||
LOG(ERROR) << "Unable to start debugger thread";
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the server in new IO thread.
|
||||
thread_.message_loop()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&NodeDebugger::StartServer, weak_factory_.GetWeakPtr(),
|
||||
port));
|
||||
}
|
||||
}
|
||||
|
||||
NodeDebugger::~NodeDebugger() {
|
||||
thread_.Stop();
|
||||
}
|
||||
|
||||
bool NodeDebugger::IsRunning() const {
|
||||
return thread_.IsRunning();
|
||||
}
|
||||
|
||||
void NodeDebugger::StartServer(int port) {
|
||||
server_ = net::TCPListenSocket::CreateAndListen("127.0.0.1", port, this);
|
||||
if (!server_) {
|
||||
LOG(ERROR) << "Cannot start debugger server";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void NodeDebugger::CloseSession() {
|
||||
accepted_socket_.reset();
|
||||
}
|
||||
|
||||
void NodeDebugger::OnMessage(const std::string& message) {
|
||||
if (message.find("\"type\":\"request\",\"command\":\"disconnect\"}") !=
|
||||
std::string::npos)
|
||||
CloseSession();
|
||||
|
||||
base::string16 message16 = base::UTF8ToUTF16(message);
|
||||
v8::Debug::SendCommand(
|
||||
isolate_,
|
||||
reinterpret_cast<const uint16_t*>(message16.data()), message16.size());
|
||||
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&v8::Debug::ProcessDebugMessages));
|
||||
}
|
||||
|
||||
void NodeDebugger::SendMessage(const std::string& message) {
|
||||
if (accepted_socket_) {
|
||||
std::string header = base::StringPrintf(
|
||||
"%s: %d\r\n\r\n", kContentLength, static_cast<int>(message.size()));
|
||||
accepted_socket_->Send(header);
|
||||
accepted_socket_->Send(message);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeDebugger::SendConnectMessage() {
|
||||
accepted_socket_->Send(base::StringPrintf(
|
||||
"Type: connect\r\n"
|
||||
"V8-Version: %s\r\n"
|
||||
"Protocol-Version: 1\r\n"
|
||||
"Embedding-Host: %s\r\n"
|
||||
"%s: 0\r\n",
|
||||
v8::V8::GetVersion(), "Atom-Shell", kContentLength), true);
|
||||
}
|
||||
|
||||
// static
|
||||
void NodeDebugger::DebugMessageHandler(const v8::Debug::Message& message) {
|
||||
NodeDebugger* self = static_cast<NodeDebugger*>(
|
||||
message.GetIsolate()->GetData(kIsolateSlot));
|
||||
|
||||
if (self) {
|
||||
std::string message8(*v8::String::Utf8Value(message.GetJSON()));
|
||||
self->thread_.message_loop()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&NodeDebugger::SendMessage, self->weak_factory_.GetWeakPtr(),
|
||||
message8));
|
||||
}
|
||||
}
|
||||
|
||||
void NodeDebugger::DidAccept(net::StreamListenSocket* server,
|
||||
scoped_ptr<net::StreamListenSocket> socket) {
|
||||
// Only accept one session.
|
||||
if (accepted_socket_) {
|
||||
socket->Send(std::string("Remote debugging session already active"), true);
|
||||
return;
|
||||
}
|
||||
|
||||
accepted_socket_ = socket.Pass();
|
||||
SendConnectMessage();
|
||||
}
|
||||
|
||||
void NodeDebugger::DidRead(net::StreamListenSocket* socket,
|
||||
const char* data,
|
||||
int len) {
|
||||
buffer_.append(data, len);
|
||||
|
||||
do {
|
||||
if (buffer_.size() == 0)
|
||||
return;
|
||||
|
||||
// Read the "Content-Length" header.
|
||||
if (content_length_ < 0) {
|
||||
size_t pos = buffer_.find("\r\n\r\n");
|
||||
if (pos == std::string::npos)
|
||||
return;
|
||||
|
||||
// We can be sure that the header is "Content-Length: xxx\r\n".
|
||||
std::string content_length = buffer_.substr(16, pos - 16);
|
||||
if (!base::StringToInt(content_length, &content_length_)) {
|
||||
DidClose(accepted_socket_.get());
|
||||
return;
|
||||
}
|
||||
|
||||
// Strip header from buffer.
|
||||
buffer_ = buffer_.substr(pos + 4);
|
||||
}
|
||||
|
||||
// Read the message.
|
||||
if (buffer_.size() >= static_cast<size_t>(content_length_)) {
|
||||
std::string message = buffer_.substr(0, content_length_);
|
||||
buffer_ = buffer_.substr(content_length_);
|
||||
|
||||
OnMessage(message);
|
||||
|
||||
// Get ready for next message.
|
||||
content_length_ = -1;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void NodeDebugger::DidClose(net::StreamListenSocket* socket) {
|
||||
// If we lost the connection, then simulate a disconnect msg:
|
||||
OnMessage("{\"seq\":1,\"type\":\"request\",\"command\":\"disconnect\"}");
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
59
atom/browser/node_debugger.h
Normal file
59
atom/browser/node_debugger.h
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_NODE_DEBUGGER_H_
|
||||
#define ATOM_BROWSER_NODE_DEBUGGER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/threading/thread.h"
|
||||
#include "net/socket/stream_listen_socket.h"
|
||||
#include "v8/include/v8-debug.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Add support for node's "--debug" switch.
|
||||
class NodeDebugger : public net::StreamListenSocket::Delegate {
|
||||
public:
|
||||
explicit NodeDebugger(v8::Isolate* isolate);
|
||||
virtual ~NodeDebugger();
|
||||
|
||||
bool IsRunning() const;
|
||||
|
||||
private:
|
||||
void StartServer(int port);
|
||||
void CloseSession();
|
||||
void OnMessage(const std::string& message);
|
||||
void SendMessage(const std::string& message);
|
||||
void SendConnectMessage();
|
||||
|
||||
static void DebugMessageHandler(const v8::Debug::Message& message);
|
||||
|
||||
// net::StreamListenSocket::Delegate:
|
||||
virtual void DidAccept(net::StreamListenSocket* server,
|
||||
scoped_ptr<net::StreamListenSocket> socket) OVERRIDE;
|
||||
virtual void DidRead(net::StreamListenSocket* socket,
|
||||
const char* data,
|
||||
int len) OVERRIDE;
|
||||
virtual void DidClose(net::StreamListenSocket* socket) OVERRIDE;
|
||||
|
||||
v8::Isolate* isolate_;
|
||||
|
||||
base::Thread thread_;
|
||||
scoped_ptr<net::StreamListenSocket> server_;
|
||||
scoped_ptr<net::StreamListenSocket> accepted_socket_;
|
||||
|
||||
std::string buffer_;
|
||||
int content_length_;
|
||||
|
||||
base::WeakPtrFactory<NodeDebugger> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(NodeDebugger);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_NODE_DEBUGGER_H_
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>atom.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.15.7</string>
|
||||
<string>0.16.1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.8.0</string>
|
||||
<key>NSMainNibFile</key>
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,15,7,0
|
||||
PRODUCTVERSION 0,15,7,0
|
||||
FILEVERSION 0,16,1,0
|
||||
PRODUCTVERSION 0,16,1,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -68,12 +68,13 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Atom-Shell"
|
||||
VALUE "FileVersion", "0.15.7"
|
||||
VALUE "FileVersion", "0.16.1"
|
||||
VALUE "InternalName", "atom.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2013 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "atom.exe"
|
||||
VALUE "ProductName", "Atom-Shell"
|
||||
VALUE "ProductVersion", "0.15.7"
|
||||
VALUE "ProductVersion", "0.16.1"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -159,6 +159,9 @@ int EventFlagsFromNSEvent(NSEvent* event) {
|
||||
[NSApp setWindowsMenu:submenu];
|
||||
else if ([[item title] isEqualToString:@"Help"])
|
||||
[NSApp setHelpMenu:submenu];
|
||||
if ([[item title] isEqualToString:@"Services"] &&
|
||||
[submenu numberOfItems] == 0)
|
||||
[NSApp setServicesMenu:submenu];
|
||||
} else {
|
||||
// The MenuModel works on indexes so we can't just set the command id as the
|
||||
// tag like we do in other menus. Also set the represented object to be
|
||||
|
||||
@@ -71,7 +71,7 @@ class MessageDialog : public views::WidgetDelegate,
|
||||
virtual views::ClientView* CreateClientView(views::Widget* widget) OVERRIDE;
|
||||
|
||||
// Overridden from views::View:
|
||||
virtual gfx::Size GetPreferredSize() OVERRIDE;
|
||||
virtual gfx::Size GetPreferredSize() const OVERRIDE;
|
||||
virtual void Layout() OVERRIDE;
|
||||
virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
|
||||
|
||||
@@ -160,7 +160,6 @@ MessageDialog::MessageDialog(NativeWindow* parent_window,
|
||||
views::Widget::InitParams params;
|
||||
params.delegate = this;
|
||||
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
|
||||
params.top_level = true;
|
||||
if (parent_) {
|
||||
params.parent = parent_->GetNativeWindow();
|
||||
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
|
||||
@@ -264,7 +263,7 @@ views::ClientView* MessageDialog::CreateClientView(views::Widget* widget) {
|
||||
return new MessageDialogClientView(this, widget);
|
||||
}
|
||||
|
||||
gfx::Size MessageDialog::GetPreferredSize() {
|
||||
gfx::Size MessageDialog::GetPreferredSize() const {
|
||||
gfx::Size size(0, buttons_[0]->GetPreferredSize().height());
|
||||
for (size_t i = 0; i < buttons_.size(); ++i)
|
||||
size.Enlarge(buttons_[i]->GetPreferredSize().width(), 0);
|
||||
|
||||
@@ -95,16 +95,16 @@ void FramelessView::UpdateWindowIcon() {
|
||||
void FramelessView::UpdateWindowTitle() {
|
||||
}
|
||||
|
||||
gfx::Size FramelessView::GetPreferredSize() {
|
||||
gfx::Size FramelessView::GetPreferredSize() const {
|
||||
return frame_->non_client_view()->GetWindowBoundsForClientBounds(
|
||||
gfx::Rect(frame_->client_view()->GetPreferredSize())).size();
|
||||
}
|
||||
|
||||
gfx::Size FramelessView::GetMinimumSize() {
|
||||
gfx::Size FramelessView::GetMinimumSize() const {
|
||||
return window_->GetMinimumSize();
|
||||
}
|
||||
|
||||
gfx::Size FramelessView::GetMaximumSize() {
|
||||
gfx::Size FramelessView::GetMaximumSize() const {
|
||||
return window_->GetMaximumSize();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,9 @@ class FramelessView : public views::NonClientFrameView {
|
||||
virtual void UpdateWindowTitle() OVERRIDE;
|
||||
|
||||
// Overridden from View:
|
||||
virtual gfx::Size GetPreferredSize() OVERRIDE;
|
||||
virtual gfx::Size GetMinimumSize() OVERRIDE;
|
||||
virtual gfx::Size GetMaximumSize() OVERRIDE;
|
||||
virtual gfx::Size GetPreferredSize() const OVERRIDE;
|
||||
virtual gfx::Size GetMinimumSize() const OVERRIDE;
|
||||
virtual gfx::Size GetMaximumSize() const OVERRIDE;
|
||||
virtual const char* GetClassName() const OVERRIDE;
|
||||
|
||||
// Not owned.
|
||||
|
||||
@@ -9,11 +9,9 @@
|
||||
#endif
|
||||
|
||||
#include "atom/browser/ui/views/menu_delegate.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "atom/browser/ui/views/submenu_button.h"
|
||||
#include "ui/base/models/menu_model.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/controls/button/menu_button.h"
|
||||
#include "ui/views/layout/box_layout.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -32,13 +30,6 @@ const char kViewClassName[] = "AtomMenuBar";
|
||||
// Default color of the menu bar.
|
||||
const SkColor kDefaultColor = SkColorSetARGB(255, 233, 233, 233);
|
||||
|
||||
// Filter out the "&" in menu label.
|
||||
base::string16 FilterMenuButtonLabel(const base::string16& label) {
|
||||
base::string16 out;
|
||||
base::RemoveChars(label, base::ASCIIToUTF16("&").c_str(), &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#if defined(USE_X11)
|
||||
void GetMenuBarColor(SkColor* enabled, SkColor* disabled, SkColor* highlight,
|
||||
SkColor* hover, SkColor* background) {
|
||||
@@ -46,10 +37,10 @@ void GetMenuBarColor(SkColor* enabled, SkColor* disabled, SkColor* highlight,
|
||||
fake_menu_bar.Own(gtk_menu_bar_new());
|
||||
|
||||
GtkStyle* style = gtk_rc_get_style(fake_menu_bar.get());
|
||||
*enabled = libgtk2ui::GdkColorToSkColor(style->text[GTK_STATE_NORMAL]);
|
||||
*disabled = libgtk2ui::GdkColorToSkColor(style->text[GTK_STATE_INSENSITIVE]);
|
||||
*highlight = libgtk2ui::GdkColorToSkColor(style->text[GTK_STATE_SELECTED]);
|
||||
*hover = libgtk2ui::GdkColorToSkColor(style->text[GTK_STATE_PRELIGHT]);
|
||||
*enabled = libgtk2ui::GdkColorToSkColor(style->fg[GTK_STATE_NORMAL]);
|
||||
*disabled = libgtk2ui::GdkColorToSkColor(style->fg[GTK_STATE_INSENSITIVE]);
|
||||
*highlight = libgtk2ui::GdkColorToSkColor(style->fg[GTK_STATE_SELECTED]);
|
||||
*hover = libgtk2ui::GdkColorToSkColor(style->fg[GTK_STATE_PRELIGHT]);
|
||||
*background = libgtk2ui::GdkColorToSkColor(style->bg[GTK_STATE_NORMAL]);
|
||||
}
|
||||
#endif
|
||||
@@ -79,21 +70,43 @@ void MenuBar::SetMenu(ui::MenuModel* model) {
|
||||
RemoveAllChildViews(true);
|
||||
|
||||
for (int i = 0; i < model->GetItemCount(); ++i) {
|
||||
views::MenuButton* button = new views::MenuButton(
|
||||
this, FilterMenuButtonLabel(model->GetLabelAt(i)), this, false);
|
||||
SubmenuButton* button = new SubmenuButton(this, model->GetLabelAt(i), this);
|
||||
button->set_tag(i);
|
||||
|
||||
#if defined(USE_X11)
|
||||
button->SetEnabledColor(enabled_color_);
|
||||
button->SetDisabledColor(disabled_color_);
|
||||
button->SetHighlightColor(highlight_color_);
|
||||
button->SetHoverColor(hover_color_);
|
||||
button->SetTextColor(views::Button::STATE_NORMAL, enabled_color_);
|
||||
button->SetTextColor(views::Button::STATE_DISABLED, disabled_color_);
|
||||
button->SetTextColor(views::Button::STATE_PRESSED, highlight_color_);
|
||||
button->SetTextColor(views::Button::STATE_HOVERED, hover_color_);
|
||||
button->SetUnderlineColor(enabled_color_);
|
||||
#elif defined(OS_WIN)
|
||||
button->SetUnderlineColor(color_utils::GetSysSkColor(COLOR_GRAYTEXT));
|
||||
#endif
|
||||
|
||||
AddChildView(button);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBar::SetAcceleratorVisibility(bool visible) {
|
||||
for (int i = 0; i < child_count(); ++i)
|
||||
static_cast<SubmenuButton*>(child_at(i))->SetAcceleratorVisibility(visible);
|
||||
}
|
||||
|
||||
int MenuBar::GetAcceleratorIndex(base::char16 key) {
|
||||
for (int i = 0; i < child_count(); ++i) {
|
||||
SubmenuButton* button = static_cast<SubmenuButton*>(child_at(i));
|
||||
if (button->accelerator() == key)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MenuBar::ActivateAccelerator(base::char16 key) {
|
||||
int i = GetAcceleratorIndex(key);
|
||||
if (i != -1)
|
||||
static_cast<SubmenuButton*>(child_at(i))->Activate();
|
||||
}
|
||||
|
||||
int MenuBar::GetItemCount() const {
|
||||
return menu_model_->GetItemCount();
|
||||
}
|
||||
@@ -130,6 +143,9 @@ void MenuBar::ButtonPressed(views::Button* sender, const ui::Event& event) {
|
||||
|
||||
void MenuBar::OnMenuButtonClicked(views::View* source,
|
||||
const gfx::Point& point) {
|
||||
// Hide the accelerator when a submenu is activated.
|
||||
SetAcceleratorVisibility(false);
|
||||
|
||||
if (!menu_model_)
|
||||
return;
|
||||
|
||||
|
||||
@@ -31,6 +31,16 @@ class MenuBar : public views::View,
|
||||
// Replaces current menu with a new one.
|
||||
void SetMenu(ui::MenuModel* menu_model);
|
||||
|
||||
// Shows underline under accelerators.
|
||||
void SetAcceleratorVisibility(bool visible);
|
||||
|
||||
// Returns which submenu has accelerator |key|, -1 would be returned when
|
||||
// there is no matching submenu.
|
||||
int GetAcceleratorIndex(base::char16 key);
|
||||
|
||||
// Shows the submenu whose accelerator is |key|.
|
||||
void ActivateAccelerator(base::char16 key);
|
||||
|
||||
// Returns there are how many items in the root menu.
|
||||
int GetItemCount() const;
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ bool MenuDelegate::IsTriggerableEvent(views::MenuItemView* source,
|
||||
return delegate()->IsTriggerableEvent(source, e);
|
||||
}
|
||||
|
||||
bool MenuDelegate::GetAccelerator(int id, ui::Accelerator* accelerator) {
|
||||
bool MenuDelegate::GetAccelerator(int id, ui::Accelerator* accelerator) const {
|
||||
return delegate()->GetAccelerator(id, accelerator);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class MenuDelegate : public views::MenuDelegate {
|
||||
virtual bool IsTriggerableEvent(views::MenuItemView* source,
|
||||
const ui::Event& e) OVERRIDE;
|
||||
virtual bool GetAccelerator(int id,
|
||||
ui::Accelerator* accelerator) OVERRIDE;
|
||||
ui::Accelerator* accelerator) const OVERRIDE;
|
||||
virtual base::string16 GetLabel(int id) const OVERRIDE;
|
||||
virtual const gfx::FontList* GetLabelFontList(int id) const OVERRIDE;
|
||||
virtual bool IsCommandEnabled(int id) const OVERRIDE;
|
||||
|
||||
@@ -30,7 +30,7 @@ void MenuLayout::Layout(views::View* host) {
|
||||
menu_bar->SetBoundsRect(menu_Bar_bounds);
|
||||
}
|
||||
|
||||
gfx::Size MenuLayout::GetPreferredSize(views::View* host) {
|
||||
gfx::Size MenuLayout::GetPreferredSize(const views::View* host) const {
|
||||
gfx::Size size = views::FillLayout::GetPreferredSize(host);
|
||||
if (!HasMenu(host))
|
||||
return size;
|
||||
@@ -39,7 +39,8 @@ gfx::Size MenuLayout::GetPreferredSize(views::View* host) {
|
||||
return size;
|
||||
}
|
||||
|
||||
int MenuLayout::GetPreferredHeightForWidth(views::View* host, int width) {
|
||||
int MenuLayout::GetPreferredHeightForWidth(
|
||||
const views::View* host, int width) const {
|
||||
int height = views::FillLayout::GetPreferredHeightForWidth(host, width);
|
||||
if (!HasMenu(host))
|
||||
return height;
|
||||
|
||||
@@ -16,8 +16,9 @@ class MenuLayout : public views::FillLayout {
|
||||
|
||||
// views::LayoutManager:
|
||||
virtual void Layout(views::View* host) OVERRIDE;
|
||||
virtual gfx::Size GetPreferredSize(views::View* host) OVERRIDE;
|
||||
virtual int GetPreferredHeightForWidth(views::View* host, int width) OVERRIDE;
|
||||
virtual gfx::Size GetPreferredSize(const views::View* host) const OVERRIDE;
|
||||
virtual int GetPreferredHeightForWidth(
|
||||
const views::View* host, int width) const OVERRIDE;
|
||||
|
||||
private:
|
||||
bool HasMenu(const views::View* host) const;
|
||||
|
||||
98
atom/browser/ui/views/submenu_button.cc
Normal file
98
atom/browser/ui/views/submenu_button.cc
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/ui/views/submenu_button.h"
|
||||
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "ui/gfx/canvas.h"
|
||||
#include "ui/gfx/text_utils.h"
|
||||
#include "ui/views/controls/button/label_button_border.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
// Filter out the "&" in menu label.
|
||||
base::string16 FilterAccecelator(const base::string16& label) {
|
||||
base::string16 out;
|
||||
base::RemoveChars(label, base::ASCIIToUTF16("&").c_str(), &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
SubmenuButton::SubmenuButton(views::ButtonListener* listener,
|
||||
const base::string16& title,
|
||||
views::MenuButtonListener* menu_button_listener)
|
||||
: views::MenuButton(listener, FilterAccecelator(title),
|
||||
menu_button_listener, false),
|
||||
accelerator_(0),
|
||||
show_underline_(false),
|
||||
underline_start_(-1),
|
||||
underline_end_(-1),
|
||||
text_width_(0),
|
||||
text_height_(0),
|
||||
underline_color_(SK_ColorBLACK) {
|
||||
#if defined(OS_LINUX)
|
||||
// Dont' use native style border.
|
||||
SetBorder(CreateDefaultBorder().PassAs<views::Border>());
|
||||
#endif
|
||||
|
||||
if (GetUnderlinePosition(title, &accelerator_, &underline_start_,
|
||||
&underline_end_))
|
||||
gfx::Canvas::SizeStringInt(GetText(), GetFontList(), &text_width_,
|
||||
&text_height_, 0, 0);
|
||||
}
|
||||
|
||||
SubmenuButton::~SubmenuButton() {
|
||||
}
|
||||
|
||||
void SubmenuButton::SetAcceleratorVisibility(bool visible) {
|
||||
if (visible == show_underline_)
|
||||
return;
|
||||
|
||||
show_underline_ = visible;
|
||||
SchedulePaint();
|
||||
}
|
||||
|
||||
void SubmenuButton::SetUnderlineColor(SkColor color) {
|
||||
underline_color_ = color;
|
||||
}
|
||||
|
||||
void SubmenuButton::OnPaint(gfx::Canvas* canvas) {
|
||||
views::MenuButton::OnPaint(canvas);
|
||||
|
||||
if (show_underline_ && (underline_start_ != underline_end_)) {
|
||||
int padding = (width() - text_width_) / 2;
|
||||
int underline_height = (height() + text_height_) / 2 - 2;
|
||||
canvas->DrawLine(gfx::Point(underline_start_ + padding, underline_height),
|
||||
gfx::Point(underline_end_ + padding, underline_height),
|
||||
underline_color_);
|
||||
}
|
||||
}
|
||||
|
||||
bool SubmenuButton::GetUnderlinePosition(const base::string16& text,
|
||||
base::char16* accelerator,
|
||||
int* start, int* end) {
|
||||
int pos, span;
|
||||
base::string16 trimmed = gfx::RemoveAcceleratorChar(text, '&', &pos, &span);
|
||||
if (pos > -1 && span != 0) {
|
||||
*accelerator = base::ToUpperASCII(trimmed[pos]);
|
||||
GetCharacterPosition(trimmed, pos, start);
|
||||
GetCharacterPosition(trimmed, pos + span, end);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SubmenuButton::GetCharacterPosition(
|
||||
const base::string16& text, int index, int* pos) {
|
||||
int height;
|
||||
gfx::Canvas::SizeStringInt(text.substr(0, index), GetFontList(), pos, &height,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
53
atom/browser/ui/views/submenu_button.h
Normal file
53
atom/browser/ui/views/submenu_button.h
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_UI_VIEWS_SUBMENU_BUTTON_H_
|
||||
#define ATOM_BROWSER_UI_VIEWS_SUBMENU_BUTTON_H_
|
||||
|
||||
#include "ui/views/controls/button/menu_button.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Special button that used by menu bar to show submenus.
|
||||
class SubmenuButton : public views::MenuButton {
|
||||
public:
|
||||
SubmenuButton(views::ButtonListener* listener,
|
||||
const base::string16& title,
|
||||
views::MenuButtonListener* menu_button_listener);
|
||||
virtual ~SubmenuButton();
|
||||
|
||||
void SetAcceleratorVisibility(bool visible);
|
||||
void SetUnderlineColor(SkColor color);
|
||||
|
||||
void SetEnabledColor(SkColor color);
|
||||
void SetBackgroundColor(SkColor color);
|
||||
|
||||
base::char16 accelerator() const { return accelerator_; }
|
||||
|
||||
// views::MenuButton:
|
||||
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
|
||||
|
||||
private:
|
||||
bool GetUnderlinePosition(const base::string16& text,
|
||||
base::char16* accelerator,
|
||||
int* start, int* end);
|
||||
void GetCharacterPosition(
|
||||
const base::string16& text, int index, int* pos);
|
||||
|
||||
base::char16 accelerator_;
|
||||
|
||||
bool show_underline_;
|
||||
|
||||
int underline_start_;
|
||||
int underline_end_;
|
||||
int text_width_;
|
||||
int text_height_;
|
||||
SkColor underline_color_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SubmenuButton);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_UI_VIEWS_SUBMENU_BUTTON_H_
|
||||
@@ -39,12 +39,12 @@ int WinFrameView::NonClientHitTest(const gfx::Point& point) {
|
||||
return FramelessView::NonClientHitTest(point);
|
||||
}
|
||||
|
||||
gfx::Size WinFrameView::GetMinimumSize() {
|
||||
gfx::Size WinFrameView::GetMinimumSize() const {
|
||||
gfx::Size size = FramelessView::GetMinimumSize();
|
||||
return gfx::win::DIPToScreenSize(size);
|
||||
}
|
||||
|
||||
gfx::Size WinFrameView::GetMaximumSize() {
|
||||
gfx::Size WinFrameView::GetMaximumSize() const {
|
||||
gfx::Size size = FramelessView::GetMaximumSize();
|
||||
return gfx::win::DIPToScreenSize(size);
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ class WinFrameView : public FramelessView {
|
||||
virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE;
|
||||
|
||||
// views::View:
|
||||
virtual gfx::Size GetMinimumSize() OVERRIDE;
|
||||
virtual gfx::Size GetMaximumSize() OVERRIDE;
|
||||
virtual gfx::Size GetMinimumSize() const OVERRIDE;
|
||||
virtual gfx::Size GetMaximumSize() const OVERRIDE;
|
||||
virtual const char* GetClassName() const OVERRIDE;
|
||||
|
||||
private:
|
||||
|
||||
34
atom/browser/ui/x/x_window_utils.cc
Normal file
34
atom/browser/ui/x/x_window_utils.cc
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/ui/x/x_window_utils.h"
|
||||
|
||||
#include "ui/base/x/x11_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
::Atom GetAtom(const char* name) {
|
||||
return XInternAtom(gfx::GetXDisplay(), name, false);
|
||||
}
|
||||
|
||||
void SetWMSpecState(::Window xwindow, bool enabled, ::Atom state) {
|
||||
XEvent xclient;
|
||||
memset(&xclient, 0, sizeof(xclient));
|
||||
xclient.type = ClientMessage;
|
||||
xclient.xclient.window = xwindow;
|
||||
xclient.xclient.message_type = GetAtom("_NET_WM_STATE");
|
||||
xclient.xclient.format = 32;
|
||||
xclient.xclient.data.l[0] = enabled ? 1 : 0;
|
||||
xclient.xclient.data.l[1] = state;
|
||||
xclient.xclient.data.l[2] = None;
|
||||
xclient.xclient.data.l[3] = 1;
|
||||
xclient.xclient.data.l[4] = 0;
|
||||
|
||||
XDisplay* xdisplay = gfx::GetXDisplay();
|
||||
XSendEvent(xdisplay, DefaultRootWindow(xdisplay), False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask,
|
||||
&xclient);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
22
atom/browser/ui/x/x_window_utils.h
Normal file
22
atom/browser/ui/x/x_window_utils.h
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_UI_X_X_WINDOW_UTILS_H_
|
||||
#define ATOM_BROWSER_UI_X_X_WINDOW_UTILS_H_
|
||||
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
namespace atom {
|
||||
|
||||
::Atom GetAtom(const char* name);
|
||||
|
||||
// Sends a message to the x11 window manager, enabling or disabling the |state|
|
||||
// for _NET_WM_STATE.
|
||||
void SetWMSpecState(::Window xwindow, bool enabled, ::Atom state);
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_UI_X_X_WINDOW_UTILS_H_
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "atom/common/atom_version.h"
|
||||
@@ -18,9 +19,6 @@ namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
// Async handle to wake up uv loop.
|
||||
uv_async_t g_next_tick_uv_handle;
|
||||
|
||||
// Async handle to execute the stored v8 callback.
|
||||
uv_async_t g_callback_uv_handle;
|
||||
|
||||
@@ -30,70 +28,26 @@ base::Closure g_v8_callback;
|
||||
// Dummy class type that used for crashing the program.
|
||||
struct DummyClass { bool crash; };
|
||||
|
||||
// Async handler to call next process.nextTick callbacks.
|
||||
void UvCallNextTick(uv_async_t* handle) {
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
node::Environment* env = node::Environment::GetCurrent(isolate);
|
||||
node::Environment::TickInfo* tick_info = env->tick_info();
|
||||
|
||||
if (tick_info->in_tick())
|
||||
return;
|
||||
|
||||
if (tick_info->length() == 0) {
|
||||
tick_info->set_index(0);
|
||||
return;
|
||||
}
|
||||
|
||||
tick_info->set_in_tick(true);
|
||||
env->tick_callback_function()->Call(env->process_object(), 0, NULL);
|
||||
tick_info->set_in_tick(false);
|
||||
}
|
||||
|
||||
// Async handler to execute the stored v8 callback.
|
||||
void UvOnCallback(uv_async_t* handle) {
|
||||
g_v8_callback.Run();
|
||||
}
|
||||
|
||||
// Called when there is a fatal error in V8, we just crash the process here so
|
||||
// we can get the stack trace.
|
||||
void FatalErrorCallback(const char* location, const char* message) {
|
||||
LOG(ERROR) << "Fatal error in V8: " << location << " " << message;
|
||||
static_cast<DummyClass*>(NULL)->crash = true;
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> DumpStackFrame(v8::Isolate* isolate,
|
||||
v8::Handle<v8::StackFrame> stack_frame) {
|
||||
mate::Dictionary frame_dict(isolate);
|
||||
frame_dict.Set("line", stack_frame->GetLineNumber());
|
||||
frame_dict.Set("column", stack_frame->GetColumn());
|
||||
return mate::ConvertToV8(isolate, frame_dict);;
|
||||
}
|
||||
|
||||
void Crash() {
|
||||
static_cast<DummyClass*>(NULL)->crash = true;
|
||||
}
|
||||
|
||||
void ActivateUVLoop() {
|
||||
uv_async_send(&g_next_tick_uv_handle);
|
||||
// Called when there is a fatal error in V8, we just crash the process here so
|
||||
// we can get the stack trace.
|
||||
void FatalErrorCallback(const char* location, const char* message) {
|
||||
LOG(ERROR) << "Fatal error in V8: " << location << " " << message;
|
||||
Crash();
|
||||
}
|
||||
|
||||
void Log(const base::string16& message) {
|
||||
logging::LogMessage("CONSOLE", 0, 0).stream() << message;
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> GetCurrentStackTrace(v8::Isolate* isolate,
|
||||
int stack_limit) {
|
||||
v8::Local<v8::StackTrace> stack_trace = v8::StackTrace::CurrentStackTrace(
|
||||
isolate, stack_limit, v8::StackTrace::kDetailed);
|
||||
|
||||
int frame_count = stack_trace->GetFrameCount();
|
||||
v8::Local<v8::Array> result = v8::Array::New(isolate, frame_count);
|
||||
for (int i = 0; i < frame_count; ++i)
|
||||
result->Set(i, DumpStackFrame(isolate, stack_trace->GetFrame(i)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ScheduleCallback(const base::Closure& callback) {
|
||||
g_v8_callback = callback;
|
||||
uv_async_send(&g_callback_uv_handle);
|
||||
@@ -103,9 +57,10 @@ void ScheduleCallback(const base::Closure& callback) {
|
||||
|
||||
|
||||
AtomBindings::AtomBindings() {
|
||||
uv_async_init(uv_default_loop(), &g_next_tick_uv_handle, UvCallNextTick);
|
||||
uv_async_init(uv_default_loop(), &call_next_tick_async_, OnCallNextTick);
|
||||
call_next_tick_async_.data = this;
|
||||
|
||||
uv_async_init(uv_default_loop(), &g_callback_uv_handle, UvOnCallback);
|
||||
v8::V8::SetFatalErrorHandler(FatalErrorCallback);
|
||||
}
|
||||
|
||||
AtomBindings::~AtomBindings() {
|
||||
@@ -113,12 +68,14 @@ AtomBindings::~AtomBindings() {
|
||||
|
||||
void AtomBindings::BindTo(v8::Isolate* isolate,
|
||||
v8::Handle<v8::Object> process) {
|
||||
v8::V8::SetFatalErrorHandler(FatalErrorCallback);
|
||||
|
||||
mate::Dictionary dict(isolate, process);
|
||||
dict.SetMethod("crash", &Crash);
|
||||
dict.SetMethod("activateUvLoop", &ActivateUVLoop);
|
||||
dict.SetMethod("log", &Log);
|
||||
dict.SetMethod("getCurrentStackTrace", &GetCurrentStackTrace);
|
||||
dict.SetMethod("scheduleCallback", &ScheduleCallback);
|
||||
dict.SetMethod("activateUvLoop",
|
||||
base::Bind(&AtomBindings::ActivateUVLoop, base::Unretained(this)));
|
||||
|
||||
v8::Handle<v8::Object> versions;
|
||||
if (dict.Get("versions", &versions))
|
||||
@@ -126,4 +83,40 @@ void AtomBindings::BindTo(v8::Isolate* isolate,
|
||||
mate::StringToV8(isolate, ATOM_VERSION_STRING));
|
||||
}
|
||||
|
||||
void AtomBindings::ActivateUVLoop(v8::Isolate* isolate) {
|
||||
node::Environment* env = node::Environment::GetCurrent(isolate);
|
||||
if (std::find(pending_next_ticks_.begin(), pending_next_ticks_.end(), env) !=
|
||||
pending_next_ticks_.end())
|
||||
return;
|
||||
|
||||
pending_next_ticks_.push_back(env);
|
||||
uv_async_send(&call_next_tick_async_);
|
||||
}
|
||||
|
||||
// static
|
||||
void AtomBindings::OnCallNextTick(uv_async_t* handle) {
|
||||
AtomBindings* self = static_cast<AtomBindings*>(handle->data);
|
||||
for (std::list<node::Environment*>::const_iterator it =
|
||||
self->pending_next_ticks_.begin();
|
||||
it != self->pending_next_ticks_.end(); ++it) {
|
||||
node::Environment* env = *it;
|
||||
node::Environment::TickInfo* tick_info = env->tick_info();
|
||||
|
||||
v8::Context::Scope context_scope(env->context());
|
||||
if (tick_info->in_tick())
|
||||
continue;
|
||||
|
||||
if (tick_info->length() == 0) {
|
||||
tick_info->set_index(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
tick_info->set_in_tick(true);
|
||||
env->tick_callback_function()->Call(env->process_object(), 0, NULL);
|
||||
tick_info->set_in_tick(false);
|
||||
}
|
||||
|
||||
self->pending_next_ticks_.clear();
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -5,10 +5,15 @@
|
||||
#ifndef ATOM_COMMON_API_ATOM_BINDINGS_H_
|
||||
#define ATOM_COMMON_API_ATOM_BINDINGS_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/callback_forward.h"
|
||||
#include <list>
|
||||
|
||||
#include "base/strings/string16.h"
|
||||
#include "v8/include/v8.h"
|
||||
#include "vendor/node/deps/uv/include/uv.h"
|
||||
|
||||
namespace node {
|
||||
class Environment;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -22,6 +27,13 @@ class AtomBindings {
|
||||
virtual void BindTo(v8::Isolate* isolate, v8::Handle<v8::Object> process);
|
||||
|
||||
private:
|
||||
void ActivateUVLoop(v8::Isolate* isolate);
|
||||
|
||||
static void OnCallNextTick(uv_async_t* handle);
|
||||
|
||||
uv_async_t call_next_tick_async_;
|
||||
std::list<node::Environment*> pending_next_ticks_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBindings);
|
||||
};
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#define ATOM_VERSION_H
|
||||
|
||||
#define ATOM_MAJOR_VERSION 0
|
||||
#define ATOM_MINOR_VERSION 15
|
||||
#define ATOM_PATCH_VERSION 7
|
||||
#define ATOM_MINOR_VERSION 16
|
||||
#define ATOM_PATCH_VERSION 1
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#ifndef ATOM_COMMON_CHROME_VERSION_H_
|
||||
#define ATOM_COMMON_CHROME_VERSION_H_
|
||||
|
||||
#define CHROME_VERSION_STRING "36.0.1985.125"
|
||||
#define CHROME_VERSION_STRING "37.0.2062.102"
|
||||
#define CHROME_VERSION "v" CHROME_VERSION_STRING
|
||||
|
||||
#endif // ATOM_COMMON_CHROME_VERSION_H_
|
||||
|
||||
@@ -1,33 +1,34 @@
|
||||
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
|
||||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Get basic type definitions.
|
||||
#define IPC_MESSAGE_IMPL
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/common_message_generator.h"
|
||||
|
||||
// Generate constructors.
|
||||
#include "ipc/struct_constructor_macros.h"
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/common_message_generator.h"
|
||||
|
||||
// Generate destructors.
|
||||
#include "ipc/struct_destructor_macros.h"
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/common_message_generator.h"
|
||||
|
||||
// Generate param traits write methods.
|
||||
#include "ipc/param_traits_write_macros.h"
|
||||
namespace IPC {
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/common_message_generator.h"
|
||||
} // namespace IPC
|
||||
|
||||
// Generate param traits read methods.
|
||||
#include "ipc/param_traits_read_macros.h"
|
||||
namespace IPC {
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/common_message_generator.h"
|
||||
} // namespace IPC
|
||||
|
||||
// Generate param traits log methods.
|
||||
#include "ipc/param_traits_log_macros.h"
|
||||
namespace IPC {
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/common_message_generator.h"
|
||||
} // namespace IPC
|
||||
|
||||
8
atom/common/common_message_generator.h
Normal file
8
atom/common/common_message_generator.h
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Multiply-included file, no traditional include guard.
|
||||
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "chrome/common/print_messages.h"
|
||||
@@ -51,6 +51,12 @@ const char kZoomFactor[] = "zoom-factor";
|
||||
// The menu bar is hidden unless "Alt" is pressed.
|
||||
const char kAutoHideMenuBar[] = "auto-hide-menu-bar";
|
||||
|
||||
// Enable window to be resized larger than screen.
|
||||
const char kEnableLargerThanScreen[] = "enable-larger-than-screen";
|
||||
|
||||
// Forces to use dark theme on Linux.
|
||||
const char kDarkTheme[] = "dark-theme";
|
||||
|
||||
} // namespace switches
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -33,6 +33,8 @@ extern const char kUseContentSize[];
|
||||
extern const char kWebPreferences[];
|
||||
extern const char kZoomFactor[];
|
||||
extern const char kAutoHideMenuBar[];
|
||||
extern const char kEnableLargerThanScreen[];
|
||||
extern const char kDarkTheme[];
|
||||
|
||||
} // namespace switches
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ void XDGUtil(const std::string& util, const std::string& arg) {
|
||||
argv.push_back(arg);
|
||||
|
||||
base::LaunchOptions options;
|
||||
options.allow_new_privs = true;
|
||||
// xdg-open can fall back on mailcap which eventually might plumb through
|
||||
// to a command that needs a terminal. Set the environment variable telling
|
||||
// it that we definitely don't have a terminal available and that it should
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef ATOM_RENDERER_ATOM_RENDER_VIEW_OBSERVER_H_
|
||||
#define ATOM_RENDERER_ATOM_RENDER_VIEW_OBSERVER_H_
|
||||
|
||||
#include "base/strings/string16.h"
|
||||
#include "content/public/renderer/render_view_observer.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
@@ -11,12 +11,15 @@
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "atom/renderer/api/atom_renderer_bindings.h"
|
||||
#include "atom/renderer/atom_render_view_observer.h"
|
||||
#include "chrome/renderer/printing/print_web_view_helper.h"
|
||||
#include "content/public/renderer/render_frame.h"
|
||||
#include "content/public/renderer/render_frame_observer.h"
|
||||
#include "content/public/renderer/render_thread.h"
|
||||
#include "base/command_line.h"
|
||||
#include "native_mate/converter.h"
|
||||
#include "third_party/WebKit/public/web/WebDocument.h"
|
||||
#include "third_party/WebKit/public/web/WebFrame.h"
|
||||
#include "third_party/WebKit/public/web/WebKit.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
@@ -82,7 +85,7 @@ AtomRendererClient::AtomRendererClient()
|
||||
AtomRendererClient::~AtomRendererClient() {
|
||||
}
|
||||
|
||||
void AtomRendererClient::RenderThreadStarted() {
|
||||
void AtomRendererClient::WebKitInitialized() {
|
||||
if (!IsNodeBindingEnabled())
|
||||
return;
|
||||
|
||||
@@ -93,18 +96,23 @@ void AtomRendererClient::RenderThreadStarted() {
|
||||
|
||||
// Create a default empty environment which would be used when we need to
|
||||
// run V8 code out of a window context (like running a uv callback).
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
v8::Isolate* isolate = blink::mainThreadIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||
global_env = node::Environment::New(context);
|
||||
}
|
||||
|
||||
void AtomRendererClient::RenderThreadStarted() {
|
||||
content::RenderThread::Get()->AddObserver(this);
|
||||
}
|
||||
|
||||
void AtomRendererClient::RenderFrameCreated(
|
||||
content::RenderFrame* render_frame) {
|
||||
new AtomRenderFrameObserver(render_frame, this);
|
||||
}
|
||||
|
||||
void AtomRendererClient::RenderViewCreated(content::RenderView* render_view) {
|
||||
new printing::PrintWebViewHelper(render_view);
|
||||
new AtomRenderViewObserver(render_view, this);
|
||||
}
|
||||
|
||||
@@ -197,6 +205,10 @@ bool AtomRendererClient::IsNodeBindingEnabled(blink::WebFrame* frame) {
|
||||
// Node integration is enabled in main frame unless explictly disabled.
|
||||
else if (frame == main_frame_)
|
||||
return true;
|
||||
// Enable node integration in chrome extensions.
|
||||
else if (frame != NULL &&
|
||||
GURL(frame->document().url()).SchemeIs("chrome-extension"))
|
||||
return true;
|
||||
else if (node_integration_ == MANUAL_ENABLE_IFRAME &&
|
||||
frame != NULL &&
|
||||
frame->uniqueName().utf8().find(kSecurityEnableNodeIntegration)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "content/public/renderer/content_renderer_client.h"
|
||||
#include "content/public/renderer/render_process_observer.h"
|
||||
|
||||
namespace node {
|
||||
class Environment;
|
||||
@@ -19,7 +20,8 @@ namespace atom {
|
||||
class AtomRendererBindings;
|
||||
class NodeBindings;
|
||||
|
||||
class AtomRendererClient : public content::ContentRendererClient {
|
||||
class AtomRendererClient : public content::ContentRendererClient,
|
||||
public content::RenderProcessObserver {
|
||||
public:
|
||||
AtomRendererClient();
|
||||
virtual ~AtomRendererClient();
|
||||
@@ -41,6 +43,9 @@ class AtomRendererClient : public content::ContentRendererClient {
|
||||
DISABLE,
|
||||
};
|
||||
|
||||
// content::RenderProcessObserver:
|
||||
virtual void WebKitInitialized() OVERRIDE;
|
||||
|
||||
// content::ContentRendererClient:
|
||||
virtual void RenderThreadStarted() OVERRIDE;
|
||||
virtual void RenderFrameCreated(content::RenderFrame* render_frame) OVERRIDE;
|
||||
|
||||
10
atom/renderer/lib/chrome-api.coffee
Normal file
10
atom/renderer/lib/chrome-api.coffee
Normal file
@@ -0,0 +1,10 @@
|
||||
url = require 'url'
|
||||
|
||||
chrome = window.chrome = window.chrome || {}
|
||||
chrome.extension =
|
||||
getURL: (path) ->
|
||||
url.format
|
||||
protocol: location.protocol
|
||||
slashes: true
|
||||
hostname: location.hostname
|
||||
pathname: path
|
||||
@@ -46,6 +46,9 @@ else
|
||||
if location.protocol is 'chrome-devtools:'
|
||||
# Override some inspector APIs.
|
||||
require path.join(__dirname, 'inspector')
|
||||
else if location.protocol is 'chrome-extension:'
|
||||
# Add implementations of chrome API.
|
||||
require path.join(__dirname, 'chrome-api')
|
||||
else
|
||||
# Override default web functions.
|
||||
require path.join(__dirname, 'override')
|
||||
|
||||
28
chromium_src/chrome/browser/browser_process.cc
Normal file
28
chromium_src/chrome/browser/browser_process.cc
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2012 The Chromium 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 "chrome/browser/browser_process.h"
|
||||
|
||||
#include "chrome/browser/printing/print_job_manager.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
BrowserProcess* g_browser_process = NULL;
|
||||
|
||||
BrowserProcess::BrowserProcess() {
|
||||
g_browser_process = this;
|
||||
|
||||
print_job_manager_.reset(new printing::PrintJobManager);
|
||||
}
|
||||
|
||||
BrowserProcess::~BrowserProcess() {
|
||||
g_browser_process = NULL;
|
||||
}
|
||||
|
||||
std::string BrowserProcess::GetApplicationLocale() {
|
||||
return l10n_util::GetApplicationLocale("");
|
||||
}
|
||||
|
||||
printing::PrintJobManager* BrowserProcess::print_job_manager() {
|
||||
return print_job_manager_.get();
|
||||
}
|
||||
41
chromium_src/chrome/browser/browser_process.h
Normal file
41
chromium_src/chrome/browser/browser_process.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// This interface is for managing the global services of the application. Each
|
||||
// service is lazily created when requested the first time. The service getters
|
||||
// will return NULL if the service is not available, so callers must check for
|
||||
// this condition.
|
||||
|
||||
#ifndef CHROME_BROWSER_BROWSER_PROCESS_H_
|
||||
#define CHROME_BROWSER_BROWSER_PROCESS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
|
||||
namespace printing {
|
||||
class PrintJobManager;
|
||||
}
|
||||
|
||||
// NOT THREAD SAFE, call only from the main thread.
|
||||
// These functions shouldn't return NULL unless otherwise noted.
|
||||
class BrowserProcess {
|
||||
public:
|
||||
BrowserProcess();
|
||||
~BrowserProcess();
|
||||
|
||||
std::string GetApplicationLocale();
|
||||
|
||||
printing::PrintJobManager* print_job_manager();
|
||||
|
||||
private:
|
||||
scoped_ptr<printing::PrintJobManager> print_job_manager_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserProcess);
|
||||
};
|
||||
|
||||
extern BrowserProcess* g_browser_process;
|
||||
|
||||
#endif // CHROME_BROWSER_BROWSER_PROCESS_H_
|
||||
949
chromium_src/chrome/browser/chrome_notification_types.h
Normal file
949
chromium_src/chrome/browser/chrome_notification_types.h
Normal file
@@ -0,0 +1,949 @@
|
||||
// Copyright 2012 The Chromium 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 CHROME_BROWSER_CHROME_NOTIFICATION_TYPES_H_
|
||||
#define CHROME_BROWSER_CHROME_NOTIFICATION_TYPES_H_
|
||||
|
||||
#include "build/build_config.h"
|
||||
#include "content/public/browser/notification_types.h"
|
||||
|
||||
namespace chrome {
|
||||
|
||||
enum NotificationType {
|
||||
NOTIFICATION_CHROME_START = content::NOTIFICATION_CONTENT_END,
|
||||
|
||||
// Browser-window ----------------------------------------------------------
|
||||
|
||||
// This message is sent after a window has been opened. The source is a
|
||||
// Source<Browser> containing the affected Browser. No details are
|
||||
// expected.
|
||||
NOTIFICATION_BROWSER_OPENED = NOTIFICATION_CHROME_START,
|
||||
|
||||
// This message is sent soon after BROWSER_OPENED, and indicates that
|
||||
// the Browser's |window_| is now non-NULL. The source is a Source<Browser>
|
||||
// containing the affected Browser. No details are expected.
|
||||
NOTIFICATION_BROWSER_WINDOW_READY,
|
||||
|
||||
// This message is sent when a browser is closing. The source is a
|
||||
// Source<Browser> containing the affected Browser. No details are expected.
|
||||
// This is sent prior to BROWSER_CLOSED, and may be sent more than once for a
|
||||
// particular browser.
|
||||
NOTIFICATION_BROWSER_CLOSING,
|
||||
|
||||
// This message is sent after a window has been closed. The source is a
|
||||
// Source<Browser> containing the affected Browser. No details are exptected.
|
||||
NOTIFICATION_BROWSER_CLOSED,
|
||||
|
||||
// This message is sent when closing a browser has been cancelled, either by
|
||||
// the user cancelling a beforeunload dialog, or IsClosingPermitted()
|
||||
// disallowing closing. This notification implies that no BROWSER_CLOSING or
|
||||
// BROWSER_CLOSED notification will be sent.
|
||||
// The source is a Source<Browser> containing the affected browser. No details
|
||||
// are expected.
|
||||
NOTIFICATION_BROWSER_CLOSE_CANCELLED,
|
||||
|
||||
// Indicates that a top window has been closed. The source is the HWND
|
||||
// that was closed, no details are expected.
|
||||
NOTIFICATION_WINDOW_CLOSED,
|
||||
|
||||
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
|
||||
// On Linux maximize can be an asynchronous operation. This notification
|
||||
// indicates that the window has been maximized. The source is
|
||||
// a Source<BrowserWindow> containing the BrowserWindow that was maximized.
|
||||
// No details are expected.
|
||||
NOTIFICATION_BROWSER_WINDOW_MAXIMIZED,
|
||||
#endif
|
||||
|
||||
// Sent when the language (English, French...) for a page has been detected.
|
||||
// The details Details<std::string> contain the ISO 639-1 language code and
|
||||
// the source is Source<WebContents>.
|
||||
NOTIFICATION_TAB_LANGUAGE_DETERMINED,
|
||||
|
||||
// Sent when a page has been translated. The source is the tab for that page
|
||||
// (Source<WebContents>) and the details are the language the page was
|
||||
// originally in and the language it was translated to
|
||||
// (std::pair<std::string, std::string>).
|
||||
NOTIFICATION_PAGE_TRANSLATED,
|
||||
|
||||
// The user has changed the browser theme. The source is a
|
||||
// Source<ThemeService>. There are no details.
|
||||
NOTIFICATION_BROWSER_THEME_CHANGED,
|
||||
|
||||
#if defined(USE_AURA)
|
||||
// The user has changed the fling curve configuration.
|
||||
// Source<GesturePrefsObserver>. There are no details.
|
||||
NOTIFICATION_BROWSER_FLING_CURVE_PARAMETERS_CHANGED,
|
||||
#endif // defined(USE_AURA)
|
||||
|
||||
// Sent when the renderer returns focus to the browser, as part of focus
|
||||
// traversal. The source is the browser, there are no details.
|
||||
NOTIFICATION_FOCUS_RETURNED_TO_BROWSER,
|
||||
|
||||
// A new tab is created from an existing tab to serve as a target of a
|
||||
// navigation that is about to happen. The source will be a Source<Profile>
|
||||
// corresponding to the profile in which the new tab will live. Details in
|
||||
// the form of a RetargetingDetails object are provided.
|
||||
NOTIFICATION_RETARGETING,
|
||||
|
||||
// Application-wide ----------------------------------------------------------
|
||||
|
||||
// This message is sent when the application is terminating (the last
|
||||
// browser window has shutdown as part of an explicit user-initiated exit,
|
||||
// or the user closed the last browser window on Windows/Linux and there are
|
||||
// no BackgroundContents keeping the browser running). No source or details
|
||||
// are passed.
|
||||
NOTIFICATION_APP_TERMINATING,
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// This notification is sent when the app has no key window, such as when
|
||||
// all windows are closed but the app is still active. No source or details
|
||||
// are provided.
|
||||
NOTIFICATION_NO_KEY_WINDOW,
|
||||
#endif
|
||||
|
||||
// This is sent when the user has chosen to exit the app, but before any
|
||||
// browsers have closed. This is sent if the user chooses to exit (via exit
|
||||
// menu item or keyboard shortcut) or to restart the process (such as in flags
|
||||
// page), not if Chrome exits by some other means (such as the user closing
|
||||
// the last window). No source or details are passed.
|
||||
//
|
||||
// Note that receiving this notification does not necessarily mean the process
|
||||
// will exit because the shutdown process can be cancelled by an unload
|
||||
// handler. Use APP_TERMINATING for such needs.
|
||||
NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
|
||||
|
||||
// Application-modal dialogs -----------------------------------------------
|
||||
|
||||
// Sent after an application-modal dialog has been shown. The source
|
||||
// is the dialog.
|
||||
NOTIFICATION_APP_MODAL_DIALOG_SHOWN,
|
||||
|
||||
// This message is sent when a new InfoBar has been added to an
|
||||
// InfoBarService. The source is a Source<InfoBarService> with a pointer to
|
||||
// the InfoBarService the InfoBar was added to. The details is a
|
||||
// Details<InfoBar::AddedDetails>.
|
||||
NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
|
||||
|
||||
// This message is sent when an InfoBar is about to be removed from an
|
||||
// InfoBarService. The source is a Source<InfoBarService> with a pointer to
|
||||
// the InfoBarService the InfoBar was removed from. The details is a
|
||||
// Details<InfoBar::RemovedDetails>.
|
||||
NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
|
||||
|
||||
// This message is sent when an InfoBar is replacing another infobar in an
|
||||
// InfoBarService. The source is a Source<InfoBarService> with a pointer to
|
||||
// the InfoBarService the InfoBar was removed from. The details is a
|
||||
// Details<InfoBar::ReplacedDetails>.
|
||||
NOTIFICATION_TAB_CONTENTS_INFOBAR_REPLACED,
|
||||
|
||||
// Used to fire notifications about how long various events took to
|
||||
// complete. E.g., this is used to get more fine grained timings from the
|
||||
// new tab page. The source is a WebContents and the details is a
|
||||
// MetricEventDurationDetails.
|
||||
NOTIFICATION_METRIC_EVENT_DURATION,
|
||||
|
||||
// This notification is sent when extensions::TabHelper::SetExtensionApp is
|
||||
// invoked. The source is the extensions::TabHelper SetExtensionApp was
|
||||
// invoked on.
|
||||
NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED,
|
||||
|
||||
// Tabs --------------------------------------------------------------------
|
||||
|
||||
// Sent when a tab is added to a WebContentsDelegate. The source is the
|
||||
// WebContentsDelegate and the details is the added WebContents.
|
||||
NOTIFICATION_TAB_ADDED,
|
||||
|
||||
// This notification is sent after a tab has been appended to the tab_strip.
|
||||
// The source is a Source<WebContents> of the tab being added. There
|
||||
// are no details.
|
||||
NOTIFICATION_TAB_PARENTED,
|
||||
|
||||
// This message is sent before a tab has been closed. The source is a
|
||||
// Source<NavigationController> with a pointer to the controller for the
|
||||
// closed tab. No details are expected.
|
||||
//
|
||||
// See also content::NOTIFICATION_WEB_CONTENTS_DESTROYED, which is sent when
|
||||
// the WebContents containing the NavigationController is destroyed.
|
||||
NOTIFICATION_TAB_CLOSING,
|
||||
|
||||
// Stuff inside the tabs ---------------------------------------------------
|
||||
|
||||
// This notification is sent when the result of a find-in-page search is
|
||||
// available with the browser process. The source is a Source<WebContents>.
|
||||
// Details encompass a FindNotificationDetail object that tells whether the
|
||||
// match was found or not found.
|
||||
NOTIFICATION_FIND_RESULT_AVAILABLE,
|
||||
|
||||
// BackgroundContents ------------------------------------------------------
|
||||
|
||||
// A new background contents was opened by script. The source is the parent
|
||||
// profile and the details are BackgroundContentsOpenedDetails.
|
||||
NOTIFICATION_BACKGROUND_CONTENTS_OPENED,
|
||||
|
||||
// The background contents navigated to a new location. The source is the
|
||||
// parent Profile, and the details are the BackgroundContents that was
|
||||
// navigated.
|
||||
NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED,
|
||||
|
||||
// The background contents were closed by someone invoking window.close()
|
||||
// or the parent application was uninstalled.
|
||||
// The source is the parent profile, and the details are the
|
||||
// BackgroundContents.
|
||||
NOTIFICATION_BACKGROUND_CONTENTS_CLOSED,
|
||||
|
||||
// The background contents is being deleted. The source is the
|
||||
// parent Profile, and the details are the BackgroundContents being deleted.
|
||||
NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
|
||||
|
||||
// The background contents has crashed. The source is the parent Profile,
|
||||
// and the details are the BackgroundContents.
|
||||
NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED,
|
||||
|
||||
// The background contents associated with a hosted app has changed (either
|
||||
// a new background contents has been created, or an existing background
|
||||
// contents has closed). The source is the parent Profile, and the details
|
||||
// are the BackgroundContentsService.
|
||||
NOTIFICATION_BACKGROUND_CONTENTS_SERVICE_CHANGED,
|
||||
|
||||
// Chrome has entered/exited background mode. The source is the
|
||||
// BackgroundModeManager and the details are a boolean value which is set to
|
||||
// true if Chrome is now in background mode.
|
||||
NOTIFICATION_BACKGROUND_MODE_CHANGED,
|
||||
|
||||
// This is sent when a login prompt is shown. The source is the
|
||||
// Source<NavigationController> for the tab in which the prompt is shown.
|
||||
// Details are a LoginNotificationDetails which provide the LoginHandler
|
||||
// that should be given authentication.
|
||||
NOTIFICATION_AUTH_NEEDED,
|
||||
|
||||
// This is sent when authentication credentials have been supplied (either
|
||||
// by the user or by an automation service), but before we've actually
|
||||
// received another response from the server. The source is the
|
||||
// Source<NavigationController> for the tab in which the prompt was shown.
|
||||
// Details are an AuthSuppliedLoginNotificationDetails which provide the
|
||||
// LoginHandler that should be given authentication as well as the supplied
|
||||
// username and password.
|
||||
NOTIFICATION_AUTH_SUPPLIED,
|
||||
|
||||
// This is sent when an authentication request has been dismissed without
|
||||
// supplying credentials (either by the user or by an automation service).
|
||||
// The source is the Source<NavigationController> for the tab in which the
|
||||
// prompt was shown. Details are a LoginNotificationDetails which provide
|
||||
// the LoginHandler that should be cancelled.
|
||||
NOTIFICATION_AUTH_CANCELLED,
|
||||
|
||||
// History -----------------------------------------------------------------
|
||||
|
||||
// Sent when a history service has finished loading. The source is the
|
||||
// profile that the history service belongs to, and the details is the
|
||||
// HistoryService.
|
||||
NOTIFICATION_HISTORY_LOADED,
|
||||
|
||||
// Sent when a URL has been added or modified. This is used by the in-memory
|
||||
// URL database and the InMemoryURLIndex (both used by autocomplete) to track
|
||||
// changes to the main history system.
|
||||
//
|
||||
// The source is the profile owning the history service that changed, and
|
||||
// the details is history::URLsModifiedDetails that lists the modified or
|
||||
// added URLs.
|
||||
NOTIFICATION_HISTORY_URLS_MODIFIED,
|
||||
|
||||
// Sent when the user visits a URL.
|
||||
//
|
||||
// The source is the profile owning the history service that changed, and
|
||||
// the details is history::URLVisitedDetails.
|
||||
NOTIFICATION_HISTORY_URL_VISITED,
|
||||
|
||||
// Sent when one or more URLs are deleted.
|
||||
//
|
||||
// The source is the profile owning the history service that changed, and
|
||||
// the details is history::URLsDeletedDetails that lists the deleted URLs.
|
||||
NOTIFICATION_HISTORY_URLS_DELETED,
|
||||
|
||||
// Sent when a keyword search term is updated. The source is the Profile and
|
||||
// the details is history::KeywordSearchUpdatedDetails.
|
||||
NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED,
|
||||
|
||||
// Sent when a keyword search term is deleted. The source is the Profile and
|
||||
// the details is history::KeywordSearchDeletedDetails.
|
||||
NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED,
|
||||
|
||||
// Sent by history when the favicon of a URL changes. The source is the
|
||||
// profile, and the details is FaviconChangedDetails (see
|
||||
// chrome/browser/favicon/favicon_changed_details.h).
|
||||
NOTIFICATION_FAVICON_CHANGED,
|
||||
|
||||
// Sent by FaviconTabHelper when a tab's favicon has been successfully
|
||||
// updated. The details are a bool indicating whether the
|
||||
// NavigationEntry's favicon URL has changed since the previous
|
||||
// NOTIFICATION_FAVICON_UPDATED notification. The details are true if
|
||||
// there was no previous NOTIFICATION_FAVICON_UPDATED notification for the
|
||||
// current NavigationEntry.
|
||||
NOTIFICATION_FAVICON_UPDATED,
|
||||
|
||||
// Profiles -----------------------------------------------------------------
|
||||
|
||||
// Sent after a Profile has been created. This notification is sent both for
|
||||
// normal and OTR profiles.
|
||||
// The details are none and the source is the new profile.
|
||||
NOTIFICATION_PROFILE_CREATED,
|
||||
|
||||
// Sent after a Profile has been added to ProfileManager.
|
||||
// The details are none and the source is the new profile.
|
||||
NOTIFICATION_PROFILE_ADDED,
|
||||
|
||||
// Sent before a Profile is destroyed. This notification is sent both for
|
||||
// normal and OTR profiles.
|
||||
// The details are none and the source is a Profile*.
|
||||
NOTIFICATION_PROFILE_DESTROYED,
|
||||
|
||||
// Sent after the URLRequestContextGetter for a Profile has been initialized.
|
||||
// The details are none and the source is a Profile*.
|
||||
NOTIFICATION_PROFILE_URL_REQUEST_CONTEXT_GETTER_INITIALIZED,
|
||||
|
||||
// TopSites ----------------------------------------------------------------
|
||||
|
||||
// Sent by TopSites when it finishes loading. The source is the profile the
|
||||
// details the TopSites.
|
||||
NOTIFICATION_TOP_SITES_LOADED,
|
||||
|
||||
// Sent by TopSites when the either one of the most visited urls changed, or
|
||||
// one of the images changes. The source is the TopSites, the details not
|
||||
// used.
|
||||
NOTIFICATION_TOP_SITES_CHANGED,
|
||||
|
||||
// Task Manager ------------------------------------------------------------
|
||||
|
||||
// Sent when a renderer process is notified of new v8 heap statistics. The
|
||||
// source is the ID of the renderer process, and the details are a
|
||||
// V8HeapStatsDetails object.
|
||||
NOTIFICATION_RENDERER_V8_HEAP_STATS_COMPUTED,
|
||||
|
||||
// Non-history storage services --------------------------------------------
|
||||
|
||||
// Sent when a TemplateURL is removed from the model. The source is the
|
||||
// Profile, and the details the id of the TemplateURL being removed.
|
||||
NOTIFICATION_TEMPLATE_URL_REMOVED,
|
||||
|
||||
// Sent when the prefs relating to the default search engine have changed due
|
||||
// to policy. Source and details are unused.
|
||||
NOTIFICATION_DEFAULT_SEARCH_POLICY_CHANGED,
|
||||
|
||||
// The state of a web resource has been changed. A resource may have been
|
||||
// added, removed, or altered. Source is WebResourceService, and the
|
||||
// details are NoDetails.
|
||||
NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED,
|
||||
|
||||
// A safe browsing database update completed. Source is the
|
||||
// SafeBrowsingService and the details are a bool indicating whether the
|
||||
// update was successful.
|
||||
NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE,
|
||||
|
||||
// Autocomplete ------------------------------------------------------------
|
||||
|
||||
// Sent by the autocomplete controller when done. The source is the
|
||||
// AutocompleteController, the details not used.
|
||||
NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY,
|
||||
|
||||
// This is sent when an item of the Omnibox popup is selected. The source
|
||||
// is the profile.
|
||||
NOTIFICATION_OMNIBOX_OPENED_URL,
|
||||
|
||||
// This is sent from Instant when the omnibox focus state changes.
|
||||
NOTIFICATION_OMNIBOX_FOCUS_CHANGED,
|
||||
|
||||
// Sent when the Google URL for a profile has been updated. Some services
|
||||
// cache this value and need to update themselves when it changes. See
|
||||
// google_util::GetGoogleURLAndUpdateIfNecessary(). The source is the
|
||||
// Profile, the details a GoogleURLTracker::UpdatedDetails containing the old
|
||||
// and new URLs.
|
||||
//
|
||||
// Note that because incognito mode requests for the GoogleURLTracker are
|
||||
// redirected to the non-incognito profile's copy, this notification will only
|
||||
// ever fire on non-incognito profiles; thus listeners should use
|
||||
// GetOriginalProfile() when constructing a Source to filter against.
|
||||
NOTIFICATION_GOOGLE_URL_UPDATED,
|
||||
|
||||
// Printing ----------------------------------------------------------------
|
||||
|
||||
// Notification from PrintJob that an event occurred. It can be that a page
|
||||
// finished printing or that the print job failed. Details is
|
||||
// PrintJob::EventDetails. Source is a PrintJob.
|
||||
NOTIFICATION_PRINT_JOB_EVENT,
|
||||
|
||||
// Sent when a PrintJob has been released.
|
||||
// Source is the WebContents that holds the print job.
|
||||
NOTIFICATION_PRINT_JOB_RELEASED,
|
||||
|
||||
// Shutdown ----------------------------------------------------------------
|
||||
|
||||
// Sent when WM_ENDSESSION has been received, after the browsers have been
|
||||
// closed but before browser process has been shutdown. The source/details
|
||||
// are all source and no details.
|
||||
NOTIFICATION_SESSION_END,
|
||||
|
||||
// User Scripts ------------------------------------------------------------
|
||||
|
||||
// Sent when there are new user scripts available. The details are a
|
||||
// pointer to SharedMemory containing the new scripts.
|
||||
NOTIFICATION_USER_SCRIPTS_UPDATED,
|
||||
|
||||
// Extensions --------------------------------------------------------------
|
||||
|
||||
// Sent when a CrxInstaller finishes. Source is the CrxInstaller that
|
||||
// finished. The details are the extension which was installed.
|
||||
NOTIFICATION_CRX_INSTALLER_DONE,
|
||||
|
||||
// Sent when the known installed extensions have all been loaded. In
|
||||
// testing scenarios this can happen multiple times if extensions are
|
||||
// unloaded and reloaded. The source is a Profile.
|
||||
NOTIFICATION_EXTENSIONS_READY,
|
||||
|
||||
// Sent when an extension icon being displayed in the location bar is updated.
|
||||
// The source is the Profile and the details are the WebContents for
|
||||
// the tab.
|
||||
NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED,
|
||||
|
||||
// DEPRECATED: Use ExtensionRegistry::AddObserver instead.
|
||||
//
|
||||
// Sent when a new extension is loaded. The details are an Extension, and
|
||||
// the source is a Profile.
|
||||
NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
|
||||
|
||||
// An error occured while attempting to load an extension. The details are a
|
||||
// string with details about why the load failed.
|
||||
NOTIFICATION_EXTENSION_LOAD_ERROR,
|
||||
|
||||
// Sent when an extension is enabled. Under most circumstances, listeners
|
||||
// will want to use NOTIFICATION_EXTENSION_LOADED_DEPRECATED. This
|
||||
// notification is only
|
||||
// fired when the "Enable" button is hit in the extensions tab. The details
|
||||
// are an Extension, and the source is a Profile.
|
||||
NOTIFICATION_EXTENSION_ENABLED,
|
||||
|
||||
// Sent when attempting to load a new extension, but they are disabled. The
|
||||
// details are an Extension*, and the source is a Profile*.
|
||||
NOTIFICATION_EXTENSION_UPDATE_DISABLED,
|
||||
|
||||
// Sent when an extension's permissions change. The details are an
|
||||
// UpdatedExtensionPermissionsInfo, and the source is a Profile.
|
||||
NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
|
||||
|
||||
// Sent when new extensions are installed, or existing extensions are updated.
|
||||
// The details are an InstalledExtensionInfo, and the source is a Profile.
|
||||
NOTIFICATION_EXTENSION_INSTALLED,
|
||||
|
||||
// An error occured during extension install. The details are a string with
|
||||
// details about why the install failed.
|
||||
NOTIFICATION_EXTENSION_INSTALL_ERROR,
|
||||
|
||||
// Sent when an extension has been uninstalled. The details are an Extension,
|
||||
// and the source is a Profile.
|
||||
NOTIFICATION_EXTENSION_UNINSTALLED,
|
||||
|
||||
// Sent when an extension uninstall is not allowed because the extension is
|
||||
// not user manageable. The details are an Extension, and the source is a
|
||||
// Profile.
|
||||
NOTIFICATION_EXTENSION_UNINSTALL_NOT_ALLOWED,
|
||||
|
||||
// DEPRECATED: Use ExtensionRegistry::AddObserver instead.
|
||||
//
|
||||
// Sent when an extension is unloaded. This happens when an extension is
|
||||
// uninstalled or disabled. The details are an UnloadedExtensionInfo, and
|
||||
// the source is a Profile.
|
||||
//
|
||||
// Note that when this notification is sent, ExtensionService has already
|
||||
// removed the extension from its internal state.
|
||||
NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
|
||||
|
||||
// Sent when an Extension object is removed from ExtensionService. This
|
||||
// can happen when an extension is uninstalled, upgraded, or blacklisted,
|
||||
// including all cases when the Extension is deleted. The details are an
|
||||
// Extension, and the source is a Profile.
|
||||
NOTIFICATION_EXTENSION_REMOVED,
|
||||
|
||||
// Sent after a new ExtensionHost is created. The details are
|
||||
// an ExtensionHost* and the source is a Profile*.
|
||||
NOTIFICATION_EXTENSION_HOST_CREATED,
|
||||
|
||||
// Sent before an ExtensionHost is destroyed. The details are
|
||||
// an ExtensionHost* and the source is a Profile*.
|
||||
NOTIFICATION_EXTENSION_HOST_DESTROYED,
|
||||
|
||||
// Sent by an ExtensionHost when it has finished its initial page load,
|
||||
// including any external resources.
|
||||
// The details are an ExtensionHost* and the source is a Profile*.
|
||||
NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
|
||||
|
||||
// Sent by an ExtensionHost when its render view requests closing through
|
||||
// window.close(). The details are an ExtensionHost* and the source is a
|
||||
// Profile*.
|
||||
NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
|
||||
|
||||
// Sent when extension render process ends (whether it crashes or closes).
|
||||
// The details are an ExtensionHost* and the source is a Profile*. Not sent
|
||||
// during browser shutdown.
|
||||
NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
|
||||
|
||||
// Sent when a background page is ready so other components can load.
|
||||
NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY,
|
||||
|
||||
// Sent when a browser action's state has changed. The source is the
|
||||
// ExtensionAction* that changed. The details are the Profile* that the
|
||||
// browser action belongs to.
|
||||
NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED,
|
||||
|
||||
// Sent when the count of page actions has changed. Note that some of them
|
||||
// may not apply to the current page. The source is a LocationBar*. There
|
||||
// are no details.
|
||||
NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED,
|
||||
|
||||
// Sent when a browser action's visibility has changed. The source is the
|
||||
// ExtensionPrefs* that changed, and the details are a std::string with the
|
||||
// extension's ID.
|
||||
NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED,
|
||||
|
||||
// Sent when a page action's visibility has changed. The source is the
|
||||
// ExtensionAction* that changed. The details are a WebContents*.
|
||||
NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
|
||||
|
||||
// Sent when a system indicator action's state has changed. The source is the
|
||||
// Profile* that the browser action belongs to. The details are the
|
||||
// ExtensionAction* that changed.
|
||||
NOTIFICATION_EXTENSION_SYSTEM_INDICATOR_UPDATED,
|
||||
|
||||
// Sent when an extension command has been removed. The source is the profile
|
||||
// and the details is a std::pair of two std::string objects (an extension ID
|
||||
// and the name of the command being removed).
|
||||
NOTIFICATION_EXTENSION_COMMAND_REMOVED,
|
||||
|
||||
// Sent when an extension command has been added. The source is the profile
|
||||
// and the details is a std::pair of two std::string objects (an extension ID
|
||||
// and the name of the command being added).
|
||||
NOTIFICATION_EXTENSION_COMMAND_ADDED,
|
||||
|
||||
// Sent when an extension command shortcut for a browser action is activated
|
||||
// on Mac. The source is the profile and the details is a std::pair of a
|
||||
// std::string containing an extension ID and a gfx::NativeWindow for the
|
||||
// associated window.
|
||||
NOTIFICATION_EXTENSION_COMMAND_BROWSER_ACTION_MAC,
|
||||
|
||||
// Sent when an extension command shortcut for a page action is activated
|
||||
// on Mac. The source is the profile and the details is a std::pair of a
|
||||
// std::string containing an extension ID and a gfx::NativeWindow for the
|
||||
// associated window.
|
||||
NOTIFICATION_EXTENSION_COMMAND_PAGE_ACTION_MAC,
|
||||
|
||||
// A new extension RenderViewHost has been registered. The details are
|
||||
// the RenderViewHost*.
|
||||
NOTIFICATION_EXTENSION_VIEW_REGISTERED,
|
||||
|
||||
// An extension RenderViewHost has been unregistered. The details are
|
||||
// the RenderViewHost*.
|
||||
NOTIFICATION_EXTENSION_VIEW_UNREGISTERED,
|
||||
|
||||
// Sent by an extension to notify the browser about the results of a unit
|
||||
// test.
|
||||
NOTIFICATION_EXTENSION_TEST_PASSED,
|
||||
NOTIFICATION_EXTENSION_TEST_FAILED,
|
||||
|
||||
// Sent by extension test javascript code, typically in a browser test. The
|
||||
// sender is a std::string representing the extension id, and the details
|
||||
// are a std::string with some message. This is particularly useful when you
|
||||
// want to have C++ code wait for javascript code to do something.
|
||||
NOTIFICATION_EXTENSION_TEST_MESSAGE,
|
||||
|
||||
// Sent when an bookmarks extensions API function was successfully invoked.
|
||||
// The source is the id of the extension that invoked the function, and the
|
||||
// details are a pointer to the const BookmarksFunction in question.
|
||||
NOTIFICATION_EXTENSION_BOOKMARKS_API_INVOKED,
|
||||
|
||||
// Sent when a downloads extensions API event is fired. The source is an
|
||||
// ExtensionDownloadsEventRouter::NotificationSource, and the details is a
|
||||
// std::string containing json. Used for testing.
|
||||
NOTIFICATION_EXTENSION_DOWNLOADS_EVENT,
|
||||
|
||||
// Sent when an omnibox extension has sent back omnibox suggestions. The
|
||||
// source is the profile, and the details are an
|
||||
// extensions::api::omnibox::SendSuggestions::Params object.
|
||||
NOTIFICATION_EXTENSION_OMNIBOX_SUGGESTIONS_READY,
|
||||
|
||||
// Sent when the user accepts the input in an extension omnibox keyword
|
||||
// session. The source is the profile.
|
||||
NOTIFICATION_EXTENSION_OMNIBOX_INPUT_ENTERED,
|
||||
|
||||
// Sent when an omnibox extension has updated the default suggestion. The
|
||||
// source is the profile.
|
||||
NOTIFICATION_EXTENSION_OMNIBOX_DEFAULT_SUGGESTION_CHANGED,
|
||||
|
||||
// Sent when the extension updater starts checking for updates to installed
|
||||
// extensions. The source is a Profile, and there are no details.
|
||||
NOTIFICATION_EXTENSION_UPDATING_STARTED,
|
||||
|
||||
// The extension updater found an update and will attempt to download and
|
||||
// install it. The source is a Profile, and the details are an
|
||||
// extensions::UpdateDetails object with the extension id and version of the
|
||||
// found update.
|
||||
NOTIFICATION_EXTENSION_UPDATE_FOUND,
|
||||
|
||||
// Upgrade notifications ---------------------------------------------------
|
||||
|
||||
// Sent when Chrome believes an update has been installed and available for
|
||||
// long enough with the user shutting down to let it take effect. See
|
||||
// upgrade_detector.cc for details on how long it waits. No details are
|
||||
// expected.
|
||||
NOTIFICATION_UPGRADE_RECOMMENDED,
|
||||
|
||||
// Sent when a critical update has been installed. No details are expected.
|
||||
NOTIFICATION_CRITICAL_UPGRADE_INSTALLED,
|
||||
|
||||
// Sent when the current install is outdated. No details are expected.
|
||||
NOTIFICATION_OUTDATED_INSTALL,
|
||||
|
||||
// Sent when the current install is outdated and auto-update (AU) is disabled.
|
||||
// No details are expected.
|
||||
NOTIFICATION_OUTDATED_INSTALL_NO_AU,
|
||||
|
||||
// Software incompatibility notifications ----------------------------------
|
||||
|
||||
// Sent when Chrome has finished compiling the list of loaded modules (and
|
||||
// other modules of interest). No details are expected.
|
||||
NOTIFICATION_MODULE_LIST_ENUMERATED,
|
||||
|
||||
// Sent when Chrome is done scanning the module list and when the user has
|
||||
// acknowledged the module incompatibility. No details are expected.
|
||||
NOTIFICATION_MODULE_INCOMPATIBILITY_BADGE_CHANGE,
|
||||
|
||||
// Content Settings --------------------------------------------------------
|
||||
|
||||
// Sent when content settings change. The source is a HostContentSettings
|
||||
// object, the details are ContentSettingsNotificationsDetails.
|
||||
NOTIFICATION_CONTENT_SETTINGS_CHANGED,
|
||||
|
||||
// Sent when the collect cookies dialog is shown. The source is a
|
||||
// TabSpecificContentSettings object, there are no details.
|
||||
NOTIFICATION_COLLECTED_COOKIES_SHOWN,
|
||||
|
||||
// Sent when a non-default setting in the the notification content settings
|
||||
// map has changed. The source is the DesktopNotificationService, the
|
||||
// details are None.
|
||||
NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
|
||||
|
||||
// Sent when content settings change for a tab. The source is a
|
||||
// content::WebContents object, the details are None.
|
||||
NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
|
||||
|
||||
// Sync --------------------------------------------------------------------
|
||||
|
||||
// The sync service has finished the datatype configuration process. The
|
||||
// source is the ProfileSyncService object of the Profile. There are no
|
||||
// details.
|
||||
NOTIFICATION_SYNC_CONFIGURE_DONE,
|
||||
|
||||
// A service is requesting a sync datatype refresh for the current profile.
|
||||
// The details value is a const syncer::ModelTypeSet.
|
||||
// If the payload map is empty, it should be treated as an invalidation for
|
||||
// all enabled types. This is used by session sync.
|
||||
NOTIFICATION_SYNC_REFRESH_LOCAL,
|
||||
|
||||
// External notification requesting a sync datatype refresh for the current
|
||||
// profile. The details value is a const syncer::ObjectIdInvalidationMap.
|
||||
// If the payload map is empty, it should be treated as an invalidation for
|
||||
// all enabled types. This is used for notifications on Android.
|
||||
NOTIFICATION_SYNC_REFRESH_REMOTE,
|
||||
|
||||
// The session service has been saved. This notification type is only sent
|
||||
// if there were new SessionService commands to save, and not for no-op save
|
||||
// operations.
|
||||
NOTIFICATION_SESSION_SERVICE_SAVED,
|
||||
|
||||
// A foreign session has been updated. If a new tab page is open, the
|
||||
// foreign session handler needs to update the new tab page's foreign
|
||||
// session data.
|
||||
NOTIFICATION_FOREIGN_SESSION_UPDATED,
|
||||
|
||||
// Foreign sessions has been disabled. New tabs should not display foreign
|
||||
// session data.
|
||||
NOTIFICATION_FOREIGN_SESSION_DISABLED,
|
||||
|
||||
// All tab metadata has been loaded from disk asynchronously.
|
||||
// Sent on the UI thread.
|
||||
// The source is the Profile. There are no details.
|
||||
NOTIFICATION_SESSION_RESTORE_COMPLETE,
|
||||
|
||||
// Cookies -----------------------------------------------------------------
|
||||
|
||||
// Sent when a cookie changes. The source is a Profile object, the details
|
||||
// are a ChromeCookieDetails object.
|
||||
NOTIFICATION_COOKIE_CHANGED,
|
||||
|
||||
// Download Notifications --------------------------------------------------
|
||||
|
||||
// Sent when a download is initiated. It is possible that the download will
|
||||
// not actually begin due to the DownloadRequestLimiter cancelling it
|
||||
// prematurely.
|
||||
// The source is the corresponding RenderViewHost. There are no details.
|
||||
NOTIFICATION_DOWNLOAD_INITIATED,
|
||||
|
||||
// Misc --------------------------------------------------------------------
|
||||
|
||||
// Sent when PerformanceMonitor has finished all the initial steps of data
|
||||
// collection and has begun passively observing. The source is the
|
||||
// PerformanceMonitor*. No details are expected.
|
||||
NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED,
|
||||
|
||||
#if defined(OS_CHROMEOS)
|
||||
// Sent when a chromium os user logs in.
|
||||
// The details are a chromeos::User object.
|
||||
NOTIFICATION_LOGIN_USER_CHANGED,
|
||||
|
||||
// Sent immediately after the logged-in user's profile is ready.
|
||||
// The details are a Profile object.
|
||||
NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
|
||||
|
||||
// Sent when the chromium session of a particular user is started.
|
||||
// If this is a new user on the machine this will not be sent until a profile
|
||||
// picture has been selected, unlike NOTIFICATION_LOGIN_USER_CHANGED which is
|
||||
// sent immediately after the user has logged in. This will be sent again if
|
||||
// the browser crashes and restarts.
|
||||
// The details are a chromeos::User object.
|
||||
NOTIFICATION_SESSION_STARTED,
|
||||
|
||||
// Sent when user image is updated.
|
||||
NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
|
||||
|
||||
// Sent by UserManager when a profile image download has been completed.
|
||||
NOTIFICATION_PROFILE_IMAGE_UPDATED,
|
||||
|
||||
// Sent by UserManager when profile image download has failed or user has the
|
||||
// default profile image or no profile image at all. No details are expected.
|
||||
NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED,
|
||||
|
||||
// Sent when a chromium os user attempts to log in. The source is
|
||||
// all and the details are AuthenticationNotificationDetails.
|
||||
NOTIFICATION_LOGIN_AUTHENTICATION,
|
||||
|
||||
// Sent when a network error message is displayed on the WebUI login screen.
|
||||
// First paint event of this fires NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
|
||||
NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
|
||||
|
||||
// Sent when the specific part of login/lock WebUI is considered to be
|
||||
// visible. That moment is tracked as the first paint event after one of the:
|
||||
// NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN
|
||||
//
|
||||
// Possible series of notifications:
|
||||
// 1. Boot into fresh OOBE
|
||||
// NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
|
||||
// 2. Boot into user pods list (normal boot). Same for lock screen.
|
||||
// NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
|
||||
// 3. Boot into GAIA sign in UI (user pods display disabled or no users):
|
||||
// if no network is connected or flaky network
|
||||
// (NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN +
|
||||
// NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE)
|
||||
// NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
|
||||
// 4. Boot into retail mode
|
||||
// NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
|
||||
// 5. Boot into kiosk mode
|
||||
// NOTIFICATION_KIOSK_APP_LAUNCHED
|
||||
NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
|
||||
|
||||
// Sent when proxy dialog is closed.
|
||||
NOTIFICATION_LOGIN_PROXY_CHANGED,
|
||||
|
||||
// Send when kiosk auto-launch warning screen is visible.
|
||||
NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_VISIBLE,
|
||||
|
||||
// Send when kiosk auto-launch warning screen had completed.
|
||||
NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_COMPLETED,
|
||||
|
||||
// Send when enable consumer kiosk warning screen is visible.
|
||||
NOTIFICATION_KIOSK_ENABLE_WARNING_VISIBLE,
|
||||
|
||||
// Send when consumer kiosk has been enabled.
|
||||
NOTIFICATION_KIOSK_ENABLED,
|
||||
|
||||
// Send when enable consumer kiosk warning screen had completed.
|
||||
NOTIFICATION_KIOSK_ENABLE_WARNING_COMPLETED,
|
||||
|
||||
// Sent when kiosk app list is loaded in UI.
|
||||
NOTIFICATION_KIOSK_APPS_LOADED,
|
||||
|
||||
// Sent when a kiosk app is launched.
|
||||
NOTIFICATION_KIOSK_APP_LAUNCHED,
|
||||
|
||||
// Sent when the user list has changed.
|
||||
NOTIFICATION_USER_LIST_CHANGED,
|
||||
|
||||
// Sent when the screen lock state has changed. The source is
|
||||
// ScreenLocker and the details is a bool specifing that the
|
||||
// screen is locked. When details is a false, the source object
|
||||
// is being deleted, so the receiver shouldn't use the screen locker
|
||||
// object.
|
||||
NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
|
||||
|
||||
// Sent by DeviceSettingsService to indicate that the ownership status
|
||||
// changed. If you can, please use DeviceSettingsService::Observer instead.
|
||||
// Other singleton-based services can't use that because Observer
|
||||
// unregistration is impossible due to unpredictable deletion order.
|
||||
NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
|
||||
|
||||
// Sent by SIM unlock dialog when it has finished with the process of
|
||||
// updating RequirePin setting. RequirePin setting might have been changed
|
||||
// to a new value or update might have been canceled.
|
||||
// In either case notification is sent and details contain a bool
|
||||
// that represents current value.
|
||||
NOTIFICATION_REQUIRE_PIN_SETTING_CHANGE_ENDED,
|
||||
|
||||
// Sent by SIM unlock dialog when it has finished the EnterPin or
|
||||
// EnterPuk dialog, either because the user cancelled, or entered a
|
||||
// PIN or PUK.
|
||||
NOTIFICATION_ENTER_PIN_ENDED,
|
||||
#endif
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
// Sent when a bookmark's context menu is shown. Used to notify
|
||||
// tests that the context menu has been created and shown.
|
||||
NOTIFICATION_BOOKMARK_CONTEXT_MENU_SHOWN,
|
||||
|
||||
// Notification that the nested loop using during tab dragging has returned.
|
||||
// Used for testing.
|
||||
NOTIFICATION_TAB_DRAG_LOOP_DONE,
|
||||
#endif
|
||||
|
||||
// Send when a context menu is shown. Used to notify tests that the context
|
||||
// menu has been created and shown.
|
||||
NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_SHOWN,
|
||||
|
||||
// Sent when the Instant Controller determines whether an Instant tab supports
|
||||
// the Instant API or not.
|
||||
NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
|
||||
|
||||
// Sent when the Instant Controller determines whether the NTP supports the
|
||||
// Instant API or not.
|
||||
NOTIFICATION_INSTANT_NTP_SUPPORT_DETERMINED,
|
||||
|
||||
// Sent when the CaptivePortalService checks if we're behind a captive portal.
|
||||
// The Source is the Profile the CaptivePortalService belongs to, and the
|
||||
// Details are a Details<CaptivePortalService::CheckResults>.
|
||||
NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
|
||||
|
||||
// Sent when the applications in the NTP app launcher have been reordered.
|
||||
// The details, if not NoDetails, is the std::string ID of the extension that
|
||||
// was moved.
|
||||
NOTIFICATION_EXTENSION_LAUNCHER_REORDERED,
|
||||
|
||||
// Sent when an app is installed and an NTP has been shown. Source is the
|
||||
// WebContents that was shown, and Details is the string ID of the extension
|
||||
// which was installed.
|
||||
NOTIFICATION_APP_INSTALLED_TO_NTP,
|
||||
|
||||
// Similar to NOTIFICATION_APP_INSTALLED_TO_NTP but used to nofity ash AppList
|
||||
// about installed app. Source is the profile in which the app is installed
|
||||
// and Details is the string ID of the extension.
|
||||
NOTIFICATION_APP_INSTALLED_TO_APPLIST,
|
||||
|
||||
#if defined(USE_ASH)
|
||||
// Sent when wallpaper show animation has finished.
|
||||
NOTIFICATION_WALLPAPER_ANIMATION_FINISHED,
|
||||
|
||||
// Sent when the Ash session has started. In its current incantation this is
|
||||
// generated when the metro app has connected to the browser IPC channel.
|
||||
// Used only on Windows.
|
||||
NOTIFICATION_ASH_SESSION_STARTED,
|
||||
// Sent when the Ash session ended. Currently this means the metro app exited.
|
||||
// Used only on Windows.
|
||||
NOTIFICATION_ASH_SESSION_ENDED,
|
||||
#endif
|
||||
|
||||
// Protocol Handler Registry -----------------------------------------------
|
||||
// Sent when a ProtocolHandlerRegistry is changed. The source is the profile.
|
||||
NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
|
||||
|
||||
// Sent when the cached profile info has changed.
|
||||
NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
|
||||
|
||||
// Sent when the cached profile has finished writing a profile picture to
|
||||
// disk.
|
||||
NOTIFICATION_PROFILE_CACHE_PICTURE_SAVED,
|
||||
|
||||
// Sent when the browser enters or exits fullscreen mode.
|
||||
NOTIFICATION_FULLSCREEN_CHANGED,
|
||||
|
||||
// Sent when the FullscreenController changes, confirms, or denies mouse lock.
|
||||
// The source is the browser's FullscreenController, no details.
|
||||
NOTIFICATION_MOUSE_LOCK_CHANGED,
|
||||
|
||||
// Sent by the PluginPrefs when there is a change of plugin enable/disable
|
||||
// status. The source is the profile.
|
||||
NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED,
|
||||
|
||||
// Panels Notifications. The Panels are small browser windows near the bottom
|
||||
// of the screen.
|
||||
// Sent when all nonblocking bounds animations are finished across panels.
|
||||
// Used only in unit testing.
|
||||
NOTIFICATION_PANEL_BOUNDS_ANIMATIONS_FINISHED,
|
||||
|
||||
// Sent when panel gains/loses focus.
|
||||
// The source is the Panel, no details.
|
||||
// Used only in unit testing.
|
||||
NOTIFICATION_PANEL_CHANGED_ACTIVE_STATUS,
|
||||
|
||||
// Sent when panel is minimized/restored/shows title only etc.
|
||||
// The source is the Panel, no details.
|
||||
NOTIFICATION_PANEL_CHANGED_EXPANSION_STATE,
|
||||
|
||||
// Sent when panel window size is known. This is for platforms where the
|
||||
// window creation is async and size of the window only becomes known later.
|
||||
// Used only in unit testing.
|
||||
NOTIFICATION_PANEL_WINDOW_SIZE_KNOWN,
|
||||
|
||||
// Sent when panel app icon is loaded.
|
||||
// Used only in unit testing.
|
||||
NOTIFICATION_PANEL_APP_ICON_LOADED,
|
||||
|
||||
// Sent when panel collection get updated.
|
||||
// The source is the PanelCollection, no details.
|
||||
// Used only in coordination with notification balloons.
|
||||
NOTIFICATION_PANEL_COLLECTION_UPDATED,
|
||||
|
||||
// Sent when panel is closed.
|
||||
// The source is the Panel, no details.
|
||||
NOTIFICATION_PANEL_CLOSED,
|
||||
|
||||
// Sent when a global error has changed and the error UI should update it
|
||||
// self. The source is a Source<Profile> containing the profile for the
|
||||
// error. The detail is a GlobalError object that has changed or NULL if
|
||||
// all error UIs should update.
|
||||
NOTIFICATION_GLOBAL_ERRORS_CHANGED,
|
||||
|
||||
// BrowsingDataRemover ----------------------------------------------------
|
||||
// Sent on the UI thread after BrowsingDataRemover has removed browsing data
|
||||
// but before it has notified its explicit observers. The source is a
|
||||
// Source<Profile> containing the profile in which browsing data was removed,
|
||||
// and the detail is a BrowsingDataRemover::NotificationDetail containing the
|
||||
// removal mask and the start of the removal timeframe with which
|
||||
// BrowsingDataRemove::Remove was called.
|
||||
NOTIFICATION_BROWSING_DATA_REMOVED,
|
||||
|
||||
// The user accepted or dismissed a SSL client authentication request.
|
||||
// The source is a Source<net::HttpNetworkSession>. Details is a
|
||||
// (std::pair<net::SSLCertRequestInfo*, net::X509Certificate*>).
|
||||
NOTIFICATION_SSL_CLIENT_AUTH_CERT_SELECTED,
|
||||
|
||||
// Session Restore --------------------------------------------------------
|
||||
|
||||
// Sent when synchronous (startup) session restore completes. No details or
|
||||
// source.
|
||||
NOTIFICATION_SESSION_RESTORE_DONE,
|
||||
|
||||
// Note:-
|
||||
// Currently only Content and Chrome define and use notifications.
|
||||
// Custom notifications not belonging to Content and Chrome should start
|
||||
// from here.
|
||||
NOTIFICATION_CHROME_END,
|
||||
};
|
||||
|
||||
} // namespace chrome
|
||||
|
||||
#endif // CHROME_BROWSER_CHROME_NOTIFICATION_TYPES_H_
|
||||
367
chromium_src/chrome/browser/printing/print_job.cc
Normal file
367
chromium_src/chrome/browser/printing/print_job.cc
Normal file
@@ -0,0 +1,367 @@
|
||||
// Copyright (c) 2012 The Chromium 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 "chrome/browser/printing/print_job.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/bind_helpers.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/threading/thread_restrictions.h"
|
||||
#include "base/threading/worker_pool.h"
|
||||
#include "base/timer/timer.h"
|
||||
#include "chrome/browser/chrome_notification_types.h"
|
||||
#include "chrome/browser/printing/print_job_worker.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/notification_service.h"
|
||||
#include "printing/printed_document.h"
|
||||
#include "printing/printed_page.h"
|
||||
|
||||
using base::TimeDelta;
|
||||
|
||||
namespace {
|
||||
|
||||
// Helper function to ensure |owner| is valid until at least |callback| returns.
|
||||
void HoldRefCallback(const scoped_refptr<printing::PrintJobWorkerOwner>& owner,
|
||||
const base::Closure& callback) {
|
||||
callback.Run();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace printing {
|
||||
|
||||
PrintJob::PrintJob()
|
||||
: ui_message_loop_(base::MessageLoop::current()),
|
||||
source_(NULL),
|
||||
worker_(),
|
||||
settings_(),
|
||||
is_job_pending_(false),
|
||||
is_canceling_(false),
|
||||
quit_factory_(this) {
|
||||
DCHECK(ui_message_loop_);
|
||||
// This is normally a UI message loop, but in unit tests, the message loop is
|
||||
// of the 'default' type.
|
||||
DCHECK(base::MessageLoopForUI::IsCurrent() ||
|
||||
ui_message_loop_->type() == base::MessageLoop::TYPE_DEFAULT);
|
||||
ui_message_loop_->AddDestructionObserver(this);
|
||||
}
|
||||
|
||||
PrintJob::~PrintJob() {
|
||||
ui_message_loop_->RemoveDestructionObserver(this);
|
||||
// The job should be finished (or at least canceled) when it is destroyed.
|
||||
DCHECK(!is_job_pending_);
|
||||
DCHECK(!is_canceling_);
|
||||
if (worker_.get())
|
||||
DCHECK(worker_->message_loop() == NULL);
|
||||
DCHECK_EQ(ui_message_loop_, base::MessageLoop::current());
|
||||
}
|
||||
|
||||
void PrintJob::Initialize(PrintJobWorkerOwner* job,
|
||||
PrintedPagesSource* source,
|
||||
int page_count) {
|
||||
DCHECK(!source_);
|
||||
DCHECK(!worker_.get());
|
||||
DCHECK(!is_job_pending_);
|
||||
DCHECK(!is_canceling_);
|
||||
DCHECK(!document_.get());
|
||||
source_ = source;
|
||||
worker_.reset(job->DetachWorker(this));
|
||||
settings_ = job->settings();
|
||||
|
||||
PrintedDocument* new_doc =
|
||||
new PrintedDocument(settings_,
|
||||
source_,
|
||||
job->cookie(),
|
||||
content::BrowserThread::GetBlockingPool());
|
||||
new_doc->set_page_count(page_count);
|
||||
UpdatePrintedDocument(new_doc);
|
||||
|
||||
// Don't forget to register to our own messages.
|
||||
registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
|
||||
content::Source<PrintJob>(this));
|
||||
}
|
||||
|
||||
void PrintJob::Observe(int type,
|
||||
const content::NotificationSource& source,
|
||||
const content::NotificationDetails& details) {
|
||||
DCHECK_EQ(ui_message_loop_, base::MessageLoop::current());
|
||||
switch (type) {
|
||||
case chrome::NOTIFICATION_PRINT_JOB_EVENT: {
|
||||
OnNotifyPrintJobEvent(*content::Details<JobEventDetails>(details).ptr());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintJob::GetSettingsDone(const PrintSettings& new_settings,
|
||||
PrintingContext::Result result) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
PrintJobWorker* PrintJob::DetachWorker(PrintJobWorkerOwner* new_owner) {
|
||||
NOTREACHED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
base::MessageLoop* PrintJob::message_loop() {
|
||||
return ui_message_loop_;
|
||||
}
|
||||
|
||||
const PrintSettings& PrintJob::settings() const {
|
||||
return settings_;
|
||||
}
|
||||
|
||||
int PrintJob::cookie() const {
|
||||
if (!document_.get())
|
||||
// Always use an invalid cookie in this case.
|
||||
return 0;
|
||||
return document_->cookie();
|
||||
}
|
||||
|
||||
void PrintJob::WillDestroyCurrentMessageLoop() {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PrintJob::StartPrinting() {
|
||||
DCHECK_EQ(ui_message_loop_, base::MessageLoop::current());
|
||||
DCHECK(worker_->message_loop());
|
||||
DCHECK(!is_job_pending_);
|
||||
if (!worker_->message_loop() || is_job_pending_)
|
||||
return;
|
||||
|
||||
// Real work is done in PrintJobWorker::StartPrinting().
|
||||
worker_->message_loop()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&HoldRefCallback, make_scoped_refptr(this),
|
||||
base::Bind(&PrintJobWorker::StartPrinting,
|
||||
base::Unretained(worker_.get()), document_)));
|
||||
// Set the flag right now.
|
||||
is_job_pending_ = true;
|
||||
|
||||
// Tell everyone!
|
||||
scoped_refptr<JobEventDetails> details(
|
||||
new JobEventDetails(JobEventDetails::NEW_DOC, document_.get(), NULL));
|
||||
content::NotificationService::current()->Notify(
|
||||
chrome::NOTIFICATION_PRINT_JOB_EVENT,
|
||||
content::Source<PrintJob>(this),
|
||||
content::Details<JobEventDetails>(details.get()));
|
||||
}
|
||||
|
||||
void PrintJob::Stop() {
|
||||
DCHECK_EQ(ui_message_loop_, base::MessageLoop::current());
|
||||
|
||||
if (quit_factory_.HasWeakPtrs()) {
|
||||
// In case we're running a nested message loop to wait for a job to finish,
|
||||
// and we finished before the timeout, quit the nested loop right away.
|
||||
Quit();
|
||||
quit_factory_.InvalidateWeakPtrs();
|
||||
}
|
||||
|
||||
// Be sure to live long enough.
|
||||
scoped_refptr<PrintJob> handle(this);
|
||||
|
||||
if (worker_->message_loop()) {
|
||||
ControlledWorkerShutdown();
|
||||
} else {
|
||||
// Flush the cached document.
|
||||
UpdatePrintedDocument(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintJob::Cancel() {
|
||||
if (is_canceling_)
|
||||
return;
|
||||
is_canceling_ = true;
|
||||
|
||||
// Be sure to live long enough.
|
||||
scoped_refptr<PrintJob> handle(this);
|
||||
|
||||
DCHECK_EQ(ui_message_loop_, base::MessageLoop::current());
|
||||
base::MessageLoop* worker_loop =
|
||||
worker_.get() ? worker_->message_loop() : NULL;
|
||||
if (worker_loop) {
|
||||
// Call this right now so it renders the context invalid. Do not use
|
||||
// InvokeLater since it would take too much time.
|
||||
worker_->Cancel();
|
||||
}
|
||||
// Make sure a Cancel() is broadcast.
|
||||
scoped_refptr<JobEventDetails> details(
|
||||
new JobEventDetails(JobEventDetails::FAILED, NULL, NULL));
|
||||
content::NotificationService::current()->Notify(
|
||||
chrome::NOTIFICATION_PRINT_JOB_EVENT,
|
||||
content::Source<PrintJob>(this),
|
||||
content::Details<JobEventDetails>(details.get()));
|
||||
Stop();
|
||||
is_canceling_ = false;
|
||||
}
|
||||
|
||||
bool PrintJob::FlushJob(base::TimeDelta timeout) {
|
||||
// Make sure the object outlive this message loop.
|
||||
scoped_refptr<PrintJob> handle(this);
|
||||
|
||||
base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||
base::Bind(&PrintJob::Quit, quit_factory_.GetWeakPtr()), timeout);
|
||||
|
||||
base::MessageLoop::ScopedNestableTaskAllower allow(
|
||||
base::MessageLoop::current());
|
||||
base::MessageLoop::current()->Run();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrintJob::DisconnectSource() {
|
||||
source_ = NULL;
|
||||
if (document_.get())
|
||||
document_->DisconnectSource();
|
||||
}
|
||||
|
||||
bool PrintJob::is_job_pending() const {
|
||||
return is_job_pending_;
|
||||
}
|
||||
|
||||
PrintedDocument* PrintJob::document() const {
|
||||
return document_.get();
|
||||
}
|
||||
|
||||
void PrintJob::UpdatePrintedDocument(PrintedDocument* new_document) {
|
||||
if (document_.get() == new_document)
|
||||
return;
|
||||
|
||||
document_ = new_document;
|
||||
|
||||
if (document_.get()) {
|
||||
settings_ = document_->settings();
|
||||
}
|
||||
|
||||
if (worker_.get() && worker_->message_loop()) {
|
||||
DCHECK(!is_job_pending_);
|
||||
// Sync the document with the worker.
|
||||
worker_->message_loop()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&HoldRefCallback, make_scoped_refptr(this),
|
||||
base::Bind(&PrintJobWorker::OnDocumentChanged,
|
||||
base::Unretained(worker_.get()), document_)));
|
||||
}
|
||||
}
|
||||
|
||||
void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) {
|
||||
switch (event_details.type()) {
|
||||
case JobEventDetails::FAILED: {
|
||||
settings_.Clear();
|
||||
// No need to cancel since the worker already canceled itself.
|
||||
Stop();
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::USER_INIT_DONE:
|
||||
case JobEventDetails::DEFAULT_INIT_DONE:
|
||||
case JobEventDetails::USER_INIT_CANCELED: {
|
||||
DCHECK_EQ(event_details.document(), document_.get());
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::NEW_DOC:
|
||||
case JobEventDetails::NEW_PAGE:
|
||||
case JobEventDetails::PAGE_DONE:
|
||||
case JobEventDetails::JOB_DONE:
|
||||
case JobEventDetails::ALL_PAGES_REQUESTED: {
|
||||
// Don't care.
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::DOC_DONE: {
|
||||
// This will call Stop() and broadcast a JOB_DONE message.
|
||||
base::MessageLoop::current()->PostTask(
|
||||
FROM_HERE, base::Bind(&PrintJob::OnDocumentDone, this));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintJob::OnDocumentDone() {
|
||||
// Be sure to live long enough. The instance could be destroyed by the
|
||||
// JOB_DONE broadcast.
|
||||
scoped_refptr<PrintJob> handle(this);
|
||||
|
||||
// Stop the worker thread.
|
||||
Stop();
|
||||
|
||||
scoped_refptr<JobEventDetails> details(
|
||||
new JobEventDetails(JobEventDetails::JOB_DONE, document_.get(), NULL));
|
||||
content::NotificationService::current()->Notify(
|
||||
chrome::NOTIFICATION_PRINT_JOB_EVENT,
|
||||
content::Source<PrintJob>(this),
|
||||
content::Details<JobEventDetails>(details.get()));
|
||||
}
|
||||
|
||||
void PrintJob::ControlledWorkerShutdown() {
|
||||
DCHECK_EQ(ui_message_loop_, base::MessageLoop::current());
|
||||
|
||||
// The deadlock this code works around is specific to window messaging on
|
||||
// Windows, so we aren't likely to need it on any other platforms.
|
||||
#if defined(OS_WIN)
|
||||
// We could easily get into a deadlock case if worker_->Stop() is used; the
|
||||
// printer driver created a window as a child of the browser window. By
|
||||
// canceling the job, the printer driver initiated dialog box is destroyed,
|
||||
// which sends a blocking message to its parent window. If the browser window
|
||||
// thread is not processing messages, a deadlock occurs.
|
||||
//
|
||||
// This function ensures that the dialog box will be destroyed in a timely
|
||||
// manner by the mere fact that the thread will terminate. So the potential
|
||||
// deadlock is eliminated.
|
||||
worker_->StopSoon();
|
||||
|
||||
// Delay shutdown until the worker terminates. We want this code path
|
||||
// to wait on the thread to quit before continuing.
|
||||
if (worker_->IsRunning()) {
|
||||
base::MessageLoop::current()->PostDelayedTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&PrintJob::ControlledWorkerShutdown, this),
|
||||
base::TimeDelta::FromMilliseconds(100));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Now make sure the thread object is cleaned up. Do this on a worker
|
||||
// thread because it may block.
|
||||
base::WorkerPool::PostTaskAndReply(
|
||||
FROM_HERE,
|
||||
base::Bind(&PrintJobWorker::Stop, base::Unretained(worker_.get())),
|
||||
base::Bind(&PrintJob::HoldUntilStopIsCalled, this),
|
||||
false);
|
||||
|
||||
is_job_pending_ = false;
|
||||
registrar_.RemoveAll();
|
||||
UpdatePrintedDocument(NULL);
|
||||
}
|
||||
|
||||
void PrintJob::HoldUntilStopIsCalled() {
|
||||
}
|
||||
|
||||
void PrintJob::Quit() {
|
||||
base::MessageLoop::current()->Quit();
|
||||
}
|
||||
|
||||
// Takes settings_ ownership and will be deleted in the receiving thread.
|
||||
JobEventDetails::JobEventDetails(Type type,
|
||||
PrintedDocument* document,
|
||||
PrintedPage* page)
|
||||
: document_(document),
|
||||
page_(page),
|
||||
type_(type) {
|
||||
}
|
||||
|
||||
JobEventDetails::~JobEventDetails() {
|
||||
}
|
||||
|
||||
PrintedDocument* JobEventDetails::document() const { return document_.get(); }
|
||||
|
||||
PrintedPage* JobEventDetails::page() const { return page_.get(); }
|
||||
|
||||
} // namespace printing
|
||||
212
chromium_src/chrome/browser/printing/print_job.h
Normal file
212
chromium_src/chrome/browser/printing/print_job.h
Normal file
@@ -0,0 +1,212 @@
|
||||
// Copyright (c) 2012 The Chromium 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 CHROME_BROWSER_PRINTING_PRINT_JOB_H_
|
||||
#define CHROME_BROWSER_PRINTING_PRINT_JOB_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "chrome/browser/printing/print_job_worker_owner.h"
|
||||
#include "content/public/browser/notification_observer.h"
|
||||
#include "content/public/browser/notification_registrar.h"
|
||||
|
||||
class Thread;
|
||||
|
||||
namespace printing {
|
||||
|
||||
// See definition below.
|
||||
class JobEventDetails;
|
||||
|
||||
class PrintedDocument;
|
||||
class PrintedPage;
|
||||
class PrintedPagesSource;
|
||||
class PrintJobWorker;
|
||||
class PrinterQuery;
|
||||
|
||||
// Manages the print work for a specific document. Talks to the printer through
|
||||
// PrintingContext through PrintJobWorker. Hides access to PrintingContext in a
|
||||
// worker thread so the caller never blocks. PrintJob will send notifications on
|
||||
// any state change. While printing, the PrintJobManager instance keeps a
|
||||
// reference to the job to be sure it is kept alive. All the code in this class
|
||||
// runs in the UI thread.
|
||||
class PrintJob : public PrintJobWorkerOwner,
|
||||
public content::NotificationObserver,
|
||||
public base::MessageLoop::DestructionObserver {
|
||||
public:
|
||||
// Create a empty PrintJob. When initializing with this constructor,
|
||||
// post-constructor initialization must be done with Initialize().
|
||||
PrintJob();
|
||||
|
||||
// Grabs the ownership of the PrintJobWorker from another job, which is
|
||||
// usually a PrinterQuery. Set the expected page count of the print job.
|
||||
void Initialize(PrintJobWorkerOwner* job, PrintedPagesSource* source,
|
||||
int page_count);
|
||||
|
||||
// content::NotificationObserver implementation.
|
||||
virtual void Observe(int type,
|
||||
const content::NotificationSource& source,
|
||||
const content::NotificationDetails& details) OVERRIDE;
|
||||
|
||||
// PrintJobWorkerOwner implementation.
|
||||
virtual void GetSettingsDone(const PrintSettings& new_settings,
|
||||
PrintingContext::Result result) OVERRIDE;
|
||||
virtual PrintJobWorker* DetachWorker(PrintJobWorkerOwner* new_owner) OVERRIDE;
|
||||
virtual base::MessageLoop* message_loop() OVERRIDE;
|
||||
virtual const PrintSettings& settings() const OVERRIDE;
|
||||
virtual int cookie() const OVERRIDE;
|
||||
|
||||
// DestructionObserver implementation.
|
||||
virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
|
||||
|
||||
// Starts the actual printing. Signals the worker that it should begin to
|
||||
// spool as soon as data is available.
|
||||
void StartPrinting();
|
||||
|
||||
// Asks for the worker thread to finish its queued tasks and disconnects the
|
||||
// delegate object. The PrintJobManager will remove its reference. This may
|
||||
// have the side-effect of destroying the object if the caller doesn't have a
|
||||
// handle to the object. Use PrintJob::is_stopped() to check whether the
|
||||
// worker thread has actually stopped.
|
||||
void Stop();
|
||||
|
||||
// Cancels printing job and stops the worker thread. Takes effect immediately.
|
||||
void Cancel();
|
||||
|
||||
// Synchronously wait for the job to finish. It is mainly useful when the
|
||||
// process is about to be shut down and we're waiting for the spooler to eat
|
||||
// our data.
|
||||
bool FlushJob(base::TimeDelta timeout);
|
||||
|
||||
// Disconnects the PrintedPage source (PrintedPagesSource). It is done when
|
||||
// the source is being destroyed.
|
||||
void DisconnectSource();
|
||||
|
||||
// Returns true if the print job is pending, i.e. between a StartPrinting()
|
||||
// and the end of the spooling.
|
||||
bool is_job_pending() const;
|
||||
|
||||
// Access the current printed document. Warning: may be NULL.
|
||||
PrintedDocument* document() const;
|
||||
|
||||
protected:
|
||||
virtual ~PrintJob();
|
||||
|
||||
private:
|
||||
// Updates document_ to a new instance.
|
||||
void UpdatePrintedDocument(PrintedDocument* new_document);
|
||||
|
||||
// Processes a NOTIFY_PRINT_JOB_EVENT notification.
|
||||
void OnNotifyPrintJobEvent(const JobEventDetails& event_details);
|
||||
|
||||
// Releases the worker thread by calling Stop(), then broadcasts a JOB_DONE
|
||||
// notification.
|
||||
void OnDocumentDone();
|
||||
|
||||
// Terminates the worker thread in a very controlled way, to work around any
|
||||
// eventual deadlock.
|
||||
void ControlledWorkerShutdown();
|
||||
|
||||
// Called at shutdown when running a nested message loop.
|
||||
void Quit();
|
||||
|
||||
void HoldUntilStopIsCalled();
|
||||
|
||||
content::NotificationRegistrar registrar_;
|
||||
|
||||
// Main message loop reference. Used to send notifications in the right
|
||||
// thread.
|
||||
base::MessageLoop* const ui_message_loop_;
|
||||
|
||||
// Source that generates the PrintedPage's (i.e. a WebContents). It will be
|
||||
// set back to NULL if the source is deleted before this object.
|
||||
PrintedPagesSource* source_;
|
||||
|
||||
// All the UI is done in a worker thread because many Win32 print functions
|
||||
// are blocking and enters a message loop without your consent. There is one
|
||||
// worker thread per print job.
|
||||
scoped_ptr<PrintJobWorker> worker_;
|
||||
|
||||
// Cache of the print context settings for access in the UI thread.
|
||||
PrintSettings settings_;
|
||||
|
||||
// The printed document.
|
||||
scoped_refptr<PrintedDocument> document_;
|
||||
|
||||
// Is the worker thread printing.
|
||||
bool is_job_pending_;
|
||||
|
||||
// Is Canceling? If so, try to not cause recursion if on FAILED notification,
|
||||
// the notified calls Cancel() again.
|
||||
bool is_canceling_;
|
||||
|
||||
// Used at shutdown so that we can quit a nested message loop.
|
||||
base::WeakPtrFactory<PrintJob> quit_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintJob);
|
||||
};
|
||||
|
||||
// Details for a NOTIFY_PRINT_JOB_EVENT notification. The members may be NULL.
|
||||
class JobEventDetails : public base::RefCountedThreadSafe<JobEventDetails> {
|
||||
public:
|
||||
// Event type.
|
||||
enum Type {
|
||||
// Print... dialog box has been closed with OK button.
|
||||
USER_INIT_DONE,
|
||||
|
||||
// Print... dialog box has been closed with CANCEL button.
|
||||
USER_INIT_CANCELED,
|
||||
|
||||
// An automated initialization has been done, e.g. Init(false, NULL).
|
||||
DEFAULT_INIT_DONE,
|
||||
|
||||
// A new document started printing.
|
||||
NEW_DOC,
|
||||
|
||||
// A new page started printing.
|
||||
NEW_PAGE,
|
||||
|
||||
// A page is done printing.
|
||||
PAGE_DONE,
|
||||
|
||||
// A document is done printing. The worker thread is still alive. Warning:
|
||||
// not a good moment to release the handle to PrintJob.
|
||||
DOC_DONE,
|
||||
|
||||
// The worker thread is finished. A good moment to release the handle to
|
||||
// PrintJob.
|
||||
JOB_DONE,
|
||||
|
||||
// All missing pages have been requested.
|
||||
ALL_PAGES_REQUESTED,
|
||||
|
||||
// An error occured. Printing is canceled.
|
||||
FAILED,
|
||||
};
|
||||
|
||||
JobEventDetails(Type type, PrintedDocument* document, PrintedPage* page);
|
||||
|
||||
// Getters.
|
||||
PrintedDocument* document() const;
|
||||
PrintedPage* page() const;
|
||||
Type type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class base::RefCountedThreadSafe<JobEventDetails>;
|
||||
|
||||
~JobEventDetails();
|
||||
|
||||
scoped_refptr<PrintedDocument> document_;
|
||||
scoped_refptr<PrintedPage> page_;
|
||||
const Type type_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JobEventDetails);
|
||||
};
|
||||
|
||||
} // namespace printing
|
||||
|
||||
#endif // CHROME_BROWSER_PRINTING_PRINT_JOB_H_
|
||||
159
chromium_src/chrome/browser/printing/print_job_manager.cc
Normal file
159
chromium_src/chrome/browser/printing/print_job_manager.cc
Normal file
@@ -0,0 +1,159 @@
|
||||
// Copyright (c) 2012 The Chromium 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 "chrome/browser/printing/print_job_manager.h"
|
||||
|
||||
#include "chrome/browser/chrome_notification_types.h"
|
||||
#include "chrome/browser/printing/print_job.h"
|
||||
#include "chrome/browser/printing/printer_query.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/notification_service.h"
|
||||
#include "printing/printed_document.h"
|
||||
#include "printing/printed_page.h"
|
||||
|
||||
namespace printing {
|
||||
|
||||
PrintQueriesQueue::PrintQueriesQueue() {
|
||||
}
|
||||
|
||||
PrintQueriesQueue::~PrintQueriesQueue() {
|
||||
base::AutoLock lock(lock_);
|
||||
queued_queries_.clear();
|
||||
}
|
||||
|
||||
void PrintQueriesQueue::SetDestination(PrintDestinationInterface* destination) {
|
||||
base::AutoLock lock(lock_);
|
||||
destination_ = destination;
|
||||
}
|
||||
|
||||
void PrintQueriesQueue::QueuePrinterQuery(PrinterQuery* job) {
|
||||
base::AutoLock lock(lock_);
|
||||
DCHECK(job);
|
||||
queued_queries_.push_back(make_scoped_refptr(job));
|
||||
DCHECK(job->is_valid());
|
||||
}
|
||||
|
||||
scoped_refptr<PrinterQuery> PrintQueriesQueue::PopPrinterQuery(
|
||||
int document_cookie) {
|
||||
base::AutoLock lock(lock_);
|
||||
for (PrinterQueries::iterator itr = queued_queries_.begin();
|
||||
itr != queued_queries_.end(); ++itr) {
|
||||
if ((*itr)->cookie() == document_cookie && !(*itr)->is_callback_pending()) {
|
||||
scoped_refptr<printing::PrinterQuery> current_query(*itr);
|
||||
queued_queries_.erase(itr);
|
||||
DCHECK(current_query->is_valid());
|
||||
return current_query;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scoped_refptr<PrinterQuery> PrintQueriesQueue::CreatePrinterQuery() {
|
||||
scoped_refptr<PrinterQuery> job = new printing::PrinterQuery;
|
||||
base::AutoLock lock(lock_);
|
||||
job->SetWorkerDestination(destination_);
|
||||
return job;
|
||||
}
|
||||
|
||||
void PrintQueriesQueue::Shutdown() {
|
||||
base::AutoLock lock(lock_);
|
||||
queued_queries_.clear();
|
||||
destination_ = NULL;
|
||||
}
|
||||
|
||||
PrintJobManager::PrintJobManager() : is_shutdown_(false) {
|
||||
registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
|
||||
content::NotificationService::AllSources());
|
||||
}
|
||||
|
||||
PrintJobManager::~PrintJobManager() {
|
||||
}
|
||||
|
||||
scoped_refptr<PrintQueriesQueue> PrintJobManager::queue() {
|
||||
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
||||
if (!queue_)
|
||||
queue_ = new PrintQueriesQueue();
|
||||
return queue_;
|
||||
}
|
||||
|
||||
void PrintJobManager::Shutdown() {
|
||||
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
||||
DCHECK(!is_shutdown_);
|
||||
is_shutdown_ = true;
|
||||
registrar_.RemoveAll();
|
||||
StopJobs(true);
|
||||
if (queue_)
|
||||
queue_->Shutdown();
|
||||
queue_ = NULL;
|
||||
}
|
||||
|
||||
void PrintJobManager::StopJobs(bool wait_for_finish) {
|
||||
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
||||
// Copy the array since it can be modified in transit.
|
||||
PrintJobs to_stop;
|
||||
to_stop.swap(current_jobs_);
|
||||
|
||||
for (PrintJobs::const_iterator job = to_stop.begin(); job != to_stop.end();
|
||||
++job) {
|
||||
// Wait for two minutes for the print job to be spooled.
|
||||
if (wait_for_finish)
|
||||
(*job)->FlushJob(base::TimeDelta::FromMinutes(2));
|
||||
(*job)->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
void PrintJobManager::Observe(int type,
|
||||
const content::NotificationSource& source,
|
||||
const content::NotificationDetails& details) {
|
||||
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
||||
switch (type) {
|
||||
case chrome::NOTIFICATION_PRINT_JOB_EVENT: {
|
||||
OnPrintJobEvent(content::Source<PrintJob>(source).ptr(),
|
||||
*content::Details<JobEventDetails>(details).ptr());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintJobManager::OnPrintJobEvent(
|
||||
PrintJob* print_job,
|
||||
const JobEventDetails& event_details) {
|
||||
switch (event_details.type()) {
|
||||
case JobEventDetails::NEW_DOC: {
|
||||
DCHECK(current_jobs_.end() == current_jobs_.find(print_job));
|
||||
// Causes a AddRef().
|
||||
current_jobs_.insert(print_job);
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::JOB_DONE: {
|
||||
DCHECK(current_jobs_.end() != current_jobs_.find(print_job));
|
||||
current_jobs_.erase(print_job);
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::FAILED: {
|
||||
current_jobs_.erase(print_job);
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::USER_INIT_DONE:
|
||||
case JobEventDetails::USER_INIT_CANCELED:
|
||||
case JobEventDetails::DEFAULT_INIT_DONE:
|
||||
case JobEventDetails::NEW_PAGE:
|
||||
case JobEventDetails::PAGE_DONE:
|
||||
case JobEventDetails::DOC_DONE:
|
||||
case JobEventDetails::ALL_PAGES_REQUESTED: {
|
||||
// Don't care.
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace printing
|
||||
104
chromium_src/chrome/browser/printing/print_job_manager.h
Normal file
104
chromium_src/chrome/browser/printing/print_job_manager.h
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) 2012 The Chromium 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 CHROME_BROWSER_PRINTING_PRINT_JOB_MANAGER_H_
|
||||
#define CHROME_BROWSER_PRINTING_PRINT_JOB_MANAGER_H_
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "base/threading/non_thread_safe.h"
|
||||
#include "content/public/browser/notification_observer.h"
|
||||
#include "content/public/browser/notification_registrar.h"
|
||||
#include "printing/print_destination_interface.h"
|
||||
|
||||
namespace printing {
|
||||
|
||||
class JobEventDetails;
|
||||
class PrintJob;
|
||||
class PrinterQuery;
|
||||
|
||||
class PrintQueriesQueue : public base::RefCountedThreadSafe<PrintQueriesQueue> {
|
||||
public:
|
||||
PrintQueriesQueue();
|
||||
|
||||
// Sets the print destination to be set on the next print job.
|
||||
void SetDestination(PrintDestinationInterface* destination);
|
||||
|
||||
// Queues a semi-initialized worker thread. Can be called from any thread.
|
||||
// Current use case is queuing from the I/O thread.
|
||||
// TODO(maruel): Have them vanish after a timeout (~5 minutes?)
|
||||
void QueuePrinterQuery(PrinterQuery* job);
|
||||
|
||||
// Pops a queued PrintJobWorkerOwner object that was previously queued or
|
||||
// create new one. Can be called from any thread.
|
||||
scoped_refptr<PrinterQuery> PopPrinterQuery(int document_cookie);
|
||||
|
||||
// Creates new query.
|
||||
scoped_refptr<PrinterQuery> CreatePrinterQuery();
|
||||
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
friend class base::RefCountedThreadSafe<PrintQueriesQueue>;
|
||||
typedef std::vector<scoped_refptr<PrinterQuery> > PrinterQueries;
|
||||
|
||||
virtual ~PrintQueriesQueue();
|
||||
|
||||
// Used to serialize access to queued_workers_.
|
||||
base::Lock lock_;
|
||||
|
||||
PrinterQueries queued_queries_;
|
||||
|
||||
scoped_refptr<PrintDestinationInterface> destination_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintQueriesQueue);
|
||||
};
|
||||
|
||||
class PrintJobManager : public content::NotificationObserver {
|
||||
public:
|
||||
PrintJobManager();
|
||||
virtual ~PrintJobManager();
|
||||
|
||||
// On browser quit, we should wait to have the print job finished.
|
||||
void Shutdown();
|
||||
|
||||
// content::NotificationObserver
|
||||
virtual void Observe(int type,
|
||||
const content::NotificationSource& source,
|
||||
const content::NotificationDetails& details) OVERRIDE;
|
||||
|
||||
// Returns queries queue. Never returns NULL. Must be called on Browser UI
|
||||
// Thread. Reference could be stored and used from any thread.
|
||||
scoped_refptr<PrintQueriesQueue> queue();
|
||||
|
||||
private:
|
||||
typedef std::set<scoped_refptr<PrintJob> > PrintJobs;
|
||||
|
||||
// Processes a NOTIFY_PRINT_JOB_EVENT notification.
|
||||
void OnPrintJobEvent(PrintJob* print_job,
|
||||
const JobEventDetails& event_details);
|
||||
|
||||
// Stops all printing jobs. If wait_for_finish is true, tries to give jobs
|
||||
// a chance to complete before stopping them.
|
||||
void StopJobs(bool wait_for_finish);
|
||||
|
||||
content::NotificationRegistrar registrar_;
|
||||
|
||||
// Current print jobs that are active.
|
||||
PrintJobs current_jobs_;
|
||||
|
||||
scoped_refptr<PrintQueriesQueue> queue_;
|
||||
|
||||
bool is_shutdown_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintJobManager);
|
||||
};
|
||||
|
||||
} // namespace printing
|
||||
|
||||
#endif // CHROME_BROWSER_PRINTING_PRINT_JOB_MANAGER_H_
|
||||
365
chromium_src/chrome/browser/printing/print_job_worker.cc
Normal file
365
chromium_src/chrome/browser/printing/print_job_worker.cc
Normal file
@@ -0,0 +1,365 @@
|
||||
// Copyright (c) 2012 The Chromium 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 "chrome/browser/printing/print_job_worker.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/bind_helpers.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/values.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/browser/chrome_notification_types.h"
|
||||
#include "chrome/browser/printing/print_job.h"
|
||||
#include "chrome/browser/printing/printing_ui_web_contents_observer.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/notification_service.h"
|
||||
#include "grit/generated_resources.h"
|
||||
#include "printing/print_job_constants.h"
|
||||
#include "printing/printed_document.h"
|
||||
#include "printing/printed_page.h"
|
||||
#include "printing/printing_utils.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace {
|
||||
|
||||
// Helper function to ensure |owner| is valid until at least |callback| returns.
|
||||
void HoldRefCallback(const scoped_refptr<printing::PrintJobWorkerOwner>& owner,
|
||||
const base::Closure& callback) {
|
||||
callback.Run();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace printing {
|
||||
|
||||
void NotificationCallback(PrintJobWorkerOwner* print_job,
|
||||
JobEventDetails::Type detail_type,
|
||||
PrintedDocument* document,
|
||||
PrintedPage* page) {
|
||||
JobEventDetails* details = new JobEventDetails(detail_type, document, page);
|
||||
content::NotificationService::current()->Notify(
|
||||
chrome::NOTIFICATION_PRINT_JOB_EVENT,
|
||||
// We know that is is a PrintJob object in this circumstance.
|
||||
content::Source<PrintJob>(static_cast<PrintJob*>(print_job)),
|
||||
content::Details<JobEventDetails>(details));
|
||||
}
|
||||
|
||||
PrintJobWorker::PrintJobWorker(PrintJobWorkerOwner* owner)
|
||||
: Thread("Printing_Worker"),
|
||||
owner_(owner),
|
||||
weak_factory_(this) {
|
||||
// The object is created in the IO thread.
|
||||
DCHECK_EQ(owner_->message_loop(), base::MessageLoop::current());
|
||||
|
||||
printing_context_.reset(PrintingContext::Create(
|
||||
g_browser_process->GetApplicationLocale()));
|
||||
}
|
||||
|
||||
PrintJobWorker::~PrintJobWorker() {
|
||||
// The object is normally deleted in the UI thread, but when the user
|
||||
// cancels printing or in the case of print preview, the worker is destroyed
|
||||
// on the I/O thread.
|
||||
DCHECK_EQ(owner_->message_loop(), base::MessageLoop::current());
|
||||
Stop();
|
||||
}
|
||||
|
||||
void PrintJobWorker::SetNewOwner(PrintJobWorkerOwner* new_owner) {
|
||||
DCHECK(page_number_ == PageNumber::npos());
|
||||
owner_ = new_owner;
|
||||
}
|
||||
|
||||
void PrintJobWorker::SetPrintDestination(
|
||||
PrintDestinationInterface* destination) {
|
||||
destination_ = destination;
|
||||
}
|
||||
|
||||
void PrintJobWorker::GetSettings(
|
||||
bool ask_user_for_settings,
|
||||
scoped_ptr<PrintingUIWebContentsObserver> web_contents_observer,
|
||||
int document_page_count,
|
||||
bool has_selection,
|
||||
MarginType margin_type) {
|
||||
DCHECK_EQ(message_loop(), base::MessageLoop::current());
|
||||
DCHECK_EQ(page_number_, PageNumber::npos());
|
||||
|
||||
// Recursive task processing is needed for the dialog in case it needs to be
|
||||
// destroyed by a task.
|
||||
// TODO(thestig): This code is wrong. SetNestableTasksAllowed(true) is needed
|
||||
// on the thread where the PrintDlgEx is called, and definitely both calls
|
||||
// should happen on the same thread. See http://crbug.com/73466
|
||||
// MessageLoop::current()->SetNestableTasksAllowed(true);
|
||||
printing_context_->set_margin_type(margin_type);
|
||||
|
||||
// When we delegate to a destination, we don't ask the user for settings.
|
||||
// TODO(mad): Ask the destination for settings.
|
||||
if (ask_user_for_settings && destination_.get() == NULL) {
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&HoldRefCallback, make_scoped_refptr(owner_),
|
||||
base::Bind(&PrintJobWorker::GetSettingsWithUI,
|
||||
base::Unretained(this),
|
||||
base::Passed(&web_contents_observer),
|
||||
document_page_count,
|
||||
has_selection)));
|
||||
} else {
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&HoldRefCallback, make_scoped_refptr(owner_),
|
||||
base::Bind(&PrintJobWorker::UseDefaultSettings,
|
||||
base::Unretained(this))));
|
||||
}
|
||||
}
|
||||
|
||||
void PrintJobWorker::SetSettings(
|
||||
const base::DictionaryValue* const new_settings) {
|
||||
DCHECK_EQ(message_loop(), base::MessageLoop::current());
|
||||
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI,
|
||||
FROM_HERE,
|
||||
base::Bind(&HoldRefCallback,
|
||||
make_scoped_refptr(owner_),
|
||||
base::Bind(&PrintJobWorker::UpdatePrintSettings,
|
||||
base::Unretained(this),
|
||||
base::Owned(new_settings))));
|
||||
}
|
||||
|
||||
void PrintJobWorker::UpdatePrintSettings(
|
||||
const base::DictionaryValue* const new_settings) {
|
||||
PrintingContext::Result result =
|
||||
printing_context_->UpdatePrintSettings(*new_settings);
|
||||
GetSettingsDone(result);
|
||||
}
|
||||
|
||||
void PrintJobWorker::GetSettingsDone(PrintingContext::Result result) {
|
||||
// Most PrintingContext functions may start a message loop and process
|
||||
// message recursively, so disable recursive task processing.
|
||||
// TODO(thestig): See above comment. SetNestableTasksAllowed(false) needs to
|
||||
// be called on the same thread as the previous call. See
|
||||
// http://crbug.com/73466
|
||||
// MessageLoop::current()->SetNestableTasksAllowed(false);
|
||||
|
||||
// We can't use OnFailure() here since owner_ may not support notifications.
|
||||
|
||||
// PrintJob will create the new PrintedDocument.
|
||||
owner_->message_loop()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&PrintJobWorkerOwner::GetSettingsDone,
|
||||
make_scoped_refptr(owner_), printing_context_->settings(),
|
||||
result));
|
||||
}
|
||||
|
||||
void PrintJobWorker::GetSettingsWithUI(
|
||||
scoped_ptr<PrintingUIWebContentsObserver> web_contents_observer,
|
||||
int document_page_count,
|
||||
bool has_selection) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
gfx::NativeView parent_view = web_contents_observer->GetParentView();
|
||||
if (!parent_view) {
|
||||
GetSettingsWithUIDone(printing::PrintingContext::FAILED);
|
||||
return;
|
||||
}
|
||||
printing_context_->AskUserForSettings(
|
||||
parent_view, document_page_count, has_selection,
|
||||
base::Bind(&PrintJobWorker::GetSettingsWithUIDone,
|
||||
base::Unretained(this)));
|
||||
}
|
||||
|
||||
void PrintJobWorker::GetSettingsWithUIDone(PrintingContext::Result result) {
|
||||
message_loop()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&HoldRefCallback, make_scoped_refptr(owner_),
|
||||
base::Bind(&PrintJobWorker::GetSettingsDone,
|
||||
base::Unretained(this), result)));
|
||||
}
|
||||
|
||||
void PrintJobWorker::UseDefaultSettings() {
|
||||
PrintingContext::Result result = printing_context_->UseDefaultSettings();
|
||||
GetSettingsDone(result);
|
||||
}
|
||||
|
||||
void PrintJobWorker::StartPrinting(PrintedDocument* new_document) {
|
||||
DCHECK_EQ(message_loop(), base::MessageLoop::current());
|
||||
DCHECK_EQ(page_number_, PageNumber::npos());
|
||||
DCHECK_EQ(document_, new_document);
|
||||
DCHECK(document_.get());
|
||||
|
||||
if (!document_.get() || page_number_ != PageNumber::npos() ||
|
||||
document_.get() != new_document) {
|
||||
return;
|
||||
}
|
||||
|
||||
base::string16 document_name =
|
||||
printing::SimplifyDocumentTitle(document_->name());
|
||||
if (document_name.empty()) {
|
||||
}
|
||||
PrintingContext::Result result =
|
||||
printing_context_->NewDocument(document_name);
|
||||
if (result != PrintingContext::OK) {
|
||||
OnFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to print already cached data. It may already have been generated for
|
||||
// the print preview.
|
||||
OnNewPage();
|
||||
// Don't touch this anymore since the instance could be destroyed. It happens
|
||||
// if all the pages are printed a one sweep and the client doesn't have a
|
||||
// handle to us anymore. There's a timing issue involved between the worker
|
||||
// thread and the UI thread. Take no chance.
|
||||
}
|
||||
|
||||
void PrintJobWorker::OnDocumentChanged(PrintedDocument* new_document) {
|
||||
DCHECK_EQ(message_loop(), base::MessageLoop::current());
|
||||
DCHECK_EQ(page_number_, PageNumber::npos());
|
||||
|
||||
if (page_number_ != PageNumber::npos())
|
||||
return;
|
||||
|
||||
document_ = new_document;
|
||||
}
|
||||
|
||||
void PrintJobWorker::OnNewPage() {
|
||||
if (!document_.get()) // Spurious message.
|
||||
return;
|
||||
|
||||
// message_loop() could return NULL when the print job is cancelled.
|
||||
DCHECK_EQ(message_loop(), base::MessageLoop::current());
|
||||
|
||||
if (page_number_ == PageNumber::npos()) {
|
||||
// Find first page to print.
|
||||
int page_count = document_->page_count();
|
||||
if (!page_count) {
|
||||
// We still don't know how many pages the document contains. We can't
|
||||
// start to print the document yet since the header/footer may refer to
|
||||
// the document's page count.
|
||||
return;
|
||||
}
|
||||
// We have enough information to initialize page_number_.
|
||||
page_number_.Init(document_->settings(), page_count);
|
||||
if (destination_.get() != NULL)
|
||||
destination_->SetPageCount(page_count);
|
||||
}
|
||||
DCHECK_NE(page_number_, PageNumber::npos());
|
||||
|
||||
while (true) {
|
||||
// Is the page available?
|
||||
scoped_refptr<PrintedPage> page = document_->GetPage(page_number_.ToInt());
|
||||
if (!page) {
|
||||
// We need to wait for the page to be available.
|
||||
base::MessageLoop::current()->PostDelayedTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&PrintJobWorker::OnNewPage, weak_factory_.GetWeakPtr()),
|
||||
base::TimeDelta::FromMilliseconds(500));
|
||||
break;
|
||||
}
|
||||
// The page is there, print it.
|
||||
SpoolPage(page.get());
|
||||
++page_number_;
|
||||
if (page_number_ == PageNumber::npos()) {
|
||||
OnDocumentDone();
|
||||
// Don't touch this anymore since the instance could be destroyed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintJobWorker::Cancel() {
|
||||
// This is the only function that can be called from any thread.
|
||||
printing_context_->Cancel();
|
||||
// Cannot touch any member variable since we don't know in which thread
|
||||
// context we run.
|
||||
}
|
||||
|
||||
void PrintJobWorker::OnDocumentDone() {
|
||||
DCHECK_EQ(message_loop(), base::MessageLoop::current());
|
||||
DCHECK_EQ(page_number_, PageNumber::npos());
|
||||
DCHECK(document_.get());
|
||||
|
||||
if (printing_context_->DocumentDone() != PrintingContext::OK) {
|
||||
OnFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
owner_->message_loop()->PostTask(
|
||||
FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_),
|
||||
JobEventDetails::DOC_DONE, document_,
|
||||
scoped_refptr<PrintedPage>()));
|
||||
|
||||
// Makes sure the variables are reinitialized.
|
||||
document_ = NULL;
|
||||
}
|
||||
|
||||
void PrintJobWorker::SpoolPage(PrintedPage* page) {
|
||||
DCHECK_EQ(message_loop(), base::MessageLoop::current());
|
||||
DCHECK_NE(page_number_, PageNumber::npos());
|
||||
|
||||
// Signal everyone that the page is about to be printed.
|
||||
owner_->message_loop()->PostTask(
|
||||
FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_),
|
||||
JobEventDetails::NEW_PAGE, document_,
|
||||
make_scoped_refptr(page)));
|
||||
|
||||
// Preprocess.
|
||||
if (printing_context_->NewPage() != PrintingContext::OK) {
|
||||
OnFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
if (destination_.get() != NULL) {
|
||||
std::vector<uint8> metabytes(page->metafile()->GetDataSize());
|
||||
bool success = page->metafile()->GetData(
|
||||
reinterpret_cast<void*>(&metabytes[0]), metabytes.size());
|
||||
DCHECK(success) << "Failed to get metafile data.";
|
||||
destination_->SetPageContent(
|
||||
page->page_number(),
|
||||
reinterpret_cast<void*>(&metabytes[0]),
|
||||
metabytes.size());
|
||||
return;
|
||||
}
|
||||
|
||||
// Actual printing.
|
||||
#if defined(OS_WIN) || defined(OS_MACOSX)
|
||||
document_->RenderPrintedPage(*page, printing_context_->context());
|
||||
#elif defined(OS_POSIX)
|
||||
document_->RenderPrintedPage(*page, printing_context_.get());
|
||||
#endif
|
||||
|
||||
// Postprocess.
|
||||
if (printing_context_->PageDone() != PrintingContext::OK) {
|
||||
OnFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
// Signal everyone that the page is printed.
|
||||
owner_->message_loop()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(NotificationCallback, make_scoped_refptr(owner_),
|
||||
JobEventDetails::PAGE_DONE, document_,
|
||||
make_scoped_refptr(page)));
|
||||
}
|
||||
|
||||
void PrintJobWorker::OnFailure() {
|
||||
DCHECK_EQ(message_loop(), base::MessageLoop::current());
|
||||
|
||||
// We may loose our last reference by broadcasting the FAILED event.
|
||||
scoped_refptr<PrintJobWorkerOwner> handle(owner_);
|
||||
|
||||
owner_->message_loop()->PostTask(
|
||||
FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_),
|
||||
JobEventDetails::FAILED, document_,
|
||||
scoped_refptr<PrintedPage>()));
|
||||
Cancel();
|
||||
|
||||
// Makes sure the variables are reinitialized.
|
||||
document_ = NULL;
|
||||
page_number_ = PageNumber::npos();
|
||||
}
|
||||
|
||||
} // namespace printing
|
||||
145
chromium_src/chrome/browser/printing/print_job_worker.h
Normal file
145
chromium_src/chrome/browser/printing/print_job_worker.h
Normal file
@@ -0,0 +1,145 @@
|
||||
// Copyright (c) 2012 The Chromium 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 CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_H_
|
||||
#define CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_H_
|
||||
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/threading/thread.h"
|
||||
#include "printing/page_number.h"
|
||||
#include "printing/print_destination_interface.h"
|
||||
#include "printing/printing_context.h"
|
||||
#include "printing/print_job_constants.h"
|
||||
|
||||
class PrintingUIWebContentsObserver;
|
||||
|
||||
namespace base {
|
||||
class DictionaryValue;
|
||||
}
|
||||
|
||||
namespace printing {
|
||||
|
||||
class PrintedDocument;
|
||||
class PrintedPage;
|
||||
class PrintJob;
|
||||
class PrintJobWorkerOwner;
|
||||
|
||||
// Worker thread code. It manages the PrintingContext, which can be blocking
|
||||
// and/or run a message loop. This is the object that generates most
|
||||
// NOTIFY_PRINT_JOB_EVENT notifications, but they are generated through a
|
||||
// NotificationTask task to be executed from the right thread, the UI thread.
|
||||
// PrintJob always outlives its worker instance.
|
||||
class PrintJobWorker : public base::Thread {
|
||||
public:
|
||||
explicit PrintJobWorker(PrintJobWorkerOwner* owner);
|
||||
virtual ~PrintJobWorker();
|
||||
|
||||
void SetNewOwner(PrintJobWorkerOwner* new_owner);
|
||||
|
||||
// Set a destination for print.
|
||||
// This supercedes the document's rendering destination.
|
||||
void SetPrintDestination(PrintDestinationInterface* destination);
|
||||
|
||||
// Initializes the print settings. If |ask_user_for_settings| is true, a
|
||||
// Print... dialog box will be shown to ask the user his preference.
|
||||
void GetSettings(
|
||||
bool ask_user_for_settings,
|
||||
scoped_ptr<PrintingUIWebContentsObserver> web_contents_observer,
|
||||
int document_page_count,
|
||||
bool has_selection,
|
||||
MarginType margin_type);
|
||||
|
||||
// Set the new print settings. This function takes ownership of
|
||||
// |new_settings|.
|
||||
void SetSettings(const base::DictionaryValue* const new_settings);
|
||||
|
||||
// Starts the printing loop. Every pages are printed as soon as the data is
|
||||
// available. Makes sure the new_document is the right one.
|
||||
void StartPrinting(PrintedDocument* new_document);
|
||||
|
||||
// Updates the printed document.
|
||||
void OnDocumentChanged(PrintedDocument* new_document);
|
||||
|
||||
// Dequeues waiting pages. Called when PrintJob receives a
|
||||
// NOTIFY_PRINTED_DOCUMENT_UPDATED notification. It's time to look again if
|
||||
// the next page can be printed.
|
||||
void OnNewPage();
|
||||
|
||||
// This is the only function that can be called in a thread.
|
||||
void Cancel();
|
||||
|
||||
protected:
|
||||
// Retrieves the context for testing only.
|
||||
PrintingContext* printing_context() { return printing_context_.get(); }
|
||||
|
||||
private:
|
||||
// The shared NotificationService service can only be accessed from the UI
|
||||
// thread, so this class encloses the necessary information to send the
|
||||
// notification from the right thread. Most NOTIFY_PRINT_JOB_EVENT
|
||||
// notifications are sent this way, except USER_INIT_DONE, USER_INIT_CANCELED
|
||||
// and DEFAULT_INIT_DONE. These three are sent through PrintJob::InitDone().
|
||||
class NotificationTask;
|
||||
|
||||
// Renders a page in the printer.
|
||||
void SpoolPage(PrintedPage* page);
|
||||
|
||||
// Closes the job since spooling is done.
|
||||
void OnDocumentDone();
|
||||
|
||||
// Discards the current document, the current page and cancels the printing
|
||||
// context.
|
||||
void OnFailure();
|
||||
|
||||
// Asks the user for print settings. Must be called on the UI thread.
|
||||
// Required on Mac and Linux. Windows can display UI from non-main threads,
|
||||
// but sticks with this for consistency.
|
||||
void GetSettingsWithUI(
|
||||
scoped_ptr<PrintingUIWebContentsObserver> web_contents_observer,
|
||||
int document_page_count,
|
||||
bool has_selection);
|
||||
|
||||
// The callback used by PrintingContext::GetSettingsWithUI() to notify this
|
||||
// object that the print settings are set. This is needed in order to bounce
|
||||
// back into the IO thread for GetSettingsDone().
|
||||
void GetSettingsWithUIDone(PrintingContext::Result result);
|
||||
|
||||
// Called on the UI thread to update the print settings. This function takes
|
||||
// the ownership of |new_settings|.
|
||||
void UpdatePrintSettings(const base::DictionaryValue* const new_settings);
|
||||
|
||||
// Reports settings back to owner_.
|
||||
void GetSettingsDone(PrintingContext::Result result);
|
||||
|
||||
// Use the default settings. When using GTK+ or Mac, this can still end up
|
||||
// displaying a dialog. So this needs to happen from the UI thread on these
|
||||
// systems.
|
||||
void UseDefaultSettings();
|
||||
|
||||
// Information about the printer setting.
|
||||
scoped_ptr<PrintingContext> printing_context_;
|
||||
|
||||
// The printed document. Only has read-only access.
|
||||
scoped_refptr<PrintedDocument> document_;
|
||||
|
||||
// The print destination, may be NULL.
|
||||
scoped_refptr<PrintDestinationInterface> destination_;
|
||||
|
||||
// The print job owning this worker thread. It is guaranteed to outlive this
|
||||
// object.
|
||||
PrintJobWorkerOwner* owner_;
|
||||
|
||||
// Current page number to print.
|
||||
PageNumber page_number_;
|
||||
|
||||
// Used to generate a WeakPtr for callbacks.
|
||||
base::WeakPtrFactory<PrintJobWorker> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintJobWorker);
|
||||
};
|
||||
|
||||
} // namespace printing
|
||||
|
||||
#endif // CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_H_
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_OWNER_H__
|
||||
#define CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_OWNER_H__
|
||||
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "printing/printing_context.h"
|
||||
|
||||
namespace base {
|
||||
class MessageLoop;
|
||||
}
|
||||
|
||||
|
||||
namespace printing {
|
||||
|
||||
class PrintJobWorker;
|
||||
class PrintSettings;
|
||||
|
||||
class PrintJobWorkerOwner
|
||||
: public base::RefCountedThreadSafe<PrintJobWorkerOwner> {
|
||||
public:
|
||||
// Finishes the initialization began by PrintJobWorker::GetSettings().
|
||||
// Creates a new PrintedDocument if necessary. Solely meant to be called by
|
||||
// PrintJobWorker.
|
||||
virtual void GetSettingsDone(const PrintSettings& new_settings,
|
||||
PrintingContext::Result result) = 0;
|
||||
|
||||
// Detach the PrintJobWorker associated to this object.
|
||||
virtual PrintJobWorker* DetachWorker(PrintJobWorkerOwner* new_owner) = 0;
|
||||
|
||||
// Retrieves the message loop that is expected to process GetSettingsDone.
|
||||
virtual base::MessageLoop* message_loop() = 0;
|
||||
|
||||
// Access the current settings.
|
||||
virtual const PrintSettings& settings() const = 0;
|
||||
|
||||
// Cookie uniquely identifying the PrintedDocument and/or loaded settings.
|
||||
virtual int cookie() const = 0;
|
||||
|
||||
protected:
|
||||
friend class base::RefCountedThreadSafe<PrintJobWorkerOwner>;
|
||||
|
||||
virtual ~PrintJobWorkerOwner() {}
|
||||
};
|
||||
|
||||
} // namespace printing
|
||||
|
||||
#endif // CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_OWNER_H__
|
||||
533
chromium_src/chrome/browser/printing/print_view_manager_base.cc
Normal file
533
chromium_src/chrome/browser/printing/print_view_manager_base.cc
Normal file
@@ -0,0 +1,533 @@
|
||||
// Copyright 2013 The Chromium 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 "chrome/browser/printing/print_view_manager_base.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/prefs/pref_service.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/timer/timer.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/browser/chrome_notification_types.h"
|
||||
#include "chrome/browser/printing/print_job.h"
|
||||
#include "chrome/browser/printing/print_job_manager.h"
|
||||
#include "chrome/browser/printing/printer_query.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "chrome/browser/ui/simple_message_box.h"
|
||||
#include "chrome/common/pref_names.h"
|
||||
#include "chrome/common/print_messages.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/notification_details.h"
|
||||
#include "content/public/browser/notification_service.h"
|
||||
#include "content/public/browser/notification_source.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "grit/generated_resources.h"
|
||||
#include "printing/metafile_impl.h"
|
||||
#include "printing/printed_document.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
using base::TimeDelta;
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace printing {
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING)
|
||||
// Limits memory usage by raster to 64 MiB.
|
||||
const int kMaxRasterSizeInPixels = 16*1024*1024;
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
PrintViewManagerBase::PrintViewManagerBase(content::WebContents* web_contents)
|
||||
: content::WebContentsObserver(web_contents),
|
||||
number_pages_(0),
|
||||
printing_succeeded_(false),
|
||||
inside_inner_message_loop_(false),
|
||||
cookie_(0),
|
||||
queue_(g_browser_process->print_job_manager()->queue()) {
|
||||
DCHECK(queue_);
|
||||
#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \
|
||||
defined(WIN_PDF_METAFILE_FOR_PRINTING)
|
||||
expecting_first_page_ = true;
|
||||
#endif
|
||||
printing_enabled_ = true;
|
||||
}
|
||||
|
||||
PrintViewManagerBase::~PrintViewManagerBase() {
|
||||
ReleasePrinterQuery();
|
||||
DisconnectFromCurrentPrintJob();
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::PrintNow(bool silent, bool print_background) {
|
||||
return PrintNowInternal(new PrintMsg_PrintPages(
|
||||
routing_id(), silent, print_background));
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::NavigationStopped() {
|
||||
// Cancel the current job, wait for the worker to finish.
|
||||
TerminatePrintJob(true);
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::RenderProcessGone(base::TerminationStatus status) {
|
||||
ReleasePrinterQuery();
|
||||
|
||||
if (!print_job_.get())
|
||||
return;
|
||||
|
||||
scoped_refptr<PrintedDocument> document(print_job_->document());
|
||||
if (document.get()) {
|
||||
// If IsComplete() returns false, the document isn't completely rendered.
|
||||
// Since our renderer is gone, there's nothing to do, cancel it. Otherwise,
|
||||
// the print job may finish without problem.
|
||||
TerminatePrintJob(!document->IsComplete());
|
||||
}
|
||||
}
|
||||
|
||||
base::string16 PrintViewManagerBase::RenderSourceName() {
|
||||
base::string16 name(web_contents()->GetTitle());
|
||||
return name;
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::OnDidGetPrintedPagesCount(int cookie,
|
||||
int number_pages) {
|
||||
DCHECK_GT(cookie, 0);
|
||||
DCHECK_GT(number_pages, 0);
|
||||
number_pages_ = number_pages;
|
||||
OpportunisticallyCreatePrintJob(cookie);
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::OnDidGetDocumentCookie(int cookie) {
|
||||
cookie_ = cookie;
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::OnDidPrintPage(
|
||||
const PrintHostMsg_DidPrintPage_Params& params) {
|
||||
if (!OpportunisticallyCreatePrintJob(params.document_cookie))
|
||||
return;
|
||||
|
||||
PrintedDocument* document = print_job_->document();
|
||||
if (!document || params.document_cookie != document->cookie()) {
|
||||
// Out of sync. It may happen since we are completely asynchronous. Old
|
||||
// spurious messages can be received if one of the processes is overloaded.
|
||||
return;
|
||||
}
|
||||
|
||||
#if (defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING)) || \
|
||||
defined(OS_MACOSX)
|
||||
const bool metafile_must_be_valid = true;
|
||||
#elif defined(OS_POSIX) || defined(WIN_PDF_METAFILE_FOR_PRINTING)
|
||||
const bool metafile_must_be_valid = expecting_first_page_;
|
||||
expecting_first_page_ = false;
|
||||
#endif
|
||||
|
||||
base::SharedMemory shared_buf(params.metafile_data_handle, true);
|
||||
if (metafile_must_be_valid) {
|
||||
if (!shared_buf.Map(params.data_size)) {
|
||||
NOTREACHED() << "couldn't map";
|
||||
web_contents()->Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
scoped_ptr<NativeMetafile> metafile(new NativeMetafile);
|
||||
if (metafile_must_be_valid) {
|
||||
if (!metafile->InitFromData(shared_buf.memory(), params.data_size)) {
|
||||
NOTREACHED() << "Invalid metafile header";
|
||||
web_contents()->Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING)
|
||||
bool big_emf = (params.data_size && params.data_size >= kMetafileMaxSize);
|
||||
int raster_size =
|
||||
std::min(params.page_size.GetArea(), kMaxRasterSizeInPixels);
|
||||
if (big_emf) {
|
||||
scoped_ptr<NativeMetafile> raster_metafile(
|
||||
metafile->RasterizeMetafile(raster_size));
|
||||
if (raster_metafile.get()) {
|
||||
metafile.swap(raster_metafile);
|
||||
} else if (big_emf) {
|
||||
// Don't fall back to emf here.
|
||||
NOTREACHED() << "size:" << params.data_size;
|
||||
TerminatePrintJob(true);
|
||||
web_contents()->Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif // OS_WIN && !WIN_PDF_METAFILE_FOR_PRINTING
|
||||
|
||||
#if !defined(WIN_PDF_METAFILE_FOR_PRINTING)
|
||||
// Update the rendered document. It will send notifications to the listener.
|
||||
document->SetPage(params.page_number,
|
||||
metafile.release(),
|
||||
#if defined(OS_WIN)
|
||||
params.actual_shrink,
|
||||
#endif // OS_WIN
|
||||
params.page_size,
|
||||
params.content_area);
|
||||
|
||||
ShouldQuitFromInnerMessageLoop();
|
||||
#else
|
||||
if (metafile_must_be_valid) {
|
||||
scoped_refptr<base::RefCountedBytes> bytes = new base::RefCountedBytes(
|
||||
reinterpret_cast<const unsigned char*>(shared_buf.memory()),
|
||||
params.data_size);
|
||||
|
||||
document->DebugDumpData(bytes, FILE_PATH_LITERAL(".pdf"));
|
||||
|
||||
if (!pdf_to_emf_converter_)
|
||||
pdf_to_emf_converter_ = PdfToEmfConverter::CreateDefault();
|
||||
|
||||
const int kPrinterDpi = print_job_->settings().dpi();
|
||||
pdf_to_emf_converter_->Start(
|
||||
bytes,
|
||||
printing::PdfRenderSettings(params.content_area, kPrinterDpi, true),
|
||||
base::Bind(&PrintViewManagerBase::OnPdfToEmfConverted,
|
||||
base::Unretained(this),
|
||||
params));
|
||||
}
|
||||
#endif // !WIN_PDF_METAFILE_FOR_PRINTING
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::OnPrintingFailed(int cookie) {
|
||||
if (cookie != cookie_) {
|
||||
NOTREACHED();
|
||||
return;
|
||||
}
|
||||
|
||||
ReleasePrinterQuery();
|
||||
|
||||
content::NotificationService::current()->Notify(
|
||||
chrome::NOTIFICATION_PRINT_JOB_RELEASED,
|
||||
content::Source<content::WebContents>(web_contents()),
|
||||
content::NotificationService::NoDetails());
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::OnShowInvalidPrinterSettingsError() {
|
||||
LOG(ERROR) << "Invalid printer settings";
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBase, message)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPrintedPagesCount,
|
||||
OnDidGetPrintedPagesCount)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDocumentCookie,
|
||||
OnDidGetDocumentCookie)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintPage, OnDidPrintPage)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintingFailed, OnPrintingFailed)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError,
|
||||
OnShowInvalidPrinterSettingsError);
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
return handled;
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::Observe(
|
||||
int type,
|
||||
const content::NotificationSource& source,
|
||||
const content::NotificationDetails& details) {
|
||||
switch (type) {
|
||||
case chrome::NOTIFICATION_PRINT_JOB_EVENT: {
|
||||
OnNotifyPrintJobEvent(*content::Details<JobEventDetails>(details).ptr());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::OnNotifyPrintJobEvent(
|
||||
const JobEventDetails& event_details) {
|
||||
switch (event_details.type()) {
|
||||
case JobEventDetails::FAILED: {
|
||||
TerminatePrintJob(true);
|
||||
|
||||
content::NotificationService::current()->Notify(
|
||||
chrome::NOTIFICATION_PRINT_JOB_RELEASED,
|
||||
content::Source<content::WebContents>(web_contents()),
|
||||
content::NotificationService::NoDetails());
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::USER_INIT_DONE:
|
||||
case JobEventDetails::DEFAULT_INIT_DONE:
|
||||
case JobEventDetails::USER_INIT_CANCELED: {
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::ALL_PAGES_REQUESTED: {
|
||||
ShouldQuitFromInnerMessageLoop();
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::NEW_DOC:
|
||||
case JobEventDetails::NEW_PAGE:
|
||||
case JobEventDetails::PAGE_DONE:
|
||||
case JobEventDetails::DOC_DONE: {
|
||||
// Don't care about the actual printing process.
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::JOB_DONE: {
|
||||
// Printing is done, we don't need it anymore.
|
||||
// print_job_->is_job_pending() may still be true, depending on the order
|
||||
// of object registration.
|
||||
printing_succeeded_ = true;
|
||||
ReleasePrintJob();
|
||||
|
||||
content::NotificationService::current()->Notify(
|
||||
chrome::NOTIFICATION_PRINT_JOB_RELEASED,
|
||||
content::Source<content::WebContents>(web_contents()),
|
||||
content::NotificationService::NoDetails());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::RenderAllMissingPagesNow() {
|
||||
if (!print_job_.get() || !print_job_->is_job_pending())
|
||||
return false;
|
||||
|
||||
// We can't print if there is no renderer.
|
||||
if (!web_contents() ||
|
||||
!web_contents()->GetRenderViewHost() ||
|
||||
!web_contents()->GetRenderViewHost()->IsRenderViewLive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the document already complete?
|
||||
if (print_job_->document() && print_job_->document()->IsComplete()) {
|
||||
printing_succeeded_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// WebContents is either dying or a second consecutive request to print
|
||||
// happened before the first had time to finish. We need to render all the
|
||||
// pages in an hurry if a print_job_ is still pending. No need to wait for it
|
||||
// to actually spool the pages, only to have the renderer generate them. Run
|
||||
// a message loop until we get our signal that the print job is satisfied.
|
||||
// PrintJob will send a ALL_PAGES_REQUESTED after having received all the
|
||||
// pages it needs. MessageLoop::current()->Quit() will be called as soon as
|
||||
// print_job_->document()->IsComplete() is true on either ALL_PAGES_REQUESTED
|
||||
// or in DidPrintPage(). The check is done in
|
||||
// ShouldQuitFromInnerMessageLoop().
|
||||
// BLOCKS until all the pages are received. (Need to enable recursive task)
|
||||
if (!RunInnerMessageLoop()) {
|
||||
// This function is always called from DisconnectFromCurrentPrintJob() so we
|
||||
// know that the job will be stopped/canceled in any case.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::ShouldQuitFromInnerMessageLoop() {
|
||||
// Look at the reason.
|
||||
DCHECK(print_job_->document());
|
||||
if (print_job_->document() &&
|
||||
print_job_->document()->IsComplete() &&
|
||||
inside_inner_message_loop_) {
|
||||
// We are in a message loop created by RenderAllMissingPagesNow. Quit from
|
||||
// it.
|
||||
base::MessageLoop::current()->Quit();
|
||||
inside_inner_message_loop_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::CreateNewPrintJob(PrintJobWorkerOwner* job) {
|
||||
DCHECK(!inside_inner_message_loop_);
|
||||
|
||||
// Disconnect the current print_job_.
|
||||
DisconnectFromCurrentPrintJob();
|
||||
|
||||
// We can't print if there is no renderer.
|
||||
if (!web_contents()->GetRenderViewHost() ||
|
||||
!web_contents()->GetRenderViewHost()->IsRenderViewLive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ask the renderer to generate the print preview, create the print preview
|
||||
// view and switch to it, initialize the printer and show the print dialog.
|
||||
DCHECK(!print_job_.get());
|
||||
DCHECK(job);
|
||||
if (!job)
|
||||
return false;
|
||||
|
||||
print_job_ = new PrintJob();
|
||||
print_job_->Initialize(job, this, number_pages_);
|
||||
registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
|
||||
content::Source<PrintJob>(print_job_.get()));
|
||||
printing_succeeded_ = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::DisconnectFromCurrentPrintJob() {
|
||||
// Make sure all the necessary rendered page are done. Don't bother with the
|
||||
// return value.
|
||||
bool result = RenderAllMissingPagesNow();
|
||||
|
||||
// Verify that assertion.
|
||||
if (print_job_.get() &&
|
||||
print_job_->document() &&
|
||||
!print_job_->document()->IsComplete()) {
|
||||
DCHECK(!result);
|
||||
// That failed.
|
||||
TerminatePrintJob(true);
|
||||
} else {
|
||||
// DO NOT wait for the job to finish.
|
||||
ReleasePrintJob();
|
||||
}
|
||||
#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \
|
||||
defined(WIN_PDF_METAFILE_FOR_PRINTING)
|
||||
expecting_first_page_ = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::PrintingDone(bool success) {
|
||||
if (!print_job_.get())
|
||||
return;
|
||||
Send(new PrintMsg_PrintingDone(routing_id(), success));
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::TerminatePrintJob(bool cancel) {
|
||||
if (!print_job_.get())
|
||||
return;
|
||||
|
||||
if (cancel) {
|
||||
// We don't need the metafile data anymore because the printing is canceled.
|
||||
print_job_->Cancel();
|
||||
inside_inner_message_loop_ = false;
|
||||
} else {
|
||||
DCHECK(!inside_inner_message_loop_);
|
||||
DCHECK(!print_job_->document() || print_job_->document()->IsComplete());
|
||||
|
||||
// WebContents is either dying or navigating elsewhere. We need to render
|
||||
// all the pages in an hurry if a print job is still pending. This does the
|
||||
// trick since it runs a blocking message loop:
|
||||
print_job_->Stop();
|
||||
}
|
||||
ReleasePrintJob();
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::ReleasePrintJob() {
|
||||
if (!print_job_.get())
|
||||
return;
|
||||
|
||||
PrintingDone(printing_succeeded_);
|
||||
|
||||
registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
|
||||
content::Source<PrintJob>(print_job_.get()));
|
||||
print_job_->DisconnectSource();
|
||||
// Don't close the worker thread.
|
||||
print_job_ = NULL;
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::RunInnerMessageLoop() {
|
||||
// This value may actually be too low:
|
||||
//
|
||||
// - If we're looping because of printer settings initialization, the premise
|
||||
// here is that some poor users have their print server away on a VPN over a
|
||||
// slow connection. In this situation, the simple fact of opening the printer
|
||||
// can be dead slow. On the other side, we don't want to die infinitely for a
|
||||
// real network error. Give the printer 60 seconds to comply.
|
||||
//
|
||||
// - If we're looping because of renderer page generation, the renderer could
|
||||
// be CPU bound, the page overly complex/large or the system just
|
||||
// memory-bound.
|
||||
static const int kPrinterSettingsTimeout = 60000;
|
||||
base::OneShotTimer<base::MessageLoop> quit_timer;
|
||||
quit_timer.Start(FROM_HERE,
|
||||
TimeDelta::FromMilliseconds(kPrinterSettingsTimeout),
|
||||
base::MessageLoop::current(), &base::MessageLoop::Quit);
|
||||
|
||||
inside_inner_message_loop_ = true;
|
||||
|
||||
// Need to enable recursive task.
|
||||
{
|
||||
base::MessageLoop::ScopedNestableTaskAllower allow(
|
||||
base::MessageLoop::current());
|
||||
base::MessageLoop::current()->Run();
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
if (inside_inner_message_loop_) {
|
||||
// Ok we timed out. That's sad.
|
||||
inside_inner_message_loop_ = false;
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::OpportunisticallyCreatePrintJob(int cookie) {
|
||||
if (print_job_.get())
|
||||
return true;
|
||||
|
||||
if (!cookie) {
|
||||
// Out of sync. It may happens since we are completely asynchronous. Old
|
||||
// spurious message can happen if one of the processes is overloaded.
|
||||
return false;
|
||||
}
|
||||
|
||||
// The job was initiated by a script. Time to get the corresponding worker
|
||||
// thread.
|
||||
scoped_refptr<PrinterQuery> queued_query = queue_->PopPrinterQuery(cookie);
|
||||
if (!queued_query) {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateNewPrintJob(queued_query)) {
|
||||
// Don't kill anything.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Settings are already loaded. Go ahead. This will set
|
||||
// print_job_->is_job_pending() to true.
|
||||
print_job_->StartPrinting();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::PrintNowInternal(IPC::Message* message) {
|
||||
// Don't print / print preview interstitials.
|
||||
if (web_contents()->ShowingInterstitialPage()) {
|
||||
delete message;
|
||||
return false;
|
||||
}
|
||||
return Send(message);
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::ReleasePrinterQuery() {
|
||||
if (!cookie_)
|
||||
return;
|
||||
|
||||
int cookie = cookie_;
|
||||
cookie_ = 0;
|
||||
queue_->SetDestination(NULL);
|
||||
|
||||
|
||||
printing::PrintJobManager* print_job_manager =
|
||||
g_browser_process->print_job_manager();
|
||||
// May be NULL in tests.
|
||||
if (!print_job_manager)
|
||||
return;
|
||||
|
||||
scoped_refptr<printing::PrinterQuery> printer_query;
|
||||
printer_query = queue_->PopPrinterQuery(cookie);
|
||||
if (!printer_query)
|
||||
return;
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&PrinterQuery::StopWorker, printer_query.get()));
|
||||
}
|
||||
|
||||
} // namespace printing
|
||||
162
chromium_src/chrome/browser/printing/print_view_manager_base.h
Normal file
162
chromium_src/chrome/browser/printing/print_view_manager_base.h
Normal file
@@ -0,0 +1,162 @@
|
||||
// Copyright 2013 The Chromium 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 CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASE_H_
|
||||
#define CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASE_H_
|
||||
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/prefs/pref_member.h"
|
||||
#include "base/strings/string16.h"
|
||||
#include "content/public/browser/notification_observer.h"
|
||||
#include "content/public/browser/notification_registrar.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "content/public/browser/web_contents_user_data.h"
|
||||
#include "printing/printed_pages_source.h"
|
||||
|
||||
struct PrintHostMsg_DidPrintPage_Params;
|
||||
|
||||
namespace content {
|
||||
class RenderViewHost;
|
||||
}
|
||||
|
||||
namespace printing {
|
||||
|
||||
class JobEventDetails;
|
||||
class PdfToEmfConverter;
|
||||
class PrintJob;
|
||||
class PrintJobWorkerOwner;
|
||||
class PrintQueriesQueue;
|
||||
|
||||
// Base class for managing the print commands for a WebContents.
|
||||
class PrintViewManagerBase : public content::NotificationObserver,
|
||||
public PrintedPagesSource,
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
virtual ~PrintViewManagerBase();
|
||||
|
||||
// Prints the current document immediately. Since the rendering is
|
||||
// asynchronous, the actual printing will not be completed on the return of
|
||||
// this function. Returns false if printing is impossible at the moment.
|
||||
virtual bool PrintNow(bool silent, bool print_background);
|
||||
|
||||
// PrintedPagesSource implementation.
|
||||
virtual base::string16 RenderSourceName() OVERRIDE;
|
||||
|
||||
protected:
|
||||
explicit PrintViewManagerBase(content::WebContents* web_contents);
|
||||
|
||||
// Helper method for Print*Now().
|
||||
bool PrintNowInternal(IPC::Message* message);
|
||||
|
||||
// Terminates or cancels the print job if one was pending.
|
||||
virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
|
||||
|
||||
// content::WebContentsObserver implementation.
|
||||
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
||||
|
||||
// IPC Message handlers.
|
||||
virtual void OnPrintingFailed(int cookie);
|
||||
|
||||
private:
|
||||
// content::NotificationObserver implementation.
|
||||
virtual void Observe(int type,
|
||||
const content::NotificationSource& source,
|
||||
const content::NotificationDetails& details) OVERRIDE;
|
||||
|
||||
// Cancels the print job.
|
||||
virtual void NavigationStopped() OVERRIDE;
|
||||
|
||||
// IPC Message handlers.
|
||||
void OnDidGetPrintedPagesCount(int cookie, int number_pages);
|
||||
void OnDidGetDocumentCookie(int cookie);
|
||||
void OnDidPrintPage(const PrintHostMsg_DidPrintPage_Params& params);
|
||||
void OnShowInvalidPrinterSettingsError();
|
||||
|
||||
// Processes a NOTIFY_PRINT_JOB_EVENT notification.
|
||||
void OnNotifyPrintJobEvent(const JobEventDetails& event_details);
|
||||
|
||||
// Requests the RenderView to render all the missing pages for the print job.
|
||||
// No-op if no print job is pending. Returns true if at least one page has
|
||||
// been requested to the renderer.
|
||||
bool RenderAllMissingPagesNow();
|
||||
|
||||
// Quits the current message loop if these conditions hold true: a document is
|
||||
// loaded and is complete and waiting_for_pages_to_be_rendered_ is true. This
|
||||
// function is called in DidPrintPage() or on ALL_PAGES_REQUESTED
|
||||
// notification. The inner message loop is created was created by
|
||||
// RenderAllMissingPagesNow().
|
||||
void ShouldQuitFromInnerMessageLoop();
|
||||
|
||||
// Creates a new empty print job. It has no settings loaded. If there is
|
||||
// currently a print job, safely disconnect from it. Returns false if it is
|
||||
// impossible to safely disconnect from the current print job or it is
|
||||
// impossible to create a new print job.
|
||||
bool CreateNewPrintJob(PrintJobWorkerOwner* job);
|
||||
|
||||
// Makes sure the current print_job_ has all its data before continuing, and
|
||||
// disconnect from it.
|
||||
void DisconnectFromCurrentPrintJob();
|
||||
|
||||
// Notify that the printing is done.
|
||||
void PrintingDone(bool success);
|
||||
|
||||
// Terminates the print job. No-op if no print job has been created. If
|
||||
// |cancel| is true, cancel it instead of waiting for the job to finish. Will
|
||||
// call ReleasePrintJob().
|
||||
void TerminatePrintJob(bool cancel);
|
||||
|
||||
// Releases print_job_. Correctly deregisters from notifications. No-op if
|
||||
// no print job has been created.
|
||||
void ReleasePrintJob();
|
||||
|
||||
// Runs an inner message loop. It will set inside_inner_message_loop_ to true
|
||||
// while the blocking inner message loop is running. This is useful in cases
|
||||
// where the RenderView is about to be destroyed while a printing job isn't
|
||||
// finished.
|
||||
bool RunInnerMessageLoop();
|
||||
|
||||
// In the case of Scripted Printing, where the renderer is controlling the
|
||||
// control flow, print_job_ is initialized whenever possible. No-op is
|
||||
// print_job_ is initialized.
|
||||
bool OpportunisticallyCreatePrintJob(int cookie);
|
||||
|
||||
// Release the PrinterQuery associated with our |cookie_|.
|
||||
void ReleasePrinterQuery();
|
||||
|
||||
content::NotificationRegistrar registrar_;
|
||||
|
||||
// Manages the low-level talk to the printer.
|
||||
scoped_refptr<PrintJob> print_job_;
|
||||
|
||||
// Number of pages to print in the print job.
|
||||
int number_pages_;
|
||||
|
||||
// Indication of success of the print job.
|
||||
bool printing_succeeded_;
|
||||
|
||||
// Running an inner message loop inside RenderAllMissingPagesNow(). This means
|
||||
// we are _blocking_ until all the necessary pages have been rendered or the
|
||||
// print settings are being loaded.
|
||||
bool inside_inner_message_loop_;
|
||||
|
||||
#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \
|
||||
defined(WIN_PDF_METAFILE_FOR_PRINTING)
|
||||
// Set to true when OnDidPrintPage() should be expecting the first page.
|
||||
bool expecting_first_page_;
|
||||
#endif
|
||||
|
||||
// The document cookie of the current PrinterQuery.
|
||||
int cookie_;
|
||||
|
||||
// Whether printing is enabled.
|
||||
bool printing_enabled_;
|
||||
|
||||
scoped_refptr<printing::PrintQueriesQueue> queue_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintViewManagerBase);
|
||||
};
|
||||
|
||||
} // namespace printing
|
||||
|
||||
#endif // CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASE_H_
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2013 The Chromium 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 "chrome/browser/printing/print_view_manager_basic.h"
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
#include "base/file_descriptor_posix.h"
|
||||
#include "chrome/common/print_messages.h"
|
||||
#include "printing/printing_context_android.h"
|
||||
#endif
|
||||
|
||||
DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintViewManagerBasic);
|
||||
|
||||
namespace printing {
|
||||
|
||||
PrintViewManagerBasic::PrintViewManagerBasic(content::WebContents* web_contents)
|
||||
: PrintViewManagerBase(web_contents) {
|
||||
}
|
||||
|
||||
PrintViewManagerBasic::~PrintViewManagerBasic() {
|
||||
}
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
void PrintViewManagerBasic::RenderProcessGone(base::TerminationStatus status) {
|
||||
PrintingContextAndroid::PdfWritingDone(file_descriptor_.fd, false);
|
||||
file_descriptor_ = base::FileDescriptor(-1, false);
|
||||
PrintViewManagerBase::RenderProcessGone(status);
|
||||
}
|
||||
|
||||
void PrintViewManagerBasic::OnPrintingFailed(int cookie) {
|
||||
PrintingContextAndroid::PdfWritingDone(file_descriptor_.fd, false);
|
||||
file_descriptor_ = base::FileDescriptor(-1, false);
|
||||
PrintViewManagerBase::OnPrintingFailed(cookie);
|
||||
}
|
||||
|
||||
bool PrintViewManagerBasic::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBasic, message)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintingFailed, OnPrintingFailed)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
|
||||
return handled ? true : PrintViewManagerBase::OnMessageReceived(message);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace printing
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright 2013 The Chromium 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 CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASIC_H_
|
||||
#define CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASIC_H_
|
||||
|
||||
#include "chrome/browser/printing/print_view_manager_base.h"
|
||||
#include "content/public/browser/web_contents_user_data.h"
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
#include "base/file_descriptor_posix.h"
|
||||
#endif
|
||||
|
||||
namespace printing {
|
||||
|
||||
// Manages the print commands for a WebContents - basic version.
|
||||
class PrintViewManagerBasic
|
||||
: public PrintViewManagerBase,
|
||||
public content::WebContentsUserData<PrintViewManagerBasic> {
|
||||
public:
|
||||
virtual ~PrintViewManagerBasic();
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
// Sets the file descriptor into which the PDF will be written.
|
||||
void set_file_descriptor(const base::FileDescriptor& file_descriptor) {
|
||||
file_descriptor_ = file_descriptor;
|
||||
}
|
||||
|
||||
// Gets the file descriptor into which the PDF will be written.
|
||||
base::FileDescriptor file_descriptor() const { return file_descriptor_; }
|
||||
|
||||
// content::WebContentsObserver implementation.
|
||||
// Terminates or cancels the print job if one was pending.
|
||||
virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
|
||||
|
||||
// content::WebContentsObserver implementation.
|
||||
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
||||
#endif
|
||||
|
||||
private:
|
||||
explicit PrintViewManagerBasic(content::WebContents* web_contents);
|
||||
friend class content::WebContentsUserData<PrintViewManagerBasic>;
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
virtual void OnPrintingFailed(int cookie) OVERRIDE;
|
||||
|
||||
// The file descriptor into which the PDF of the page will be written.
|
||||
base::FileDescriptor file_descriptor_;
|
||||
#endif
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintViewManagerBasic);
|
||||
};
|
||||
|
||||
} // namespace printing
|
||||
|
||||
#endif // CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASIC_H_
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2011 The Chromium 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 CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_OBSERVER_H_
|
||||
#define CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_OBSERVER_H_
|
||||
|
||||
namespace printing {
|
||||
|
||||
// An interface the PrintViewManager uses to notify an observer when the print
|
||||
// dialog is shown. Register the observer via PrintViewManager::set_observer.
|
||||
class PrintViewManagerObserver {
|
||||
public:
|
||||
// Notifies the observer that the print dialog was shown.
|
||||
virtual void OnPrintDialogShown() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~PrintViewManagerObserver() {}
|
||||
};
|
||||
|
||||
} // namespace printing
|
||||
|
||||
#endif // CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_OBSERVER_H_
|
||||
143
chromium_src/chrome/browser/printing/printer_query.cc
Normal file
143
chromium_src/chrome/browser/printing/printer_query.cc
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright (c) 2012 The Chromium 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 "chrome/browser/printing/printer_query.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/bind_helpers.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/threading/thread_restrictions.h"
|
||||
#include "base/values.h"
|
||||
#include "chrome/browser/printing/print_job_worker.h"
|
||||
#include "chrome/browser/printing/printing_ui_web_contents_observer.h"
|
||||
|
||||
namespace printing {
|
||||
|
||||
PrinterQuery::PrinterQuery()
|
||||
: io_message_loop_(base::MessageLoop::current()),
|
||||
worker_(new PrintJobWorker(this)),
|
||||
is_print_dialog_box_shown_(false),
|
||||
cookie_(PrintSettings::NewCookie()),
|
||||
last_status_(PrintingContext::FAILED) {
|
||||
DCHECK(base::MessageLoopForIO::IsCurrent());
|
||||
}
|
||||
|
||||
PrinterQuery::~PrinterQuery() {
|
||||
// The job should be finished (or at least canceled) when it is destroyed.
|
||||
DCHECK(!is_print_dialog_box_shown_);
|
||||
// If this fires, it is that this pending printer context has leaked.
|
||||
DCHECK(!worker_.get());
|
||||
}
|
||||
|
||||
void PrinterQuery::GetSettingsDone(const PrintSettings& new_settings,
|
||||
PrintingContext::Result result) {
|
||||
is_print_dialog_box_shown_ = false;
|
||||
last_status_ = result;
|
||||
if (result != PrintingContext::FAILED) {
|
||||
settings_ = new_settings;
|
||||
cookie_ = PrintSettings::NewCookie();
|
||||
} else {
|
||||
// Failure.
|
||||
cookie_ = 0;
|
||||
}
|
||||
|
||||
if (!callback_.is_null()) {
|
||||
// This may cause reentrancy like to call StopWorker().
|
||||
callback_.Run();
|
||||
callback_.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
PrintJobWorker* PrinterQuery::DetachWorker(PrintJobWorkerOwner* new_owner) {
|
||||
DCHECK(callback_.is_null());
|
||||
DCHECK(worker_.get());
|
||||
|
||||
worker_->SetNewOwner(new_owner);
|
||||
return worker_.release();
|
||||
}
|
||||
|
||||
base::MessageLoop* PrinterQuery::message_loop() {
|
||||
return io_message_loop_;
|
||||
}
|
||||
|
||||
const PrintSettings& PrinterQuery::settings() const {
|
||||
return settings_;
|
||||
}
|
||||
|
||||
int PrinterQuery::cookie() const {
|
||||
return cookie_;
|
||||
}
|
||||
|
||||
void PrinterQuery::GetSettings(
|
||||
GetSettingsAskParam ask_user_for_settings,
|
||||
scoped_ptr<PrintingUIWebContentsObserver> web_contents_observer,
|
||||
int expected_page_count,
|
||||
bool has_selection,
|
||||
MarginType margin_type,
|
||||
const base::Closure& callback) {
|
||||
DCHECK_EQ(io_message_loop_, base::MessageLoop::current());
|
||||
DCHECK(!is_print_dialog_box_shown_);
|
||||
|
||||
StartWorker(callback);
|
||||
|
||||
// Real work is done in PrintJobWorker::GetSettings().
|
||||
is_print_dialog_box_shown_ = ask_user_for_settings == ASK_USER;
|
||||
worker_->message_loop()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&PrintJobWorker::GetSettings,
|
||||
base::Unretained(worker_.get()),
|
||||
is_print_dialog_box_shown_,
|
||||
base::Passed(&web_contents_observer),
|
||||
expected_page_count,
|
||||
has_selection,
|
||||
margin_type));
|
||||
}
|
||||
|
||||
void PrinterQuery::SetSettings(const base::DictionaryValue& new_settings,
|
||||
const base::Closure& callback) {
|
||||
StartWorker(callback);
|
||||
|
||||
worker_->message_loop()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&PrintJobWorker::SetSettings,
|
||||
base::Unretained(worker_.get()),
|
||||
new_settings.DeepCopy()));
|
||||
}
|
||||
|
||||
void PrinterQuery::SetWorkerDestination(
|
||||
PrintDestinationInterface* destination) {
|
||||
worker_->SetPrintDestination(destination);
|
||||
}
|
||||
|
||||
void PrinterQuery::StartWorker(const base::Closure& callback) {
|
||||
DCHECK(callback_.is_null());
|
||||
DCHECK(worker_.get());
|
||||
|
||||
// Lazily create the worker thread. There is one worker thread per print job.
|
||||
if (!worker_->message_loop())
|
||||
worker_->Start();
|
||||
|
||||
callback_ = callback;
|
||||
}
|
||||
|
||||
void PrinterQuery::StopWorker() {
|
||||
if (worker_.get()) {
|
||||
// http://crbug.com/66082: We're blocking on the PrinterQuery's worker
|
||||
// thread. It's not clear to me if this may result in blocking the current
|
||||
// thread for an unacceptable time. We should probably fix it.
|
||||
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
||||
worker_->Stop();
|
||||
worker_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool PrinterQuery::is_callback_pending() const {
|
||||
return !callback_.is_null();
|
||||
}
|
||||
|
||||
bool PrinterQuery::is_valid() const {
|
||||
return worker_.get() != NULL;
|
||||
}
|
||||
|
||||
} // namespace printing
|
||||
110
chromium_src/chrome/browser/printing/printer_query.h
Normal file
110
chromium_src/chrome/browser/printing/printer_query.h
Normal file
@@ -0,0 +1,110 @@
|
||||
// Copyright (c) 2012 The Chromium 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 CHROME_BROWSER_PRINTING_PRINTER_QUERY_H_
|
||||
#define CHROME_BROWSER_PRINTING_PRINTER_QUERY_H_
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "chrome/browser/printing/print_job_worker_owner.h"
|
||||
#include "printing/print_job_constants.h"
|
||||
|
||||
class PrintingUIWebContentsObserver;
|
||||
|
||||
namespace base {
|
||||
class DictionaryValue;
|
||||
class MessageLoop;
|
||||
}
|
||||
|
||||
namespace printing {
|
||||
|
||||
class PrintDestinationInterface;
|
||||
class PrintJobWorker;
|
||||
|
||||
// Query the printer for settings.
|
||||
class PrinterQuery : public PrintJobWorkerOwner {
|
||||
public:
|
||||
// GetSettings() UI parameter.
|
||||
enum GetSettingsAskParam {
|
||||
DEFAULTS,
|
||||
ASK_USER,
|
||||
};
|
||||
|
||||
PrinterQuery();
|
||||
|
||||
// PrintJobWorkerOwner implementation.
|
||||
virtual void GetSettingsDone(const PrintSettings& new_settings,
|
||||
PrintingContext::Result result) OVERRIDE;
|
||||
virtual PrintJobWorker* DetachWorker(PrintJobWorkerOwner* new_owner) OVERRIDE;
|
||||
virtual base::MessageLoop* message_loop() OVERRIDE;
|
||||
virtual const PrintSettings& settings() const OVERRIDE;
|
||||
virtual int cookie() const OVERRIDE;
|
||||
|
||||
// Initializes the printing context. It is fine to call this function multiple
|
||||
// times to reinitialize the settings. |web_contents_observer| can be queried
|
||||
// to find the owner of the print setting dialog box. It is unused when
|
||||
// |ask_for_user_settings| is DEFAULTS.
|
||||
void GetSettings(
|
||||
GetSettingsAskParam ask_user_for_settings,
|
||||
scoped_ptr<PrintingUIWebContentsObserver> web_contents_observer,
|
||||
int expected_page_count,
|
||||
bool has_selection,
|
||||
MarginType margin_type,
|
||||
const base::Closure& callback);
|
||||
|
||||
// Updates the current settings with |new_settings| dictionary values.
|
||||
void SetSettings(const base::DictionaryValue& new_settings,
|
||||
const base::Closure& callback);
|
||||
|
||||
// Set a destination for the worker.
|
||||
void SetWorkerDestination(PrintDestinationInterface* destination);
|
||||
|
||||
// Stops the worker thread since the client is done with this object.
|
||||
void StopWorker();
|
||||
|
||||
// Returns true if a GetSettings() call is pending completion.
|
||||
bool is_callback_pending() const;
|
||||
|
||||
PrintingContext::Result last_status() const { return last_status_; }
|
||||
|
||||
// Returns if a worker thread is still associated to this instance.
|
||||
bool is_valid() const;
|
||||
|
||||
private:
|
||||
virtual ~PrinterQuery();
|
||||
|
||||
// Lazy create the worker thread. There is one worker thread per print job.
|
||||
void StartWorker(const base::Closure& callback);
|
||||
|
||||
// Main message loop reference. Used to send notifications in the right
|
||||
// thread.
|
||||
base::MessageLoop* const io_message_loop_;
|
||||
|
||||
// All the UI is done in a worker thread because many Win32 print functions
|
||||
// are blocking and enters a message loop without your consent. There is one
|
||||
// worker thread per print job.
|
||||
scoped_ptr<PrintJobWorker> worker_;
|
||||
|
||||
// Cache of the print context settings for access in the UI thread.
|
||||
PrintSettings settings_;
|
||||
|
||||
// Is the Print... dialog box currently shown.
|
||||
bool is_print_dialog_box_shown_;
|
||||
|
||||
// Cookie that make this instance unique.
|
||||
int cookie_;
|
||||
|
||||
// Results from the last GetSettingsDone() callback.
|
||||
PrintingContext::Result last_status_;
|
||||
|
||||
// Callback waiting to be run.
|
||||
base::Closure callback_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrinterQuery);
|
||||
};
|
||||
|
||||
} // namespace printing
|
||||
|
||||
#endif // CHROME_BROWSER_PRINTING_PRINTER_QUERY_H_
|
||||
233
chromium_src/chrome/browser/printing/printing_message_filter.cc
Normal file
233
chromium_src/chrome/browser/printing/printing_message_filter.cc
Normal file
@@ -0,0 +1,233 @@
|
||||
// Copyright (c) 2012 The Chromium 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 "chrome/browser/printing/printing_message_filter.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/browser/printing/printer_query.h"
|
||||
#include "chrome/browser/printing/print_job_manager.h"
|
||||
#include "chrome/browser/printing/printing_ui_web_contents_observer.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "chrome/browser/profiles/profile_io_data.h"
|
||||
#include "chrome/common/print_messages.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace {
|
||||
|
||||
void RenderParamsFromPrintSettings(const printing::PrintSettings& settings,
|
||||
PrintMsg_Print_Params* params) {
|
||||
params->page_size = settings.page_setup_device_units().physical_size();
|
||||
params->content_size.SetSize(
|
||||
settings.page_setup_device_units().content_area().width(),
|
||||
settings.page_setup_device_units().content_area().height());
|
||||
params->printable_area.SetRect(
|
||||
settings.page_setup_device_units().printable_area().x(),
|
||||
settings.page_setup_device_units().printable_area().y(),
|
||||
settings.page_setup_device_units().printable_area().width(),
|
||||
settings.page_setup_device_units().printable_area().height());
|
||||
params->margin_top = settings.page_setup_device_units().content_area().y();
|
||||
params->margin_left = settings.page_setup_device_units().content_area().x();
|
||||
params->dpi = settings.dpi();
|
||||
// Currently hardcoded at 1.25. See PrintSettings' constructor.
|
||||
params->min_shrink = settings.min_shrink();
|
||||
// Currently hardcoded at 2.0. See PrintSettings' constructor.
|
||||
params->max_shrink = settings.max_shrink();
|
||||
// Currently hardcoded at 72dpi. See PrintSettings' constructor.
|
||||
params->desired_dpi = settings.desired_dpi();
|
||||
// Always use an invalid cookie.
|
||||
params->document_cookie = 0;
|
||||
params->selection_only = settings.selection_only();
|
||||
params->supports_alpha_blend = settings.supports_alpha_blend();
|
||||
params->should_print_backgrounds = settings.should_print_backgrounds();
|
||||
params->title = settings.title();
|
||||
params->url = settings.url();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PrintingMessageFilter::PrintingMessageFilter(int render_process_id)
|
||||
: BrowserMessageFilter(PrintMsgStart),
|
||||
render_process_id_(render_process_id),
|
||||
queue_(g_browser_process->print_job_manager()->queue()) {
|
||||
DCHECK(queue_);
|
||||
}
|
||||
|
||||
PrintingMessageFilter::~PrintingMessageFilter() {
|
||||
}
|
||||
|
||||
bool PrintingMessageFilter::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(PrintingMessageFilter, message)
|
||||
#if defined(OS_WIN)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_DuplicateSection, OnDuplicateSection)
|
||||
#endif
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings,
|
||||
OnGetDefaultPrintSettings)
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
return handled;
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void PrintingMessageFilter::OnDuplicateSection(
|
||||
base::SharedMemoryHandle renderer_handle,
|
||||
base::SharedMemoryHandle* browser_handle) {
|
||||
// Duplicate the handle in this process right now so the memory is kept alive
|
||||
// (even if it is not mapped)
|
||||
base::SharedMemory shared_buf(renderer_handle, true, PeerHandle());
|
||||
shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), browser_handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
content::WebContents* PrintingMessageFilter::GetWebContentsForRenderView(
|
||||
int render_view_id) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
content::RenderViewHost* view = content::RenderViewHost::FromID(
|
||||
render_process_id_, render_view_id);
|
||||
return view ? content::WebContents::FromRenderViewHost(view) : NULL;
|
||||
}
|
||||
|
||||
struct PrintingMessageFilter::GetPrintSettingsForRenderViewParams {
|
||||
printing::PrinterQuery::GetSettingsAskParam ask_user_for_settings;
|
||||
int expected_page_count;
|
||||
bool has_selection;
|
||||
printing::MarginType margin_type;
|
||||
};
|
||||
|
||||
void PrintingMessageFilter::GetPrintSettingsForRenderView(
|
||||
int render_view_id,
|
||||
GetPrintSettingsForRenderViewParams params,
|
||||
const base::Closure& callback,
|
||||
scoped_refptr<printing::PrinterQuery> printer_query) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
content::WebContents* wc = GetWebContentsForRenderView(render_view_id);
|
||||
if (wc) {
|
||||
scoped_ptr<PrintingUIWebContentsObserver> wc_observer(
|
||||
new PrintingUIWebContentsObserver(wc));
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&printing::PrinterQuery::GetSettings, printer_query,
|
||||
params.ask_user_for_settings, base::Passed(&wc_observer),
|
||||
params.expected_page_count, params.has_selection,
|
||||
params.margin_type, callback));
|
||||
} else {
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&PrintingMessageFilter::OnGetPrintSettingsFailed, this,
|
||||
callback, printer_query));
|
||||
}
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnGetPrintSettingsFailed(
|
||||
const base::Closure& callback,
|
||||
scoped_refptr<printing::PrinterQuery> printer_query) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
printer_query->GetSettingsDone(printing::PrintSettings(),
|
||||
printing::PrintingContext::FAILED);
|
||||
callback.Run();
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
scoped_refptr<printing::PrinterQuery> printer_query;
|
||||
if (false) {
|
||||
// Reply with NULL query.
|
||||
OnGetDefaultPrintSettingsReply(printer_query, reply_msg);
|
||||
return;
|
||||
}
|
||||
printer_query = queue_->PopPrinterQuery(0);
|
||||
if (!printer_query)
|
||||
printer_query = queue_->CreatePrinterQuery();
|
||||
|
||||
// Loads default settings. This is asynchronous, only the IPC message sender
|
||||
// will hang until the settings are retrieved.
|
||||
GetPrintSettingsForRenderViewParams params;
|
||||
params.ask_user_for_settings = printing::PrinterQuery::DEFAULTS;
|
||||
params.expected_page_count = 0;
|
||||
params.has_selection = false;
|
||||
params.margin_type = printing::DEFAULT_MARGINS;
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&PrintingMessageFilter::GetPrintSettingsForRenderView, this,
|
||||
reply_msg->routing_id(), params,
|
||||
base::Bind(&PrintingMessageFilter::OnGetDefaultPrintSettingsReply,
|
||||
this, printer_query, reply_msg),
|
||||
printer_query));
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnGetDefaultPrintSettingsReply(
|
||||
scoped_refptr<printing::PrinterQuery> printer_query,
|
||||
IPC::Message* reply_msg) {
|
||||
PrintMsg_Print_Params params;
|
||||
if (!printer_query.get() ||
|
||||
printer_query->last_status() != printing::PrintingContext::OK) {
|
||||
params.Reset();
|
||||
} else {
|
||||
RenderParamsFromPrintSettings(printer_query->settings(), ¶ms);
|
||||
params.document_cookie = printer_query->cookie();
|
||||
}
|
||||
PrintHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg, params);
|
||||
Send(reply_msg);
|
||||
// If printing was enabled.
|
||||
if (printer_query.get()) {
|
||||
// If user hasn't cancelled.
|
||||
if (printer_query->cookie() && printer_query->settings().dpi()) {
|
||||
queue_->QueuePrinterQuery(printer_query.get());
|
||||
} else {
|
||||
printer_query->StopWorker();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnScriptedPrint(
|
||||
const PrintHostMsg_ScriptedPrint_Params& params,
|
||||
IPC::Message* reply_msg) {
|
||||
scoped_refptr<printing::PrinterQuery> printer_query =
|
||||
queue_->PopPrinterQuery(params.cookie);
|
||||
if (!printer_query)
|
||||
printer_query = queue_->CreatePrinterQuery();
|
||||
GetPrintSettingsForRenderViewParams settings_params;
|
||||
settings_params.ask_user_for_settings = printing::PrinterQuery::ASK_USER;
|
||||
settings_params.expected_page_count = params.expected_pages_count;
|
||||
settings_params.has_selection = params.has_selection;
|
||||
settings_params.margin_type = params.margin_type;
|
||||
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&PrintingMessageFilter::GetPrintSettingsForRenderView, this,
|
||||
reply_msg->routing_id(), settings_params,
|
||||
base::Bind(&PrintingMessageFilter::OnScriptedPrintReply, this,
|
||||
printer_query, reply_msg),
|
||||
printer_query));
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnScriptedPrintReply(
|
||||
scoped_refptr<printing::PrinterQuery> printer_query,
|
||||
IPC::Message* reply_msg) {
|
||||
PrintMsg_PrintPages_Params params;
|
||||
if (printer_query->last_status() != printing::PrintingContext::OK ||
|
||||
!printer_query->settings().dpi()) {
|
||||
params.Reset();
|
||||
} else {
|
||||
RenderParamsFromPrintSettings(printer_query->settings(), ¶ms.params);
|
||||
params.params.document_cookie = printer_query->cookie();
|
||||
params.pages =
|
||||
printing::PageRange::GetPages(printer_query->settings().ranges());
|
||||
}
|
||||
PrintHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, params);
|
||||
Send(reply_msg);
|
||||
if (params.params.dpi && params.params.document_cookie) {
|
||||
queue_->QueuePrinterQuery(printer_query.get());
|
||||
} else {
|
||||
printer_query->StopWorker();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) 2012 The Chromium 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 CHROME_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_
|
||||
#define CHROME_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "content/public/browser/browser_message_filter.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "base/memory/shared_memory.h"
|
||||
#endif
|
||||
|
||||
struct PrintHostMsg_ScriptedPrint_Params;
|
||||
|
||||
namespace base {
|
||||
class DictionaryValue;
|
||||
class FilePath;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace printing {
|
||||
class PrinterQuery;
|
||||
class PrintJobManager;
|
||||
class PrintQueriesQueue;
|
||||
}
|
||||
|
||||
// This class filters out incoming printing related IPC messages for the
|
||||
// renderer process on the IPC thread.
|
||||
class PrintingMessageFilter : public content::BrowserMessageFilter {
|
||||
public:
|
||||
explicit PrintingMessageFilter(int render_process_id);
|
||||
|
||||
// content::BrowserMessageFilter methods.
|
||||
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
||||
|
||||
private:
|
||||
virtual ~PrintingMessageFilter();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Used to pass resulting EMF from renderer to browser in printing.
|
||||
void OnDuplicateSection(base::SharedMemoryHandle renderer_handle,
|
||||
base::SharedMemoryHandle* browser_handle);
|
||||
#endif
|
||||
|
||||
// Given a render_view_id get the corresponding WebContents.
|
||||
// Must be called on the UI thread.
|
||||
content::WebContents* GetWebContentsForRenderView(int render_view_id);
|
||||
|
||||
// GetPrintSettingsForRenderView must be called via PostTask and
|
||||
// base::Bind. Collapse the settings-specific params into a
|
||||
// struct to avoid running into issues with too many params
|
||||
// to base::Bind.
|
||||
struct GetPrintSettingsForRenderViewParams;
|
||||
|
||||
// Retrieve print settings. Uses |render_view_id| to get a parent
|
||||
// for any UI created if needed.
|
||||
void GetPrintSettingsForRenderView(
|
||||
int render_view_id,
|
||||
GetPrintSettingsForRenderViewParams params,
|
||||
const base::Closure& callback,
|
||||
scoped_refptr<printing::PrinterQuery> printer_query);
|
||||
|
||||
void OnGetPrintSettingsFailed(
|
||||
const base::Closure& callback,
|
||||
scoped_refptr<printing::PrinterQuery> printer_query);
|
||||
|
||||
// Get the default print setting.
|
||||
void OnGetDefaultPrintSettings(IPC::Message* reply_msg);
|
||||
void OnGetDefaultPrintSettingsReply(
|
||||
scoped_refptr<printing::PrinterQuery> printer_query,
|
||||
IPC::Message* reply_msg);
|
||||
|
||||
// The renderer host have to show to the user the print dialog and returns
|
||||
// the selected print settings. The task is handled by the print worker
|
||||
// thread and the UI thread. The reply occurs on the IO thread.
|
||||
void OnScriptedPrint(const PrintHostMsg_ScriptedPrint_Params& params,
|
||||
IPC::Message* reply_msg);
|
||||
void OnScriptedPrintReply(
|
||||
scoped_refptr<printing::PrinterQuery> printer_query,
|
||||
IPC::Message* reply_msg);
|
||||
|
||||
const int render_process_id_;
|
||||
|
||||
scoped_refptr<printing::PrintQueriesQueue> queue_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintingMessageFilter);
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2013 The Chromium 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 "chrome/browser/printing/printing_ui_web_contents_observer.h"
|
||||
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
||||
PrintingUIWebContentsObserver::PrintingUIWebContentsObserver(
|
||||
content::WebContents* web_contents)
|
||||
: content::WebContentsObserver(web_contents) {
|
||||
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
||||
}
|
||||
|
||||
gfx::NativeView PrintingUIWebContentsObserver::GetParentView() {
|
||||
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
||||
return web_contents() ? web_contents()->GetNativeView() : NULL;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright 2013 The Chromium 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 CHROME_BROWSER_PRINTING_PRINTING_UI_WEB_CONTENTS_OBSERVER_H_
|
||||
#define CHROME_BROWSER_PRINTING_PRINTING_UI_WEB_CONTENTS_OBSERVER_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
|
||||
// Wrapper used to keep track of the lifetime of a WebContents.
|
||||
// Lives on the UI thread.
|
||||
class PrintingUIWebContentsObserver : public content::WebContentsObserver {
|
||||
public:
|
||||
explicit PrintingUIWebContentsObserver(content::WebContents* web_contents);
|
||||
|
||||
// Return the parent NativeView of the observed WebContents.
|
||||
gfx::NativeView GetParentView();
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintingUIWebContentsObserver);
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_PRINTING_PRINTING_UI_WEB_CONTENTS_OBSERVER_H_
|
||||
0
chromium_src/chrome/browser/profiles/profile.h
Normal file
0
chromium_src/chrome/browser/profiles/profile.h
Normal file
0
chromium_src/chrome/browser/ui/simple_message_box.h
Normal file
0
chromium_src/chrome/browser/ui/simple_message_box.h
Normal file
0
chromium_src/chrome/common/pref_names.h
Normal file
0
chromium_src/chrome/common/pref_names.h
Normal file
60
chromium_src/chrome/common/print_messages.cc
Normal file
60
chromium_src/chrome/common/print_messages.cc
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2012 The Chromium 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 "chrome/common/print_messages.h"
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/strings/string16.h"
|
||||
#include "ui/gfx/size.h"
|
||||
|
||||
PrintMsg_Print_Params::PrintMsg_Print_Params()
|
||||
: page_size(),
|
||||
content_size(),
|
||||
printable_area(),
|
||||
margin_top(0),
|
||||
margin_left(0),
|
||||
dpi(0),
|
||||
min_shrink(0),
|
||||
max_shrink(0),
|
||||
desired_dpi(0),
|
||||
document_cookie(0),
|
||||
selection_only(false),
|
||||
supports_alpha_blend(false),
|
||||
print_scaling_option(blink::WebPrintScalingOptionSourceSize),
|
||||
title(),
|
||||
url(),
|
||||
should_print_backgrounds(false) {
|
||||
}
|
||||
|
||||
PrintMsg_Print_Params::~PrintMsg_Print_Params() {}
|
||||
|
||||
void PrintMsg_Print_Params::Reset() {
|
||||
page_size = gfx::Size();
|
||||
content_size = gfx::Size();
|
||||
printable_area = gfx::Rect();
|
||||
margin_top = 0;
|
||||
margin_left = 0;
|
||||
dpi = 0;
|
||||
min_shrink = 0;
|
||||
max_shrink = 0;
|
||||
desired_dpi = 0;
|
||||
document_cookie = 0;
|
||||
selection_only = false;
|
||||
supports_alpha_blend = false;
|
||||
print_scaling_option = blink::WebPrintScalingOptionSourceSize;
|
||||
title.clear();
|
||||
url.clear();
|
||||
should_print_backgrounds = false;
|
||||
}
|
||||
|
||||
PrintMsg_PrintPages_Params::PrintMsg_PrintPages_Params()
|
||||
: pages() {
|
||||
}
|
||||
|
||||
PrintMsg_PrintPages_Params::~PrintMsg_PrintPages_Params() {}
|
||||
|
||||
void PrintMsg_PrintPages_Params::Reset() {
|
||||
params.Reset();
|
||||
pages = std::vector<int>();
|
||||
}
|
||||
241
chromium_src/chrome/common/print_messages.h
Normal file
241
chromium_src/chrome/common/print_messages.h
Normal file
@@ -0,0 +1,241 @@
|
||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// IPC messages for printing.
|
||||
// Multiply-included message file, hence no include guard.
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/shared_memory.h"
|
||||
#include "base/values.h"
|
||||
#include "ipc/ipc_message_macros.h"
|
||||
#include "printing/page_size_margins.h"
|
||||
#include "printing/print_job_constants.h"
|
||||
#include "third_party/WebKit/public/web/WebPrintScalingOption.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
#include "ui/gfx/rect.h"
|
||||
|
||||
#ifndef CHROME_COMMON_PRINT_MESSAGES_H_
|
||||
#define CHROME_COMMON_PRINT_MESSAGES_H_
|
||||
|
||||
struct PrintMsg_Print_Params {
|
||||
PrintMsg_Print_Params();
|
||||
~PrintMsg_Print_Params();
|
||||
|
||||
// Resets the members of the struct to 0.
|
||||
void Reset();
|
||||
|
||||
gfx::Size page_size;
|
||||
gfx::Size content_size;
|
||||
gfx::Rect printable_area;
|
||||
int margin_top;
|
||||
int margin_left;
|
||||
double dpi;
|
||||
double min_shrink;
|
||||
double max_shrink;
|
||||
int desired_dpi;
|
||||
int document_cookie;
|
||||
bool selection_only;
|
||||
bool supports_alpha_blend;
|
||||
blink::WebPrintScalingOption print_scaling_option;
|
||||
base::string16 title;
|
||||
base::string16 url;
|
||||
bool should_print_backgrounds;
|
||||
};
|
||||
|
||||
struct PrintMsg_PrintPages_Params {
|
||||
PrintMsg_PrintPages_Params();
|
||||
~PrintMsg_PrintPages_Params();
|
||||
|
||||
// Resets the members of the struct to 0.
|
||||
void Reset();
|
||||
|
||||
PrintMsg_Print_Params params;
|
||||
std::vector<int> pages;
|
||||
};
|
||||
|
||||
#endif // CHROME_COMMON_PRINT_MESSAGES_H_
|
||||
|
||||
#define IPC_MESSAGE_START PrintMsgStart
|
||||
|
||||
IPC_ENUM_TRAITS_MAX_VALUE(printing::MarginType,
|
||||
printing::MARGIN_TYPE_LAST)
|
||||
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebPrintScalingOption,
|
||||
blink::WebPrintScalingOptionLast)
|
||||
|
||||
// Parameters for a render request.
|
||||
IPC_STRUCT_TRAITS_BEGIN(PrintMsg_Print_Params)
|
||||
// Physical size of the page, including non-printable margins,
|
||||
// in pixels according to dpi.
|
||||
IPC_STRUCT_TRAITS_MEMBER(page_size)
|
||||
|
||||
// In pixels according to dpi_x and dpi_y.
|
||||
IPC_STRUCT_TRAITS_MEMBER(content_size)
|
||||
|
||||
// Physical printable area of the page in pixels according to dpi.
|
||||
IPC_STRUCT_TRAITS_MEMBER(printable_area)
|
||||
|
||||
// The y-offset of the printable area, in pixels according to dpi.
|
||||
IPC_STRUCT_TRAITS_MEMBER(margin_top)
|
||||
|
||||
// The x-offset of the printable area, in pixels according to dpi.
|
||||
IPC_STRUCT_TRAITS_MEMBER(margin_left)
|
||||
|
||||
// Specifies dots per inch.
|
||||
IPC_STRUCT_TRAITS_MEMBER(dpi)
|
||||
|
||||
// Minimum shrink factor. See PrintSettings::min_shrink for more information.
|
||||
IPC_STRUCT_TRAITS_MEMBER(min_shrink)
|
||||
|
||||
// Maximum shrink factor. See PrintSettings::max_shrink for more information.
|
||||
IPC_STRUCT_TRAITS_MEMBER(max_shrink)
|
||||
|
||||
// Desired apparent dpi on paper.
|
||||
IPC_STRUCT_TRAITS_MEMBER(desired_dpi)
|
||||
|
||||
// Cookie for the document to ensure correctness.
|
||||
IPC_STRUCT_TRAITS_MEMBER(document_cookie)
|
||||
|
||||
// Should only print currently selected text.
|
||||
IPC_STRUCT_TRAITS_MEMBER(selection_only)
|
||||
|
||||
// Does the printer support alpha blending?
|
||||
IPC_STRUCT_TRAITS_MEMBER(supports_alpha_blend)
|
||||
|
||||
// Specifies the page scaling option for preview printing.
|
||||
IPC_STRUCT_TRAITS_MEMBER(print_scaling_option)
|
||||
|
||||
// Title string to be printed as header if requested by the user.
|
||||
IPC_STRUCT_TRAITS_MEMBER(title)
|
||||
|
||||
// URL string to be printed as footer if requested by the user.
|
||||
IPC_STRUCT_TRAITS_MEMBER(url)
|
||||
|
||||
// True if print backgrounds is requested by the user.
|
||||
IPC_STRUCT_TRAITS_MEMBER(should_print_backgrounds)
|
||||
IPC_STRUCT_TRAITS_END()
|
||||
|
||||
IPC_STRUCT_BEGIN(PrintMsg_PrintPage_Params)
|
||||
// Parameters to render the page as a printed page. It must always be the same
|
||||
// value for all the document.
|
||||
IPC_STRUCT_MEMBER(PrintMsg_Print_Params, params)
|
||||
|
||||
// The page number is the indicator of the square that should be rendered
|
||||
// according to the layout specified in PrintMsg_Print_Params.
|
||||
IPC_STRUCT_MEMBER(int, page_number)
|
||||
IPC_STRUCT_END()
|
||||
|
||||
IPC_STRUCT_TRAITS_BEGIN(printing::PageSizeMargins)
|
||||
IPC_STRUCT_TRAITS_MEMBER(content_width)
|
||||
IPC_STRUCT_TRAITS_MEMBER(content_height)
|
||||
IPC_STRUCT_TRAITS_MEMBER(margin_left)
|
||||
IPC_STRUCT_TRAITS_MEMBER(margin_right)
|
||||
IPC_STRUCT_TRAITS_MEMBER(margin_top)
|
||||
IPC_STRUCT_TRAITS_MEMBER(margin_bottom)
|
||||
IPC_STRUCT_TRAITS_END()
|
||||
|
||||
IPC_STRUCT_TRAITS_BEGIN(PrintMsg_PrintPages_Params)
|
||||
// Parameters to render the page as a printed page. It must always be the same
|
||||
// value for all the document.
|
||||
IPC_STRUCT_TRAITS_MEMBER(params)
|
||||
|
||||
// If empty, this means a request to render all the printed pages.
|
||||
IPC_STRUCT_TRAITS_MEMBER(pages)
|
||||
IPC_STRUCT_TRAITS_END()
|
||||
|
||||
// Parameters to describe a rendered page.
|
||||
IPC_STRUCT_BEGIN(PrintHostMsg_DidPrintPage_Params)
|
||||
// A shared memory handle to the EMF data. This data can be quite large so a
|
||||
// memory map needs to be used.
|
||||
IPC_STRUCT_MEMBER(base::SharedMemoryHandle, metafile_data_handle)
|
||||
|
||||
// Size of the metafile data.
|
||||
IPC_STRUCT_MEMBER(uint32, data_size)
|
||||
|
||||
// Cookie for the document to ensure correctness.
|
||||
IPC_STRUCT_MEMBER(int, document_cookie)
|
||||
|
||||
// Page number.
|
||||
IPC_STRUCT_MEMBER(int, page_number)
|
||||
|
||||
// Shrink factor used to render this page.
|
||||
IPC_STRUCT_MEMBER(double, actual_shrink)
|
||||
|
||||
// The size of the page the page author specified.
|
||||
IPC_STRUCT_MEMBER(gfx::Size, page_size)
|
||||
|
||||
// The printable area the page author specified.
|
||||
IPC_STRUCT_MEMBER(gfx::Rect, content_area)
|
||||
IPC_STRUCT_END()
|
||||
|
||||
// Parameters for the IPC message ViewHostMsg_ScriptedPrint
|
||||
IPC_STRUCT_BEGIN(PrintHostMsg_ScriptedPrint_Params)
|
||||
IPC_STRUCT_MEMBER(int, cookie)
|
||||
IPC_STRUCT_MEMBER(int, expected_pages_count)
|
||||
IPC_STRUCT_MEMBER(bool, has_selection)
|
||||
IPC_STRUCT_MEMBER(printing::MarginType, margin_type)
|
||||
IPC_STRUCT_END()
|
||||
|
||||
|
||||
// Messages sent from the browser to the renderer.
|
||||
|
||||
// Tells the render view to switch the CSS to print media type, renders every
|
||||
// requested pages and switch back the CSS to display media type.
|
||||
IPC_MESSAGE_ROUTED2(PrintMsg_PrintPages,
|
||||
bool /* silent print */,
|
||||
bool /* print page's background */)
|
||||
|
||||
// Tells the render view that printing is done so it can clean up.
|
||||
IPC_MESSAGE_ROUTED1(PrintMsg_PrintingDone,
|
||||
bool /* success */)
|
||||
|
||||
// Messages sent from the renderer to the browser.
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Duplicates a shared memory handle from the renderer to the browser. Then
|
||||
// the renderer can flush the handle.
|
||||
IPC_SYNC_MESSAGE_ROUTED1_1(PrintHostMsg_DuplicateSection,
|
||||
base::SharedMemoryHandle /* renderer handle */,
|
||||
base::SharedMemoryHandle /* browser handle */)
|
||||
#endif
|
||||
|
||||
// Tells the browser that the renderer is done calculating the number of
|
||||
// rendered pages according to the specified settings.
|
||||
IPC_MESSAGE_ROUTED2(PrintHostMsg_DidGetPrintedPagesCount,
|
||||
int /* rendered document cookie */,
|
||||
int /* number of rendered pages */)
|
||||
|
||||
// Sends the document cookie of the current printer query to the browser.
|
||||
IPC_MESSAGE_ROUTED1(PrintHostMsg_DidGetDocumentCookie,
|
||||
int /* rendered document cookie */)
|
||||
|
||||
// Tells the browser that the print dialog has been shown.
|
||||
IPC_MESSAGE_ROUTED0(PrintHostMsg_DidShowPrintDialog)
|
||||
|
||||
// Sends back to the browser the rendered "printed page" that was requested by
|
||||
// a ViewMsg_PrintPage message or from scripted printing. The memory handle in
|
||||
// this message is already valid in the browser process.
|
||||
IPC_MESSAGE_ROUTED1(PrintHostMsg_DidPrintPage,
|
||||
PrintHostMsg_DidPrintPage_Params /* page content */)
|
||||
|
||||
// The renderer wants to know the default print settings.
|
||||
IPC_SYNC_MESSAGE_ROUTED0_1(PrintHostMsg_GetDefaultPrintSettings,
|
||||
PrintMsg_Print_Params /* default_settings */)
|
||||
|
||||
// It's the renderer that controls the printing process when it is generated
|
||||
// by javascript. This step is about showing UI to the user to select the
|
||||
// final print settings. The output parameter is the same as
|
||||
// ViewMsg_PrintPages which is executed implicitly.
|
||||
IPC_SYNC_MESSAGE_ROUTED1_1(PrintHostMsg_ScriptedPrint,
|
||||
PrintHostMsg_ScriptedPrint_Params,
|
||||
PrintMsg_PrintPages_Params
|
||||
/* settings chosen by the user*/)
|
||||
|
||||
// This is sent when there are invalid printer settings.
|
||||
IPC_MESSAGE_ROUTED0(PrintHostMsg_ShowInvalidPrinterSettingsError)
|
||||
|
||||
// Tell the browser printing failed.
|
||||
IPC_MESSAGE_ROUTED1(PrintHostMsg_PrintingFailed,
|
||||
int /* document cookie */)
|
||||
1001
chromium_src/chrome/renderer/printing/print_web_view_helper.cc
Normal file
1001
chromium_src/chrome/renderer/printing/print_web_view_helper.cc
Normal file
File diff suppressed because it is too large
Load Diff
218
chromium_src/chrome/renderer/printing/print_web_view_helper.h
Normal file
218
chromium_src/chrome/renderer/printing/print_web_view_helper.h
Normal file
@@ -0,0 +1,218 @@
|
||||
// Copyright (c) 2012 The Chromium 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 CHROME_RENDERER_PRINTING_PRINT_WEB_VIEW_HELPER_H_
|
||||
#define CHROME_RENDERER_PRINTING_PRINT_WEB_VIEW_HELPER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/memory/shared_memory.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/time/time.h"
|
||||
#include "content/public/renderer/render_view_observer.h"
|
||||
#include "content/public/renderer/render_view_observer_tracker.h"
|
||||
#include "printing/metafile_impl.h"
|
||||
#include "third_party/WebKit/public/platform/WebCanvas.h"
|
||||
#include "third_party/WebKit/public/web/WebNode.h"
|
||||
#include "third_party/WebKit/public/web/WebPrintParams.h"
|
||||
#include "ui/gfx/size.h"
|
||||
|
||||
struct PrintMsg_Print_Params;
|
||||
struct PrintMsg_PrintPage_Params;
|
||||
struct PrintMsg_PrintPages_Params;
|
||||
|
||||
namespace base {
|
||||
class DictionaryValue;
|
||||
}
|
||||
|
||||
namespace blink {
|
||||
class WebFrame;
|
||||
class WebView;
|
||||
}
|
||||
|
||||
namespace printing {
|
||||
|
||||
struct PageSizeMargins;
|
||||
class PrepareFrameAndViewForPrint;
|
||||
|
||||
// Stores reference to frame using WebVew and unique name.
|
||||
// Workaround to modal dialog issue on Linux. crbug.com/236147.
|
||||
// If WebFrame someday supports WeakPtr, we should use it here.
|
||||
class FrameReference {
|
||||
public:
|
||||
explicit FrameReference(blink::WebLocalFrame* frame);
|
||||
FrameReference();
|
||||
~FrameReference();
|
||||
|
||||
void Reset(blink::WebLocalFrame* frame);
|
||||
|
||||
blink::WebLocalFrame* GetFrame();
|
||||
blink::WebView* view();
|
||||
|
||||
private:
|
||||
blink::WebView* view_;
|
||||
blink::WebLocalFrame* frame_;
|
||||
};
|
||||
|
||||
// PrintWebViewHelper handles most of the printing grunt work for RenderView.
|
||||
// We plan on making print asynchronous and that will require copying the DOM
|
||||
// of the document and creating a new WebView with the contents.
|
||||
class PrintWebViewHelper
|
||||
: public content::RenderViewObserver,
|
||||
public content::RenderViewObserverTracker<PrintWebViewHelper> {
|
||||
public:
|
||||
explicit PrintWebViewHelper(content::RenderView* render_view);
|
||||
virtual ~PrintWebViewHelper();
|
||||
|
||||
void PrintNode(const blink::WebNode& node);
|
||||
|
||||
private:
|
||||
enum PrintingResult {
|
||||
OK,
|
||||
FAIL_PRINT_INIT,
|
||||
FAIL_PRINT,
|
||||
};
|
||||
|
||||
// RenderViewObserver implementation.
|
||||
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
||||
virtual void PrintPage(blink::WebLocalFrame* frame,
|
||||
bool user_initiated) OVERRIDE;
|
||||
|
||||
// Message handlers ---------------------------------------------------------
|
||||
void OnPrintPages(bool silent, bool print_background);
|
||||
void OnPrintingDone(bool success);
|
||||
|
||||
// Get |page_size| and |content_area| information from
|
||||
// |page_layout_in_points|.
|
||||
void GetPageSizeAndContentAreaFromPageLayout(
|
||||
const PageSizeMargins& page_layout_in_points,
|
||||
gfx::Size* page_size,
|
||||
gfx::Rect* content_area);
|
||||
|
||||
// Update |ignore_css_margins_| based on settings.
|
||||
void UpdateFrameMarginsCssInfo(const base::DictionaryValue& settings);
|
||||
|
||||
// Main printing code -------------------------------------------------------
|
||||
|
||||
void Print(blink::WebLocalFrame* frame,
|
||||
const blink::WebNode& node,
|
||||
bool silent = false,
|
||||
bool print_background = false);
|
||||
|
||||
// Notification when printing is done - signal tear-down/free resources.
|
||||
void DidFinishPrinting(PrintingResult result);
|
||||
|
||||
// Print Settings -----------------------------------------------------------
|
||||
|
||||
// Initialize print page settings with default settings.
|
||||
// Used only for native printing workflow.
|
||||
bool InitPrintSettings(bool fit_to_paper_size);
|
||||
|
||||
// Calculate number of pages in source document.
|
||||
bool CalculateNumberOfPages(blink::WebLocalFrame* frame,
|
||||
const blink::WebNode& node,
|
||||
int* number_of_pages);
|
||||
|
||||
// Get final print settings from the user.
|
||||
// Return false if the user cancels or on error.
|
||||
bool GetPrintSettingsFromUser(blink::WebFrame* frame,
|
||||
const blink::WebNode& node,
|
||||
int expected_pages_count);
|
||||
|
||||
// Page Printing / Rendering ------------------------------------------------
|
||||
|
||||
void OnFramePreparedForPrintPages();
|
||||
void PrintPages();
|
||||
bool PrintPagesNative(blink::WebFrame* frame,
|
||||
int page_count,
|
||||
const gfx::Size& canvas_size);
|
||||
void FinishFramePrinting();
|
||||
|
||||
// Prints the page listed in |params|.
|
||||
#if defined(OS_LINUX) || defined(OS_ANDROID)
|
||||
void PrintPageInternal(const PrintMsg_PrintPage_Params& params,
|
||||
const gfx::Size& canvas_size,
|
||||
blink::WebFrame* frame,
|
||||
Metafile* metafile);
|
||||
#else
|
||||
void PrintPageInternal(const PrintMsg_PrintPage_Params& params,
|
||||
const gfx::Size& canvas_size,
|
||||
blink::WebFrame* frame);
|
||||
#endif
|
||||
|
||||
// Render the frame for printing.
|
||||
bool RenderPagesForPrint(blink::WebLocalFrame* frame,
|
||||
const blink::WebNode& node);
|
||||
|
||||
// Platform specific helper function for rendering page(s) to |metafile|.
|
||||
#if defined(OS_WIN)
|
||||
void RenderPage(const PrintMsg_Print_Params& params,
|
||||
int page_number,
|
||||
blink::WebFrame* frame,
|
||||
bool is_preview,
|
||||
Metafile* metafile,
|
||||
double* scale_factor,
|
||||
gfx::Size* page_size_in_dpi,
|
||||
gfx::Rect* content_area_in_dpi);
|
||||
#elif defined(OS_MACOSX)
|
||||
void RenderPage(const PrintMsg_Print_Params& params,
|
||||
int page_number,
|
||||
blink::WebFrame* frame,
|
||||
bool is_preview,
|
||||
Metafile* metafile,
|
||||
gfx::Size* page_size,
|
||||
gfx::Rect* content_rect);
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
// Renders page contents from |frame| to |content_area| of |canvas|.
|
||||
// |page_number| is zero-based.
|
||||
// When method is called, canvas should be setup to draw to |canvas_area|
|
||||
// with |scale_factor|.
|
||||
static float RenderPageContent(blink::WebFrame* frame,
|
||||
int page_number,
|
||||
const gfx::Rect& canvas_area,
|
||||
const gfx::Rect& content_area,
|
||||
double scale_factor,
|
||||
blink::WebCanvas* canvas);
|
||||
|
||||
// Helper methods -----------------------------------------------------------
|
||||
|
||||
bool CopyMetafileDataToSharedMem(Metafile* metafile,
|
||||
base::SharedMemoryHandle* shared_mem_handle);
|
||||
|
||||
// Helper method to get page layout in points and fit to page if needed.
|
||||
static void ComputePageLayoutInPointsForCss(
|
||||
blink::WebFrame* frame,
|
||||
int page_index,
|
||||
const PrintMsg_Print_Params& default_params,
|
||||
bool ignore_css_margins,
|
||||
double* scale_factor,
|
||||
PageSizeMargins* page_layout_in_points);
|
||||
|
||||
bool GetPrintFrame(blink::WebLocalFrame** frame);
|
||||
|
||||
// Script Initiated Printing ------------------------------------------------
|
||||
|
||||
// WebView used only to print the selection.
|
||||
scoped_ptr<PrepareFrameAndViewForPrint> prep_frame_view_;
|
||||
|
||||
scoped_ptr<PrintMsg_PrintPages_Params> print_pages_params_;
|
||||
bool is_print_ready_metafile_sent_;
|
||||
bool ignore_css_margins_;
|
||||
|
||||
// Let the browser process know of a printing failure. Only set to false when
|
||||
// the failure came from the browser in the first place.
|
||||
bool notify_browser_of_print_failure_;
|
||||
|
||||
bool print_node_in_progress_;
|
||||
|
||||
base::WeakPtrFactory<PrintWebViewHelper> weak_ptr_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintWebViewHelper);
|
||||
};
|
||||
|
||||
} // namespace printing
|
||||
|
||||
#endif // CHROME_RENDERER_PRINTING_PRINT_WEB_VIEW_HELPER_H_
|
||||
@@ -0,0 +1,157 @@
|
||||
// Copyright (c) 2012 The Chromium 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 "chrome/renderer/printing/print_web_view_helper.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "chrome/common/print_messages.h"
|
||||
#include "content/public/renderer/render_thread.h"
|
||||
#include "printing/metafile.h"
|
||||
#include "printing/metafile_impl.h"
|
||||
#include "printing/metafile_skia_wrapper.h"
|
||||
#include "printing/page_size_margins.h"
|
||||
#include "skia/ext/platform_device.h"
|
||||
#include "skia/ext/vector_canvas.h"
|
||||
#include "third_party/WebKit/public/web/WebLocalFrame.h"
|
||||
|
||||
#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
|
||||
#include "base/process/process_handle.h"
|
||||
#else
|
||||
#include "base/file_descriptor_posix.h"
|
||||
#endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
|
||||
|
||||
namespace printing {
|
||||
|
||||
using blink::WebFrame;
|
||||
|
||||
bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame,
|
||||
int page_count,
|
||||
const gfx::Size& canvas_size) {
|
||||
NativeMetafile metafile;
|
||||
if (!metafile.Init())
|
||||
return false;
|
||||
|
||||
const PrintMsg_PrintPages_Params& params = *print_pages_params_;
|
||||
std::vector<int> printed_pages;
|
||||
|
||||
if (params.pages.empty()) {
|
||||
for (int i = 0; i < page_count; ++i) {
|
||||
printed_pages.push_back(i);
|
||||
}
|
||||
} else {
|
||||
// TODO(vitalybuka): redesign to make more code cross platform.
|
||||
for (size_t i = 0; i < params.pages.size(); ++i) {
|
||||
if (params.pages[i] >= 0 && params.pages[i] < page_count) {
|
||||
printed_pages.push_back(params.pages[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (printed_pages.empty())
|
||||
return false;
|
||||
|
||||
PrintMsg_PrintPage_Params page_params;
|
||||
page_params.params = params.params;
|
||||
for (size_t i = 0; i < printed_pages.size(); ++i) {
|
||||
page_params.page_number = printed_pages[i];
|
||||
PrintPageInternal(page_params, canvas_size, frame, &metafile);
|
||||
}
|
||||
|
||||
// blink::printEnd() for PDF should be called before metafile is closed.
|
||||
FinishFramePrinting();
|
||||
|
||||
metafile.FinishDocument();
|
||||
|
||||
// Get the size of the resulting metafile.
|
||||
uint32 buf_size = metafile.GetDataSize();
|
||||
DCHECK_GT(buf_size, 0u);
|
||||
|
||||
#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
||||
int sequence_number = -1;
|
||||
base::FileDescriptor fd;
|
||||
|
||||
// Ask the browser to open a file for us.
|
||||
Send(new PrintHostMsg_AllocateTempFileForPrinting(routing_id(),
|
||||
&fd,
|
||||
&sequence_number));
|
||||
if (!metafile.SaveToFD(fd))
|
||||
return false;
|
||||
|
||||
// Tell the browser we've finished writing the file.
|
||||
Send(new PrintHostMsg_TempFileForPrintingWritten(routing_id(),
|
||||
sequence_number));
|
||||
return true;
|
||||
#else
|
||||
PrintHostMsg_DidPrintPage_Params printed_page_params;
|
||||
printed_page_params.data_size = 0;
|
||||
printed_page_params.document_cookie = params.params.document_cookie;
|
||||
|
||||
{
|
||||
scoped_ptr<base::SharedMemory> shared_mem(
|
||||
content::RenderThread::Get()->HostAllocateSharedMemoryBuffer(
|
||||
buf_size).release());
|
||||
if (!shared_mem.get()) {
|
||||
NOTREACHED() << "AllocateSharedMemoryBuffer failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!shared_mem->Map(buf_size)) {
|
||||
NOTREACHED() << "Map failed";
|
||||
return false;
|
||||
}
|
||||
metafile.GetData(shared_mem->memory(), buf_size);
|
||||
printed_page_params.data_size = buf_size;
|
||||
shared_mem->GiveToProcess(base::GetCurrentProcessHandle(),
|
||||
&(printed_page_params.metafile_data_handle));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < printed_pages.size(); ++i) {
|
||||
printed_page_params.page_number = printed_pages[i];
|
||||
Send(new PrintHostMsg_DidPrintPage(routing_id(), printed_page_params));
|
||||
// Send the rest of the pages with an invalid metafile handle.
|
||||
printed_page_params.metafile_data_handle.fd = -1;
|
||||
}
|
||||
return true;
|
||||
#endif // defined(OS_CHROMEOS)
|
||||
}
|
||||
|
||||
void PrintWebViewHelper::PrintPageInternal(
|
||||
const PrintMsg_PrintPage_Params& params,
|
||||
const gfx::Size& canvas_size,
|
||||
WebFrame* frame,
|
||||
Metafile* metafile) {
|
||||
PageSizeMargins page_layout_in_points;
|
||||
double scale_factor = 1.0f;
|
||||
ComputePageLayoutInPointsForCss(frame, params.page_number, params.params,
|
||||
ignore_css_margins_, &scale_factor,
|
||||
&page_layout_in_points);
|
||||
gfx::Size page_size;
|
||||
gfx::Rect content_area;
|
||||
GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, &page_size,
|
||||
&content_area);
|
||||
gfx::Rect canvas_area = content_area;
|
||||
|
||||
SkBaseDevice* device = metafile->StartPageForVectorCanvas(page_size,
|
||||
canvas_area,
|
||||
scale_factor);
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
// The printPage method take a reference to the canvas we pass down, so it
|
||||
// can't be a stack object.
|
||||
skia::RefPtr<skia::VectorCanvas> canvas =
|
||||
skia::AdoptRef(new skia::VectorCanvas(device));
|
||||
MetafileSkiaWrapper::SetMetafileOnCanvas(*canvas, metafile);
|
||||
skia::SetIsDraftMode(*canvas, is_print_ready_metafile_sent_);
|
||||
|
||||
RenderPageContent(frame, params.page_number, canvas_area, content_area,
|
||||
scale_factor, canvas.get());
|
||||
|
||||
// Done printing. Close the device context to retrieve the compiled metafile.
|
||||
if (!metafile->FinishPage())
|
||||
NOTREACHED() << "metafile failed";
|
||||
}
|
||||
|
||||
} // namespace printing
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2012 The Chromium 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 "chrome/renderer/printing/print_web_view_helper.h"
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/mac/scoped_nsautorelease_pool.h"
|
||||
#include "base/metrics/histogram.h"
|
||||
#include "chrome/common/print_messages.h"
|
||||
#include "printing/metafile.h"
|
||||
#include "printing/metafile_impl.h"
|
||||
#include "printing/metafile_skia_wrapper.h"
|
||||
#include "printing/page_size_margins.h"
|
||||
#include "skia/ext/platform_device.h"
|
||||
#include "skia/ext/vector_canvas.h"
|
||||
#include "third_party/WebKit/public/platform/WebCanvas.h"
|
||||
#include "third_party/WebKit/public/web/WebLocalFrame.h"
|
||||
|
||||
namespace printing {
|
||||
|
||||
using blink::WebFrame;
|
||||
|
||||
void PrintWebViewHelper::PrintPageInternal(
|
||||
const PrintMsg_PrintPage_Params& params,
|
||||
const gfx::Size& canvas_size,
|
||||
WebFrame* frame) {
|
||||
NativeMetafile metafile;
|
||||
if (!metafile.Init())
|
||||
return;
|
||||
|
||||
int page_number = params.page_number;
|
||||
gfx::Size page_size_in_dpi;
|
||||
gfx::Rect content_area_in_dpi;
|
||||
RenderPage(print_pages_params_->params, page_number, frame, false, &metafile,
|
||||
&page_size_in_dpi, &content_area_in_dpi);
|
||||
metafile.FinishDocument();
|
||||
|
||||
PrintHostMsg_DidPrintPage_Params page_params;
|
||||
page_params.data_size = metafile.GetDataSize();
|
||||
page_params.page_number = page_number;
|
||||
page_params.document_cookie = params.params.document_cookie;
|
||||
page_params.page_size = page_size_in_dpi;
|
||||
page_params.content_area = content_area_in_dpi;
|
||||
|
||||
// Ask the browser to create the shared memory for us.
|
||||
if (!CopyMetafileDataToSharedMem(&metafile,
|
||||
&(page_params.metafile_data_handle))) {
|
||||
page_params.data_size = 0;
|
||||
}
|
||||
|
||||
Send(new PrintHostMsg_DidPrintPage(routing_id(), page_params));
|
||||
}
|
||||
|
||||
void PrintWebViewHelper::RenderPage(
|
||||
const PrintMsg_Print_Params& params, int page_number, WebFrame* frame,
|
||||
bool is_preview, Metafile* metafile, gfx::Size* page_size,
|
||||
gfx::Rect* content_rect) {
|
||||
double scale_factor = 1.0f;
|
||||
double webkit_shrink_factor = frame->getPrintPageShrink(page_number);
|
||||
PageSizeMargins page_layout_in_points;
|
||||
gfx::Rect content_area;
|
||||
|
||||
ComputePageLayoutInPointsForCss(frame, page_number, params,
|
||||
ignore_css_margins_, &scale_factor,
|
||||
&page_layout_in_points);
|
||||
GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, page_size,
|
||||
&content_area);
|
||||
if (content_rect)
|
||||
*content_rect = content_area;
|
||||
|
||||
scale_factor *= webkit_shrink_factor;
|
||||
|
||||
gfx::Rect canvas_area = content_area;
|
||||
|
||||
{
|
||||
SkBaseDevice* device = metafile->StartPageForVectorCanvas(
|
||||
*page_size, canvas_area, scale_factor);
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
skia::RefPtr<skia::VectorCanvas> canvas =
|
||||
skia::AdoptRef(new skia::VectorCanvas(device));
|
||||
blink::WebCanvas* canvas_ptr = canvas.get();
|
||||
MetafileSkiaWrapper::SetMetafileOnCanvas(*canvas, metafile);
|
||||
skia::SetIsDraftMode(*canvas, is_print_ready_metafile_sent_);
|
||||
skia::SetIsPreviewMetafile(*canvas, is_preview);
|
||||
|
||||
RenderPageContent(frame, page_number, canvas_area, content_area,
|
||||
scale_factor, canvas_ptr);
|
||||
}
|
||||
|
||||
// Done printing. Close the device context to retrieve the compiled metafile.
|
||||
metafile->FinishPage();
|
||||
}
|
||||
|
||||
} // namespace printing
|
||||
@@ -0,0 +1,193 @@
|
||||
// Copyright (c) 2012 The Chromium 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 "chrome/renderer/printing/print_web_view_helper.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/metrics/histogram.h"
|
||||
#include "base/process/process_handle.h"
|
||||
#include "base/win/scoped_gdi_object.h"
|
||||
#include "base/win/scoped_hdc.h"
|
||||
#include "base/win/scoped_select_object.h"
|
||||
#include "chrome/common/print_messages.h"
|
||||
#include "printing/metafile.h"
|
||||
#include "printing/metafile_impl.h"
|
||||
#include "printing/metafile_skia_wrapper.h"
|
||||
#include "printing/page_size_margins.h"
|
||||
#include "printing/units.h"
|
||||
#include "skia/ext/platform_device.h"
|
||||
#include "skia/ext/refptr.h"
|
||||
#include "skia/ext/vector_canvas.h"
|
||||
#include "third_party/WebKit/public/web/WebLocalFrame.h"
|
||||
#include "ui/gfx/gdi_util.h"
|
||||
#include "ui/gfx/point.h"
|
||||
#include "ui/gfx/rect.h"
|
||||
#include "ui/gfx/size.h"
|
||||
|
||||
namespace printing {
|
||||
|
||||
using blink::WebFrame;
|
||||
|
||||
void PrintWebViewHelper::PrintPageInternal(
|
||||
const PrintMsg_PrintPage_Params& params,
|
||||
const gfx::Size& canvas_size,
|
||||
WebFrame* frame) {
|
||||
// Generate a memory-based metafile. It will use the current screen's DPI.
|
||||
// Each metafile contains a single page.
|
||||
scoped_ptr<NativeMetafile> metafile(new NativeMetafile);
|
||||
metafile->Init();
|
||||
DCHECK(metafile->context());
|
||||
skia::InitializeDC(metafile->context());
|
||||
|
||||
int page_number = params.page_number;
|
||||
|
||||
// Calculate the dpi adjustment.
|
||||
// Browser will render context using desired_dpi, so we need to calculate
|
||||
// adjustment factor to play content on the printer DC later during the
|
||||
// actual printing.
|
||||
double actual_shrink = static_cast<float>(params.params.desired_dpi /
|
||||
params.params.dpi);
|
||||
gfx::Size page_size_in_dpi;
|
||||
gfx::Rect content_area_in_dpi;
|
||||
|
||||
// Render page for printing.
|
||||
RenderPage(params.params, page_number, frame, false, metafile.get(),
|
||||
&actual_shrink, &page_size_in_dpi, &content_area_in_dpi);
|
||||
|
||||
// Close the device context to retrieve the compiled metafile.
|
||||
if (!metafile->FinishDocument())
|
||||
NOTREACHED();
|
||||
|
||||
if (!params.params.supports_alpha_blend && metafile->IsAlphaBlendUsed()) {
|
||||
scoped_ptr<NativeMetafile> raster_metafile(
|
||||
metafile->RasterizeAlphaBlend());
|
||||
if (raster_metafile.get())
|
||||
metafile.swap(raster_metafile);
|
||||
}
|
||||
|
||||
// Get the size of the compiled metafile.
|
||||
uint32 buf_size = metafile->GetDataSize();
|
||||
DCHECK_GT(buf_size, 128u);
|
||||
|
||||
PrintHostMsg_DidPrintPage_Params page_params;
|
||||
page_params.data_size = buf_size;
|
||||
page_params.metafile_data_handle = NULL;
|
||||
page_params.page_number = page_number;
|
||||
page_params.document_cookie = params.params.document_cookie;
|
||||
page_params.actual_shrink = actual_shrink;
|
||||
page_params.page_size = page_size_in_dpi;
|
||||
page_params.content_area = content_area_in_dpi;
|
||||
|
||||
if (!CopyMetafileDataToSharedMem(metafile.get(),
|
||||
&(page_params.metafile_data_handle))) {
|
||||
page_params.data_size = 0;
|
||||
}
|
||||
|
||||
Send(new PrintHostMsg_DidPrintPage(routing_id(), page_params));
|
||||
}
|
||||
|
||||
void PrintWebViewHelper::RenderPage(
|
||||
const PrintMsg_Print_Params& params, int page_number, WebFrame* frame,
|
||||
bool is_preview, Metafile* metafile, double* actual_shrink,
|
||||
gfx::Size* page_size_in_dpi, gfx::Rect* content_area_in_dpi) {
|
||||
PageSizeMargins page_layout_in_points;
|
||||
double css_scale_factor = 1.0f;
|
||||
ComputePageLayoutInPointsForCss(frame, page_number, params,
|
||||
ignore_css_margins_, &css_scale_factor,
|
||||
&page_layout_in_points);
|
||||
gfx::Size page_size;
|
||||
gfx::Rect content_area;
|
||||
GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, &page_size,
|
||||
&content_area);
|
||||
int dpi = static_cast<int>(params.dpi);
|
||||
// Calculate the actual page size and content area in dpi.
|
||||
if (page_size_in_dpi) {
|
||||
*page_size_in_dpi = gfx::Size(
|
||||
static_cast<int>(ConvertUnitDouble(page_size.width(), kPointsPerInch,
|
||||
dpi)),
|
||||
static_cast<int>(ConvertUnitDouble(page_size.height(), kPointsPerInch,
|
||||
dpi)));
|
||||
}
|
||||
|
||||
if (content_area_in_dpi) {
|
||||
*content_area_in_dpi = gfx::Rect(
|
||||
static_cast<int>(ConvertUnitDouble(content_area.x(), kPointsPerInch,
|
||||
dpi)),
|
||||
static_cast<int>(ConvertUnitDouble(content_area.y(), kPointsPerInch,
|
||||
dpi)),
|
||||
static_cast<int>(ConvertUnitDouble(content_area.width(), kPointsPerInch,
|
||||
dpi)),
|
||||
static_cast<int>(ConvertUnitDouble(content_area.height(),
|
||||
kPointsPerInch, dpi)));
|
||||
}
|
||||
|
||||
float webkit_page_shrink_factor = frame->getPrintPageShrink(page_number);
|
||||
float scale_factor = css_scale_factor * webkit_page_shrink_factor;
|
||||
|
||||
gfx::Rect canvas_area = content_area;
|
||||
|
||||
SkBaseDevice* device = metafile->StartPageForVectorCanvas(
|
||||
page_size, canvas_area, scale_factor);
|
||||
DCHECK(device);
|
||||
// The printPage method may take a reference to the canvas we pass down, so it
|
||||
// can't be a stack object.
|
||||
skia::RefPtr<skia::VectorCanvas> canvas =
|
||||
skia::AdoptRef(new skia::VectorCanvas(device));
|
||||
|
||||
float webkit_scale_factor = RenderPageContent(frame, page_number, canvas_area,
|
||||
content_area, scale_factor,
|
||||
canvas.get());
|
||||
|
||||
if (*actual_shrink <= 0 || webkit_scale_factor <= 0) {
|
||||
NOTREACHED() << "Printing page " << page_number << " failed.";
|
||||
} else {
|
||||
// While rendering certain plugins (PDF) to metafile, we might need to
|
||||
// set custom scale factor. Update |actual_shrink| with custom scale
|
||||
// if it is set on canvas.
|
||||
// TODO(gene): We should revisit this solution for the next versions.
|
||||
// Consider creating metafile of the right size (or resizable)
|
||||
// https://code.google.com/p/chromium/issues/detail?id=126037
|
||||
if (!MetafileSkiaWrapper::GetCustomScaleOnCanvas(
|
||||
*canvas, actual_shrink)) {
|
||||
// Update the dpi adjustment with the "page |actual_shrink|" calculated in
|
||||
// webkit.
|
||||
*actual_shrink /= (webkit_scale_factor * css_scale_factor);
|
||||
}
|
||||
}
|
||||
|
||||
bool result = metafile->FinishPage();
|
||||
DCHECK(result);
|
||||
}
|
||||
|
||||
bool PrintWebViewHelper::CopyMetafileDataToSharedMem(
|
||||
Metafile* metafile, base::SharedMemoryHandle* shared_mem_handle) {
|
||||
uint32 buf_size = metafile->GetDataSize();
|
||||
base::SharedMemory shared_buf;
|
||||
if (buf_size >= kMetafileMaxSize) {
|
||||
NOTREACHED() << "Buffer too large: " << buf_size;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate a shared memory buffer to hold the generated metafile data.
|
||||
if (!shared_buf.CreateAndMapAnonymous(buf_size)) {
|
||||
NOTREACHED() << "Buffer allocation failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the bits into shared memory.
|
||||
if (!metafile->GetData(shared_buf.memory(), buf_size)) {
|
||||
NOTREACHED() << "GetData() failed";
|
||||
shared_buf.Unmap();
|
||||
return false;
|
||||
}
|
||||
shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), shared_mem_handle);
|
||||
shared_buf.Unmap();
|
||||
|
||||
Send(new PrintHostMsg_DuplicateSection(routing_id(), *shared_mem_handle,
|
||||
shared_mem_handle));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace printing
|
||||
0
chromium_src/grit/generated_resources.h
Normal file
0
chromium_src/grit/generated_resources.h
Normal file
@@ -3,6 +3,8 @@
|
||||
* [Quick start](tutorial/quick-start.md)
|
||||
* [Application distribution](tutorial/application-distribution.md)
|
||||
* [Use native node modules](tutorial/use-native-node-modules.md)
|
||||
* [Debugging browser process](tutorial/debugging-browser-process.md)
|
||||
* [DevTools extension](tutorial/devtools-extension.md)
|
||||
|
||||
## API references
|
||||
|
||||
|
||||
@@ -87,6 +87,14 @@ executed. It is possible that a window cancels the quitting by returning
|
||||
Quit the application directly, it will not try to close all windows so cleanup
|
||||
code will not run.
|
||||
|
||||
## app.getDataPath()
|
||||
|
||||
Returns the path for storing configuration files, with app name appended.
|
||||
|
||||
* `%APPDATA%\MyAppName` on Windows
|
||||
* `~/.config/MyAppName` on Linux
|
||||
* `~/Library/Application Support/MyAppName` on OS X
|
||||
|
||||
## app.getVersion()
|
||||
|
||||
Returns the version of loaded application, if no version is found in
|
||||
@@ -103,6 +111,14 @@ to the spec of npm modules. So usually you should also specify a `productName`
|
||||
field, which is your application's full capitalized name, and it will be
|
||||
preferred over `name` by atom-shell.
|
||||
|
||||
## app.resolveProxy(url, callback)
|
||||
|
||||
* `url` URL
|
||||
* `callback` Function
|
||||
|
||||
Resolves the proxy information for `url`, the `callback` would be called with
|
||||
`callback(proxy)` when the request is done.
|
||||
|
||||
## app.commandLine.appendSwitch(switch, [value])
|
||||
|
||||
Append a switch [with optional value] to Chromium's command line.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user