问题发现

在业务逻辑中发现有时使用chrome.app.window.create这个API创建出来的窗口无法使用其他的API,不仅其他chrome.app.window的API说window is undefined而且还有奇怪的警告和报错

Creating sandboxed window, it doesn't have access to the chrome.app API. The chrome.app.window.create callback will be called, but there will be no object provided for the sandboxed window.
Error handling response: TypeError: Cannot read property 'window' of undefined
ar extensions::app.window:149:49

第一个报警是sandboxed window的报警,提示当前创建的窗口加载的页面可能是一个sandboxed page

查询了官方文档,发现如果需要创建一个sandboxed window需要在chrome app的manifest文件中添加如下声明

"sandbox": {
"pages": ["index.html"]
},

但是我并没有添加类似的声明。最后发现是同时创建了两个id一样使用资源一样的窗口就会报这个错误。一开始认为是资源占用,于是我修改了两个窗口加载的资源

chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create("index.html", {id: "test"});
chrome.app.window.create("index2.html", {id: "test"});
});

仍然会出现上述报错,原因可能是出在同时创建了两个id一样的窗口了。而且出现这个错误的时候第二个窗口其实是创建不出来的。

第二次测试

如果不同时创建会出这个问题么?怀着疑问我做了第二次测试。

app window的创建是一个异步的过程,当窗口真正创建完成的时候会有一个回调函数。google官方也说明如果想要通过chrome.app.window.get(id)这个API通过id来获取窗口对象的话应该在回调内部执行,确保窗口已经完全创建完成。否则可能会拿到不完整的窗口对象。

于是测试代码被改成了这样

chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create("index.html", {id: "test"}, function(window) {
chrome.app.window.create("index2.html", {id: "test"});
});
});

此时不会再报错,但是第二个窗口依然不会被创建。

id是用来标识唯一窗口的,猜也猜得到如果创建两个id相同的窗口是会被拒绝的,但是控制台并没有类似的日志或者提示。

回到一开始的那个Error报错。指向了一个js文件的149行,查找了一下这个js是chrome的内部编译进去的js代码,于是我搞来了chromium的源码,看到了这个文件app_window_custom_bindings.js的149行。

    if (windowParams.existingWindow) {
// Not creating a new window, but activating an existing one, so trigger
// callback with existing window and don't do anything else.
let windowResult = view ? view.chrome.app.window.current() : undefined;
maybeCallback(windowResult);
return;
}

和猜想的一样是已存在一个相同id的窗口的话是不允许创建新窗口的。同时也是let windowResult = view ? view.chrome.app.window.current() : undefined;这句代码报的错。而这个代码的下面就是那句报警

    if (!view || !view.chrome.app) {
var sandbox_window_message = 'Creating sandboxed window, it doesn\'t ' +
'have access to the chrome.app API.';
if (callback) {
sandbox_window_message = sandbox_window_message +
' The chrome.app.window.create callback will be called, but ' +
'there will be no object provided for the sandboxed window.';
}
console.warn(sandbox_window_message);
maybeCallback(undefined);
return;
}

原因就是view.chrome.app这个东西是undefined,view这个对象是通过v8调用c++的接口拿到的let view = appWindowNatives.GetFrame(windowParams.frameId,true /* notifyBrowser */);

void AppWindowCustomBindings::GetFrame(
const v8::FunctionCallbackInfo<v8::Value>& args) {
// TODO(jeremya): convert this to IDL nocompile to get validation, and turn
// these argument checks into CHECK().
if (args.Length() != 2)
return; if (!args[0]->IsInt32() || !args[1]->IsBoolean())
return; int frame_id = args[0].As<v8::Int32>()->Value();
bool notify_browser = args[1].As<v8::Boolean>()->Value(); if (frame_id == MSG_ROUTING_NONE)
return; content::RenderFrame* app_frame =
content::RenderFrame::FromRoutingID(frame_id);
if (!app_frame)
return; if (notify_browser) {
app_frame->Send(
new ExtensionHostMsg_AppWindowReady(app_frame->GetRoutingID()));
} v8::Local<v8::Value> window =
app_frame->GetWebFrame()->MainWorldScriptContext()->Global(); // If the new window loads a sandboxed page and has started loading its
// document, its security origin is unique and the background script is not
// allowed accessing its window.
v8::Local<v8::Context> caller_context =
args.GetIsolate()->GetCurrentContext();
if (!ContextCanAccessObject(caller_context,
v8::Local<v8::Object>::Cast(window), true)) {
return;
} args.GetReturnValue().Set(window);
}

是最后一句返回了对象args.GetReturnValue().Set(window);,当在创建窗口完成之前就去获取view的话,此时的view是没有绑定app的接口的,所以是访问不到app接口的。这个绑定接口的操作在src/extensions/renderer/dispatcher.cc中

