diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 5b723801cd..7cefe8e45e 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -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(); diff --git a/atom/browser/api/atom_api_web_view_manager.cc b/atom/browser/api/atom_api_web_view_manager.cc index d77ea18d6d..221d0d7118 100644 --- a/atom/browser/api/atom_api_web_view_manager.cc +++ b/atom/browser/api/atom_api_web_view_manager.cc @@ -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 { 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) { diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index 8db71fd303..fad952d533 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -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( + 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( + web_contents->GetUserData(web_view::kWebViewInfoKeyName)); + if (info) { + prefs->web_security_enabled = !info->web_view_info().disable_web_security; return; } diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index b4f61d0f19..4463115cfe 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -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 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); diff --git a/atom/browser/atom_browser_main_parts.h b/atom/browser/atom_browser_main_parts.h index a2909cac53..d952f43288 100644 --- a/atom/browser/atom_browser_main_parts.h +++ b/atom/browser/atom_browser_main_parts.h @@ -6,10 +6,14 @@ #define ATOM_BROWSER_ATOM_BROWSER_MAIN_PARTS_H_ #include +#include +#include #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 destruction_callbacks_; + // partition_id => browser_context + base::ScopedPtrHashMap> + browser_context_map_; + static AtomBrowserMainParts* self_; DISALLOW_COPY_AND_ASSIGN(AtomBrowserMainParts); diff --git a/atom/browser/lib/guest-view-manager.coffee b/atom/browser/lib/guest-view-manager.coffee index 398cdb5d94..5812746990 100644 --- a/atom/browser/lib/guest-view-manager.coffee +++ b/atom/browser/lib/guest-view-manager.coffee @@ -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 diff --git a/atom/browser/web_view_constants.cc b/atom/browser/web_view_constants.cc new file mode 100644 index 0000000000..6f8314cbcf --- /dev/null +++ b/atom/browser/web_view_constants.cc @@ -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 diff --git a/atom/browser/web_view_constants.h b/atom/browser/web_view_constants.h new file mode 100644 index 0000000000..0831bdbdf1 --- /dev/null +++ b/atom/browser/web_view_constants.h @@ -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_ diff --git a/atom/browser/web_view_guest_delegate.cc b/atom/browser/web_view_guest_delegate.cc index 8e1810c4a3..a954cea8dc 100644 --- a/atom/browser/web_view_guest_delegate.cc +++ b/atom/browser/web_view_guest_delegate.cc @@ -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); } } diff --git a/atom/browser/web_view_manager.cc b/atom/browser/web_view_manager.cc index 7dba6c06dd..9d0b933759 100644 --- a/atom/browser/web_view_manager.cc +++ b/atom/browser/web_view_manager.cc @@ -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(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; diff --git a/atom/browser/web_view_manager.h b/atom/browser/web_view_manager.h index b1bea92702..20c0448497 100644 --- a/atom/browser/web_view_manager.h +++ b/atom/browser/web_view_manager.h @@ -8,8 +8,10 @@ #include #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 web_contents_embdder_map_; + std::map 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 element_instance_id_to_guest_map_; - typedef std::map WebViewInfoMap; - // web_contents => (guest_instance_id, embedder, ...) - WebViewInfoMap webview_info_map_; - base::Lock lock_; DISALLOW_COPY_AND_ASSIGN(WebViewManager); diff --git a/docs-translations/zh-CN/development/atom-shell-vs-node-webkit.md b/docs-translations/zh-CN/development/atom-shell-vs-node-webkit.md new file mode 100644 index 0000000000..cf6859d506 --- /dev/null +++ b/docs-translations/zh-CN/development/atom-shell-vs-node-webkit.md @@ -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 上下文。 diff --git a/docs-translations/zh-CN/development/coding-style.md b/docs-translations/zh-CN/development/coding-style.md new file mode 100644 index 0000000000..82219467b1 --- /dev/null +++ b/docs-translations/zh-CN/development/coding-style.md @@ -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)。 diff --git a/docs-translations/zh-TW/tutorial/online-offline-events.md b/docs-translations/zh-TW/tutorial/online-offline-events.md new file mode 100644 index 0000000000..a4366f88a0 --- /dev/null +++ b/docs-translations/zh-TW/tutorial/online-offline-events.md @@ -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 + + + + + + +``` + +您也許有時候也會有想要在主行程裡回應這些事件的情況。然而,在主行程裡並沒有 `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 + + + + + + +``` diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index 6b64a0269c..c1b1f705e9 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -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 + + +``` + +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: diff --git a/filenames.gypi b/filenames.gypi index 807ccd32bb..2f97d01507 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -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', diff --git a/spec/fixtures/pages/partition/one.html b/spec/fixtures/pages/partition/one.html new file mode 100644 index 0000000000..ad22c341df --- /dev/null +++ b/spec/fixtures/pages/partition/one.html @@ -0,0 +1,4 @@ + diff --git a/spec/webview-spec.coffee b/spec/webview-spec.coffee index 6eb391ac94..fe281510b4 100644 --- a/spec/webview-spec.coffee +++ b/spec/webview-spec.coffee @@ -154,6 +154,45 @@ describe ' 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) ->