OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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. | |
4 | |
5 package org.chromium.android_webview; | |
6 | |
7 import java.util.ArrayDeque; | |
hush (inactive)
2015/02/13 03:25:08
please add a new line after this.
sgurun-gerrit only
2015/02/13 05:11:59
Done.
| |
8 /** | |
9 * Sanity checks and sends post messages to web. Queues messages if necessary. | |
10 */ | |
11 public class PostMessageSender implements AwMessagePortService.MessageChannelObs erver { | |
12 | |
13 /** | |
14 * The interface for message handler. | |
15 */ | |
16 public static interface PostMessageSenderDelegate { | |
17 void postMessageToWeb(String frameName, String message, String sourceOri gin, | |
18 String targetOrigin, int[] sentPorts); | |
19 }; | |
20 | |
21 // A struct to store Message parameters that are sent from App to Web. | |
22 private static class PostMessageParams { | |
23 public String frameName; | |
24 public String message; | |
25 public String sourceOrigin; | |
26 public String targetOrigin; | |
27 public MessagePort[] sentPorts; | |
28 | |
29 public PostMessageParams(String frameName, String message, String source Origin, | |
30 String targetOrigin, MessagePort[] sentPorts) { | |
31 this.frameName = frameName; | |
32 this.message = message; | |
33 this.sourceOrigin = sourceOrigin; | |
34 this.targetOrigin = targetOrigin; | |
35 this.sentPorts = sentPorts; | |
36 } | |
37 } | |
38 | |
39 private PostMessageSenderDelegate mDelegate; | |
40 private AwMessagePortService mService; | |
41 | |
42 // If a message that is sent from android webview to web has a pending port (a port that | |
43 // is not internally created yet), this message, and any following messages will be | |
44 // queued until the transferred port becomes ready. This is necessary to pre vent any | |
45 // reordering. | |
46 private boolean mShouldQueue = false; | |
47 private ArrayDeque<PostMessageParams> mMessageQueue = new ArrayDeque<PostMes sageParams>(); | |
48 | |
49 public PostMessageSender(PostMessageSenderDelegate delegate, AwMessagePortSe rvice service) { | |
50 mDelegate = delegate; | |
51 mService = service; | |
52 } | |
53 | |
54 // Return true if any sent port is pending. | |
55 private boolean anySentPortIsPending(MessagePort[] sentPorts) { | |
56 if (sentPorts != null) { | |
57 for (MessagePort port : sentPorts) { | |
58 if (!port.isReady()) { | |
59 return true; | |
60 } | |
61 } | |
62 } | |
63 return false; | |
64 } | |
65 | |
66 // By default the sender is always ready. | |
67 protected boolean senderIsReady() { | |
68 return true; | |
69 } | |
70 | |
71 // A message to a frame is queued if: | |
72 // 1. Sender is not ready to post. When posting messages to frames, sender i s always | |
73 // ready. However, when posting messages using message channels, sender may be in | |
74 // a pending state. | |
75 // 2. The mShouldQueue mode is already on. Having mShouldQueue mode true mea ns | |
76 // there is a already a message with a pending port in queue. | |
77 // 3. The message includes a port that is not ready yet. | |
78 private boolean shouldQueueMessage(MessagePort[] sentPorts) { | |
79 // if messages to frames are already in queue mode, simply queue it, no need to | |
80 // check ports. | |
81 if (mShouldQueue || !senderIsReady()) { | |
82 return true; | |
83 } | |
84 if (anySentPortIsPending(sentPorts)) { | |
85 mShouldQueue = true; | |
hush (inactive)
2015/02/13 03:25:08
I feel it is weird that a method that looks like i
sgurun-gerrit only
2015/02/13 05:11:59
this is a private method so I did not worry too mu
| |
86 return true; | |
87 } | |
88 return false; | |
89 } | |
90 | |
91 private void postMessageToWeb(String frameName, String message, String sourc eOrigin, | |
92 String targetOrigin, MessagePort[] sentPorts) { | |
93 int[] portIds = null; | |
94 if (sentPorts != null) { | |
95 portIds = new int[sentPorts.length]; | |
96 for (int i = 0; i < sentPorts.length; i++) { | |
97 portIds[i] = sentPorts[i].portId(); | |
98 } | |
99 mService.removeSentPorts(portIds); | |
100 } | |
101 mDelegate.postMessageToWeb(frameName, message, sourceOrigin, targetOrigi n, portIds); | |
102 } | |
103 | |
104 /* | |
105 * Sanity checks the message and queues it if necessary. Posts the message t o delegate | |
106 * when message can be sent. | |
107 */ | |
108 public void postMessage(String frameName, String message, String sourceOrigi n, | |
hush (inactive)
2015/02/13 03:25:08
name it postMessageIfPossible?
sgurun-gerrit only
2015/02/13 05:11:59
I think the name is compatible with HTML5 MessageP
| |
109 String targetOrigin, MessagePort[] sentPorts) throws IllegalStateExc eption { | |
110 // Sanity check all the ports that are being transferred. | |
111 if (sentPorts != null) { | |
112 for (MessagePort p : sentPorts) { | |
113 if (p.isClosed() || p.isTransferred()) { | |
114 throw new IllegalStateException("Port cannot be transferred" ); | |
115 } | |
116 p.setTransferred(); | |
117 } | |
118 } | |
119 if (shouldQueueMessage(sentPorts)) { | |
120 mMessageQueue.add(new PostMessageParams(frameName, message, sourceOr igin, | |
121 targetOrigin, sentPorts)); | |
122 } else { | |
123 postMessageToWeb(frameName, message, sourceOrigin, targetOrigin, sen tPorts); | |
124 } | |
125 } | |
126 | |
127 /* | |
128 * Starts posting any messages that are queued. | |
129 */ | |
130 public void onMessageChannelCreated() { | |
131 PostMessageParams msg; | |
132 | |
133 if (!senderIsReady()) { | |
134 return; | |
135 } | |
136 | |
137 while ((msg = mMessageQueue.peek()) != null) { | |
138 // If there are still pending ports, message cannot be posted. | |
139 if (anySentPortIsPending(msg.sentPorts)) { | |
140 return; | |
141 } | |
142 mMessageQueue.remove(); | |
143 postMessageToWeb(msg.frameName, msg.message, msg.sourceOrigin, msg.t argetOrigin, | |
144 msg.sentPorts); | |
145 } | |
146 // No more messages in the queue. | |
147 mShouldQueue = false; | |
148 } | |
149 } | |
OLD | NEW |