<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Emile M.</title>
    <description>The latest articles on Forem by Emile M. (@emile1636).</description>
    <link>https://forem.com/emile1636</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1671729%2F910a9bb9-688c-4416-97fd-a971ded9d4c8.jpg</url>
      <title>Forem: Emile M.</title>
      <link>https://forem.com/emile1636</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/emile1636"/>
    <language>en</language>
    <item>
      <title>How to send native message via Dart for Browser Extensions (Chrome, Firefox)</title>
      <dc:creator>Emile M.</dc:creator>
      <pubDate>Thu, 25 Jul 2024 04:05:34 +0000</pubDate>
      <link>https://forem.com/emile1636/how-to-send-native-message-via-dart-for-browser-extensions-chrome-firefox-9pj</link>
      <guid>https://forem.com/emile1636/how-to-send-native-message-via-dart-for-browser-extensions-chrome-firefox-9pj</guid>
      <description>&lt;p&gt;When developing an extension for multiple browsers, you may need an application (either local or cloud-based) that can manage or share state &amp;amp; logic across the extensions/browsers. If the local application route is your preferred choice, browsers have a protocol, called Native Messaging Protocol, to communicate with local applications via standard-in and standard-out.&lt;/p&gt;

&lt;p&gt;This post explains how to send &amp;amp; receive those native messages in a compiled Dart code host application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging" rel="noopener noreferrer"&gt;Mozilla's Excellent Docs on Native Messaging&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/fme-developer-stories/native-messaging-as-bridge-between-web-and-desktop-d288ea28cfd7" rel="noopener noreferrer"&gt;Introduction to Native Message Protocol specifics&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EfihD6rg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:640/format:webp/1%2AyZ3is4r7CnO6WeuB1jMaQg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EfihD6rg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:640/format:webp/1%2AyZ3is4r7CnO6WeuB1jMaQg.png" alt="Native Message image" width="442" height="82"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Messages are sent as UTF8-encoded JSON preceded by a 32bit unsigned length in native byte order.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;stdout.write()&lt;/code&gt; encodes the output provided to the &lt;code&gt;write()&lt;/code&gt; function which causes issues since the native messaging protocol requires header have length of data sent in bytes.&lt;br&gt;
So &lt;code&gt;stdout.add()&lt;/code&gt; (which does not encode during output) needs to be used&lt;/p&gt;

&lt;p&gt;&lt;code&gt;data&lt;/code&gt; being send should be valid JSON, in order to match native messaging protocol requirements&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample Code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:convert'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:io'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:typed_data'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;/// Send out JSON String native message to browser extension &lt;/span&gt;
&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;sendNativeMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//Convert int to bytes&lt;/span&gt;
  &lt;span class="n"&gt;Uint8List&lt;/span&gt; &lt;span class="n"&gt;int32bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Uint8List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asByteData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setUint32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Endian&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;//Convert data into utf8-encoded bytes&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;encodedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Uint8List&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;//Output the encoded data's length as bytes&lt;/span&gt;
  &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int32bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encodedData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="c1"&gt;//Output the encoded data's bytes&lt;/span&gt;
  &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encodedData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;/// Receive Native Message bytes and decode to JSON String&lt;/span&gt;
&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;receiveNativeMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//Get new mutable list from a immutable list&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;dataBytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;//Remove the length bytes from bytes list that are part of native messaing protocol spec.&lt;/span&gt;
  &lt;span class="c1"&gt;//(The first 4 hex bytes)&lt;/span&gt;
  &lt;span class="n"&gt;dataBytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removeRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;//Decode from bytes list to JSON string&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataBytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>dart</category>
      <category>browser</category>
      <category>webdev</category>
      <category>desktop</category>
    </item>
    <item>
      <title>Fix for Remote Desktop Error code 0x207 on Mac for Ubuntu</title>
      <dc:creator>Emile M.</dc:creator>
      <pubDate>Thu, 18 Jul 2024 02:52:17 +0000</pubDate>
      <link>https://forem.com/emile1636/rdp-error-code-0x207-on-mac-for-ubuntu-24-d6d</link>
      <guid>https://forem.com/emile1636/rdp-error-code-0x207-on-mac-for-ubuntu-24-d6d</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2nzu3p2uig7mjqcx5sf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2nzu3p2uig7mjqcx5sf.png" alt="RDP Error Message" width="538" height="596"&gt;&lt;/a&gt;&lt;br&gt;
