Merge remote-tracking branch 'atom/master'
This commit is contained in:
commit
44528ce60e
18 changed files with 379 additions and 73 deletions
|
@ -159,11 +159,19 @@ WebContents::WebContents(const mate::Dictionary& options) {
|
|||
|
||||
type_ = is_guest ? WEB_VIEW : BROWSER_WINDOW;
|
||||
|
||||
auto browser_context = AtomBrowserMainParts::Get()->browser_context();
|
||||
content::BrowserContext* browser_context =
|
||||
AtomBrowserMainParts::Get()->browser_context();
|
||||
content::WebContents* web_contents;
|
||||
if (is_guest) {
|
||||
content::SiteInstance* site_instance = content::SiteInstance::CreateForURL(
|
||||
browser_context, GURL("chrome-guest://fake-host"));
|
||||
GURL guest_site;
|
||||
options.Get("partition", &guest_site);
|
||||
// use hosts' browser_context when no partition is specified.
|
||||
if (!guest_site.query().empty()) {
|
||||
browser_context = AtomBrowserMainParts::Get()
|
||||
->GetBrowserContextForPartition(guest_site);
|
||||
}
|
||||
auto site_instance =
|
||||
content::SiteInstance::CreateForURL(browser_context, guest_site);
|
||||
content::WebContents::CreateParams params(browser_context, site_instance);
|
||||
guest_delegate_.reset(new WebViewGuestDelegate);
|
||||
params.guest_delegate = guest_delegate_.get();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/web_view_constants.h"
|
||||
#include "atom/browser/web_view_manager.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
|
@ -34,16 +35,19 @@ struct Converter<atom::WebViewManager::WebViewInfo> {
|
|||
return false;
|
||||
|
||||
GURL preload_url;
|
||||
if (!options.Get("preloadUrl", &preload_url))
|
||||
if (!options.Get(atom::web_view::kPreloadUrl, &preload_url))
|
||||
return false;
|
||||
|
||||
if (!preload_url.is_empty() &&
|
||||
!net::FileURLToFilePath(preload_url, &(out->preload_script)))
|
||||
return false;
|
||||
|
||||
return options.Get("nodeIntegration", &(out->node_integration)) &&
|
||||
options.Get("plugins", &(out->plugins)) &&
|
||||
options.Get("disableWebSecurity", &(out->disable_web_security));
|
||||
return options.Get(atom::web_view::kNodeIntegration,
|
||||
&(out->node_integration)) &&
|
||||
options.Get(atom::web_view::kPlugins, &(out->plugins)) &&
|
||||
options.Get(atom::web_view::kPartitionId, &(out->partition_id)) &&
|
||||
options.Get(atom::web_view::kDisableWebSecurity,
|
||||
&(out->disable_web_security));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -67,12 +71,15 @@ void AddGuest(int guest_instance_id,
|
|||
content::WebContents* guest_web_contents,
|
||||
atom::WebViewManager::WebViewInfo info) {
|
||||
auto manager = GetWebViewManager(embedder);
|
||||
if (manager) {
|
||||
info.guest_instance_id = guest_instance_id;
|
||||
info.embedder = embedder;
|
||||
if (manager)
|
||||
manager->AddGuest(guest_instance_id, element_instance_id, embedder,
|
||||
guest_web_contents, info);
|
||||
}
|
||||
guest_web_contents);
|
||||
|
||||
info.guest_instance_id = guest_instance_id;
|
||||
info.embedder = embedder;
|
||||
auto data = new atom::WebViewManager::WebViewInfoUserData(info);
|
||||
guest_web_contents->SetUserData(
|
||||
atom::web_view::kWebViewInfoKeyName, data);
|
||||
}
|
||||
|
||||
void RemoveGuest(content::WebContents* embedder, int guest_instance_id) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/web_view_manager.h"
|
||||
#include "atom/browser/web_view_constants.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
|
@ -74,8 +75,12 @@ ProcessOwner GetProcessOwner(int process_id,
|
|||
return OWNER_NATIVE_WINDOW;
|
||||
|
||||
// Then search for guest WebContents.
|
||||
if (WebViewManager::GetInfoForWebContents(web_contents, info))
|
||||
auto data = static_cast<WebViewManager::WebViewInfoUserData*>(
|
||||
web_contents->GetUserData(web_view::kWebViewInfoKeyName));
|
||||
if (data) {
|
||||
*info = data->web_view_info();
|
||||
return OWNER_GUEST_WEB_CONTENTS;
|
||||
}
|
||||
|
||||
return OWNER_NONE;
|
||||
}
|
||||
|
@ -155,9 +160,10 @@ void AtomBrowserClient::OverrideWebkitPrefs(
|
|||
|
||||
// Custom preferences of guest page.
|
||||
auto web_contents = content::WebContents::FromRenderViewHost(host);
|
||||
WebViewManager::WebViewInfo info;
|
||||
if (WebViewManager::GetInfoForWebContents(web_contents, &info)) {
|
||||
prefs->web_security_enabled = !info.disable_web_security;
|
||||
auto info = static_cast<WebViewManager::WebViewInfoUserData*>(
|
||||
web_contents->GetUserData(web_view::kWebViewInfoKeyName));
|
||||
if (info) {
|
||||
prefs->web_security_enabled = !info->web_view_info().disable_web_security;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,23 @@
|
|||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
const base::FilePath::CharType kStoragePartitionDirname[] = "Partitions";
|
||||
|
||||
void GetStoragePartitionConfig(const GURL& partition,
|
||||
base::FilePath* partition_path,
|
||||
bool* in_memory,
|
||||
std::string* id) {
|
||||
*in_memory = (partition.path() != "/persist");
|
||||
net::UnescapeRule::Type flags =
|
||||
net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS;
|
||||
*id = net::UnescapeURLComponent(partition.query(), flags);
|
||||
*partition_path = base::FilePath(kStoragePartitionDirname).AppendASCII(*id);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
AtomBrowserMainParts* AtomBrowserMainParts::self_ = NULL;
|
||||
|
||||
|
@ -50,6 +67,21 @@ AtomBrowserMainParts* AtomBrowserMainParts::Get() {
|
|||
return self_;
|
||||
}
|
||||
|
||||
content::BrowserContext* AtomBrowserMainParts::GetBrowserContextForPartition(
|
||||
const GURL& partition) {
|
||||
std::string id;
|
||||
bool in_memory;
|
||||
base::FilePath partition_path;
|
||||
GetStoragePartitionConfig(partition, &partition_path, &in_memory, &id);
|
||||
if (browser_context_map_.contains(id))
|
||||
return browser_context_map_.get(id);
|
||||
|
||||
scoped_ptr<brightray::BrowserContext> browser_context(CreateBrowserContext());
|
||||
browser_context->Initialize(partition_path.value(), in_memory);
|
||||
browser_context_map_.set(id, browser_context.Pass());
|
||||
return browser_context_map_.get(id);
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::RegisterDestructionCallback(
|
||||
const base::Closure& callback) {
|
||||
destruction_callbacks_.push_back(callback);
|
||||
|
|
|
@ -6,10 +6,14 @@
|
|||
#define ATOM_BROWSER_ATOM_BROWSER_MAIN_PARTS_H_
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/containers/scoped_ptr_hash_map.h"
|
||||
#include "base/timer/timer.h"
|
||||
#include "brightray/browser/browser_main_parts.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
|
||||
class BrowserProcess;
|
||||
|
||||
|
@ -29,6 +33,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
|||
|
||||
static AtomBrowserMainParts* Get();
|
||||
|
||||
// Returns the BrowserContext associated with the partition.
|
||||
content::BrowserContext* GetBrowserContextForPartition(
|
||||
const GURL& partition);
|
||||
|
||||
// Register a callback that should be destroyed before JavaScript environment
|
||||
// gets destroyed.
|
||||
void RegisterDestructionCallback(const base::Closure& callback);
|
||||
|
@ -70,6 +78,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
|||
// List of callbacks should be executed before destroying JS env.
|
||||
std::list<base::Closure> destruction_callbacks_;
|
||||
|
||||
// partition_id => browser_context
|
||||
base::ScopedPtrHashMap<std::string, scoped_ptr<brightray::BrowserContext>>
|
||||
browser_context_map_;
|
||||
|
||||
static AtomBrowserMainParts* self_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBrowserMainParts);
|
||||
|
|
|
@ -38,12 +38,29 @@ moveLastToFirst = (list) ->
|
|||
getNextInstanceId = (webContents) ->
|
||||
++nextInstanceId
|
||||
|
||||
# Generate URL encoded partition id.
|
||||
getPartitionId = (partition) ->
|
||||
# Guest site url will be chrome-guest://fake-host/{persist}?{partitionId}
|
||||
partitionId = "chrome-guest://fake-host/"
|
||||
if partition
|
||||
persist = partition.startsWith('persist:')
|
||||
if persist
|
||||
partition = partition.substring('persist:'.length)
|
||||
partitionId += 'persist?'
|
||||
else
|
||||
# Just to differentiate from same persistant ID
|
||||
partition += "_temp"
|
||||
partitionId += '?'
|
||||
partitionId += encodeURIComponent(partition)
|
||||
return partitionId
|
||||
|
||||
# Create a new guest instance.
|
||||
createGuest = (embedder, params) ->
|
||||
webViewManager ?= process.atomBinding 'web_view_manager'
|
||||
|
||||
id = getNextInstanceId embedder
|
||||
guest = webContents.create {isGuest: true, embedder}
|
||||
partitionId = getPartitionId params.partition
|
||||
guest = webContents.create {isGuest: true, partition: partitionId, embedder}
|
||||
guestInstances[id] = {guest, embedder}
|
||||
|
||||
# Destroy guest when the embedder is gone or navigated.
|
||||
|
@ -120,6 +137,7 @@ attachGuest = (embedder, elementInstanceId, guestInstanceId, params) ->
|
|||
plugins: params.plugins
|
||||
disableWebSecurity: params.disablewebsecurity
|
||||
preloadUrl: params.preload ? ''
|
||||
partitionId: getPartitionId(params.partition)
|
||||
|
||||
guest.attachParams = params
|
||||
embedderElementsMap[key] = guestInstanceId
|
||||
|
|
24
atom/browser/web_view_constants.cc
Normal file
24
atom/browser/web_view_constants.cc
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/web_view_constants.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace web_view {
|
||||
|
||||
const char kPreloadUrl[] = "preloadUrl";
|
||||
const char kNodeIntegration[] = "nodeIntegration";
|
||||
const char kPlugins[] = "plugins";
|
||||
const char kDisableWebSecurity[] = "disableWebSecurity";
|
||||
const char kPartitionId[] = "partitionId";
|
||||
|
||||
const int kDefaultWidth = 300;
|
||||
const int kDefaultHeight = 300;
|
||||
|
||||
const char kWebViewInfoKeyName[] = "web_view_info";
|
||||
|
||||
} // namespace web_view
|
||||
|
||||
} // namespace atom
|
27
atom/browser/web_view_constants.h
Normal file
27
atom/browser/web_view_constants.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_WEB_VIEW_CONSTANTS_H_
|
||||
#define ATOM_BROWSER_WEB_VIEW_CONSTANTS_H_
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace web_view {
|
||||
|
||||
extern const char kPreloadUrl[];
|
||||
extern const char kNodeIntegration[];
|
||||
extern const char kPlugins[];
|
||||
extern const char kDisableWebSecurity[];
|
||||
extern const char kPartitionId[];
|
||||
|
||||
extern const int kDefaultWidth;
|
||||
extern const int kDefaultHeight;
|
||||
|
||||
extern const char kWebViewInfoKeyName[];
|
||||
|
||||
} // namespace web_view
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_WEB_VIEW_CONSTANTS_H_
|
|
@ -5,6 +5,7 @@
|
|||
#include "atom/browser/web_view_guest_delegate.h"
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/web_view_constants.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "content/public/browser/guest_host.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
|
@ -13,13 +14,6 @@
|
|||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
const int kDefaultWidth = 300;
|
||||
const int kDefaultHeight = 300;
|
||||
|
||||
} // namespace
|
||||
|
||||
WebViewGuestDelegate::WebViewGuestDelegate()
|
||||
: guest_opaque_(true),
|
||||
guest_host_(nullptr),
|
||||
|
@ -178,7 +172,7 @@ gfx::Size WebViewGuestDelegate::GetDefaultSize() const {
|
|||
return embedder_web_contents_->GetRenderWidgetHostView()
|
||||
->GetVisibleViewportSize();
|
||||
} else {
|
||||
return gfx::Size(kDefaultWidth, kDefaultHeight);
|
||||
return gfx::Size(web_view::kDefaultWidth, web_view::kDefaultHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,37 +5,12 @@
|
|||
#include "atom/browser/web_view_manager.h"
|
||||
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
WebViewManager* GetManagerFromWebContents(
|
||||
const content::WebContents* web_contents) {
|
||||
auto context = web_contents->GetBrowserContext();
|
||||
if (!context)
|
||||
return nullptr;
|
||||
return static_cast<WebViewManager*>(context->GetGuestManager());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
bool WebViewManager::GetInfoForWebContents(
|
||||
const content::WebContents* web_contents, WebViewInfo* info) {
|
||||
auto manager = GetManagerFromWebContents(web_contents);
|
||||
if (!manager)
|
||||
return false;
|
||||
base::AutoLock auto_lock(manager->lock_);
|
||||
auto iter = manager->webview_info_map_.find(web_contents);
|
||||
if (iter == manager->webview_info_map_.end())
|
||||
return false;
|
||||
*info = iter->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
WebViewManager::WebViewManager(content::BrowserContext* context) {
|
||||
}
|
||||
|
||||
|
@ -45,11 +20,9 @@ WebViewManager::~WebViewManager() {
|
|||
void WebViewManager::AddGuest(int guest_instance_id,
|
||||
int element_instance_id,
|
||||
content::WebContents* embedder,
|
||||
content::WebContents* web_contents,
|
||||
const WebViewInfo& info) {
|
||||
content::WebContents* web_contents) {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
web_contents_embdder_map_[guest_instance_id] = { web_contents, embedder };
|
||||
webview_info_map_[web_contents] = info;
|
||||
web_contents_embedder_map_[guest_instance_id] = { web_contents, embedder };
|
||||
|
||||
// Map the element in embedder to guest.
|
||||
int owner_process_id = embedder->GetRenderProcessHost()->GetID();
|
||||
|
@ -59,12 +32,10 @@ void WebViewManager::AddGuest(int guest_instance_id,
|
|||
|
||||
void WebViewManager::RemoveGuest(int guest_instance_id) {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
if (!ContainsKey(web_contents_embdder_map_, guest_instance_id))
|
||||
if (!ContainsKey(web_contents_embedder_map_, guest_instance_id))
|
||||
return;
|
||||
|
||||
auto web_contents = web_contents_embdder_map_[guest_instance_id].web_contents;
|
||||
web_contents_embdder_map_.erase(guest_instance_id);
|
||||
webview_info_map_.erase(web_contents);
|
||||
web_contents_embedder_map_.erase(guest_instance_id);
|
||||
|
||||
// Remove the record of element in embedder too.
|
||||
for (const auto& element : element_instance_id_to_guest_map_)
|
||||
|
@ -82,15 +53,15 @@ content::WebContents* WebViewManager::GetGuestByInstanceID(
|
|||
return nullptr;
|
||||
|
||||
int guest_instance_id = element_instance_id_to_guest_map_[key];
|
||||
if (ContainsKey(web_contents_embdder_map_, guest_instance_id))
|
||||
return web_contents_embdder_map_[guest_instance_id].web_contents;
|
||||
if (ContainsKey(web_contents_embedder_map_, guest_instance_id))
|
||||
return web_contents_embedder_map_[guest_instance_id].web_contents;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool WebViewManager::ForEachGuest(content::WebContents* embedder_web_contents,
|
||||
const GuestCallback& callback) {
|
||||
for (auto& item : web_contents_embdder_map_)
|
||||
for (auto& item : web_contents_embedder_map_)
|
||||
if (item.second.embedder == embedder_web_contents &&
|
||||
callback.Run(item.second.web_contents))
|
||||
return true;
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
#include <map>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/supports_user_data.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "content/public/browser/browser_plugin_guest_manager.h"
|
||||
#include "content/public/browser/site_instance.h"
|
||||
|
||||
namespace content {
|
||||
class BrowserContext;
|
||||
|
@ -27,12 +29,20 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
|||
bool plugins;
|
||||
bool disable_web_security;
|
||||
base::FilePath preload_script;
|
||||
GURL partition_id;
|
||||
};
|
||||
|
||||
// Finds the WebViewManager attached with |web_contents| and returns the
|
||||
// WebViewInfo of it.
|
||||
static bool GetInfoForWebContents(const content::WebContents* web_contents,
|
||||
WebViewInfo* info);
|
||||
class WebViewInfoUserData : public base::SupportsUserData::Data {
|
||||
public:
|
||||
explicit WebViewInfoUserData(WebViewInfo info)
|
||||
: web_view_info_(info) {}
|
||||
~WebViewInfoUserData() override {}
|
||||
|
||||
WebViewInfo& web_view_info() { return web_view_info_; }
|
||||
|
||||
private:
|
||||
WebViewInfo web_view_info_;
|
||||
};
|
||||
|
||||
explicit WebViewManager(content::BrowserContext* context);
|
||||
virtual ~WebViewManager();
|
||||
|
@ -40,8 +50,7 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
|||
void AddGuest(int guest_instance_id,
|
||||
int element_instance_id,
|
||||
content::WebContents* embedder,
|
||||
content::WebContents* web_contents,
|
||||
const WebViewInfo& info);
|
||||
content::WebContents* web_contents);
|
||||
void RemoveGuest(int guest_instance_id);
|
||||
|
||||
protected:
|
||||
|
@ -57,7 +66,7 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
|||
content::WebContents* embedder;
|
||||
};
|
||||
// guest_instance_id => (web_contents, embedder)
|
||||
std::map<int, WebContentsWithEmbedder> web_contents_embdder_map_;
|
||||
std::map<int, WebContentsWithEmbedder> web_contents_embedder_map_;
|
||||
|
||||
struct ElementInstanceKey {
|
||||
int embedder_process_id;
|
||||
|
@ -81,10 +90,6 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
|||
// (embedder_process_id, element_instance_id) => guest_instance_id
|
||||
std::map<ElementInstanceKey, int> element_instance_id_to_guest_map_;
|
||||
|
||||
typedef std::map<const content::WebContents*, WebViewInfo> WebViewInfoMap;
|
||||
// web_contents => (guest_instance_id, embedder, ...)
|
||||
WebViewInfoMap webview_info_map_;
|
||||
|
||||
base::Lock lock_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WebViewManager);
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
# Electron 和 NW.js (原名 node-webkit) 在技术上的差异
|
||||
|
||||
__备注:Electron 的原名是 Atom Shell。__
|
||||
|
||||
与 NW.js 相似,Electron 提供了一个能通过 JavaScript 和 HTML 创建桌面应用的平台,同时集成 Node 来授予网页访问底层系统的权限。
|
||||
|
||||
但是这两个项目也有本质上的区别,使得 Electron 和 NW.js 成为两个相互独立的产品。
|
||||
|
||||
__1. 应用的入口__
|
||||
|
||||
在 NW.js 中,一个应用的主入口是一个页面。你在 `package.json` 中指定一个主页面,它会作为应用的主窗口被打开。
|
||||
|
||||
在 Electron 中,入口是一个 JavaScript 脚本。不同于直接提供一个URL,你需要手动创建一个浏览器窗口,然后通过 API 加载 HTML 文件。你还可以监听窗口事件,决定何时让应用退出。
|
||||
|
||||
Electron 的工作方式更像 Node.js 运行时。 Electron 的 APIs 更加底层,因此你可以它替代 [PhantomJS](http://phantomjs.org/) 做浏览器测试。
|
||||
|
||||
__2. 构建系统__
|
||||
|
||||
为了避免构建整个 Chromium 带来的复杂度,Electron 通过 [`libchromiumcontent`](https://github.com/brightray/libchromiumcontent) 来访问 Chromium 的 Content API。`libchromiumcontent` 是一个独立的、引入了 Chromium Content 模块及其所有依赖的共享库。用户不需要一个强劲的机器来构建 Electron。
|
||||
|
||||
__3. Node 集成__
|
||||
|
||||
在 NW.js,网页中的 Node 集成需要通过给 Chromium 打补丁来实现。但在 Electron 中,我们选择了另一种方式:通过各个平台的消息循环与 libuv 的循环集成,避免了直接在 Chromium 上做改动。你可以看 [`node_bindings`](../../atom/common/) 来了解这是如何完成的。
|
||||
|
||||
__4. 多上下文__
|
||||
|
||||
如果你是有经验的 NW.js 用户,你应该会熟悉 Node 上下文和 web 上下文的概念。这些概念的产生源于 NW.js 的实现方式。
|
||||
|
||||
通过使用 Node 的[多上下文](http://strongloop.com/strongblog/whats-new-node-js-v0-12-multiple-context-execution/)特性,Electron不需要在网页中引入新的 JavaScript 上下文。
|
30
docs-translations/zh-CN/development/coding-style.md
Normal file
30
docs-translations/zh-CN/development/coding-style.md
Normal file
|
@ -0,0 +1,30 @@
|
|||
# 编码规范
|
||||
|
||||
以下是 Electron 项目中代码书写规范的指导方针。
|
||||
|
||||
## C++ 和 Python
|
||||
|
||||
对于 C++ 和 Python,我们追随 Chromium 的[Coding
|
||||
Style](http://www.chromium.org/developers/coding-style)。你可以通过 `script/cpplint.py` 来检验所有文件是否符合要求。
|
||||
|
||||
我们使用的 Pyhton 版本是 Python 2.7。
|
||||
|
||||
其中 C++ 代码中用到了许多 Chromium 的抽象和类型,我们希望你对其有所熟悉。一个好的去处是
|
||||
Chromium 的[重要的抽象和数据结构](https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures)。这个文档提到了一些特殊的类型、域内类型(当超出作用域时会自动释放内存)、日志机制等等。
|
||||
|
||||
## CoffeeScript
|
||||
|
||||
对于 CoffeeScript,我们追随 GitHub 的[Style
|
||||
Guide](https://github.com/styleguide/javascript) 及如下规则:
|
||||
|
||||
* 文件不应该以换行结尾,因为我们要匹配 Google 的规范。
|
||||
* 文件名应该以 `-` 作连接而不是 `_`,等等。
|
||||
`file-name.coffee` 而不是 `file_name.coffee`,因为在
|
||||
[github/atom](https://github.com/github/atom) 模块名通常都是 `module-name` 的形式。这条规则仅应用于 `.coffee` 文件。
|
||||
|
||||
## API 名称
|
||||
|
||||
当新建一个API时,我们应该倾向于 getters 和 setters 的方式,而不是
|
||||
jQuery 的单函数形式。例如,`.getText()` 和 `.setText(text)`
|
||||
优于 `.text([text])`。这里是相关的
|
||||
[讨论记录](https://github.com/atom/electron/issues/46)。
|
80
docs-translations/zh-TW/tutorial/online-offline-events.md
Normal file
80
docs-translations/zh-TW/tutorial/online-offline-events.md
Normal file
|
@ -0,0 +1,80 @@
|
|||
# 在線/離線事件偵測
|
||||
|
||||
我們可以在渲染引擎 (renderer) 的行程裡用標準的 HTML5 API 來實作在線與離線事件的偵測。
|
||||
請參考以下範例:
|
||||
|
||||
_main.js_
|
||||
|
||||
```javascript
|
||||
var app = require('app');
|
||||
var BrowserWindow = require('browser-window');
|
||||
var onlineStatusWindow;
|
||||
|
||||
app.on('ready', function() {
|
||||
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false });
|
||||
onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html');
|
||||
});
|
||||
```
|
||||
|
||||
_online-status.html_
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
var alertOnlineStatus = function() {
|
||||
window.alert(navigator.onLine ? 'online' : 'offline');
|
||||
};
|
||||
|
||||
window.addEventListener('online', alertOnlineStatus);
|
||||
window.addEventListener('offline', alertOnlineStatus);
|
||||
|
||||
alertOnlineStatus();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
您也許有時候也會有想要在主行程裡回應這些事件的情況。然而,在主行程裡並沒有 `navigator` 這個物件,因此不能直接地偵測這些事件。
|
||||
但我們可以使用 Electron 所提供的跨行程 (inter-process) 溝通的工具,事件就可以被傳送到主程序內並做您所需的處理。
|
||||
請參考以下範例:
|
||||
|
||||
_main.js_
|
||||
|
||||
```javascript
|
||||
var app = require('app');
|
||||
var ipc = require('ipc');
|
||||
var BrowserWindow = require('browser-window');
|
||||
var onlineStatusWindow;
|
||||
|
||||
app.on('ready', function() {
|
||||
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false });
|
||||
onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html');
|
||||
});
|
||||
|
||||
ipc.on('online-status-changed', function(event, status) {
|
||||
console.log(status);
|
||||
});
|
||||
```
|
||||
|
||||
_online-status.html_
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
var ipc = require('ipc');
|
||||
var updateOnlineStatus = function() {
|
||||
ipc.send('online-status-changed', navigator.onLine ? 'online' : 'offline');
|
||||
};
|
||||
|
||||
window.addEventListener('online', updateOnlineStatus);
|
||||
window.addEventListener('offline', updateOnlineStatus);
|
||||
|
||||
updateOnlineStatus();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
|
@ -131,6 +131,24 @@ page is loaded, use the `setUserAgent` method to change the user agent.
|
|||
|
||||
If "on", the guest page will have web security disabled.
|
||||
|
||||
### partition
|
||||
|
||||
```html
|
||||
<webview src="https://github.com" partition="persist:github"></webview>
|
||||
<webview src="http://electron.atom.io" partition="electron"></webview>
|
||||
```
|
||||
|
||||
Sets the storage partition used by the `webview`. If the storage partition ID starts with `persist:`,
|
||||
the `webview` will use a persistent storage partition available to all `webview` in the app with
|
||||
the same storage partition ID. if there is no `persist:` prefix, the `webview` will
|
||||
use an in-memory storage partition. By assigning the same partition ID, multiple `webview`
|
||||
can share the same storage partition. If the storage partition ID is unset then default storage
|
||||
of the app will be used.
|
||||
|
||||
This value can only be modified before the first navigation, since the storage partition of an active
|
||||
renderer process cannot change. Subsequent attempts to modify the value will fail with a
|
||||
DOM exception.
|
||||
|
||||
## Methods
|
||||
|
||||
The `webview` tag has the following methods:
|
||||
|
|
|
@ -226,6 +226,8 @@
|
|||
'atom/browser/ui/x/window_state_watcher.h',
|
||||
'atom/browser/ui/x/x_window_utils.cc',
|
||||
'atom/browser/ui/x/x_window_utils.h',
|
||||
'atom/browser/web_view_constants.cc',
|
||||
'atom/browser/web_view_constants.h',
|
||||
'atom/browser/web_view_guest_delegate.cc',
|
||||
'atom/browser/web_view_guest_delegate.h',
|
||||
'atom/browser/web_view_manager.cc',
|
||||
|
|
4
spec/fixtures/pages/partition/one.html
vendored
Normal file
4
spec/fixtures/pages/partition/one.html
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
<script>
|
||||
const item = window.localStorage.getItem('test');
|
||||
console.log([item, window.localStorage.length].join(' '));
|
||||
</script>
|
|
@ -154,6 +154,45 @@ describe '<webview> tag', ->
|
|||
webview.src = "data:text/html;base64,#{encoded}"
|
||||
document.body.appendChild webview
|
||||
|
||||
describe 'partition attribute', ->
|
||||
it 'inserts no node symbols when not set', (done) ->
|
||||
webview.addEventListener 'console-message', (e) ->
|
||||
assert.equal e.message, 'undefined undefined undefined undefined'
|
||||
done()
|
||||
webview.src = "file://#{fixtures}/pages/c.html"
|
||||
webview.partition = "test"
|
||||
document.body.appendChild webview
|
||||
|
||||
it 'inserts node symbols when set', (done) ->
|
||||
webview.addEventListener 'console-message', (e) ->
|
||||
assert.equal e.message, 'function object object'
|
||||
done()
|
||||
webview.setAttribute 'nodeintegration', 'on'
|
||||
webview.src = "file://#{fixtures}/pages/d.html"
|
||||
webview.partition = "test"
|
||||
document.body.appendChild webview
|
||||
|
||||
it 'isolates storage for different id', (done) ->
|
||||
listener = (e) ->
|
||||
assert.equal e.message, " 0"
|
||||
webview.removeEventListener 'console-message', listener
|
||||
done()
|
||||
window.localStorage.setItem 'test', 'one'
|
||||
webview.addEventListener 'console-message', listener
|
||||
webview.src = "file://#{fixtures}/pages/partition/one.html"
|
||||
webview.partition = "test"
|
||||
document.body.appendChild webview
|
||||
|
||||
it 'uses current session storage when no id is provided', (done) ->
|
||||
listener = (e) ->
|
||||
assert.equal e.message, "one 1"
|
||||
webview.removeEventListener 'console-message', listener
|
||||
done()
|
||||
window.localStorage.setItem 'test', 'one'
|
||||
webview.addEventListener 'console-message', listener
|
||||
webview.src = "file://#{fixtures}/pages/partition/one.html"
|
||||
document.body.appendChild webview
|
||||
|
||||
describe 'new-window event', ->
|
||||
it 'emits when window.open is called', (done) ->
|
||||
webview.addEventListener 'new-window', (e) ->
|
||||
|
|
Loading…
Reference in a new issue