В этом топике я постараюсь рассказать о работе с API вконтакте из расширения для Google Chrome.
По сути, самая сложная часть это получение токена для доступа к API вконтакте, но обо всём по порядку. Для пущей наглядности я приведу пример минимально полезного расширения (что бы оно хоть что-то полезное делало, а вообще оно было сделано для удобного рехостинга гифок). И так расширение будет простое, но рабочее.
Что делает это расширение:
1. Регистрируется в контекстном меню браузера.
2. Получает URL картинки, на которой кликнули и выбрали пункт меню нашего расширения.
3. Авторизуется по протоколу OAuth 2.0 и получает доступ к API вконтакте (если его ещё нет), а также сохраняет токен в хранилище google chrome.
4. Загружает картинку из кэша браузера в blob с помощью XMLHttpRequest.
5. Выполняет несколько запросов к API вконтакте и сохраняет картинку в разделе Документы (на сайте вконтакте). Заодно показывая результат работы в конце.
Почему раздел документы? Очень просто, лимит 200мб на файл и неограниченное место под документы, плюс отличная скорость загрузки.
Я полагаю, что базовые знания по расширениям google chrome у вас уже есть, иначе вам стоит почитать документацию – там всё очень просто. И тут на хабре было достаточно постов даже для самых начинающих. Так же посмотрите, как регистрировать приложения для вконтакте, там тоже всё очень просто. Вам всё равно придётся это прочитать, так что не откладывайте. По быстрому зарегистрировать приложение для вконтакте можно по этой ссылке.
Все исходники расширения доступны на github. Я привожу тут кусочки кода из этого самого расширения для наглядности. Само же расширение (уже собранное, одобренное и готовое к работе) находится по этой ссылке.
Начнём с краткого описания компонентов нашего расширения:
manifest.json – манифест, основной файл расширения. Описание нашего расширения со всеми опциями и правами доступа.
background.js – основной скрипт который регистрирует и получает уведомления о клике на картинке, а так же получает токен для доступа к API вконтакте.
upload.html – страница-заглушка, показывающая, что расширение чем-то занято (отображается анимированный гиф) пока работает upload.js.
upload.js – скрипт выполняющий непосредственно загрузку картинки на сервер вконтакте.
wait.gif – собственно гифка – прогресс бар.
imageinfo-128.png – иконка приложения большая.
imageinfo-16.png – иконка приложения маленькая.
imageinfo-48.png – иконка приложения средненькая.
Теперь более детально о важных вещах:
В манифесте расширения обозначены требуемые нам для работы компоненты:
"permissions": [ "contextMenus", "tabs", "storage" , "http://*/*", "https://*/*" ]
Мы получаем доступ к контекстному меню браузера, к вкладкам, к хранилищу браузера и расширение будет активно на всех открываемых страницах.
Далее, в нашем основном скрипте, описанном в манифесте как:
"background": { "scripts": [ "background.js" ]}
Добавляем наш пунктик в контекстное меню браузера:
chrome.contextMenus.create(
{
"title": "Rehost on vk.com",
"type": "normal",
"contexts": ["image"],
"onclick": getClickHandler()
});
Соответственно по клику на нашем пункте в контекстном меню будет вызвана функция getClickHandler(). Далее, в getClickHandler() уже начинается интересное. Для начала проверяем токен для доступа к API вконтакте в хранилище google chrome, вдруг мы уже его получили.
chrome.storage.local.get({'vkaccess_token': {}}, function(items) { ...
storage API в google chrome – асинхронное, поэтому приходится работать с ним таким образом. В этом расширении я использую локальное хранилище, хотя ничто не мешает использовать специальное, sync хранилище, которое будет синхронизироваться со всеми вашими браузерами(google chrome) через аккаунт google. Очень удобно для многих вещей, но смысла конкретно для этого расширения — нет. Главное не забывать, что sync хранилище ограничено в количестве сохраняемых элементов и их размере. Локальное хранилище напротив, позволяет хранить вообще безграничное количество информации.
И так, мы проверили и узнали, что токена в хранилище нет. Надо идти авторизовываться и получать токен для доступа к API вконтакте по средствам протокола OAuth 2.0. Для этого мы откроем вкладку со специальным адресом на сервере вконтакте и передадим ему:
https://oauth.vk.com/authorize?client_id=3315996&scope=docs,offline&redirect_uri=http%3A%2F%2Foauth.vk.com%2Fblank.html&display=page&response_type=token
1. client_id=3315996 — это id вашего приложения, который вам выдаст вконтакте. Зарегистрировать своё приложение нужно по этому адресу. Для регистрации приложения и получения своего id просто пишите название и выбираете Standalone-приложение. Не надо использовать мой id для своих приложений, ни к чему хорошему это не приведёт. Для каждого приложения должен быть зарегистрировать свой client_id.
2. scope=docs,offline – это запрашиваемые api к которым будет иметь доступ ваше приложение. Так как нам ничего кроме документов не надо, мы запрашиваем доступ только к ним. Доступ offline – даёт нам токен, который не будет истекать после определённого времени. Иначе придётся время от времени получать токен снова.
3. redirect_uri = поскольку у нас отдельное приложение и никакого своего сервера нет, мы выбираем специальный uri на сервере вконтакте, на который будет перенаправлен браузер получивший токен (ну или не получивший). Токен будет в параметрах этого uri (Всё это части стандарта авторизации по протоколу OAuth 2.0. Очень просто и удобно).
4. display=page – внешний вид окна авторизации
5. response_type=token – то, что бы запрашиваем у сервера вконтакте.
Про все эти опции доходчиво написано на странице разработчиков вконтакте.
И так, как происходит авторизация вконтакте. Наше расширение открывает вкладку в браузере по специально сформировванному uri на сервере вконтакте, где в параметрах запрашивает необходимый доступ.
var authUrl = 'https://oauth.vk.com/authorize?client_id=3315996&scope=docs,offline&redirect_uri=http%3A%2F%2Foauth.vk.com%2Fblank.html&display=page&response_type=token';
chrome.tabs.create({url: authUrl,selected: true}, function(tab) {...
Сервер вконтакте проверяет авторизован ли пользователь на сайте (если нет, то сначала надо будет ввести пароль и логин)
(это картинки из документации вконтакте, приведены для примера)
и далее спрашивает, разрешить ли вашему приложению то, что оно запрашивает.
Если вы отвечаете — разрешить, тогда совершается переход на страницу указанную в redirect_uri и в параметрах этого uri будет запрашиваемый нами access_token для доступа к API вконтакте. Если не разрешите, то в параметрах будет error=access_denied и ничего у нас не выйдет.
Мы конечно разрешим доступ и в открытой нами вкладке произойдёт редирект на страницу oauth.vk.com/blank.html с нужным нам токеном в параметрах. Чтобы получить токен, мы после открытия вкладки установим обработчик обновления вкладок.
authTabId = tab.id;
chrome.tabs.onUpdated.addListener(function tabUpdateListener(tabId, changeInfo)
{
if(tabId == authTabId && changeInfo.url != undefined && changeInfo.status == "loading")
{
if ( changeInfo.url.indexOf('oauth.vk.com/blank.html') > -1 ) { ...
Сохраним Id нашей вкладки и станем ждать, когда пользователь разрешит нам доступ и в uri вкладки появится access_token. Как только при обновлении данных вкладки мы находим access_token, мы его извлекаем и сохраняем в нашем storage:
chrome.storage.local.set({'vkaccess_token': accToken}, function() { ...
И далее сразу приступаем ко второй части нашего расширения. А именно получение картинки и загрузка картинки на сервер вконтакте.
Для этого мы перенаправим нашу вкладку (ту же самую ) на заранее подготовленную страницу в нашем расширении — upload.html. В параметрах передадим всё, что нами нужно для работы. Это токен доступа и uri картинки. Эта страница нужна лишь для того, чтобы показать пользователю, что что-то происходит. Вдруг заргузка займёт много времени, а наша страница может в это время показывать анимированный прогресс бар. Что-то шевелится – пользователь спокоен.
Сюда же мы переходим если токен уже был получен и сохранён в storage.
chrome.tabs.update(tabId,{'url': 'upload.html#' + imgSrc + '&' + accToken,'active': true}, function(tab){});
На нашей странице upload.html всё просто. По умолчанию она показывает прогресс бар – гифку. А в фоне работает скрипт upload.js.
Ничего особенно там нет: в начале вы получаем нашу картинку из кэша браузера в виде blob’a, выполняя GET запрос.
var x = new XMLHttpRequest();
x.onload = function()
{
..
}
x.responseType = 'blob';
x.open('GET', imageUrl);
x.send();
Картинка ведь уже скачана самим браузером и это будет быстро. Заодно мы обходим всякие хитрые хостинги картинок, которые по приходу с гугла показывают картинку, а как только реферере становится не гугл, под картинкой появляется реклама ресурса. В итоге у нас чистая картинка какой мы её и видели.
Далее идёт череда запросов к вконтакте API строго в соответствии с документацией. Мы получаем адрес сервера для загрузки картинки ( docs.getUploadServer ), создаём форму с помощью FormData() и добавляем туда полученный blob с картинкой, присваивая ему имя картинки. Оправляем картинку POST’ом на сервер, сохраняем картинку на сервере ( docs.save ) и получая uri картинки в ответе переходим по нему, чтобы показать пользователю в нашей вкладке свежезагруженную картинку уже на сервере вконтакте.
Вот собственно и всё. Я не JavaScript специалист, потому уж не обессудьте за качество кода.
Автор: crea7or