Networking

Cloud Phone is a remote, Chromium-based browser that supports many of the same Web APIs as Google Chrome for fetching, streaming, and uploading data.
At a Glance
- Requests on Cloud Phone apps originate from CloudMosa data centers
- The user’s IP address is available in the
X-Forwarded-For
header - Screen renders, not data fetching, consume user bandwidth
- Cloud Phone fully supports XHR, Fetch, WebSockets, Server-Sent Events, and the Beacon API
- Cloud Phone does not support WebRTC or the Network Information API
- Caches are ephemeral, encrypted, and purged when the user exit the Cloud Phone app
Cloud Phone Architecture
Learn the foundations behind the Cloud Phone remote browser
Cloud Rendering
Cloud Phone renders your app on powerful servers, sending only a compressed representation in Puffin Vector Graphics Language (PVGL) to the Client running on a user’s phone.
Regular Browser: Web Browser ⟺ App Server Cloud Phone: Cloud Phone Client ⟺ Cloud Phone Server ⟺ App Server
Your server interacts with servers in CloudMosa data centers, not the end user directly.
X-Forwarded-For
Header
The user’s IP address is available via the X-Forwarded-For
header (XFF) sent with every HTTP request.
X-Forwarded-For: 1.2.3.4
Cloud Phone traffic originates from the following IP address ranges:
- 45.33.128.0/20
- 107.178.32.0/20
- 203.116.120.0/24
- 203.116.121.0/24
- 203.116.134.0/24
- 203.116.135.0/24
This list of CloudMosa IP addresses is subject to change.
The XFF header may contain multiple, comma-separated values if you use a content delivery network (CDN), proxy, load balancer, or similar networking appliance. When parsing the XFF header, use input sanitization to scrub erroneous or malicious values.
X-Forwarded-For: 1.1.1.1, 1.2.3.4
Geolocation
Leverage an IP Geolocation service to approximate user location. CDNs like Amazon CloudFront and Cloudflare use the remote IP address, not the X-Forwarded-For
header, to determine user geolocation. Geolocation headers like CloudFront-Viewer-Country
or CF-IPCountry
will match the CloudMosa data center, not the end user.
Latency
Cloud Phone is not suitable for real-time applications due to cloud rendering.
Dynamic content updates rendered require two round-trip connections between the client to server and server to your app. Although CloudMosa data centers have direct connections to high-performance internet backbones, this impacts perceived latency.
Bandwidth
The end-user bandwidth your Cloud Phone app consumes does not depend on how much data is loaded, unlike a desktop browser. Cloud Phone only sends the Client a highly-optimized PVGL representation.
Screen updates, not resource fetching, consumes data on Cloud Phone. Excessive animations can consume more data than downloading payloads. If your app loads a 1 MB JSON file, it does not consume 1 MB of user bandwidth.
In Context. Video streaming uses the most bandwidth. It’s estimated that watching videos on Cloud Phone consumes about 120 MB (QQVGA) and 360 MB (QVGA) of data per hour.
Security Fundamentals
Cloud Phone follows the same security principles as Google Chrome, including restrictions on how a document or script from one origin can interact with a resource from another origin.
Same Origin Policy (SOP)
The origin of a Cloud Phone app is specified at widget creation time. The origin is defined by the scheme (protocol), hostname (domain), and port of the URL
Origin Example
For example, the Svelte Tutorial is hosted on GitHub Pages. In this instance:
URL: https://cloudmosa.github.io/cloudphone-svelte-sample/
- Scheme:
https
- Hostname:
cloudmosa.github.io
- Port:
443
(HTTPS default)
The origin does not include the path, /cloudphone-svelte-sample/
. Access to resources from another origin are subject to Cross-Origin Resource Sharing (CORS) restrictions.
Cross-Origin Resource Sharing (CORS)
CORS is an HTTP-header based mechanism to allow any origins, other than your own, to load remote resources. Browsers make a “preflight” request using the OPTIONS
HTTP method to determine if cross-origin sharing is permitted. Headers including the Access-Control-Allow-Origin
determine whether a corresponding GET
or POST
request is allowed or blocked.
CORS is handled the same on Chrome and Cloud Phone. CORS can be complex, so we recommended further reading to validate your implementation.
You cannot disable the Same Origin Policy on Cloud Phone.
Content Security Policy (CSP)
A Content Security Policy (CSP) allows you to restrict certain behaviors for increased security. A CSP can disallow inline scripts or eval
, both of which reduce the attack surface for Cross-Site Scripting (XSS) attacks.
Cloud Phone respects CSPs just like Google Chrome. Read to learn more and check out Google’s CSP Evaluator to identify subtle CSP bypasses.
SSL, TLS, and Certificates
Cloud Phone supports the same Security Socket Layer (SSL) and Transport Layer Security (TLS) protocols as the version of Google Chrome used on Cloud Phone servers. Supported protocols include:
- TLS 1.2
- TLS 1.3
- EV
- SHA-2
- ECDSA
Cloud Phone only supports secure HTTPS connections. HTTP (insecure) connections are not supported.
HyperText Transfer Protocol (HTTP)
Cloud Phone supports all common HTTP versions. Newer HTTP versions like Quick UDP Internet Connections (QUIC) offer improved performance, multiplexing, reliability, and security.
Supported HTTP Versions
- HTTP 1.1
- HTTP 2.0 (over TLS)
- HTTP 3.0 (QUIC)
Requests are upgraded to HTTP/3 using the Alt-Svc
header, or a special ALTSVC
HTTP/2 frame. Alternatively, the first request can be sent via HTTP/3 using the SVCB
/HTTPS
DNS record types.
APIs
Cloud Phone supports the same APIs as Google Chrome.
XMLHttpRequest (XHR)
XMLHttpRequest (XHR) is the origin method for retrieving remote resources without full page reloads. XHR is the foundation of dynamic HTML (DHTML) and Asynchronous JavaScript and XML (Ajax). XHR dates back to 2000, and has been available since Chrome Version 1.
Response Types
The responsetype
property specifies the expected response data type including text
(default), json
, document
, blob
, or arraybuffer
.
const req = new XMLHttpRequest();
req.onload = (e) => {
const text = req.response; // String
/* … */
};
req.open("GET", url);
req.responseType = "text";
req.send();
Monitor Progress
Use the progress
event to show a loading indicator for large uploads or downloads.
const req = new XMLHttpRequest();
req.addEventListener("progress", updateProgress);
req.open("GET", url);
// …
// transfer progress from your app to Cloud Phone server
function updateProgress(event) {
if (event.lengthComputable) {
const percentComplete = Math.round((event.loaded / event.total) * 100);
// …
} else {
// cannot compute progress, total size unknown
}
}
req.send();
Only requests where the lengthComputable
field is true
have determinate progress. This is often because your response is missing the Content-Length
header, or the value returned is 0.
Fetch API
fetch
is a global function for loading remote resources, like XMLHttpRequest. It returns a Promise that is fulfilled with a Response object from the server.
function getDataPromise() {
return fetch(url)
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP status: ${response.status}`);
}
return response.json();
})
.then((respJson) => {
if (!respJson.ok) {
throw new Error(`Response error: ${respJson.code}`);
}
return respJson;
});
}
The Fetch API can also be used with the asynchronous JavaScript.
async function getDataAsync() {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP status: ${response.status}`);
}
const respJson = await response.json();
if (!respJson.ok) {
throw new Error(`Response error: ${respJson.code}`);
}
return respJson;
}
Fetch vs XMLHttpRequest
fetch
and XMLHttpRequest
are both used to load remote resources. Beyond syntax, there are a few functional differences.
- Fetch easily supports the Cache API with
Request
andResponse
objects - Fetch supports the
no-cors
request mode for server that don’t implement CORS - Fetch offers response streaming, while XHR buffers the entire response into memory
- XMLHttpRequest allows progress tracking and
fetch
does not
Streams API
Cloud Phone supports Streams for reading or writing large amounts of data without buffering it entirely into memory. The Streams API provide ReadableStream
and WritableStream
objects that flows from an underlying source like a remote resource that you want to read or write data in small pieces or “chunks”. Chunks in a stream are enqueued: waiting in a queue to be read.
Server-Sent Events (SSE)
Most JavaScript APIs allow you to request data from a server, while Server-Sent Events (SSE) can send data from your server to your app. This is a one-way connection where a connection is defined using the EventSource
interface.
const evtSource = new EventSource("/api/v1/sse");
evtSource.onmessage = (e) => {
console.log(e.data);
};
WebSocket
WebSockets provide a full-duplex, bidirectional connection to send and receive messages between your app and server. Cloud Phone supports the same WebSocket features as the corresponding version of Google Chrome, including the Promise-based WebSocketStream
.
WebTransport
The WebTransport API is a modern update to WebSockets leveraging HTTP/3 to support multiple streams, backpressure, unidirectional streams, out-of-order delivery, and both reliable transmission using streams or unreliable transmission via datagrams. Cloud Phone supports the same WebTransport options and functions as the corresponding version of Google Chrome.
WebRTC
Web Real-Time Communication (RTC) APIs for candidate selection and peer-to-peer connections are not supported on Cloud Phone at this time.
You can connect to the microphone using navigator.mediaDevices.getUserMedia()
which provides access to a MediaStream
. This is available on Cloud Phone 3.0 or higher.
Beacon API
The navigator.sendBeacon
function asynchronously sends an HTTP POST
request alongside a small amount of data, primarily for analytics. Paired with the visibilitychange
event, sendBeacon
can send analytics to your server when the Cloud Phone session ends.
document.addEventListener("visibilitychange", function logData() {
if (document.visibilityState === "hidden") {
navigator.sendBeacon("/log", analyticsData);
}
});
fetchLater
fetchLater
is an experimental API to provide a deferred fetch
as a beacon. Unlike sendBeacon
, fetchLater
is not limited to only the HTTP POST
method. Most of the options are the same between fetch
and fetchLater
.
fetchLater('/log', {
method: 'GET',
cache: 'no-store',
});
fetchLater
is experimental and may not work as expected.
Network Information
The Network Information API is inaccurate on Cloud Phone. Do
Caching
Cloud Phone only caches responses encrypted in memory for the duration of a user session. Caches are purged shortly after the user exits the Cloud Phone app, and cache storage is never shared between users or sessions.
Conclusion
Cloud Phone offers a comprehensive set of Networking APIs for uploading and downloading remote resources. These APIs provide flexibility for your app to fetch the latest weather information or stock data, upload a microphone recording, or display an incoming message. Register for the Cloud Phone Developer Program and get started on the Simulator today.