【Chromium】sandboxed window问题记录

问题发现

在业务逻辑中发现有时使用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 appmanifest文件中添加如下声明

"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这个东西是undefinedview这个对象是通过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的报错

原文地址:https://www.cnblogs.com/lenomirei/p/10541117.html

时间: 2024-08-07 21:41:35

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

Context 对应的Unable to add window 错误记录

近日在使用 AlertDialog时发现一个错误:Unable to add window -- token null is not for an application,从前面观察是无法添加一个新的窗口到这个context,后来想了想前面是用的getApplicationContext()传递过来的context, 看来不能往context中加window吧,就改成了activity.this,代表一个具体的activity了,这样就OK了,记录下以后应该能解决这种添加新窗口传递context

携程apollo window搭建记录

1.下载项目 github 地址 https://github.com/ctripcorp/apollo 源代码下载地址 https://github.com/ctripcorp/apollo/releases 源代码下载镜像地址http://github-mirror.bugkiller.org/ctripcorp/apollo/releases github 直接下载不下来,用镜像速度很快 下载部署文件三个 apollo-adminservice-1.5.1-github.zip apoll

window 2000记录3389密码工具

findpass http://www.xfocus.net/tools/200307/445.html

UI Framework-1: Browser Window

Browser Window The Chromium browser window is represented by several objects, some of which are included in this diagram: Frame The frame is the portion of the browser window that includes the title bar, sizing borders, and other areas traditionally

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 Flash Player to view this content? If you have installed Flash Player for Chromium, but cannot see Flash-based content, you may have disabled Flash Play

一段简单的显示当前页面FPS的代码

写前端代码,尤其是做一个前端框架的时候,经常需要及时知道代码的大致性能,这时候如果能有个好的办法能一直看到当前页面的fps就好了. 整体思路是一秒有一千毫秒,先记录当前时间作为最后一次记录fps的时间,通过 requestAnimationFrame 回调不断给累加fsp计数器,并且判断上次记录fps的时间是否达到1000毫秒以上,如果满足条件,就将fps累加器的值作为当前fps显示,并且重置fps累加器. 这里写了段比较简单的显示FPS的代码: 1 var showFPS = (functio

闭包以及作用域

2. 其实LZ要理解这个问题,要明白JS中的作用域(scope). 每个函数在创建完成时,他有3个重要的内置属性(property)也同时被创建.{ AO //记录function内的变量,参数等信息 this // 就是在调用this.xx的时候的this scope // 指向外层函数AO的一个链(在实现的时候,可能通过数组来实现). } JS中,大家经常讲的Scope其实是这样:SCOPE=AO+scope. 回到闭包的问题上: 如果我们这样写这个程序: for(var i =0; i<l

js实现类似jquery基础功能 简单选择器/事件/属性

按钮样式定义 <style> .btn{display: inline-block;width: 100px;height: 20px;color: #fff;font-size: 12px;background-color: #0033dd;text-align: center;line-height: 20px;text-decoration: none;border:  5px #0000ff outset;} .btn-big-test{width: 300px;height: 85p

iOS开发——悬浮按钮

项目中需要在创建一个悬浮按钮,自己觉得光创建一个按钮不能滑动有点不太优化,就自己试着做了一个可以随意拖动的悬浮按钮,希望大家能够多多支持. -(void)viewDidLoad { //创建悬浮按钮 self.editEventsButton=[UIButton buttonWithType:UIButtonTypeCustom]; self.editEventsButton.frame=CGRectMake(0, 0, 60, 60); [self.editEventsButton setBa