因此,似乎我们在与Google Chrome(PPAPI)集成的Flash Player中的设备(相机和麦克风)出现了另一个问题 . 许多Flash开发人员都可以记住clickjacking problem并且对Google Chrome中实现的此问题进行了丑陋的修复 . 目前,如果您有一些使用相机或麦克风的应用程序,Google Chrome用户必须允许访问其设备两次:适用于Flash Player(以Flash对象为中心的小窗口)和Google Chrome(带有地址栏下方按钮的灰色面板) .

直到最近,授予摄像头访问权限的整个过程如下所示:

  • 应用程序要将摄像头附加到Video对象或NetStream .

  • 即使未经许可,您也可以获取相机名称并使用它们填充一些UI组件 .

  • Flash Player使用"Allow"和"Deny"按钮显示安全性面板 .

  • 谷歌浏览器显示它自己的安全面板,因此两个安全面板同时可见 .

  • 用户在Flash Player安全性面板中按"Allow"按钮 .

  • 现在你对camera.muted属性有误,但是相机显示零FPS,因为浏览器仍然拒绝访问 .

  • 用户在浏览器安全面板中按"Allow"按钮 .

  • 赢!您可以随处访问 .

当然,Google Chrome的第二个安全小组真的很痛苦 . 用户只是没有注意到它 . Flash开发人员使用应用程序和FAQ页面中的提示来处理此问题 . 但现在我们又遇到了一个大问题 .

最近授予摄像头访问权限的过程改为:应用程序想要将摄像头连接到Video对象或NetStream .

  • 在浏览器中授予访问权限之前,您无法获取摄像机名称 . 在camera.name属性中只有空格(" ",代码为32的符号) .

  • Flash Player使用"Allow"和"Deny"按钮显示安全性面板 .

  • 在使用Flash Player授予访问权限之前,Google Chrome不会显示其安全面板 .

  • 用户在Flash Player安全性面板中按"Allow"按钮 .

  • 现在你的camera.muted属性为false,但是相机显示零FPS并且没有名称,因为浏览器仍然拒绝访问 .

  • 谷歌浏览器显示它自己的安全面板 .

  • 用户在浏览器安全面板中按"Allow"按钮(由于某种原因,此面板显示两次) .

  • 现在您可以在任何地方授予访问权限,但设备仍然只有空格而不是真实姓名 .

不幸的是,AS3在浏览器授予访问权限后不会更新摄像机名称 . 在浏览器访问授权之前,相机名称在Flash Player设置窗口中为空事件 . 所以它's impossible now to get camera names in Flash application running in Google Chrome without reloading. User need to grant access in browser first, than reload application and only after that we can get camera names in AS3. I have tried to use flash.media.scanHardware() to refresh camera names, but it seems it'不起作用 . 我也创建了一个小例子并在线发布:http://wonderfl.net/c/rcIh

您可以在Google Chrome中自行测试 . 只是不要忘记每次都清楚你的选择 . 您需要从chrome:// settings / contentExceptions #media-stream中的列表中删除"wonderfl.net"条目,以清除您的prevoius选项 . 我也收到了Opera用户的类似投诉 .

这是我的代码:

