|
1 /* |
|
2 * Helper structures to track callbacks from image and channel loads. |
|
3 */ |
|
4 |
|
5 // START_REQUEST and STOP_REQUEST are used by ChannelListener, and |
|
6 // stored in ChannelListener.requestStatus. |
|
7 const START_REQUEST = 0x01; |
|
8 const STOP_REQUEST = 0x02; |
|
9 const DATA_AVAILABLE = 0x04; |
|
10 |
|
11 // One bit per callback that imageListener below implements. Stored in |
|
12 // ImageListener.state. |
|
13 const SIZE_AVAILABLE = 0x01; |
|
14 const FRAME_UPDATE = 0x02; |
|
15 const FRAME_COMPLETE = 0x04; |
|
16 const LOAD_COMPLETE = 0x08; |
|
17 const DECODE_COMPLETE = 0x10; |
|
18 |
|
19 // An implementation of imgIScriptedNotificationObserver with the ability to |
|
20 // call specified functions on onStartRequest and onStopRequest. |
|
21 function ImageListener(start_callback, stop_callback) |
|
22 { |
|
23 this.sizeAvailable = function onSizeAvailable(aRequest) |
|
24 { |
|
25 do_check_false(this.synchronous); |
|
26 |
|
27 this.state |= SIZE_AVAILABLE; |
|
28 |
|
29 if (this.start_callback) |
|
30 this.start_callback(this, aRequest); |
|
31 } |
|
32 this.frameComplete = function onFrameComplete(aRequest) |
|
33 { |
|
34 do_check_false(this.synchronous); |
|
35 |
|
36 this.state |= FRAME_COMPLETE; |
|
37 } |
|
38 this.decodeComplete = function onDecodeComplete(aRequest) |
|
39 { |
|
40 do_check_false(this.synchronous); |
|
41 |
|
42 this.state |= DECODE_COMPLETE; |
|
43 } |
|
44 this.loadComplete = function onLoadcomplete(aRequest) |
|
45 { |
|
46 do_check_false(this.synchronous); |
|
47 |
|
48 try { |
|
49 aRequest.requestDecode(); |
|
50 } catch (e) { |
|
51 do_print("requestDecode threw " + e); |
|
52 } |
|
53 |
|
54 this.state |= LOAD_COMPLETE; |
|
55 |
|
56 if (this.stop_callback) |
|
57 this.stop_callback(this, aRequest); |
|
58 } |
|
59 this.frameUpdate = function onFrameUpdate(aRequest) |
|
60 { |
|
61 } |
|
62 this.isAnimated = function onIsAnimated() |
|
63 { |
|
64 } |
|
65 |
|
66 // Initialize the synchronous flag to true to start. This must be set to |
|
67 // false before exiting to the event loop! |
|
68 this.synchronous = true; |
|
69 |
|
70 // A function to call when onStartRequest is called. |
|
71 this.start_callback = start_callback; |
|
72 |
|
73 // A function to call when onStopRequest is called. |
|
74 this.stop_callback = stop_callback; |
|
75 |
|
76 // The image load/decode state. |
|
77 // A bitfield that tracks which callbacks have been called. Takes the bits |
|
78 // defined above. |
|
79 this.state = 0; |
|
80 } |
|
81 |
|
82 function NS_FAILED(val) |
|
83 { |
|
84 return !!(val & 0x80000000); |
|
85 } |
|
86 |
|
87 function ChannelListener() |
|
88 { |
|
89 this.onStartRequest = function onStartRequest(aRequest, aContext) |
|
90 { |
|
91 if (this.outputListener) |
|
92 this.outputListener.onStartRequest(aRequest, aContext); |
|
93 |
|
94 this.requestStatus |= START_REQUEST; |
|
95 } |
|
96 |
|
97 this.onDataAvailable = function onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount) |
|
98 { |
|
99 if (this.outputListener) |
|
100 this.outputListener.onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount); |
|
101 |
|
102 this.requestStatus |= DATA_AVAILABLE; |
|
103 } |
|
104 |
|
105 this.onStopRequest = function onStopRequest(aRequest, aContext, aStatusCode) |
|
106 { |
|
107 if (this.outputListener) |
|
108 this.outputListener.onStopRequest(aRequest, aContext, aStatusCode); |
|
109 |
|
110 // If we failed (or were canceled - failure is implied if canceled), |
|
111 // there's no use tracking our state, since it's meaningless. |
|
112 if (NS_FAILED(aStatusCode)) |
|
113 this.requestStatus = 0; |
|
114 else |
|
115 this.requestStatus |= STOP_REQUEST; |
|
116 } |
|
117 |
|
118 // A listener to pass the notifications we get to. |
|
119 this.outputListener = null; |
|
120 |
|
121 // The request's status. A bitfield that holds one or both of START_REQUEST |
|
122 // and STOP_REQUEST, according to which callbacks have been called on the |
|
123 // associated request. |
|
124 this.requestStatus = 0; |
|
125 } |