Uma introdução longa e tediosa com uma reivindicação de megalomania
Depois que descobri que, como sempre, algo não me agradava muito neste mundo. Ou seja, inserindo algum tipo de consulta longa em um mecanismo de pesquisa em um computador desktop e depois alternando para um tablet, não consegui recuperar o texto da consulta literalmente para obter exatamente os mesmos resultados. Tudo começou tão bem. Vi no mecanismo de pesquisa um link para a resposta à minha pergunta e percebi que ele promete um longo assunto de leitura. Então desliguei o computador e me sentei no sofá com o tablet com o pensamento de que agora vou digitar tudo novamente no mecanismo de pesquisa, vou abrir esse link agora no tablet e deitar-me calmamente em uma posição mais confortável, vou ler ... Mas não aqui foi. Algumas pequenas discrepâncias no texto - e meu link não está mais no mecanismo de busca. Reproduzir o link em si também não é uma opção: é muito longo. Confundindo as opções para o texto da consulta, eu estava quase furiosa por quebrar o tablet. Droga, eu tive que me levantar, ligar o computador novamente, iniciar o navegador e mergulhar na história para encontrar o texto exato da minha solicitação.

Extensão instalada no Chrome e FirefoxIdéia
Pensei, mas seria bom escrever uma extensão para o navegador que permitisse transferir qualquer uma das guias abertas pelo servidor para qualquer outro computador e continuar trabalhando com elas lá. Sim, alguns navegadores já possuem um recurso de nuvem - você só precisa fazer login nos dois dispositivos e ... Mas esse é o problema. Mas e se eu tiver o Chrome no meu computador e o Firefox no meu tablet? E então ... Basta fazer login, sim. Se ainda me lembrava da minha senha da conta do Google. E eu simplesmente não tenho uma conta no Firefox. Eu nem sei se existem contas lá? Obviamente, existem serviços em nuvem de terceiros nos quais você pode se registrar e, provavelmente, de alguma forma lançar o link desejado para si mesmo. Mas ainda é necessário registrar-se e memorizar firmemente outra senha ... Não, isso é completamente irreal. No final, você pode lançar um link para si mesmo pelo correio. Mas tudo isso leva muito tempo, copie e cole de e depois na barra de endereços, o que, por exemplo, em um tablet é extremamente inconveniente. Não, tudo isso é algum tipo de bobagem ...
Deitada no sofá, percebi lentamente que todas essas ações exigem muito movimento ... Não, pessoal, isso não é necessário. E quando eu entendo que algo não combina comigo neste mundo, então me sento para escrever código para fazer tudo do meu jeito. Eu pensei que estava autorizado nas redes sociais, tanto no tablet quanto no computador desktop. E em navegadores diferentes, por exemplo, no mesmo computador - também. Em geral, a solução para mim era óbvia - autenticar o usuário através das redes sociais.
Digressão lírica
A propósito, quando escrevo algo próprio, também o faço do meu jeito. Escrevo em javaScript puro em um bloco de anotações avançado, não uso o github, não uso bibliotecas de terceiros, nem uso o jquery. Portanto, não haverá tutorial sobre como escrever uma extensão do navegador. Eu não vou te ensinar isso. Não faça como eu faço. Eu te aviso - este é um mau exemplo. Também quero contar a todos os críticos em potencial, antecipando a reação deles - sim, concordo plenamente com toda a sua raiva justa. Sim, não é possível colocar o script inteiro em um ou dois arquivos, mas é preciso dividir tudo, como uma salada, em vários pedaços pequenos, para que ele possa ser coletado por 3 horas em um comando longo e inteligente na linha de comando. Sim, você não pode combinar código javascript e código html em um arquivo - é melhor estragar outro nível de abstração que os combinará. Sim, você não pode usar o layout da tabela, mas droga, é ferro! E ainda mais - agora eles vão me queimar - você não pode usar o innerHtml e criar uma estrutura html complexa de uma só vez, mas você precisa anexar e desanexar todos os filhos em um loop, anexar cuidadosamente e excluir cada manipulador ... Sim, estou fazendo tudo errado. Pecador, eu me arrependo. Mas eu faço conscientemente, porque é mais fácil. E quem vai me proibir? No final, não é ilegal, é? Não sei programar como o mod moderno exige, e nem quero tentar, porque acredito que o diagrama do processo de desenvolvimento é desnecessariamente complicado. Sou a favor de escrever código com as mãos e não construí-lo a partir das peças de outra pessoa sem escrever uma única linha. No entanto, meu código é leve, não precisa ser montado por uma equipe especial e funciona rapidamente. Estou escrevendo código usando a tecnologia F5. É quando, para ver como a versão atual funciona a qualquer momento do processo de desenvolvimento, basta clicar no navegador F5.

