Release 5.2
diff --git a/src/js/facebook.js b/src/js/facebook.js
new file mode 100644
index 0000000..68cb091
--- /dev/null
+++ b/src/js/facebook.js
@@ -0,0 +1,139 @@
+const FB_APP_ID = CURRENT_LOCALE == 'zh_CN' ? 170328509685996 : 118170701590738;

+const FB_REDIRECT_URI = 'http://www.facebook.com/connect/login_success.html';

+const FB_PERMISSION = 'offline_access,user_photos,publish_stream';

+const FB_ACCESS_TOKEN_URL = 'https://www.facebook.com/dialog/oauth';

+const FB_PHOTO_UPLOAD_URL = 'https://graph.facebook.com/me/photos';

+const FB_USER_INFO_URL = 'https://graph.facebook.com/me';

+const FB_LOGOUT_URL = 'http://m.facebook.com/logout.php?confirm=1';

+

+var Facebook = {

+  siteId: 'facebook',

+  redirectUrl: FB_REDIRECT_URI,

+  currentUserId: null,

+  accessTokenCallback: null,

+

+  isRedirectUrl: function(url) {

+    return url.indexOf(FB_REDIRECT_URI) == 0;

+  },

+  

+  getAccessToken: function(callback) {

+    Facebook.accessTokenCallback = callback;

+    var url = FB_ACCESS_TOKEN_URL + '?client_id=' + FB_APP_ID +

+      '&redirect_uri=' + FB_REDIRECT_URI + '&scope=' + FB_PERMISSION +

+      '&response_type=token';

+    chrome.tabs.create({url: url});

+  },

+

+  parseAccessToken: function(url) {

+    var queryString = url.split('#')[1] || url.split('?')[1];

+    var queries = queryString.split('&');

+    var queryMap = {};

+    queries.forEach(function(pair) {

+      queryMap[pair.split('=')[0]] = pair.split('=')[1];

+    });

+    var accessToken = queryMap['access_token'];

+    if (accessToken) {

+      var user = new User({

+        accessToken: accessToken

+      });

+      Facebook.accessTokenCallback('success', user);

+    } else if (queryMap['error']) {

+      Facebook.accessTokenCallback('failure', 'user_denied');

+    }

+    Facebook.accessTokenCallback = null;

+  },

+

+  getUserInfo: function(user, callback) {

+    ajax({

+      url: FB_USER_INFO_URL,

+      parameters: {

+        'access_token': user.accessToken

+      },

+      success: function(userInfo) {

+        userInfo = JSON.parse(userInfo);

+        if (callback) {

+          user.id = userInfo.id;

+          user.name = userInfo.name;

+          callback('success', user);

+        }

+      },

+      status: {

+        others: function() {

+          if (callback)

+            callback('failure', 'failed_to_get_user_info');

+        }

+      }

+    });

+  },

+  

+  upload: function(user, caption, imageData, callback) {

+    caption = ajax.encodeForBinary(caption);

+    var params = {

+      'access_token': user.accessToken,

+      message: caption

+    };

+    

+    var binaryData = {

+      boundary: MULTIPART_FORMDATA_BOUNDARY,

+      data: imageData,

+      value: 'test.png',

+      type: 'image/png'

+    };

+    

+    ajax({

+      url: FB_PHOTO_UPLOAD_URL,

+      parameters: params,

+      multipartData: binaryData,

+      success: function(data) {

+        callback('success', JSON.parse(data).id);

+      },

+      status: {

+        others: function(data) {

+          var message;

+          if (data) {

+            data = JSON.parse(data);

+            if (data.error.message.indexOf('access token') >= 0) {

+              // User removed application permission

+              // {"error":{"type":"OAuthException",

+              // "message":"Error validating access token."}}

+              message = 'bad_access_token';

+            } else {

+              // {"error":{"type":"OAuthException",

+              // "message":"(#1) An unknown error occurred"}}

+              message = 'unknown_error';

+            }

+          } else {

+            message = 'failed_to_connect_to_server';

+          }

+          callback('failure', message);

+        }

+      }

+    });

+  },

+

+  getPhotoLink: function(user, photoId, callback) {

+    ajax({

+      url: 'https://graph.facebook.com/' + photoId,

+      parameters: {

+        'access_token': user.accessToken

+      },

+      complete: function(statusCode, data) {

+        if (statusCode == 200) {

+          callback('success', JSON.parse(data).link);

+        } else {

+          callback('failure', 'failed_to_get_photo_link');

+        }

+      }

+    });

+  },

+

+  logout: function(callback) {

+    ajax({

+      url: FB_LOGOUT_URL,

+      success: function(data) {

+        if (callback)

+          callback(data);

+      }

+    });

+  }

+};
\ No newline at end of file