Вчера задался себе таким вопросом: как можно обезопасить мой профиль в Google Chrome и вообще все данные, которые в нем хранятся? Немножко погуглив, я нашел ссылки на кучу расширений (типа этого), которые позволяют устанавливать пароль как на браузер так и на отдельные его профиле (это логично, если знать как работает Chrome в режиме мультипрофильности). Я начал их устанавливать и сразу тесты на баги. И как оказалось ни один из них не хочет адекватно работать в режиме мультипрофильности. Не очень-то долго думая я решил написать собственное расширение и заодно разобраться в Google Chrome API.Немного почитав документацию и разобравшись в принципе работы расширений я приступил к работе.
Принцып написания расширений
Дехто думає, що розширення це щось таке заморське, непідвласне простим людям. Насправді для його написання достатньо всього лиш блокнота, в якому це все писати, і браузера, в якому тестувати написане.Итак, любое расширение для Chrome состоит из следующих составляющих:
- Файл манифеста manifest.json, в котором записывается информация о приложении;
- Иные файлы, которые используются в расширении: это могут быть html-странички, скрипты, картинки и т.д.
Для запуска готовой работы нужно всего лишь на стрничке расширений в режиме разработчика загрузить ваше творение.Итак, приступим к работе!
Пишем файл манифеста
Файл манифеста хранится в корневой папке проекта и, как вы уже поняли, представляет из себя набор данных в формате JSON. Рассмотрим исхоник манифеста, а после этого я опишу каждый пункт подробнее.
{
"name": "Profile Guard",
"description": "Google Chrome profile protection by password",
"version": "0.1",
"permissions": [ "tabs" ],
"background_page": "background.html",
"icons": {
"48":"images/bigicon.jpg"
},
"browser_action": {
"default_title": "Profile Guard",
"default_icon": "images/icon.png",
"popup": "popup.html"
}
}
А теперь по порядку:
- name, description и version — собственно имя расширения, его короткое описание и номер версии;
- permissions — массив с дополнительными правами расширения на выполнение тех или иных действий. Подробнее почитать можно здесь. В даном случае расширение может знать об открытых вкладках и окнах браузера;
- background_page — главная страника которая запускается при запуске браузера и работает на фоне;
- icons — набор иконок разных размеров;
- browser_action — описание кнопочки на панели инструментов. default_title — текст при наведении на кнопку, default_icon — иконка на кнопке, popup — html-страничка, которая откроется в попапе после клика;
Кроме этих параметров в файле манифеста может быть и много других.
Фоновая страничка
Фоновая страничка будет проверять установлен ли пароль и запрашивать его при открытии браузера или создании окна с неким профилем. От протестированных мною расширений моё отличается именно тем, что более менее адекватно работает в режиме мультипрофильности.Пароль от нашего профиля будет храниться в localStorage['profile_password']. localStorage — это массив, в котором расширение может хранить свои какие-то данные, не беспокоясь о том, что какое-то другое расширение доступиться к этим данным. Для каждого расширения и профиля это отдельная переменная, поэтому можно устанавливать разные пароли на разные профили.
<html>
<head>
<title>Profile Guard background page</title>
</head>
<body onload="pass();">
<script type="text/javascript">
function pass(){
chrome.windows.getAll(function(wins){
if(wins.length==1){
if(localStorage["profile_password"]){
var pass = prompt("Please enter password:","");
if(pass!=localStorage["profile_password"]){
alert("Access denied!");
chrome.windows.getCurrent(function (window){chrome.windows.remove(window.id)});
}
}
}
});
}
chrome.windows.onCreated.addListener(function(window){
pass();
});
</script>
</body>
</html>
Установка и изменение пароля
Устанавливать и изменять пароль мы сможем на страничке, которая открывается в попапе popup.html. Изначально пароль не установлен и его можно будет установить. Пожже его можно будет изменить или вовсе удалить. Короче говоря всяческие манипуляции с паролем для входа.Исходник файла запихиваю в спойлер, особо пояснять ничего не буду, по-моему и так всё понятно.
<html>
<head>
<title>Profile Guard background page</title>
<style>
body {
font-family: sans-serif;
background: #f5f5f5;
color: #666E79;
width: 250px;
}
div.form {
background: white;
border: solid 1px #e8e8e8;
border-radius: 5px;
}
h1 {
margin:0;
padding: 0;
font-size: 20px;
text-align: center;
line-height: 40px;
}
h2 {
margin: 0 10px;
padding: 0;
font-size: 14px;
line-height: 30px;
}
button {
border:solid 1px #5E697C;
background: URL(images/button.jpg);
color: white;
font-size: 13px;
line-height: 22px;
margin: 10px auto 15px;
display: block;
border-radius: 4px;
cursor: pointer;
font-weight: bolder;
text-shadow: rgba(0,0,0,0.2) -1px -1px 0px;
padding: 1 10px;
}
button:hover {
background: URL(images/hover.jpg);
}
.newbutton {
margin: 15px 0;
}
.field {
padding: 5px 15px;
text-align:right;
}
label {
color: #989898;
font-weight: bolder;
font-size: 12px;
float:left;
line-height: 25px;
}
input {
width: 135px;
text-align:left;
}
</style>
<script>
function view(){
if(!localStorage["profile_password"]){
elnewbutton.style.display = "block";
elnewpass.style.display = "none";
elchpass.style.display = "none";
} else {
elnewbutton.style.display = "none";
elnewpass.style.display = "none";
elchpass.style.display = "block";
}
}
function newpass(){
if(!localStorage["profile_password"]){
elnewpass.style.display = "block";
elnewbutton.style.display = "none";
}
}
function newset(){
if(!localStorage["profile_password"]){
var pass = npass.value;
var conf = nconf.value;
if(pass){
if(pass!=conf){
alert("Passwords don't match!");
npass.value = "";
nconf.value = "";
} else {
localStorage["profile_password"] = pass;
view();
alert("Password successfully changed");
}
}
}
}
function chset(){
if(localStorage["profile_password"]){
var old = cold.value;
var pass = cpass.value;
var conf = cconf.value;
if(old!=localStorage["profile_password"]){
alert("Old password is entered incorrectly");
cold.value = "";
} else {
if(pass){
if(pass!=conf){
cpass.value = "";
cconf.value = "";
alert("Passwords do not match!");
} else {
localStorage["profile_password"] = pass;
view();
alert("Password successfully changed");
}
}
}
}
}
function claerpass(){
if(localStorage["profile_password"]){
var old = cold.value;
if(!old){
alert("Enter old password first!");
} else {
if(old!=localStorage["profile_password"]){
alert("Old password is entered incorrectly");
cold.value = "";
} else {
localStorage["profile_password"] = "";
view();
alert("Password successfully deleted");
}
}
}
}
</script>
</head>
<body onload="view();">
<div class="form">
<h1>Profile Guard</h1>
</div>
<div class="newbutton" id="newbutton">
<button id="elnewbutton" onclick="newpass();">Set new password</button>
</div>
<div class="newpass form" id="elnewpass" style="display:block;">
<h2>Set password</h2>
<div class="field">
<label>Password</label>
<input type="password" id="npass" />
</div>
<div class="field">
<label>Confirm</label>
<input type="password" id="nconf" />
</div>
<button id="elnewset" onclick="newset();">Set new password</button>
</div>
<div class="newpass form" id="elchpass" style="display:block;">
<h2>Password change</h2>
<div class="field">
<label>Old password</label>
<input type="password" id="cold" />
</div>
<div class="field">
<label>Password</label>
<input type="password" id="cpass" />
</div>
<div class="field">
<label>Confirm</label>
<input type="password" id="cconf" />
</div>
<button id="elchset" onclick="chset();">Change password</button>
<button id="elclear" onclick="claerpass();">Delete password</button>
</div>
</body>
</html>
Завершающий этап
В завершение нам нужно упаковать наше творение, это можна сделать на странице расширений нажав на кнопку «Упаковка расширений». Указав папку с нашим расширением на выходе мы получаем два файла: .crx — файл с самим расширением, .rem — файл с секретным ключом. В придачу вы можете поделится своим творением с людьми, залив его на Chrome WebStore, но для этого нужно заплатить гуглу взнос в размере $5 (но это лишь первый раз, при регистрации).Прошу не судить строго, ведь это моё первое расширение. Скачать исходник можно по ссылке. Уапкованное расширение не даю, так как в хроме можно устанавливать лишь расширения с Вебстора.
Пишите свои замечания и замеченные баги.
Автор: makzimko