首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在OSX上的NPAPI浏览器插件中安全地打开对话框?

如何在OSX上的NPAPI浏览器插件中安全地打开对话框?
EN

Stack Overflow用户
提问于 2011-12-10 09:56:08
回答 3查看 1.2K关注 0票数 2

我的问题是: JavaScript会调用插件,它会派生一个打开NSOpenPanel (或NSSavePanel)对话框的线程。这通常是可行的,但有时它会在火狐和Chrome的"runModal“上崩溃。崩溃似乎是随机发生的,在某些机器(可能是10.7)上发生的频率比其他机器更高。崩溃的堆栈位置会有所不同,但通常发生在打开对话框的线程上。

我使用POSIX线程,因为它是跨平台的代码,但我确实生成了一个指向let Cocoa know的NSThread

代码语言:javascript
复制
NSThread* t = [[NSThread alloc] init];
[t start];
[t release];

打开对话框的代码:

代码语言:javascript
复制
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // necessary?
NSOpenPanel* openPanel = [NSOpenPanel openPanel];
[openPanel setAllowsMultipleSelection:_allowMultipleFiles];
[openPanel setCanChooseFiles:YES];
[openPanel setCanChooseDirectories:YES];
NSInteger result = [openPanel runModal]; // crash
... handle result ...
[pool release];

堆栈跟踪:

代码语言:javascript
复制
Process:         plugin-container [25536]
Path:            /Applications/Firefox.app/Contents/MacOS/plugin-container.app/Contents/MacOS/plugin-container
Identifier:      org.mozilla.plugincontainer
Version:         ??? (1.0)
Code Type:       X86-64 (Native)
Parent Process:  firefox-bin [25531]

Date/Time:       2011-12-09 17:12:04.271 -0800
OS Version:      Mac OS X 10.6.8 (10K549)
Report Version:  6

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x000000000000000d
Crashed Thread:  14

Thread 14 Crashed:
0   XUL                             0x0000000100d84ff4 mac_plugin_interposing_child_OnSetCursor + 38068
1   XUL                             0x0000000100dd38bd mac_plugin_interposing_child_OnSetCursor + 359805
2   XUL                             0x0000000100d7b247 mac_plugin_interposing_child_OnHideCursor + 1175
3   com.apple.AppKit                0x00007fff801cbfdb _NSCreateWindowWithOpaqueShape2 + 610
4   com.apple.AppKit                0x00007fff80160691 -[NSWindow _commonAwake] + 1214
5   com.apple.AppKit                0x00007fff803c282f -[NSWindow _setModal:] + 138
6   com.apple.AppKit                0x00007fff803c2183 -[NSApplication _orderFrontModalWindow:relativeToWindow:] + 482
7   com.apple.AppKit                0x00007fff803c1ce7 -[NSApplication _commonBeginModalSessionForWindow:relativeToWindow:modalDelegate:didEndSelector:contextInfo:] + 714
8   com.apple.AppKit                0x00007fff803c1a18 -[NSApplication beginModalSessionForWindow:] + 36
9   com.apple.AppKit                0x00007fff803c193a -[NSApplication runModalForWindow:] + 106
10  XUL                             0x0000000100d7af01 mac_plugin_interposing_child_OnHideCursor + 337
11  com.apple.AppKit                0x00007fff80627112 -[NSSavePanel runModal] + 318
12  com.aspera.AsperaWeb            0x000000010509f9d4 Connect::Web::MacOpenFolderDialogImpl::doShow() + 596
13  com.aspera.AsperaWeb            0x00000001050a0fa3 Connect::Web::IDialogImpl::show() + 45
14  com.aspera.AsperaWeb            0x00000001050a1e07 Connect::Web::OpenFolderDialog::showHelper(bool) + 141
15  com.aspera.AsperaWeb            0x00000001050a1ef0 Connect::Web::OpenFolderDialog::run() + 42
16  com.aspera.AsperaWeb            0x000000010509eb91 Connect::Web::SingleJobWorker::run() + 63
17  com.aspera.AsperaWeb            0x0000000105098160 start_helper + 38
18  libSystem.B.dylib               0x00007fff8593afd6 _pthread_start + 331
19  libSystem.B.dylib               0x00007fff8593ae89 thread_start + 13

Thread 14 crashed with X86 Thread State (64-bit):
  rax: 0x0000000000000000  rbx: 0x0000000102063840  rcx: 0x0000000000000000  rdx: 0x0000000101e27ee0
  rdi: 0x0000000101e0bcc8  rsi: 0x0000000000000000  rbp: 0x0000000101e27ef0  rsp: 0x000000011d5805e0
   r8: 0x0000000101e0bcc8   r9: 0x00000001040fc0a4  r10: 0x00007fffffe001a0  r11: 0x0000000000000202
  r12: 0x0000000101e27ee0  r13: 0x0000000000000001  r14: 0x000000011d5805e0  r15: 0x000000011d580754
  rip: 0x0000000100d84ff4  rfl: 0x0000000000010246  cr2: 0x000000000000000d

我猜在辅助线程上打开对话框有问题。也许我需要在主线上打开它?但是,我确实希望让JavaScript调用保持异步。我看的是NSNotificationQueue或者performSelectorOnMainThread

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-12-10 13:14:19

我在FireBreath中使用了一个对话框抽象:https://gist.github.com/1368648

事实证明,您不能在辅助线程上使用runModal;它必须在应用程序的主线程上。这在NPAPI插件中是一个挑战,因为你也不能在NPAPI调用期间阻塞主线程,否则浏览器(至少是chrome和firefox 4+)可能会杀死你。

解决方案是让它在主线程上运行,但不是作为NPAPI调用的一部分;您可以使用performSelectorOnMainThread来实现这一点,而不是等待它完成。如果您提供了某种回调( NPObject javascript函数效果很好),那么您可以在对话完成时调用它。

FireBreath将此方法用于其BrowserHost::ScheduleOnMainThread函数,这就是我在我引用的要点中使用的方法。有人(你?)在gist上发表了一条评论,询问它是否适用于我;评论时的gist没有,但我已经更新了修复程序(我昨天才发现)。自从我们将其更新为稍后使用performSelectorOnMainThread运行调用以来,我一直无法重现崩溃。

回过头来看,您已经熟悉以这种方式在主线程上回调:How to callback plugin thread on Safari 5.1 on OSX?

您可以使用相同的技术;您可能认为阻塞线程也是危险的,但是因为在模式对话框期间系统事件循环继续运行,所以您没有问题;您的代码不会返回,但仍然会调度其他事件。浏览器不会等待NPAPI调用返回,所以看起来没有任何问题。

票数 4
EN

Stack Overflow用户

发布于 2011-12-10 23:18:30

所有的Appkit都不是线程安全的,并且所有的Appkit方法都应该发生在主线程上。你可以使用performselectoronmainthread...方法来强制逻辑位于主线程上。

票数 2
EN

Stack Overflow用户

发布于 2011-12-10 10:18:33

打开的面板无论如何都应该是异步的,所以没有理由不能在主线程上显示打开的面板。简单地说,不要使用runModal。理想情况下,应在浏览器窗口中将其显示为工作表。

当它返回给您时,您可以通过您已经计划使用的任何方式将结果返回到JavaScript端。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8453795

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档