The following example shows how to create a simple Facebook login button with Facebook javascript API:

Normally, this page would be reloaded if user finished authorized your app. But it won’t be reloaded in Chrome due to the follwing error:

Unsafe JavaScript attempt to access frame with URL https://s-static.ak.fbcdn.net/connect/xd_proxy.php?version=3#cb=f363e58d9&origin=http%3A%2F%2Fwww.ab.com%2Ffcb27588&relation=opener&transport=postmessage&frame=fac4c0f18&access_token=AAAEHZBpoK3B0BALv8Cf96gaKEnn4ZBtXgjCOQCFFhVDL4K0rZAE2NGDcqZCPlZByNNKEDmYSGKHQv8jAUM2yGZCHkOcyXUKhoZD&expires_in=0&signed_request=g7sYd_XQx-EBPtQQGk-0ISRMrUDnT4L4WHAmlNsVFBU.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImNvZGUiOiJBUURKYkZBNjZuemduSDBBN0dXWmd2SGxZZkQxQVp4Qm1MSnc0Z3ppUV9FQ25VeEYyZmcyTmJGcFh3UHZDeWhyYnFrT1RxNmRVc2xsb0d4dlFCd290UjRyV0ZsSnJtVjFoNy1QUTlJbTRROXh3MmNKMGU1b0NReWtmT1ZZcXhMUDRVRldVSDgwVU5ic1BLTHdyNk80cFlSVVItQzNIYjhyRWgxek40ZFEzSkpreXhBcU1KSHljcWxETzh2dF96T3ZpN0EiLCJpc3N1ZWRfYXQiOjEzMzExMzg3MjQsInVzZXJfaWQiOiIxMTI5MjgzNDM3In0 from frame with URL http://www.ab.com/login.html. Domains, protocols and ports must match.

Some people use FB.getLoginStatus() to check if user authorized app at page loaded. If page could be reloaded, it’s no problem. However, in this case, it’s not. 

There are several questions on StackOverflow related to this:

http://stackoverflow.com/questions/3577947/facebook-gives-unsafe-javascript-attempt-to-access-frame-with-url-error-in-chr

http://stackoverflow.com/questions/8013008/facebook-authentication-unsafe-javascript-attempt-to-access-frame-with-url

http://stackoverflow.com/questions/3010170/unsafe-javascript-attempt-to-access-frame-with-url-error-being-continuously

But none of these solves my problem. I don’t want to solve this with introduce PHP sdk. I would like to solve it with pure front end codes. 

Therefore, I find 3 solutions:

  1. Ignore the error and register login event to solve the problem:
  2. Add attribute “show-faces="true”“ to <fb:login-button> to solve
  3. Add attribute "render-in-iframe="true”“ to <fb:login-button> to solve. This is a bad idea since this is an undocumented attribute.

