Networking

NASA photo of earth at night

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.

XFF Example
  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.

XFF Example
  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.

xhrResponseType.js
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.

xhrProgress.js
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.

fetchPromise.js
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.

fetchAsync.js
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 and Response 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.

sse.js
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.

sendBeacon.js
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.js
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.