No entanto, eu ainda tinha que desligar os manipuladores em um loop, porque, caso contrário, a extensão não passaria no teste. Também em extensões, apenas no caso, no arquivo de índice html - de repente - scripts dinamicamente conectados são proibidos. Então eu os conectei através da tag de script.
Armazenamento da guia
Por isso, decidi que as guias abertas no navegador deveriam ser salvas em determinadas listas, que serão chamadas de computadores - Computador doméstico, Computador comercial, Computador local. Local - é quando a lista não está armazenada no servidor, mas no banco de dados do navegador e, portanto, você pode usá-la apenas no navegador em que está salva. Isso é para aquelas guias que não precisam ser lançadas entre computadores diferentes. Bem, o restante das listas pode ser visualizado em qualquer computador e navegador dentre os suportados pela extensão.
Para cada guia, o usuário pode deixar um comentário de texto arbitrário. Por exemplo, é conveniente me lembrar de quais séries parei ao assistir à série e também marcar por mim o que está na página, se não estiver claro por seu título e tipo de link.
De acordo com a documentação para a criação de extensões para Chrome e Firefox, o código de extensão deve estar localizado em dois arquivos - o principal e o segundo plano. O script principal lida com a exibição da interface do usuário, e o script em segundo plano pode controlar as guias do navegador e trocar dados com o servidor. Gerenciar guias no Chrome e Firefox é muito semelhante. Por exemplo, o manipulador de eventos para abrir ou fechar guias no Chrome é assim:
chrome.tabs.onUpdated.addListener( function(tabId, changeInfo) { });
E no Firefox assim:
browser.tabs.onUpdated.addListener( function(tabId, changeInfo, tabInfo) { });
E a função que exibe uma lista de todas as guias abertas é escrita exatamente da mesma forma para os dois navegadores:
chrome.tabs.query({},function(data){ });
Sim, sim, o Chrome também grava o Chrome no Firefox ... etc. Isso é um pouco estranho, no entanto, o fato de os navegadores estarem caminhando para padronizar suas APIs é muito encorajador.
Na verdade, toda a funcionalidade da extensão é alcançada usando várias funções - abra a janela da extensão clicando em seu ícone, leia abas abertas, feche a aba, crie uma nova aba, ouça os eventos da aba e troque dados com a janela da extensão. Só isso. Esses métodos estão disponíveis apenas no script em segundo plano.
Após a leitura, as guias abertas no navegador são enviadas ao meu servidor e salvas em um banco de dados SQL regular. O script do servidor está escrito em PHP. Há uma tabela de usuário que armazena links para linhas em outra tabela - a tabela de dados. Esses dados são os endereços das páginas, seus nomes e comentários de texto do usuário, armazenados no formato de cadeias de texto em um campo de tipo de texto com cerca de um kilobyte. Os dados são armazenados em forma não criptografada. Cerca de 1.000 guias podem ser salvas por megabyte. Um máximo de 25 desses armazenamentos ("Computadores") é fornecido para cada usuário.
No entanto, a versão gratuita da extensão limita o usuário a dois armazenamentos - Computador doméstico e Computador comercial, e cada um deles pode armazenar não mais que 10 guias. Ainda estou trabalhando na versão paga e nos métodos de pagamento. Haverá até 25 "computadores" e até cerca de 1000 guias em cada um, além de opções de imagens de fundo, ícones e nomes para cada computador, listas hierárquicas e muito mais.
Há outro repositório - computador local. Não há restrições aqui, pois os dados da guia são armazenados no banco de dados do navegador local no computador do usuário. Aqui você pode armazenar quantas guias quiser, mas não mais do que o disco rígido permite. Além disso, como os dados não são armazenados no Armazenamento Local, mas no DB indexado, não há limite de 5 ou alguns megabytes. É importante não limpar acidentalmente este repositório junto com o histórico do navegador. Também pretendo exportar e importar guias para um arquivo de texto.
Para trabalhar com o indexedDB, escrevi uma pequena sub-biblioteca com apenas 106 linhas de comprimento. Ao contrário do banco de dados no servidor, aqui todos os dados não precisam ser destilados em uma sequência de texto, mas podem ser salvos imediatamente na matriz associativa como estão. O princípio do armazenamento existe: a chave é o valor. E o valor pode ser uma enorme matriz associativa.
Autenticação de usuário
FirefoxA autorização, como já observei, ocorre por meio de redes sociais e, no servidor, usando o protocolo OAuth. Ele ainda é suportado pelo Facebook e pelo VKontakte, mas pretendo aumentar o número de métodos de autenticação do usuário. O esquema de autorização do servidor OAuth é descrito em detalhes na documentação das duas redes sociais, portanto, não faz sentido insistir nele em detalhes. Observo apenas que não gostei do fato de que, durante a autorização, uma nova guia do navegador é aberta, mesmo que o usuário já esteja conectado à rede social e já tenha concedido os direitos de extensão. Essa guia deve ser capturada pelo script de extensão em segundo plano e forçada a fechar e, em geral, não parece esteticamente agradável, se encaixa nas outras guias e pisca quando aparece e é destruída.
Para fechá-lo, no VKontakte, você precisa verificar a presença do endereço no manipulador de eventos da guia:
oauth.vk.com/blank.html
E para o Facebook:
https://www.facebook.com/connect/blank.html
E apenas no caso:
facebook.com/connect/login_success.html
Portanto, no início, enviei um assembly de extensão para a Google Web Store, no qual a autorização foi realizada no cliente com uma solicitação preliminar da rede social da API javascript do cliente correspondente. Além disso, como a extensão está instalada no usuário e preciso autorizar no meu servidor, eu também extraí o html do meu servidor no script de extensão no i-frame, mas já puxei a API da rede social nele ...
E o esquema de troca de dados com o servidor era assim. Uma página de índice de extensão envia um comando (informações de clique, por exemplo) para um script de extensão em segundo plano. O script de segundo plano usando postMessage envia dados para o h-frame i-frame. O I-frame envia dados para o script php no servidor. O servidor responde no i-frame, o i-frame responde no script em segundo plano, o script em segundo plano responde no índice, o usuário vê a resposta. Ufa ... E o mais importante - tudo funcionou!
Em geral, isso não funcionou. O Google envolveu minha extensão com vários formulários, entre os quais havia algo vago que, dizem eles, sua extensão não está de acordo com nossa política de segurança. Através da correspondência com suporte, consegui obter detalhes. Ou seja, eles não gostaram do fato de a extensão extrair html e js de servidores de terceiros ... Em geral, eu tive que terminar com a autorização do cliente e retornar ao servidor. Sim, enviando uma solicitação de postagem http a partir de um script de extensão em segundo plano diretamente para o servidor, no entanto, acabou sendo permitido. Bem, tudo bem. Isso é ainda melhor. Descobriu-se mais curto e não há necessidade de extrair API javascript das redes sociais - este é um tempo de espera extra para o usuário.
Exibir guias
Voltar para as opções de expansão. A lista de guias em si é uma série de linhas em que primeiro vem o ícone da imagem, depois o título da página e, finalmente, o link. O que não couber no tamanho da linha designado na tela é cortado. Mas o banco de dados é salvo completamente. Além disso, qualquer linha pode ser movida para cima da tela na forma de um ladrilho colorido. Isto é para os sites mais importantes que devem estar diante de seus olhos em primeiro lugar.
Lista de guias do ChromeAs cores dos ladrilhos são selecionadas automaticamente com base no nome de domínio do site. A função aceita o URL. O nome do domínio é dividido em três grupos aproximadamente iguais de caracteres.Os primeiros caracteres de cada grupo são convertidos nos valores dos componentes de cores: R, G, B. Essa conversão é realizada da seguinte maneira. Os códigos desses três caracteres são reduzidos para o intervalo d1, de 0 a 25, levando o restante da divisão em 26. Até os caracteres do alfabeto russo serão reduzidos para esse intervalo. Não importa que a 27ª letra se torne a primeira lá: não precisamos que os componentes de cores de todas as letras do alfabeto sejam necessariamente diferentes, que sejam repetidos. Em seguida, os três números obtidos no intervalo d1 (0 ... 25) são reduzidos proporcionalmente no intervalo d2 (150 ... 255). Em geral, esses intervalos são definidos no início da função e podem ser alterados para outros. Peguei 150 ... 255 para que os componentes da cor sejam brilhantes. Se você definir, por exemplo, 0 ... 100, os ladrilhos ficarão escuros. Assim, três caracteres do nome de domínio são convertidos em 3 números do intervalo 150 ... 255. E então, como você provavelmente adivinhou, eles são interpretados como os componentes de cores dos ladrilhos R, G e B. Tudo é muito simples.
getSiteColor=function(url) { var d1=[0,25], d2=[150,255]; var code=0, codep=0, color=0, str='', domen='', ar=[], inc=0; ar=url.split('//'); if (ar.length>1) {str=ar[1];} else {str=ar[0];}; str=str.split('www.').join(''); domen=str.split('/')[0]; str=domen.split('.').join(''); ar=[]; inc=Math.floor(str.length/3); if (str.length % 3 >0) {inc++;}; for (var i=0; i<str.length; i+=inc) { code=str.slice(i, i+1).charCodeAt(0); codep=code % (d1[1]-d1[0]+1); color=Math.round( codep * (d2[1]-d2[0]) / (d1[1]-d1[0]) ) + d2[0]; ar.push(color); }; return {r:ar[0], g:ar[1], b:ar[2], domen:domen}; }
Estrutura de documento HTML
Um documento html consiste em vários elementos de tela com posicionamento absoluto, combinados por sobreposição e um bloco div no qual a lista é exibida. Uma função é pendurada no redimensionamento da janela do navegador que redimensiona todos esses elementos, ajustando-os à nova altura e largura. Também há um tamanho mínimo de superação que causa o aparecimento de barras de rolagem. A imagem de fundo é exibida na tela inferior. Decidi que, para listas diferentes (computadores), diferentes planos de fundo devem ser configurados para facilitar a navegação do usuário. A imagem de fundo enche a janela com a preservação de suas proporções e é levemente iluminada para não chamar a atenção para si mesma - um retângulo translúcido branco é desenhado em cima dela. Acima da tela de fundo, encontra-se a tela do menu principal, ela preenche apenas a parte superior da tela. Bem e ainda mais alto está o bloco div, no qual a lista de guias é formada. A navegação no menu Canvas é feita através da minha mini-biblioteca.