In solution 2 and 3, login-button seems to be placed into an iframe. And 3 would display an incomplete login button (bug?)

    Thrift是由Facebook開發的一套RPC system, 廣泛的被很多軟體應用, 像是HBase, Hadoop, Cassandra… 也支援了許多語言 , 可以跨語言做RPC

    但….Thrift的document真是么壽的少…少的實在有夠可憐….本來想說實作一個java client連到node.js寫的server, 搞半天東挖挖西挖挖後才搞定…..

    首先是安裝到我的mac就把我搞暈了(加上感冒本來就暈), 一開始我用macport裝, 但裝完後, 找不到libthrift.jar, 所以只好上網站抓source來build, 所幸可以只build java library的部份, 不用整個thrift都build, 這部份倒不難, 用ant就搞定了

    裝完thrift後, 寫好程式, build java版本時就出了問題了, javac說TClient不是個interface, 追進code才發現, 我自己build的jar是最新版的 (0.8), 但port幫我裝的是0.6, 產生的codes完全不相容, 後來改用brew裝(就是不想從頭從Source build), 終於是0.8版的了(port上的也太舊了吧)

    這邊實作一個簡單的加法器, Server side是跑node.js, Client是java, 有空在來試試別的組合, 建一個新檔"computer.thrift", 內容如下:

    這邊定義一個簡單的Service - “Computer”, 只含有一個方法"add", 內容很簡單, 就是用來回傳a+b的值, “namespace java com.thrift.gen"的用途就是指定產生的java code的package, 如果沒指定就是沒package, i64指得就是64bit integer

    接下來就是要用thrift產生對應的程式碼:

    thrift –gen js:node –gen java computer.thrift

    這行指令同時產生for node.js的版本(在gen-nodejs目錄), 跟java版本

    Server implementation

    先安裝thrift module (for node.js)

    npm install thrift

    實作server.js:

    https://gist.github.com/1523666.js?file=gistfile1

    在Server裡面實作add, 由於是asynchronous的, 所以結果由callback回傳

    至於Client端的部份也蠻簡單的:

    在網路上找到的sample, 都使用TSocket, 但用TSocket在這範例, client/server都會掛掉, 追了server code發現, node.js server default應該是用Framed transport, 所以在Client端加上TFramedTransport就OK了

    Open graph的確是個好物, 雖然說早在去年的f8就已經推出了, 但現在更加完備了, 其實也等不及看會有啥應用推出了, 當然自己也想來玩看看,  本想照Tutorial依樣畫葫蘆抄一個體驗看看, 又覺這樣太無聊, 又想說試看看heroku + node.js, 沒真的玩過node.js, 就拿這題目試試

    今天剛好在Facebook上講到拉麵, 所以就拿我最愛吃的拉麵來當題目了.. :P

    web.js和兩個views(index.ejs, men.js)的sources放在這

    實作筆記:

    1. Tutorial裡的範例是拿Heroku + PHP, 但其實這跟拿哪一種來實作沒太大差異, 裡面的範例幾乎全部都是javascript辦到的, 所以就算把範例放到其他平台也適用
    2. Tutorial裡的範例比較靜態, 全部實作在html內就好, 我把它改成"/ramen/id"當一個物件, 但每一個物件都還是透過"men.ejs"去render
    3. heroku提供的node.js連結Facebook的範本是透過server side的everyauth+facebook-client, 我把這些都拿掉, 純用Facebook javascript api
    4. 在web.js裡實作兩個uri, “/” (index.ejs) 和 “/ramen/id” (men.ejs), 拉麵資料由web.js在render時傳給template, 目前先寫死
    5. Object debugger是蠻好用的東西, meta data寫錯一直post不出去, 剛開始沒用這抓錯還真不知道錯哪
    6. Social plugin的activity feed似乎不包含自己的

    最後在Timeline上呈現的樣子:

    用Graph API取得自己的Activities:

    https://graph.facebook.com/me/[name_space]:[action_type]/ramen

    ex. https://graph.facebook.com/me/soulogramen:eat/ramen

     

    上次的作法:

    var button1 = findview(R.id(‘button1’));

    button1.setOnClickListener(function(view, methodName)
    {
         if (methodName == “onClick”) {
             log(“MyScript”, “clicked”);
    } });

    當然不是很滿意, “if(methodName == "onClick”)“這樣的寫法太醜了啦!

    所以這次的目標是:

    button1.onclick = function(view) {

         log("MyScript”, “clicked”);

         alert('Hi there!’);

    };

    這樣比較像印象中javascript的寫法

    為了達到這目的, 必須在View中加入onclick這個property, 但原本View class(Java)並沒這東西, 如何將它包裝出來?

    Rhino對於Javascript使用原生的java objects並不是直接使用, 還是有透過一層包裝, 因此這就是要做出這個property的路了, 包裝的點在於WrapFactory, 而原生的Java object會被包裝長NativeJavaObject 

    而Rhino允許我們用自己的WrapFactory取代原本的, 像是這樣:

    jsContext.setWrapFactory(new AndroidWrapFactory());

    因此我們會需要自己實作這一個AndroidWrapFactory, 把原本的View改用不同的包裝, 而非原本的NativeJavaObject, 基本上只需要實作wrapAsJavaObject即可:

    這邊用了一個新實作的ViewWrapper來取代NativeJavaObject

    本來我的打算是繼承自NativeJavaObject, 然後再加入自己的東西, 不過後來發現這樣的作法總會在"put"時出差錯, 原因是NativeJavaObject是沒辦法加入新的member了(其實這說法有點問題, 應該是只要設prototype給它的話還是可以), 加上一些比較實用的function是定義在ScriptableObject的裡面, 因此, 我最後採用ScriptableObject來包裝

    但要如何在ScriptableObject裡面實現像NativeJavaObject那樣可以直接叫用原本的Java class裡面的member呢?這部份不用自己實作, 只要把原本的NativeJavaObject當做這新的ViewWrapper的prototype就好了, 所以這邊constructor呼叫的super contructor是:

    public ScriptableObject(Scriptable scope, Scriptable prototype)

    ===> super(scope, new NativeJavaObject(scope, javaObject, staticType));

    defineProperty這包裝是從ScritableObject那邊改寫其中一個過來的, 主要是用來讓我們可以把這些"onlick",“onlongclick"包裝成property, 在ViewWrapper可以實作getter和setter, 為了避免名稱上的混淆, 所以把getter的prefix定義成"jsget"而setter是"jsset”

    在onlick的setter中, 除了將function object存起來外, 還直接對原本包裝的View設一個OnClickListener, 動作則是執行這個Function object

    最後, 前面的範例裡面有一個"alert('Hi! there’)“, 因此為了"alert()"多實作一個Alert.java出來(跟上面的無關啦), 這是source:

    接下來的目標, 

    • 包裝一個實際真的可以拿來開發的package, release 0.1 alpha
    • 實作XmlHttpRequest
    • Adapter & AdapterView, Service & Provider

    Install “scons” first.

    Run “scons target=x64” -> Done