Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / remoting / webapp / video_frame_recorder.js
blob67301622c9cbe146c704838f80c5d156d22cec0e
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 /**
6  * @fileoverview
7  * Class implement the video frame recorder extension client.
8  */
10 'use strict';
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
15 /**
16  * @constructor
17  * @param {remoting.ClientPlugin} plugin
18  */
19 remoting.VideoFrameRecorder = function(plugin) {
20   this.fileWriter_ = null;
21   this.isRecording_ = false;
22   this.plugin_ = plugin;
25 /**
26  * Starts or stops video recording.
27  */
28 remoting.VideoFrameRecorder.prototype.startStopRecording = function() {
29   var data = {};
30   if (this.isRecording_) {
31     this.isRecording_ = false;
32     data = { type: 'stop' }
34     chrome.fileSystem.chooseEntry(
35         {type: 'saveFile', suggestedName: 'videoRecording.pb'},
36         this.onFileChosen_.bind(this));
37   } else {
38     this.isRecording_ = true;
39     data = { type: 'start' }
40   }
41   this.plugin_.sendClientMessage('video-recorder', JSON.stringify(data));
44 /**
45  * Returns true if the session is currently being recorded.
46  * @return {boolean}
47  */
48 remoting.VideoFrameRecorder.prototype.isRecording = function() {
49   return this.isRecording_;
52 /**
53  * Handles 'video-recorder' extension messages and returns true. Returns
54  * false for all other message types.
55  * @param {string} type Type of extension message.
56  * @param {string} data Content of the extension message.
57  * @return {boolean}
58  */
59 remoting.VideoFrameRecorder.prototype.handleMessage =
60     function(type, data) {
61   if (type != 'video-recorder') {
62     return false;
63   }
65   var message = getJsonObjectFromString(data);
66   var messageType = getStringAttr(message, 'type');
67   var messageData = getStringAttr(message, 'data');
69   if (messageType == 'next-frame-reply') {
70     if (!this.fileWriter_) {
71       console.log("Received frame but have no writer");
72       return true;
73     }
74     if (!messageData) {
75       console.log("Finished receiving frames");
76       this.fileWriter_ = null;
77       return true;
78     }
80     console.log("Received frame");
81     /* jscompile gets confused if you refer to this as just atob(). */
82     var videoPacketString = /** @type {string?} */ window.atob(messageData);
84     console.log("Converted from Base64 - length:" + videoPacketString.length);
85     var byteArrays = [];
87     for (var offset = 0; offset < videoPacketString.length; offset += 512) {
88         var slice = videoPacketString.slice(offset, offset + 512);
89         var byteNumbers = new Array(slice.length);
90         for (var i = 0; i < slice.length; i++) {
91             byteNumbers[i] = slice.charCodeAt(i);
92         }
93         var byteArray = new Uint8Array(byteNumbers);
94         byteArrays.push(byteArray);
95     }
97     console.log("Writing frame");
98     videoPacketString = null;
99     /**
100      * Our current compiler toolchain only understands the old (deprecated)
101      * Blob constructor, which does not accept any parameters.
102      * TODO(wez): Remove this when compiler is updated (see crbug.com/405298).
103      * @suppress {checkTypes}
104      * @param {Array} parts
105      * @return {Blob}
106      */
107     var makeBlob = function(parts) {
108       return new Blob(parts);
109     }
110     var videoPacketBlob = makeBlob(byteArrays);
111     byteArrays = null;
113     this.fileWriter_.write(videoPacketBlob);
115     return true;
116   }
118   console.log("Unrecognized message: " + messageType);
119   return true;
122 /** @param {FileEntry} fileEntry */
123 remoting.VideoFrameRecorder.prototype.onFileChosen_ = function(fileEntry) {
124   if (!fileEntry) {
125     console.log("Cancelled save of video frames.");
126   } else {
127     /** @type {function(string):void} */
128     chrome.fileSystem.getDisplayPath(fileEntry, function(path) {
129       console.log("Saving video frames to:" + path);
130     });
131     fileEntry.createWriter(this.onFileWriter_.bind(this));
132   }
135 /** @param {FileWriter} fileWriter */
136 remoting.VideoFrameRecorder.prototype.onFileWriter_ = function(fileWriter) {
137   console.log("Obtained FileWriter for video frame write");
138   fileWriter.onwriteend = this.onWriteComplete_.bind(this);
139   this.fileWriter_ = fileWriter;
140   this.fetchNextFrame_();
143 remoting.VideoFrameRecorder.prototype.onWriteComplete_ = function(e) {
144   console.log("Video frame write complete");
145   this.fetchNextFrame_();
148 remoting.VideoFrameRecorder.prototype.fetchNextFrame_ = function() {
149   console.log("Request next video frame");
150   var data = { type: 'next-frame' }
151   this.plugin_.sendClientMessage('video-recorder', JSON.stringify(data));