В наши дни сервисы закладок стоят десять центов. Когда ваша карьера и увлечения требуют от вас сохранения сотен ссылок, все становится беспорядочным. В конце концов я остановился на Diigo из-за его поддержки списков и тегов — вы можете добавить несколько тегов к каждой закладке и добавить каждую закладку в список. Но посещение этих закладок утомительно — сначала я должен открыть свою библиотеку Diigo на новой вкладке, а затем нажать на закладку в списке передо мной. Если моя библиотека сложна и глубоко вложена, тем больше проблем — мне нужно дополнительно отфильтровать результаты поиска, щелкнув фильтры слева, и я уже трачу гораздо больше времени, пытаясь добраться до своего сайта, отмеченного закладкой, чем должен ,
планирование
В этой серии мы создадим расширение Google Chrome, которое подключается к API-интерфейсу Diigo, извлекает сохраненные там закладки и синхронизирует их в папку на панели закладок Chrome. Эта папка будет иметь несколько уровней:
- Корневой уровень. Здесь будет подпапка «Теги», а также все закладки пользователя, помеченные как bbs-root.
- Уровень тегов. Подпапка «tags» будет содержать одну папку для каждого тега, который пользователь имеет в своей библиотеке Diigo. При входе в указанную папку перечисляются все сообщения с данным тегом.
К сожалению, поскольку API Diigo недостаточно развит, нет возможности удалить теги, если они оставлены пустыми, а также нет способа удалить закладку из Diigo, если она удаляется в Chrome, — пока. Если этот API появится, я оставлю это кому-то другому, чтобы написать последующую статью. Аналогично, API Diigo не поддерживает списки на данный момент. Как только они добавят эту функцию, это будет достаточно просто, чтобы обновить это расширение с подпапкой «Списки».
Важно отметить, что Google очень монополистичен со своим сервисом закладок. В Chrome встроен максимальный предел записи , что означает, что вы не можете делать более 100 записей (создавать, обновлять и удалять) с помощью API chrome.bookmarks
Это означает, что если кто-то имеет более 100 тегов / списков / закладок в Diigo, их браузеру потребуется несколько часов, чтобы извлечь их все и в конечном итоге согласиться на меньшее количество записей (только обновления, создания и удаления с этого момента должны быть намного меньше общий). Мы также будем использовать конструкции JavaScript 1.7, такие как ключевое слово let
, поэтому вам нужно перейти в chrome://flags
Может ли это быть сделано без let
Абсолютно. Но я твердо верю, что держаться подальше от новых технологий только потому, что они еще не везде, вредно как для разработчиков, так и для сети в целом. JS 1.7 вышел 7 лет назад, что примерно триста лет в интернете. Помимо let
«строгий режим» , потому что let
Обратите внимание, что это означает, что люди без экспериментального JS не смогут установить и использовать это расширение, по крайней мере до тех пор, пока поддержка JS 1.7 не будет включена по умолчанию в Chrome.
Бутстрапирование
Сначала давайте создадим папку, в которой мы будем хранить исходный код нашего расширения. Создайте структуру папок, такую как эта, и оставьте файлы JS и JSON пустыми.
/
icons/
background.js
manifest.json
Далее нам нужно заполнить файл manifest.json
{
"name": "Diigo Bookmark Bar Sync",
"description": "Sync Diigo Bookmarks to Chrome",
"version": "1.0.0.0",
"background": {
"scripts": ["background.js"]
},
"permissions": [
"bookmarks", "https://secure.diigo.com/api/v2/"
],
"browser_action": {
"default_icon": {
"19": "icons/19.png",
"38": "icons/38.png"
},
"default_title": "Diigo BBS"
},
"icons": {
"16": "icons/16.png",
"48": "icons/48.png",
"128": "icons/128.png"
},
"manifest_version": 2
}
Если вы следовали моему предыдущему руководству по расширению Chrome для Sitepoint , вы должны быть знакомы со всеми ключами и их значениями.
Есть три новинки, с которыми вы, возможно, не знакомы: тот факт, что мы используем фоновую страницу JS вместо HTML (в любом случае не имеет значения — JS незаметно быстрее), мы запрашиваем разрешение «закладки», чтобы попросить Chrome разрешить мы редактируем их, и мы запрашиваем разрешение на доступ к https://secure.diigo.com/api/v2/
перекрестным происхождением ajax или, другими словами, позволяет нам выполнять вызовы Ajax на Diigo без поднятия флагов безопасности ,
Мы также используем browser_action , что означает, что у нас всегда будет постоянная иконка NEXT на омнибар — а не внутри нее, пока мы находимся на конкретной странице, как в случае с действиями на странице.
Сделайте несколько иконок для вашего расширения в размерах, указанных в файле manifest.json, и добавьте их в папку с иконками, или просто загрузите мою и поместите их туда.
На этом этапе мы можем протестировать наше расширение, загрузив его на вкладку расширений (chrome: // extensions). Убедитесь, что «Режим разработчика» установлен, и нажмите «Загрузить распакованное расширение», затем укажите Chrome на папку, в которую вы положили файлы. Если все идет хорошо, значок расширения должен появиться в верхней панели справа от омнибара, и если вы наведете на него курсор мыши, вы увидите всплывающее окно «Diigo BBS».
Diigo API
Чтобы получить доступ к API Diigo, вам необходимо зарегистрироваться для получения ключа API . Это предоставит вам строку случайных символов, которую вам нужно отправлять вместе с каждым запросом API Diigo, чтобы идентифицировать себя (на самом деле, чтобы идентифицировать ваше приложение — у каждого приложения будет свой ключ API).
API Diigo сильно недоразвит, но RESTful, что означает, что мы каждый раз вызываем один и тот же URL-адрес для воздействия на один и тот же объект (т.е. закладки), но меняем тип запроса (GET-выборки, POST-обновления и вставки, DELETE удаляет закладку — еще не реализовано ). Мы скоро объясним это немного глубже.
По сути, общение с API так же просто, как отправка запроса на URL, заполненный необходимыми параметрами. Если мы предполагаем, что есть пользователь с именем «Джоэл», для получения 10 закладок Джоэла мы используем https://secure.diigo.com/api/v2/bookmarks?key=your_api_key&user=joel&count=100&filter=all
Ответом на этот запрос будет либо код ошибки, если что-то пошло не так, либо JSON-объект. Этот объект JSON либо не будет содержать ничего, если у Джоэла нет закладок, либо будет содержать блоки данных, соответствующие информации об этих закладках, во многом аналогично тому, как показано в документации по API:
[
{
"title":"Diigo API Help",
"url":"http://www.diigo.com/help/api.html",
"user":"foo",
"desc":"",
"tags":"test,diigo,help",
"shared":"yes",
"created_at":"2008/04/30 06:28:54 +0800",
"updated_at":"2008/04/30 06:28:54 +0800",
"comments":[],
"annotations":[]
},
{
"title":"Google Search",
"url":"http://www.google.com",
"user":"bar",
"desc":"",
"tags":"test,search",
"shared":"yes",
"created_at":"2008/04/30 06:28:54 +0800",
"updated_at":"2008/04/30 06:28:54 +0800",
"comments":[],
"annotations":[]
}
]
Легко извлечь все необходимое из этих данных JSON, как только мы их получим, но мы вернемся к этому через минуту.
Документы API говорят
Аутентификация использует базовую аутентификацию HTTP — стандартный метод аутентификации, который включает в себя имя пользователя и пароль в кодировке base64 в заголовке запроса авторизации.
..но нет ни объяснения, ни демонстрации этого.
Это означает следующее: когда вы открываете фактический URL-адрес для API в браузере, попробуйте щелкнуть здесь , вам будет предложено ввести имя пользователя и пароль.
Если вы не ввели правильные учетные данные, вы получите ответ 403, что означает, что у вас недостаточно доступа.
Если у вас есть надлежащие учетные данные, вы можете получить доступ к URL-адресу двумя способами: либо ввести их и отправить форму, либо включить их в URL-адрес, например: https://myusername:[email protected]/api/v2/bookmarks?key=your_api_key&user=joel&count=100&filter=all
myusername
mypassword
Вы даже можете проверить это прямо сейчас в своем браузере, если вы зарегистрировали ключ API и у вас есть действующая учетная запись Diigo. Вы должны получить либо пустой массив ([]), либо список ваших закладок (или публичные закладки пользователя, которого вы определили в параметре user URL-адреса).
Так что же означает кодирование base64? Это означает, что нам нужно запустить имя пользователя и пароль через дополнительный фильтр, чтобы учесть любые странные символы в пароле. Таким образом, строка myuser:mypass
bXl1c2VyOm15cGFzcw==
здесь ).
Итак, как мы можем собрать все это вместе?
Кодирование и отправка
Для начала нам понадобится способ кодирования строки в base64. Поскольку JS не имеет этой встроенной функциональности, мы можем использовать код из Webtoolkit . Вставьте этот код в файл background.js
Если вы хотите, вы можете даже уменьшить его, чтобы сделать его более компактным.
Далее нам нужно указать URL-адрес API, который мы хотим авторизовать. Это делается с помощью заголовка Authorize, и при использовании собственных объектов XHR для Ajax мы можем сделать это с помощью xml.setRequestHeader('Authorization', auth);
метод, где auth
Давайте создадим общую функцию, которая генерирует эту строку авторизации.
function make_basic_auth(user, password) {
var tok = user + ':' + password;
var hash = Base64.encode(tok);
return "Basic " + hash;
}
Как видите, возвращаемая строка будет «Basic» + все, что было вычислено из user + pass string в качестве значения Base64. Эта строка — то, что нужно заголовку авторизации, чтобы получить доступ к URL-адресу, на который мы ее отправим. По сути, он идентичен вводу имени пользователя и пароля вручную при доступе к URL-адресу через браузер.
Вы можете быть удивлены — не могли бы мы просто добавить пользователя: перейти к началу URL-адреса так же, как и в браузере, и просто игнорировать бизнес Base64? Да, но тогда вы не учитываете разные символы и можете столкнуться с серьезными проблемами с недопустимыми запросами — например, символ «@» обозначает начало адреса сервера, а наличие его в пароле может привести к тому, что мы усилия.
Наконец, давайте сделаем XHR-запрос к API.
var auth = make_basic_auth('user','pass');
var url = 'https://secure.diigo.com/api/v2/bookmarks?key=your_api_key&user=desireduser&count=100&filter=all';
xml = new XMLHttpRequest();
xml.open('GET', url);
xml.setRequestHeader('Authorization', auth);
xml.send();
xml.onreadystatechange = function() {
if (xml.readyState === 4) {
if (xml.status === 200) {
console.log(xml.responseText);
} else {
console.error("Something went wrong!");
}
}
};
Конечно, замените «user», «pass», «your_api_key» и «desireduser» на ваши значения.
Если мы теперь перезагрузим наше расширение с открытой фоновой страницей (нажмите _generated_background_page.html
Заключение части 1
В этой части мы загрузили наше расширение, объяснили, реализовали и продемонстрировали вызов API Diigo. Во второй части мы напишем основную часть нашего расширения.