If you're like me and were staring at this error popup then allow me to share what worked for me:&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;p&gt;You should've already enabled Remote Login in Ubuntu's/Gnome's settings with a username and password&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6aoanrzip90b6p2y9jn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6aoanrzip90b6p2y9jn.png" alt="Ubuntu Remote Login settings" width="800" height="614"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;It doesn't have to be a real user on device, just a username and password for RDP authentication purposes&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;p&gt;You've likely already done this first step but if you haven't&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;'Add PC' in Microsoft Windows App (previously called Remote Desktop for Mac) with all changes that you'd like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe50m2fs77jaq7tsxn3qf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe50m2fs77jaq7tsxn3qf.png" alt="The Add PC dialog box for Microsoft Remote Desktop App" width="715" height="709"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Export the config to a location of your choosing&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F34o96zlqnxczfgnzucem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F34o96zlqnxczfgnzucem.png" alt="The dropdown for exporting RDP config file" width="612" height="478"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open the RDP config file (that you exported in the previous step) with any text editor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Edit the line that states:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;use redirection server name:i:0&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;to&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;use redirection server name:i:1&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Note: the last 0 has to be changed to a 1&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save file and open the RDP connection from this newly edited/saved file directly (Either by double-clicking or by dragging in the config to Microsoft Windows App)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;Hope it helped!&lt;/p&gt;

</description>
      <category>rdp</category>
      <category>ubuntu</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>gRPC - Unimplemented Error 12</title>
      <dc:creator>Emile M.</dc:creator>
      <pubDate>Sun, 23 Jun 2024 21:22:25 +0000</pubDate>
      <link>https://forem.com/emile1636/grpc-unimplemented-error-12-16ck</link>
      <guid>https://forem.com/emile1636/grpc-unimplemented-error-12-16ck</guid>
      <description>&lt;p&gt;Hello, world!&lt;br&gt;
Just a word of caution to all.&lt;/p&gt;

&lt;p&gt;When you are using proto files for gRPC calls be sure that your generated proto files' versions are the same.&lt;/p&gt;

&lt;p&gt;I had the great privilege of debugging a &lt;code&gt;gRPC Error Code 12 - Unimplemented&lt;/code&gt; for 2 days because my client was using older proto files generated without the "package ____ " line while my server had the newer generated files WITH "package ____" on it. &lt;/p&gt;

&lt;p&gt;(You can also get &lt;code&gt;Unimplemented&lt;/code&gt; error if your compression and encodings are different between client and server. &lt;a href="https://grpc.io/docs/guides/compression/"&gt;See here&lt;/a&gt;) &lt;/p&gt;

&lt;p&gt;Turns out, that insignificant package line makes a difference to your gRPC message path and your client and your server will be talking about 2 different things (even though you think they are the same) &lt;/p&gt;

&lt;p&gt;gRPC message path:&lt;/p&gt;

&lt;p&gt;With package name:&lt;br&gt;
&lt;code&gt;/{package-name}/{rpc function}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Without package name:&lt;br&gt;
&lt;code&gt;/{rpc function}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Had to dig through the haystack of gRPC calls with Wireshark to even understand what was happening. (&lt;a href="https://grpc.io/blog/wireshark/"&gt;See Wireshark documentation here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;If only there had been better error messages or documentation, instead of a cryptic &lt;code&gt;Unimplemented&lt;/code&gt; error that doesn't even show anything meaningful on a Google search. Fun!&lt;/p&gt;

</description>
      <category>grpc</category>
      <category>protobuf</category>
      <category>debugging</category>
    </item>
  </channel>
</rss>