std::unique_ptr<ExtensionBindingsSystem> Dispatcher::CreateBindingsSystem(
std::unique_ptr<IPCMessageSender> ipc_sender) {
std::unique_ptr<ExtensionBindingsSystem> bindings_system;
if (base::FeatureList::IsEnabled(extensions_features::kNativeCrxBindings)) {
auto system =
std::make_unique<NativeExtensionBindingsSystem>(std::move(ipc_sender));
delegate_->InitializeBindingsSystem(this, system.get());
bindings_system = std::move(system);
} else {
bindings_system = std::make_unique<JsExtensionBindingsSystem>(
&source_map_, std::move(ipc_sender));
}
return bindings_system;
}

当这个函数的执行时机晚于获取view函数的执行时机的话,就会出现app undefined的报错

【Chromium】sandboxed window问题记录的更多相关文章

  1. 使用window.localStorage,window.localStorage记录点击次数

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. sublime window 配置记录 (转)

    大家好,今天给大家分享一款编辑器:sublime text2    我用过很多编辑器,EditPlus.EmEditor.Notepad++.Notepad2.UltraEdit.Editra.Vim ...

  3. android应用开发之Window,View和WindowManager .

    ViewManager  vm = a.getWindowManager(); vm.add(view,l); window :一个抽象的窗口基类,控制顶层窗口的外观和行为.作为顶层窗口,可控制窗口背 ...

  4. chromium之task

    // A task is a generic runnable thingy, usually used for running code on a // different thread or fo ...

  5. UI Framework-1: Browser Window

    Browser Window The Chromium browser window is represented by several objects, some of which are incl ...

  6. I have Flash Player installed, but I am unable to view Flash content in Chromium. How do I enable Flash Player to view this content?

    I have Flash Player installed, but I am unable to view Flash content in Chromium. How do I enable Fl ...

  7. 页面元素坐标和偏移(clientX/pageX/screenX/layerX/offsetWidth/scrollWidth/clientWidth等)相关整理

    鼠标事件都是在特定位置发生的,我们可以通过event事件对象的各种属性来获得事件发生的坐标位置,有相对于视口的,有相对于整个文档的,同样页面元素的位置也有相对视口的,也有滚动后的,这些都比较容易混淆, ...

  8. Html定位精要

    Html定位基础 Html的布局是文档流模型,块元素独占一行,内联元素并列一行. 相对定位 position: relative 相对于自己定位 不脱离文档流,元素原有位置被保留 绝对定位 posit ...

  9. Window7下vagrant的部署

    1. 下载并安装VirtualBox     下载地址:https://www.virtualbox.org/wiki/Downloads,下载最新的安装包,接下来的安装步骤就是下一步下一步了,你懂的 ...

随机推荐

  1. GitHub创建项目,保存代码。

    平时学习会写一些代码,虽然只是零零散散的功能,但是基本都是在一个项目下操作,偶尔会忘记代码编辑顺序.国庆这几天在家,想把GitHub用起来,实现自己代码的可追溯,可查询.学习本篇博客,你需要一点的Gi ...

  2. Spring aop+自定义注解统一记录用户行为日志

    写在前面 本文不涉及过多的Spring aop基本概念以及基本用法介绍,以实际场景使用为主. 场景 我们通常有这样一个需求:打印后台接口请求的具体参数,打印接口请求的最终响应结果,以及记录哪个用户在什 ...

  3. ubuntu apt update时W: GPG error http://ppa.launchpad.net lucid Release没有公钥无法验证NO_PUBKEY签名问题解决

    在安装更新时,即在运行命令行sudo apt-get update 或者运行更新管理器的时候,出现W: GPG 错误: W: GPG error: http://ppa.launchpad.net/o ...

  4. dotnet publish

    发布Release版本:dotnet publish --configuration Release 发布Debug版本:dotnet publish --configuration Debug

  5. 51nod1965. 奇怪的式子(min_25筛)

    题目链接 http://www.51nod.com/Challenge/Problem.html#!#problemId=1965 题解 需要求的式子显然是个二合一形式,我们将其拆开,分别计算 \(\ ...

  6. Windows网络服务渗透攻击分类

    网络服务渗透攻击分为三类 一.针对于windows系统自带的网络服务的渗透攻击 1.针对于NetBIOS的攻击 NetBIOS以运行在TCP/IP系统中的NBT协议来实现,具体包括在UDP的137端口 ...

  7. ajax防止表单自动提交

    重写表单的checkForm方法,并用if和else解决异步判断的问题. function checkForm(){ 1 var flag = false; $.ajaxSetup({async : ...

  8. ator自动生成mybatis配置和类信息

    generator自动生成mybatis的xml配置.model.map等信息: 1.下载mybatis-generator-core-1.3.2.jar包.        网址:http://cod ...

  9. 造一个轮子然后安装到pypi上

    之前写了一个爬虫的包,主要是根据自己写爬虫的情况总结一下. 因为每次都要重复写一些代码,所以提炼出来,类似一个框架的样子吧. 开始是放在自己的项目里引用,但如果换了一个项目,就得重新拷一遍,很麻烦. ...

  10. Go语言学习笔记一: Hello World

    Go语言学习笔记一: Hello World 听说Go语言又快又简单.即具有C语言的运行速度,又具有Python语言的开发效率,不知道真的假的.所以特意来学学这门"老"语言. 下载 ...