Samsung / tizen-common-web

Apache License 2.0
11 stars 4 forks source link

Apollo subscriptions work only if developer mode is set to local on TV #10

Open IureaBogdan opened 1 year ago

IureaBogdan commented 1 year ago

Hello!

We have an Angular app which is then used as source for a Tizen TV Web App.

The app receives data using ApolloClient subscription.

Behavior:

I mention that the app also works on Chrome, Opera, Mozilla.

Is there something that we are missing?

SejoongDeJang commented 1 year ago

The 7011 port is charged to the developer mode. The port number might be increased to 7012 and more. Is it related to your ApolloClient subscription?

There is no reason to block your program in Tizen OS.

IureaBogdan commented 1 year ago

We are using Angular Apollo Client in order to connect to a graphql server. In our case Hasura. In order to use the apollo client, it has to be configured.

// Apollo client configuration with http + websocket. 
function createApollo(httpLink: HttpLink): ApolloClientOptions<any> {
   const uri = 'http://192.168.10.100:8080/api/graphql/'
  // Create a http link:
  const http = httpLink.create({
    uri,
  });

  console.log(' --- ws starting init');

  // Create a WebSocket link:
  const wsLink = new GraphQLWsLink(
    createClient({
      url: uri.replace('http://', 'ws://'),
    })
  );

  console.log(' --- ws initialised');

  // using the ability to split links, you can send data to each link
  // depending on what kind of operation is being sent
  const link = split(
    // split based on operation type
    ({ query }) => {
      const definition = getMainDefinition(query);
      return definition.kind === 'OperationDefinition' && definition.operation === 'subscription';
    },
    wsLink,
    http
  );

  return {
    link,
    cache: new InMemoryCache(),
  };
}
/// ApolloClient configuration using only http
export function createApollo(httpLink: HttpLink): ApolloClientOptions<any> {
  const uri = 'http://192.168.10.100:8080/api/graphql/'
  return {
    link: httpLink.create({ uri }),
    cache: new InMemoryCache(),
  };
}

Running the app outside developer mode using the http only configuration is normal. It works as expected.

Running the app with the http + websocket configuration works only if we are setting the developer mode to local.

App behavior in developer mode -> local.

App behavior in developer mode -> off.

My question is: Why the app is not opening/not responding in developer mode -> off? This behavior happens only if we use the http + socket apolloclient configuration.

Also, in order to see if there is a implementation incompatibility in apollo, we used the native implementation of the WebSockets, but the app is still not responding. It has the same behavior like the apolloclient with http and socket configuration.

I didn't mentioned, but we are installing the app via UrlLauncher.

SejoongDeJang commented 1 year ago

Your code might be correct. I guess your development environment have trouble. Which one is your device environment?

  1. Using a Real Device 1.1. Using a wits on a Real Device
  2. Using a Emulator 2.1. Using a wits on a Emulator
IureaBogdan commented 1 year ago

The app is installed via URL Launcher on a Real Device.

The application works fine with URL Launcher Developer Mode -> Local, but when the URL Launcher Developer Mode is switched to Off, the screen goes blank after the app is being installed/relaunched.

I was thinking that maybe there is a problem with the socket protocol. Just for testing, I used a Secure Web Socket Client Implementation that is guaranteed to work. The behavior is the same as the one mentioned above, Web Sockets don't work with URL Launcher Developer Mode -> Off.

I removed the alerts logs from Secure Web Socket Client Implementation and added their messages as DOM unordered list items.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'container',
  templateUrl: './container.component.html',
})
export class ContainerComponent implements OnInit {
  messages = [];

  ngOnInit(): void {
    let socket = new WebSocket('wss://javascript.info/article/websocket/demo/hello');
    let that = this;
    socket.onopen = function (e) {
      that.messages.push('[open] Connection established');
      that.messages.push('Sending to server');
      socket.send('My name is John');
    };

    socket.onmessage = function (event) {
      that.messages.push(`[message] Data received from server: ${event.data}`);
    };

    socket.onclose = function (event) {
      if (event.wasClean) {
        that.messages.push(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
      } else {
        // e.g. server process killed or network down
        // event.code is usually 1006 in this case
        that.messages.push('[close] Connection died');
      }
    };

    socket.onerror = function (error) {
      that.messages.push(`[error] ${error.message}`);
    };
  }
}
<ul style='color: red;'>
  <li *ngFor='let message of messages'>{{message}}</li>
</ul>

Running as Web App on PC with Chrome/Opera/Mozilla:

Chrome Snapshot Client WebSocketSecure

Running on a real Samsung device as Tizen Web App, launched with URL Launcher Developer Mode -> Local:

developer-mode-local-app developer-mode-local

Running on a real Samsung device as Tizen Web App, launched with URL Launcher Developer Mode -> Off:

developer-mode-off-app developer-mode-off

IureaBogdan commented 1 year ago

I found the issue that was causing this behavior. The app had the following content-security-policy in config.xml:

  <tizen:content-security-policy>connect-src 'self' http: https:; img-src 'self' data: https: http:;</tizen:content-security-policy>

I replaced it (temporarily) with:

  <tizen:content-security-policy>allow '*'; media-src *; img-src *;</tizen:content-security-policy>

Now the app works fine in developer mode -> off.

SejoongDeJang commented 1 year ago

That's good news :D

I thought that your device is a Smart TV. The URL launcher Settings is not supported in a Smart TV. Your device should be a Smart Signage.

Your effort will be helpful to another developers. Really thanks your help!