Navegador Opera e YandexLocalização
Na tela principal, há uma bandeira, clicando no qual a interface alterna entre russo e inglês. Aqui a página é redirecionada para o mesmo endereço, mas com um parâmetro na linha de comando. Este parâmetro é lido antes de carregar todos os outros elementos. E com base em seu valor, este ou aquele arquivo js com frases em russo ou inglês é carregado na matriz associativa para frases: lng_en.js ou lng_ru.js. E no próprio aplicativo, para exibir frases de interface, já são usados links para cadeias de texto desse array associativo. Além disso, dependendo do valor na barra de endereço, é carregado um arquivo contendo os elementos da interface gráfica - botões: buttons_en.png ou buttons_ru.png. Decidi que é melhor criar botões junto com os ícones e inscrições em cada idioma no editor de gráficos do que criar um botão vazio e sobrepor ícones e inscrições nele, especialmente porque não existem muitos deles e toda essa lista de sprites pesa apenas 50 Kb Eu pretendo continuar trabalhando no design e tornar todos os botões diferentes em forma.

O arquivo geral com sprites main.png, que contém elementos gráficos que não estão vinculados a uma localização específica, é carregado de qualquer maneira.
Versão Web
Eu pensei que seria bom se os links armazenados com cuidado a partir do computador de casa ou do trabalho pudessem ser visualizados a partir do telefone. Mas nem todos os navegadores de sistemas operacionais móveis oferecem suporte a extensões. Então eu criei uma montagem da web. Ao visitar o site em um endereço específico, você ainda pode fazer login usando uma das redes sociais e visualizar suas guias.
Sim, não há como adicionar guias à lista ou editar. Mas você pode pelo menos abrir abas da lista e visualizar as páginas. Acho que vale a pena trabalhar na versão móvel deste site e exibir listas maiores de guias.
Versão da Web no IE 11Publicidade
Até agora, não trabalhei na promoção da minha expansão. Ele acabou de criar grupos nas redes sociais e convidou todos os seus amigos para lá. Sim, ele lançou uma campanha publicitária no Yandex Direct por 1.500 rublos. Ela não deu nenhum resultado especial, mas talvez eu não tenha feito o anúncio corretamente. Ou talvez o problema seja que eu indiquei um link para a versão em inglês da página inicial da extensão. E talvez valesse a pena dar um link não para a página inicial, mas imediatamente para uma das lojas de extensão. Como você sabe, eu não sou um gênio do marketing. Em geral, tentarei novamente com outros parâmetros. A campanha deu 39 cliques. É difícil dizer se eu adquiri alguns novos usuários como resultado disso.
Havia uma singularidade com a versão no Firefox.
As estatísticas de 17 de outubro mostram até 227 downloads. Não sei se a campanha no Yandex.Direct contribuiu para isso ou não, mas por algum motivo, 1-2 downloads por dia continuam novamente. Ao mesmo tempo, para a extensão do Firefox, existe o conceito de usuários diários:
Por que houve 227 downloads, mas havia apenas 1-2 usuários diários, não está claro. Talvez tenha sido algum tipo de falha. Em geral, eu ainda não entendi o que era, e onde estão todas essas pessoas ...
As estatísticas na loja de extensões da Chrome Web Store agradaram a uma programação eternamente sem carregamento - foi o que eu não vi - e a 5 a 10 usuários diários.
Além disso, enviei a montagem para a loja de extensões Opera. No entanto, tendo apresentado duas versões e sem esperar a moderação de nenhuma delas, em algum momento cuspi em espalhar novas por lá. E, de fato, por que isso é necessário se o Opera instala perfeitamente extensões da loja do Chrome.
Sumário
Criei três compilações de extensão - para Chrome, Firefox e a versão da web. Na verdade, todos os três conjuntos são um e o mesmo conjunto, o que simplesmente indica na configuração qual mecanismo do navegador está sendo usado no momento. E as funções correspondentes para trabalhar com guias são inicializadas. Altero esse valor antes de embalar em zip e enviar o pacote para o armazenamento de extensões apropriado.
As versões para Chrome e Firefox foram testadas e colocadas em suas respectivas lojas oficiais de extensão. Além disso, o registro como desenvolvedor de extensões no Google custa US $ 5. Mozilla tem de graça. A versão web da extensão está localizada no servidor. A montagem da loja do Chrome funciona bem em navegadores compatíveis: também pode ser instalada no Yandex Browser e no Opera. Eu pretendo lançar novas versões com recursos ainda mais avançados.
Em geral, as extensões do navegador são poder. Agora não preciso me levantar do sofá e também não há necessidade de raiva para quebrar o tablet. Este é o Zen completo. Bom para todos.