Outro dia, quando fui me logar no Gmail, digitei rapidamente meu login, apertei tab, digitei a senha e apertei enter. Na pressa, não percebi que, em vez de tab, eu tinha apertado shift. Ou seja, o campo login ficou preenchido como “loginsenha”, e a senha ficou em branco. Até aí tudo bem, o Gmail simplesmente me deu um aviso de login ou senha inválidos. Porém, esse “loginsenha” ficou no histórico de preenchimento de campos, o que é bem incômodo, já que contém minha senha. Eu queria excluir este item do histórico, mas sem perder todo o histórico do browser.

O Firefox possui uma opção “Clear Recent History”, no menu “Tools”, que permite excluir o histórico somente para um período de tempo (última hora, últimas 2 ou 4 horas, último dia ou tudo), e permite selecionar também o que se deseja excluir (URLs acessadas, downloads, formulários preenchidos, cookies, cache, logins ativos e preferências de sites). Apesar de esta opção ser bastante completa, eu queria algo mais específico: excluir somente aquele item.

Após uma rápida pesquisa no Google, encontrei algumas referências interessantes, e descobri que a solução era extremamente simples. Para excluir um item do histórico de preenchimento de campos de formulários, basta clicar no campo e, ao aparecer a lista de valores armazenados no histórico, selecione o item que você quer excluir usando a seta para baixo e pressione Del. É só isso!

Também é possível excluir itens individuais do histórico de URLs acessadas. Para isso, repita o procedimento acima, trocando apenas o Del por Shift+Del.

Referências:


Muitos componentes JSF, como os do Tomahawk, por exemplo, possuem o atributo rendered. Este atributo, como diz o nome, indica se o componente será renderizado ou não. No valor deste atributo, é possível utilizar expressões JSF EL; desta forma, a lógica que indicará se o elemento será exibido ou não pode (e deve) ser transferida para um Managed Bean. Isso permite que evitemos colocar muita lógica nos XHTMLs, deixando-os mais limpos e organizados.