package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.TimerEvent;
    import flash.media.Camera;
    import flash.media.Microphone;
    import flash.media.Video;
    import flash.media.scanHardware;
    import flash.text.TextField;
    import flash.utils.Timer;

    public class BrowserPermissionTest extends Sprite
    {
        private var output:TextField;
        private var timer:Timer;

        public function BrowserPermissionTest()
        {
            super();

            addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        }

        private function addedToStageHandler(event:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);

            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;

            output = new TextField();
            output.border = true;
            output.multiline = true;
            output.wordWrap = true;
            output.x = output.y = 10;
            addChild(output);

            updateView();
            stage.addEventListener(Event.RESIZE, stage_resizeHandler);

            var i:int;
            var numCameras:int = 0;
            var numMicrophones:int = 0;

            if (Camera.isSupported)
            {
                var cameraNames:Array = Camera.names;
                numCameras = cameraNames ? cameraNames.length : 0;
                if (numCameras > 0)
                {
                    log("Cameras:");
                    for (i = 0; i < numCameras; i++)
                    {
                        var cameraName:String = cameraNames[i];
                        log((i + 1) + ". \"" + cameraName + "\"");
                    }
                }
                else
                {
                    log("Camera not found.");
                }
            }
            else
            {
                log("Camera is not supported.");
            }

            log("");

            if (Microphone.isSupported)
            {
                var microphoneNames:Array = Microphone.names;
                numMicrophones = microphoneNames ? microphoneNames.length : 0;
                if (numMicrophones > 0)
                {
                    log("Microphones:");
                    for (i = 0; i < numMicrophones; i++)
                    {
                        var microphoneName:String = microphoneNames[i];
                        log((i + 1) + ". \"" + microphoneName + "\"");
                    }
                }
                else
                {
                    log("Microphone not found.");
                }
            }
            else
            {
                log("Microphone is not supported.");
            }

            log("");

            if (numCameras > 0 || numMicrophones > 0)
            {
                if (numCameras > 0)
                {
                    var defaultCamera:Camera = Camera.getCamera();
                    var video:Video = new Video(1, 1);
                    addChild(video);
                    video.attachCamera(defaultCamera);
                    defaultCamera.muted ? devicesMutedInFlashPlayer() : devicesUnmutedInFlashPlayer();
                }
                else if (numMicrophones > 0)
                {
                    var defaultMicrophone:Microphone = Microphone.getMicrophone();
                    defaultMicrophone.setLoopBack(true);
                    defaultMicrophone.muted ? devicesMutedInFlashPlayer() : devicesUnmutedInFlashPlayer();
                }
                else
                {
                    log("No devices found for test.");
                }               
            }
        }

        private function devicesMutedInFlashPlayer():void
        {
            log("Devices are muted in Flash Player.");
            log("Starting permission check timer...");

            timer = new Timer(100);
            timer.addEventListener(TimerEvent.TIMER, flashPlayerPermissionTimer_timerHandler);
            timer.start();
        }

        private function flashPlayerPermissionTimer_timerHandler(event:TimerEvent):void
        {
            var defaultCamera:Camera = Camera.getCamera();
            if (!isDevicesMutedInFlashPlayer())
            {
                timer.stop();
                timer.removeEventListener(TimerEvent.TIMER, flashPlayerPermissionTimer_timerHandler);
                timer = null;

                devicesUnmutedInFlashPlayer();
            }
        }

        private function devicesUnmutedInFlashPlayer():void
        {
            log("Devices are unmuted in Flash Player.");
            isDevicesMutedInBrowser() ? devicesMutedInBrowser() : devicesUnmutedInBrowser();
        }

        private function devicesMutedInBrowser():void
        {
            log("Devices are muted in browser.");
            log("Starting permission check timer...");

            timer = new Timer(100);
            timer.addEventListener(TimerEvent.TIMER, browserPermissionTimer_timerHandler);
            timer.start();
        }

        private function browserPermissionTimer_timerHandler(event:TimerEvent):void
        {
            scanHardware();
            if (!isDevicesMutedInBrowser())
            {
                timer.stop();
                timer.removeEventListener(TimerEvent.TIMER, browserPermissionTimer_timerHandler);
                timer = null;

                devicesUnmutedInBrowser();
            }
        }

        private function devicesUnmutedInBrowser():void
        {
            log("Devices are unmuted in browser.");
        }

        private function isDevicesMutedInFlashPlayer():Boolean
        {
            var cameraNames:Array = Camera.names;
            var numCameras:int = cameraNames ? cameraNames.length : 0;
            if (numCameras > 0)
            {
                var defaultCamera:Camera = Camera.getCamera();
                return defaultCamera.muted;
            }
            else
            {
                var microphoneNames:Array = Camera.names;
                var numMicrophones:int = microphoneNames ? microphoneNames.length : 0;
                if (numMicrophones > 0)
                {
                    var defaultMicrophone:Microphone = Microphone.getMicrophone();
                    return defaultMicrophone.muted;
                }
            }
            return true;
        }

        private function isDevicesMutedInBrowser():Boolean
        {
            var cameraNames:Array = Camera.names;
            var numCameras:int = cameraNames.length;
            for (var i:int = 0; i < numCameras; i++)
            {
                var cameraName:String = cameraNames[i];
                if (cameraName != " ")
                {
                    return false;
                }
            }

            var microphoneNames:Array = Microphone.names;
            var numMicrophones:int = microphoneNames.length;
            for (i = 0; i < numMicrophones; i++)
            {
                var microphoneName:String = microphoneNames[i];
                if (microphoneName != " ")
                {
                    return false;
                }
            }

            return true;
        }

        private function log(text:String):void
        {
            output.appendText(text + "\n");
        }

        private function updateView():void
        {
            output.width = stage.stageWidth - 2 * output.x;
            output.height = stage.stageHeight - 2 * output.y;
        }

        private function stage_resizeHandler(event:Event):void
        {
            updateView();
        }
    }
}

所以,我想知道这是一个错误或谷歌Chrome团队实施的某种新安全功能?也许有人已经遇到过这个问题,可以分享更多关于它的信息 . 现在看起来现代浏览器使用所有功能和丑陋的解决方案来杀死Flash .

PS:你可以在我的留言中找到一些愚蠢的错误 . 对不起我的英语不好 .