Porém, em determinados momentos, precisamos fazer a renderização condicional de elementos que os componentes JSF não oferecem. Uma possível solução seria inserir este elemento num <t:div>, por exemplo, pois este componente do Tomahawk possui o atributo rendered. Porém, estaríamos criando um <div> em torno do elemento desejado sem necessidade. O melhor neste caso seria utilizar o componente [](http://myfaces.apache.org/tomahawk-project/tomahawk/tagdoc/t_htmlTag.html).

O <t:htmlTag> possui um atributo value que define a tag HTML que será renderizada em seu lugar, caso o atributo rendered seja igual a true. Se o value for vazio, ele não criará nenhuma tag adicional; assim, o <t:htmlTag> servirá somente para a renderização condicional de tudo o que estiver dentro deste componente.

Atenção: o atributo value é obrigatório; se você omití-lo, o componente não funcionará! Para que ele não gere nenhuma tag, é necessário definir value="", como no exemplo abaixo:

<t:htmlTag rendered="#{tipo.exibeDescricao}" value="">
    <div id="divDescricao_#{tipo.id}">
        <h:outputText value=" #{messages.descricao}" />
        <h:inputTextarea styleClass="inputAreaTexto" id="descricao" value="#{descricaoTipo}" />
    </div>
</t:htmlTag>

Muitos usuários de Linux têm dual boot com uma instalação de Windows, geralmente para executar alguma aplicação específica, como jogos mais recentes ou o iTunes (apesar de que o Ubuntu 10.04 deve suportar iPod e iPhone).

Quem utiliza esta configuração e usa Firefox em ambos os sistemas operacionais acaba tendo dois perfis independentes no browser, e não consegue acessar bookmarks, histórico e extensões instaladas no outro sistema. Uma solução para este problema é compartilhar os perfis do Firefox entre os sistemas operacionais.

O Firefox armazena um diretório com configurações pessoais do usuário. No Linux, esse diretório fica tipicamente em /home/usuario/.mozilla/Firefox/, e no Windows, em C:\Documents and Settings\usuario\Dados de aplicativos\Mozilla\Firefox\. Este diretório contém, entre outras coisas, um subdiretório Profiles com todos os perfis criados (mais detalhes sobre isso no post sobre gerenciamento de perfis no Firefox) e um arquivo profiles.ini. Este arquivo é carregado na inicialização do browser, e faz referência aos perfis utilizados. O formato do arquivo é como mostra o exemplo abaixo:

[General]
StartWithLastProfile=1

[Profile0]
Name=default
IsRelative=1
Path=Profiles/dwi06ij0.default

[Profile1]
Name=teste
IsRelative=1
Path=Profiles/nkc5ofgt.default
Default=1

O arquivo é dividido em seções. A primeira, General, tem somente o parâmetro StartWithLastProfile: se for 0, será exibida a tela de seleção de perfis; se for 1, o último perfil que foi usado será escolhido automaticamente.

As seções seguintes definem todos os perfis criados. Cada perfil tem um nome e um path - que será relativo ao diretório de configurações do Firefox se IsRelative for 1, e absoluto em caso contrário. O parâmetro Default indica se este é o perfil padrão.

Para que os dois sistemas operacionais compartilhem um perfil, primeiramente é necessário montar a partição do usuário utilizada pelo outro sistema operacional. Isso pode ser feito de duas maneiras:

Mapeando uma partição do Windows no Linux

Para montar uma partição do Windows, basta utilizar o comando mount, como no exemplo abaixo:

sudo mount /dev/sda1 /media/windows

Neste exemplo, a partição do Windows é /dev/sda1, e o diretório destino (que deve ser criado antes) é /media/windows. A partição pode ser FAT32 ou NTFS - neste caso, é necessário instalar o ntfs-3g, que já vem por padrão na maioria das distribuições atuais. Para que a partição seja montada automaticamente na inicialização do sistema, inclua a linha abaixo no arquivo /etc/fstab:

/dev/sda1 /media/windows ntfs defaults 0 0

Caso a partição seja FAT32, substitua ntfs por vfat na linha acima.

A configuração acima também pode ser feita utilizando uma ferramenta gráfica como o ntfs-config.

Mapeando uma partição do Linux no Windows

Para isso, é necessário instalar uma ferramenta como o Ext2 IFS - que, apesar do nome, também suporta ext3. Ao instalar esta ferramenta, será possível mapear qualquer partição ext2 ou ext3 como um drive comum. A figura abaixo mostra uma tela da ferramenta, onde aparecem todas as partições dos discos locais. Em cada partição do Linux, há uma combo box que permite selecionar a letra em que a partição será mapeada - selecionando none o mapeamento será desfeito.

Ext2 IFS

Entre as duas opções, pessoalmente, prefiro a segunda, pois não gosto da ideia do Windows acessando minhas partições do Linux - só mapeio uma partição com o Ext2 IFS quando preciso copiar algum arquivo, depois desfaço o mapeamento.

Após realizar o mapeamento da partição, de uma das duas formas acima, basta configurar o arquivo profiles.ini do Firefox. Para isso, é possível configurar o path completo para o perfil desejado e definir o parâmetro IsRelative=0, ou fazer um link no diretório onde o Firefox armazena os perfis e configurar o path relativo, com o parâmetro IsRelative=1. A primeira configuração ficaria como no exemplo abaixo:

[Profile0]
Name=default
IsRelative=0
Path=/media/windows/Documents and Settings/guilherme/Dados de aplicativos/Mozilla/Firefox/Profiles/sa8ww6mz.default

Para a segunda configuração, é necessário criar um link com o comando ln:

ln -s /media/windows/Documents\ and\ Settings/guilherme/Dados\ de\ aplicativos/Mozilla/Firefox/Profiles/sa8ww6mz.default /home/guilherme/.mozilla/Firefox/Profiles/

Neste caso, a configuração do arquivo ficaria assim:

[Profile0]
Name=default
IsRelative=1
Path=Profiles/sa8ww6mz.default

Possíveis problemas

Apesar de funcionar muito bem, o compartilhamento de perfis pode trazer alguns problemas:

  • Se as versões do Firefox nos dois sistemas forem diferentes (o que é muito comum, pois o repositório do Ubuntu costuma demorar para atualizar as versões), cada vez que você abrir o browser num sistema após tê-lo acessado no outro será como se você tivesse atualizado a versão do Firefox, ou seja, a inicialização será mais lenta, pois ele verificará a compatibilidade de cada extensão instalada com a versão atual;
  • Se você tentar abrir o Firefox num sistema operacional após ele ter travado no outro sistema, ele exibirá uma mensagem informando que já existe uma sessão aberta. Isso acontece por que, quando o Firefox é iniciado, ele cria um arquivo vazio chamado parent.lock no diretório do perfil que você estiver usando. Este arquivo é excluído quando o browser é fechado. Se isso ocorrer de maneira incomum (ex: travamento do browser ou do sistema operacional), este arquivo impedirá a abertura de outra sessão. Para resolver o problema, exclua esse arquivo;
  • Algumas extensões são incompativeis com determinados sistemas operacionais e versões de browser. Se for o caso, estas extensões serão desativadas pelo browser.

No final do século 20, a disputa entre os dois browsers mais populares da época, Netscape e Internet Explorer, ficou conhecida como guerra dos browsers. Nos últimos anos, após um período negro de domínio do IE, outros browsers começaram a crescer e recuperar o espaço que era ocupado pelo falecido Netscape.

Mais recentemente, desde o ano passado, os browsers mais modernos começaram a dar suporte ao HTML 5 - o Firefox, por exemplo, suporta desde a versão 3.5. Entre diversas novidades, o recurso mais popular do HTML 5 é a tag <video>, que permite a execução de vídeos sem o uso de plugins. A imensa maioria dos sites de vídeo usam Flash, que é uma tecnologia proprietária, e não é suportada em plataformas como o iPhone/iPod Touch. Porém, juntamente com esta nova tag surgiu uma polêmica.

No mês passado, o Youtube - seguido posteriormente por outros sites de vídeos - anunciou que começaria a oferecer vídeos em HTML 5, porém usando o codec H.264. Apesar de suportar HTML 5, o Firefox não tem suporte a este codec, pelo fato de ele ser proprietário, e exigir o pagamento de licenças caríssimas. O Firefox suporta somente o codec OGG Theora, que é open source. Esta atitude do Youtube criou uma grande polêmica: por que eles deixariam de usar uma tecnologia proprietária (Flash) para adotar outra igualmente proprietária (H.264)? O uso de HTML 5 deixa a impressão de que o Youtube partiu para tecnologias abertas, mas isto não ocorreu, devido ao codec escolhido.

Enquanto isso, o Safari (incluindo aí o iPhone) suporta o codec H.264, mas não suporta Theora; o Google Chrome suporta ambos os formatos; o Opera começará a suportar vídeos com codec Theora a partir da versão 10.50; e o IE 8 nem suporta HTML 5, criando um cenário totalmente heterogêneo. Um dos problemas desta divisão é que começamos a nos distanciar da padronização - que é o objetivo principal do W3C - e criar um ambiente onde cada browser suporta diferentes formatos de vídeo, retornando à época da guerra dos browsers, onde dificilmente uma página era igualmente visualizada no IE e no Netscape. Outro problema é que, como o Firefox não consegue exibir os vídeos em HTML 5 do Youtube, muita gente diz erradamente que o Firefox não suporta HTML 5, quando na verdade é um problema de codec.

A solução para os desenvolvedores é oferecer seus vídeos em mais de um formato, multiplicando, desta forma, o espaço necessário e o trabalho de codificação dos vídeos. O Video For Everybody ajuda a resolver este problema, oferecendo um trecho de código HTML que deixa a cargo do browser a escolha da opção mais adequada - se o browser suportar HTML 5 e Theora, este vídeo será exibido; se suportar HTML 5 e H.264, usará este formato; caso contrário, usará o plugin de Flash ou QuickTime, caso estejam instalados. Em último caso, exibe uma imagem do vídeo com um link para download. Esta solução exige o armazenamento do vídeo em dois formatos, mas parece uma boa solução diante de tantas variantes.

Referências:


Até a década de 1990, era muito comum escrevermos datas com apenas 2 dígitos representando o ano (ex: 1996 -> 96). Como todos já sabem, esta prática levou ao famoso bug do milênio, pois, desta forma, o ano 2000 tornava-se 0 (ou 100, dependendo do caso), gerando uma série de problemas, especialmente em códigos que calculavam um período entre duas datas. Felizmente, hoje em dia não temos mais esta preocupação. Ou temos?

Outro dia fui testar um sistema em diversos browsers, e ao realizar o teste no Opera, verifiquei que o componente inputCalendar do Tomahawk abria no ano de 3910. Testei no Firefox, Google Chrome e Internet Explorer 6, 7 e 8, e todos eles funcionavam corretamente. Resolvi olhar o código fonte do componente, e descobri que ele verificava o ano atual usando o método getYear da classe Date. Este método é fonte de diversos problemas e gambiarras em códigos Javascript que manipulam datas. O motivo é que diferentes browsers interpretam o método de maneiras diferentes. De acordo com a especificação ECMA-262, a função getYear deveria retornar o ano atual menos 1900. Nas versões mais recentes, o Firefox e o Google Chrome seguem esta especificação, retornando 110 para o ano de 2010. Já o Opera e o IE retornam 2010, contrariando a especificação e gerando os problemas já conhecidos. É muito comum encontrarmos códigos que verificam qual é o browser (com comentários condicionais ou verificações por Javascript) e, quando não for o IE, somando 1900 ao valor retornado pelo getYear. Esta verdadeira gambiarra não resolve completamente, pois, como já citado, o Opera se comporta da mesma forma que o IE.

A solução ideal para este problema é substituir o método getYear por getFullYear. Este método retorna o ano completo, com 4 dígitos, em todos os browsers, eliminando qualquer necessidade de verificação de browser. Esta recomendação, inclusive, faz parte da especificação ECMA-262, na página 242:

The getFullYear method is preferred for nearly all purposes, because it avoids the “year 2000 problem.”

Após corrigir este bug do Tomahawk, abri uma issue no Jira do projeto, anexando um patch para corrigir o problema.

Outras Referências: