After some blogging abstinence I am back. And we are coming up with a really nice topic, which hasn’t been blogged about out there on the web yet ;)
It’s all about Apple’s UTI’s and what Apple omitted to say about them.
UTI’s are one of the most powerful features of MacOSX and most CoreServices like LaunchServices, Spotlight and Quicklook depend upon it.
However documentation about it is unclear about which strategy applies when UTI’s are missing.
So what are UTI’s anyway:
UTI stays for Uniform Type Identifier, which means they identify a file type, very similar to a file extension or a MIME type, but more generic and with builtin inheritance.
So for example an image file has the UTI public.image, which inherits from public.data.
(you can learn more about UTI’s here)
Ok. That’s great, but where does a file hold the information about its UTI? Extension information comes from the filename and MIME types come from HTTP header information, but UTI??
Well it turns out that UTI information is stored in the extended attributes of a file on HFS+. You can show this metadata by typing mdls “filename” in a Terminal window.
The fields kMDItemContentType and kMDItemContentTypeTree will save information about the filetype and its inheritance.
But what happens if a file has not been created by a Mac OSX application and therefore has no UTI information at all??? That’s actually an interesting question, cause it happens quite oft.
MacOS X will generate a dynamic UTI, but most importantly it will fall back to file extensions, which is what Apple calls “Idintifier Tags”, but lets look at the information lookup flow a bit.
Lets say you have this awesome new file extension called .markdown and want to preview it with Quicklook.
The relevant UTI information looks like this:
In case of Readme.md the relevant information is:
kMDItemContentType = “dyn.ah62d4rv4ge8043a”
kMDItemContentTypeTree = (
“dyn.ah62d4rv4ge8043a”,
“public.data”,
“public.item”
)
OSX has no clue about it. So what’s gonna happen? First off, OS X will generate a dynamic UTI, but that’s not of a big help here. (see above)
So Quicklook will lookup the file extension and choose the appropriate program, that can ‘handle’ such file.
How can Quicklook know about which program is mapped to a certain file extension?
Each application has an Info.plist file in it’s Contents folder. This Info.plist can contain a key called UTImportedTypeDeclarations or UTExportedTypeDeclarations, both of which do more or less the same. The first is more generic as it says, which UTI’s (but also file extensions) an application will handle and registers it in the system. (The second one, says, that the application is not only able to handle such type, but is the actual ‘owner’ of the type).
Within UTImportedTypeDeclarations the application can then give a list of UTI Types the file type also conforms to. So an UTI inheritance list gets generated. E.g. Markdown being also public.plain-text.
So what we have till here is: file extension -> application that says it can handle extension -> inherited UTI’s for file extension.
Now back to Quicklook. Based upon the file extension Quicklook will try to find a Quicklook generator (.qlgenerator), a small Plugin, that says how to render a file type. First in the Application, then in ~/Library and /Library. The Quicklook generator itself has an Info.plist, where it can communicate to the system, which UTI’s (or file extensions) it is able to handle.
As a side information: Quicklook generators always renderer ouput to PDF, Text or Image Buffers.
If for a certain UTI or file type no qlgenerator is found Quicklook will display a standard dialog, but no Preview :(
As with Markdown, there is no .qlgenerator installed per default (actually one exists at https://github.com/toland/qlmarkdown, but we won’t use this one now).
As Markdown actually is a text file, it would be sufficient to start of the classic public-plain-text UTI qlgenerator, but markdown has no inheritance list that includes plain-text.
However if nothing is found the next lower UTI communicated by the application in UTTypeConformsTo is taken. This is where we can hook in the magic.
So take an application of your choice (which one is not important) and paste in the following in the Info.plist.
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.plain-text</string>
</array>
<key>UTTypeDescription</key>
<string>Markdown document</string>
<key>UTTypeIconFile</key>
<string>public.text.icns</string>
<key>UTTypeIdentifier</key>
<string>net.daringfireball.markdown</string>
<key>UTTypeReferenceURL</key>
<string>http://daringfireball.net/projects/markdown/</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>markdown</string>
<string>mdown</string>
<string>md</string>
<string>mdml</string>
<string>text</string>
<string>mdwn</string>
<string>mkd</string>
<string>mmd</string>
<string>rst</string>
</array>
</dict>
</dict>
</array>
So what we have now is: file extension -> application that says it can handle extension -> inherited UTI’s for file extension under ConformsTo is plain-text-> inherited UTI qlgenerator for plain-text will be used if no qppropriate qlgenerator was found before.
In order to reload the UTI table for the application, delete the app from the Application folder, then go to Trash and put it back into Applications. (Comments on an easier way to reregister the UTI’s of an app are appreciated!)
and here we go! :) Quicklook for Markdown!
Please note, that it was not important at all, which UTI the file has or which application we choose, as we are (ab)using the UTTypeTagSpecification of the application, mapping an extension to a list of conforming UTI’s.
Final hint: We were talking about Quicklook to find the right qlgenerator for preview here, still this has nothing to do with the application, which will be opening the file. This depends also on UTI’s and File Extensions, CFBundleDocumentTypes, Creator Codes etc. but each app registers for them seperately. There is a very nice Preference Pane, that shows all registered extensions for an application and it’s called: RCDefaultApp http://www.rubicode.com/Software/RCDefaultApp/
Go get it and play around with the mappings!
I discover myself all the time comparing programming languages to brain functions.
While I have never designed a programming language myself, I have used many of them, and think, that I know their strengths and weaknesses quite well by now.
But more importantly, I have studied brain functions and neural sciences to some extend over the years (especially starting with reading von Neumann’s and Turings books)
It is not a case that von Neumann, was also one of the founders of the computer paradigm. After all he just invented computers after the human prototype he was studying.
Over the decades however programming languages diverged from his principles and I always found myself reaching a dead end after some while with modern programming languages like Ruby, Java, .Net. etc. Strangely at first contact with Javascript over 15 years ago, I suddenly had this “feels right” feeling, but couldn’t describe why. Today, after some more years and some more experience with computer languages, I finally understand why Javascript not only feels right to me, but objectively is the right language for building future applications.
Let me explain why:
Preamble: I must explain some basics of how basic brain functionality in order to explain my conclusions:
So what’s the brain for?
The brain is a world simulator. It’s a big approximator. It takes input from it’s senors (the eyes, etc.) and produces output (which in someway should reproduce what’s happening or will happen in the real world)
How does the brain do that? It does it by a process called “learning”, which was studied quite extensively by von Neumann, reaching also very surprising conclusions about the learning process itsself. All that neural networks do, is they modify their connection weightings all time, until the output produced by the network is coherent to what the sensor input says. It’s some sort of “Calibration” that takes place during learning. When you learn things right, chances are you will make the right conclusions, before things happen, and you probably will survive. Yes, you see that car rushing at you with 100 km/h. Well your brain should be able to precalculate, that if it continous on its trail like that it will just hit you in the next minute. Therefore it’s better to jump in the bush before. Your brain might even be able to precalculate, that the driver might be drunk or that he will see you in the next 20 seconds and therefore tell you to wait a moment to not make too fast or early conclusions. Your brain is fantastic!
Ok. Probably you knew this already.
What does this have to do with programming languages?
Well. If you think about the above, there is a powerful conclusion you can make, which is:
The brain is a (sophisticated) computer! It’s a big processor. But most importantly and this is what computer languages forgot over the years. It’s a parallel processor! That’s what most programming languages are not. They just took some of von Neumann’s paradigms, but forgot about the most important ones. Parallelism and self modification. Aehm, self modification? Yes, the brain modifies it’s functions by learning. Neural networks function, in that electronic impulses coming from the human sensors, run through it parallely. It’s evented non-blocking IO. Yes! I hope now you understand the hype about node.js. Node is an evented non-blocking IO framework written in Javascript.
Ok so let’s see why Javascript fits in perfectly in imitating the brain.
a) No types: types are stupid. The brain has no notion of a type. A neuron is a neuron. A type is an artifical creation of computer scientists, in order to distinguish, what an object can do. It turns out, that object are actually all the same. They are objects in OO programming languages. The type comes over their metadata and the objects they are connected with in memory. In fact one of the big “revolution” in OOP languages was to move away from basic types like int, float, etc. to a generic object oriented model. However still some languages use types to distinguish such basic objects. It’s not necessary. The compiler can find out by itself over heuristics. That’s what Javascripts tracing JIT does! And as we see in the last years with Tracemonkey, Spidermonkey and Google V8 or Crankshaft it starts doing it really well and fast!
b) Dynamic: Javascript is a dynamic language. This means that code can modify code during runtime. This was something like the devil for programming language designers over the last decades. They thought it was evil to do that and would lead to code, that wasn’t clear anymore and so they tried to prevent such use in their languages. Well it turns out that they were wrong. Self modifying code will be the future, and while we are not there yet, I think it will be the 4th and last revolution in software design in this century.
c) Functions in Javascript are first class citizens: Well to explain this I have again to make reference to brain functions and “brain functions”.
What are equivalent to functions in the brain? Well the brain has no distinction between functions and memory. Everything is taking up memory in the neural network. Functions and data. But Functions are like a set of neurons, with a specific scope. That’s data (signals) runs through them to produce some output data (other signals). In fact the way this works in Javascript is completely the same. Functions are just again objects in memory and thus can group functionality. Not only! They will also map to process memory perfectly.
The objects that run through such functions are electric impulse codificated objects coming directly from our sensors.
In computers sensors quantize these information to 0-1 bit streams.
So a binary diff function somewhat operates however on the same memory and therefore is a first class citizen. That’s why javascript is the future of languages, cause it treats functions as first class citizens, whereas other languages don’t.
d) Javascript scope and closures: Javascripts scope keeps your working environment and variable in place, also after you come back from some asynchronous function. This is important and is like the brain is connected to neurons it uses more often in a more “near” or “local scope” fashion.
e) IPC communication: well todo communication we need to marshal data in a protocol. The way this is done nowadays is mainly http. And parsing text on both sides. Javascript is a perfect fit for this with it’s human readable JSON object notation.
f) Push and not pull, and Javascripts event model: The brain works by emitting electrical signals to connected neurons. The brain doesn’t “call” functions it always “emits” events. In computer science it is well known by now that passing objects to functions leads to tight coupling, which makes code less maintainable over time. Javascript although it is not perfect has a quite simple notation for emitting events. Whilst other languages can do that too over patterns like inheritance, delegates and interfaces or notification centers. Javascript’s implementation is more powerful cause it uses simple function pointers, which are more leightweight, than passing around objects.
g) Inheritance, Annotations and Mixins: The brain has no notion of inhertitance. It’s an interconnected graph so there is no hierarchy. While other languages try to create object hierarchies through inheritance, Javascript doesn’t. Instead you can modify or extend every existing object or just “connect” to it over a pointer. That’s why Javascript immitates better the connection between neurons, than any other language I know.
This article was really fun writing. I think creating the brain analogy was a good idea. Comparing programming language features to brain functions, somewhat works quite well, so this means that there is a strong correlation between the two.
Have another brain analogy. Post me a line.
It’s in these days and weeks, where everyone talked about wikileaks and it’s founder Julian Assange, that I read much about national security and secrets, but I realize, that what people mean with these terms and what they really stand for are somewhat completely different things and that’s what makes the discussion full of misunderstandings.
E.g. today I read the following note:
“he [Mr. Assange] doesn’t accept any secrets of governments, whereas he himself makes heavy use of them with his project Wikileaks”.
I want to analyze, the sentence above and show, why this is a wrong conclusion.
First off I want to explain the simple and powerful concept of Wikileaks. Wikileaks is all about transparency, to fight corruption and abuse. Nothing more nothing less.
It’s about bringing transparency to where concentration of power runs together and where wrong decisions can really be threats for society and humanity, meaning in governments and big societies.
As soon as you understand that, you understand that Wikileaks is not a threat for democracy, but the fundamental of it. No government or company has the right to preclude information from the public.
Does this mean, that there don’t have to be secrets anymore? Absolutely not!
But lets analyze the term secret a bit more:
A secret is something, that only some people are authorized to see. Not everyone. It’s about authorization in a value system. Who can see the secret? That’s already more difficult to define: In most cases there is a fine grained hierarchy of “trust”, that determines who is authorized to access secret information and this shows already, that secrets are somewhat “unnatural” to nature and difficult to handle. After all it’s human being accessing secrets.
What kind of information might be secret?
- well obviously the information must have some value. It is not your shopping list. What’s the highest value an information can have? When information becomes so filtered, that it becomes knowledge. Does knowledge have to be secret? No, knowledge is a public porperty of humanity. So what has to be secret? Well it turns out, that there are not many informations, that have to be kept secret. In nature secrets don’t exist! And there is a good reason for it. The natural value system regulates itsself by weightings. So authorization is replaced by heuristics. That’s how humans act between each other. You won’t tell all your private things to a perfect stranger, but perhaps to your mother. That’s because, your mother has a higher rating of trust in your brains neural circuit.
I have always wondered, how potentially insecure networks, like e.g. credit card networks are after all quite safe. Well it turns out, that they make heavy use of these heuristics. E.g. they can detect over mathematical algorithms, if an access pattern is somewhat “unnatural” to your normal behaviour and block your card. As a simple case immagine your credit card is stolen and someone is continuously accessing your bank account from abroad. This is an unnatural context for your normal behaviour and might therefore be detected by the system as a fraud.
After this excurse, I want to go back to the initial question:
Do states have to have secrets?
The answer is yes, until we don’t live in a perfect world, states sometimes must have secrets (especially, when it comes to national security), but most of the time the answer is NO! Why? Cause states are only legitimated by the civilization itsself. (It’s the people who finance governments, it’s their money!). So everything they do must be transparent to the people. Governments don’t have to ask every individual its consent, but it must be transparent, what they intend to do and how they gonna spend the money. I am really astonished these days, to see how many politicians and journalists seem to not have understood this.
Does Wikileaks have secrets? No! Cause Wikileaks is not about authorizing anybody to have the information, the information is completely public. It’s about anonymizing the source of the information so that no one not even Wikileaks itsself can find out where this information came from and trying to make sure the authenticity of it, This is fundamental in democracy (see the constitutional anonymity principle in elections).
So to keep the conclusion of this article short:
When people talk about secrets, they should differenciate between authorization and anonymizing!
I could have called this blog article Sammy Davis Jr. and Frank Sinatra - Me and my shadow, but no one would have understood, that this is all about fancy web development and Node.js. However after you have read this article, you might actually think and smile, about what a good fit this title would actually be…so let’s go:
Yeah, we all love the fancy world of AJAX, but unfortunately, we don’t live in a perfect world. When it comes to publishing real world apps to the Web, normally the first thing you encounter is the world crashing in your face, cause you start to test your page in non fancy browsers (yeah talking about you here, IE ;)
I follow up to the great writeup from Ben Nolan and Dav Glass upon how to do progressive enhancement with node.js and the concept of serverside DOM rendering of javascript, if for some reason it is not available in the clients browser.
While Ben’s writeup is somewhat theoretic and involves Firefox pushState functionality, Dav gives a real cool demo with YUI 3.
All this fancyness however comes with higher complexity…so I actually left it apart until I discovered Sammy.js a week ago and hey, saw it clear in front of me: That was the solution to progressive enhancement we are all searching for!
What’s Sammy.js and what does it have to do with progressive enhancement?
Sammy.js (yeah Sammy David Jr. inspired) is to the clients browser, what is Express.js (Sinatra inspired) to the server. Or to put it simple, Sammy.js is all about encoding AJAX state on the client into the hash URL, whereas Express is about serverside routes = encoding serverside state into the URL.
What is so beautiful here is, that while both do substantially the same, but one on the client to enable your seemless AJAX navigation, and the other on the Server to prevent you from writing strange regexp patterns and do unfancy URL parsing, the way they encode state is quite the same: they both use URL encoding.
So let’s look @ how Sammy encodes an URL:
// string
get('/user/:id', function() {
...
});
And now lets look @ how Express encodes an URL:
app.get('/user/:id', function(req, res){
...
});
Looks familiar? This is because both use “routes” as there way of mapping query strings to variables, so in the above example, user:id could be the name of a user to search for.
With sammy, this search would happen on the client involvimng perhaps some AJAX request to the client. With express this search is done on the server.
All things are beautiful here, cause Sammy will keep away nasty problems developers had to face with AJAX development. E.g. the browsers back button not working. Sammy does it all for you and it does it the same way as Express does it on the Server!
Well, so how do you connect both up together:
The point is you don’t have to do anything! If the browser has Javascript support, Sammy will disable the links (prevent the default action for clicks) and handle them with Sammy’s Javascript functions instead.
If there is no Javascript support, the Browser will simply call out to the Server and Express will handle the request, like in a normal Client-Server scenario.
Well there is one Gotcha however. AJAX apps normally do massive clientrside DOM manipulation, whereas this cannot be done on the Server normally.
Well fortunately there comes some help from Elijah Insua and his awesom JSDOM project on Github. JSDom basically is a serverside DOM parser and enables you even to use JQuery on the server.
So big up yourself and get fancy with Sammy and Express!
This post is a small tip about how I revamped console.log.
Actually console.log is a handy function, but having a stacktrace at the time of the log would be sometimes nice. Therefore I wrote a log function, which keeps stacktraces of the log in a global history. So you keep logging as before and when you need more information you can get it from the global history object. The idea for this came to me, when I saw a similar implementation from Paul Irish (without stacktrace though).
so I revamped it to something like this:
Try it out in console:
UPDATE: Actually Chrome Extensions do ask you for a permission, when you install them to have privileged access to certain domains, which they couldn’t access due to Cross Domain Origin Policy. However this just means, that e.g. they cannot do e.g. a POST to yourbank.com, if you hadn’t allowed them. But nothing hinders them to spy on your passwords, etc.
This is a fast writeup of what came to my mind today. As the Browser is always more becoming a Platform for “Applications” (Extensions) to run on, I started thinking about some security implications today.
I am using the Google Chrome Extension API lately to develop for a Google Chrome Extension.
I realized quickly, that many many extensions can load Javascript (so called contentscripts) on every page, doing all kind of weird stuff.
This is nothing new, cause everyone knows that Javascript is not safe right? Well no!
Javascript is as safe as any other language, but the point is the architecture of Web-Browsers today allows extensions to run scripts and potentially, spy on your web-browsing, banking activities and so on.
Background pages and content scripts are actually a big security flaw. Just immagine only some things they can do:
The only “normative” force is that extensions are actually delivered in Javascript and therefore can be inspected by developers. So normally they won’t do weird stuff. But anyways, who knows?
I think Google should start allowing only signed extensions, which they have reviewed to not do any harmful stuff, similar to how Apple reviews their apps and let only signed extensions run on the Google Chrome platform. By the way the same is true other web-browsers like Firefox and IE9 too.
I think Safari is the only browser allowing only signed extensions, which is a big plus.
Comments are appreciated!
I just found out a feature of Chromes debugger today, that I was searching for a while, but never found out:
How to set breakpoints in code, so that when you run over a function the debugger will automatically stop at that line of code.
Whenever you use the special keyword debugger in your script, FireBug / Chrome will treat that line as if it was a breakpoint, and stop your script right there.
This is so handy! Of course you can still set breakpoints by clicking on the line number in debugger.
So have fun debugging your code!
There are some unsung revolutions coming up this year.
While Microsoft and the others are chasing behind to catch up on the mobile market, but will always remain one step behind with Google and Apple, both companies are already up into other things, especially TV.
So fresh so good. Google is here with the long awaited Google TV and I must say “Yeah I like it!”.
While there has been some buzz around Apple’s TV, presented last month, but always declared a “hobby” of the company, I think Google TV has taken the right direction and introduced some really nice new features, especially one: Apps for TV.
While the idea of Apps, could actually come from Apple itsself (see the iPhone), Apple TV lacks to become the platform for Apps, the iPhone became. Hey you Apple guys, I think this was a big mistake and I think it is the real revolution behind Google TV.
I think, that its clear by now, that TV’s need some update and especially need their own UI and controls to interact with. It’s similar to how the iPhone revolutionized the mobile market, with it’s innovative touch interface.
You cannot just bring a classical webpage like Facebook to the TV screen, you have to modify it, to make use of TV’s features. (see my follow up guide on UI design for TV apps)
The combination Google chose is great, and is the same that Apple chose too, a mobile device, like the iPhone, with a rich UI as remote control and a TV as the screen for it. Apps for TV will have to be developed to render pages, that look nice on a big screen, while still being used from a cell phone device. (Googles Android and iPhone being a good platform for that)
Google TV (contrary to Apple TV) also greatly interacts with the “old” way of watching TV, making it a good start of migration to some sort of web based TV, that Apple TV is.
So while Apple TV is becoming more the “video recorder” substitute in our homes making it possible to rent and buy films, Google TV is becoming the “set top box” substitute, making it possible to connect to your Satellite, the Web and see webpages on your TV screen.
So ok Google, I think you got it good this time! I think we will see many cool apps come out for Google TV in the next time.
Here is my comparison to what are the main differences and “killer” features:
Apple Tv vs Google TV:
Sources:
GoogleTV:
AppleTV:
Stream vids to the TV:
(through vids on it from iPhone, Mac)
Google TV: no, yet?
AppleTV: yes
Stream from it:
Google TV: no, yet
AppleTV: no
Remote control it with your phone:
Google TV: yes
Apple TV: yes
Apps:
Google TV: yes
Apple TV: no
Today I had another mind-blowing experience.
As I was writing a software project in Node, which has reached it’s critical level for me, where I just don’t want to go on, with sys.puts and sys.inspect to find out, what my code is doing, I was in search of a Debugger for node.
Yesterday I tried out Cloud9’s Javscript IDE, but while being really a great project, is still in the very beginnings and I wasn’t able to set breakpoints in Chrome nor in Firefox. Perhaps I was doing something wrong, but it just didn’t work out of the box for me and I couldn’t find any documentaion yet. Anyways, Cloud9 is going to be really a great IDE some day!
So I was tinkering around and remembered, that I came accross a link to a project that involves Webkit’s Web Inspector as a debugger for Node.js. The Project is called Node- Inspector.
A npm install node-inspector gave me a good start and I got all that was necessary on my system.
Node-Inspector itsself is written in Javascript as it should be and runs with node. ;) The way node-inspector works is that it spawns a Webserver on port 8080 by default, where you can see Web Inspectors debugger Interface. Then it connects to Node’s Debug port, which in my case is 5858.
There is some confusion in the Readme and the screencast of how to startup node-inspector.
However a fast node —help, made things clear.
So here is my Installation Instruction:
Start node-inspector, by typing: node-inspector& (this will start the Webserver)
Startup your favourite Webkit browser (e.g. Safari, Chrome, etc) and go to 127.0.0.1:8080
start node with the —debug-brk option. This will start a TCP debug port at 5858 and set a startup breakpoint on the first line of your Javascript file.
So if youR Javascript file is called “hello.js”.
node —debug-brk hello.js will startup things.
Now go back to your browser and hit the “Connect to Node” button.
all your node are belong to us now!
Web Inspector is about the greatest debugger around and seeing it full screen debugging node is just mind-blowing cool!
So check it out!

There are companies, that will never learn. One of them is Microsoft.
I thought, I will never blog about companies and stuff, cause this blog is mainly intended to my writeups about AJAX geekiness, but the news and writeups spreading on the next “big thing” from Microsoft urges me to share some thoughts, about this “new” phone operating system.
What I see from the videos on Youtube is a far from complete phone operating system.
Rule No #1: Free Markets and the Killer Feature
Dear Microsoft, there are markets, which you don’t conquer being “fast”, but only having a killer feature. While Microsoft was not fast at all, since the iPhone is dominating the Market with it’s innovative design and features since 4 years, Windows Mobile 7 was anounced only last autumn. So while Microsoft’s decision was to launch Windows Mobile 7 in these months, it is still is to see if there is enough innovation in it.
Of course in pay markets also price plays a role, and Microsoft can surely be competitive, if they want to (by greatly reducing their profit). In fact Microsoft will not make any profit at all with Windows Mobile 7, cause there is already a cheap (cause free) OS in the market: namely ANDROID from Google!
I think, that from, what I see Windows Mobile 7, doesn’t offer any feature, that you won’t find on iPhone.
Rule No #2: Save costs by using a common codebase
Windows Mobile 7 seems to be built on Silverlight (Microsofts proprietary Flash software). This means, that developing Windows Mobile 7 and Windows are two completely different things. No common codebase (Silverlight) is bad for costs.
Rule No #3: Innovation in the UI
I do not see any innovation in the UI: Despite some “Widgets” which you can put on the start screen, and which will clutter up the Home screen even more, than Apple’s app centric approach, I don’t see anything new!
You must think, that this is the best Microsoft’s engineers seem to be able to come up with at the moment!
While with Windows the excuse has always been, that Microsoft can’t confront people with too radical changes in the UI (although windows made such changes, not for the better, by introducing even more substructures and even more complicated workflows), with Windows Mobile 7 they had the opportunity of a fresh relaunch.
Well, for me the conclusion is clear from what I can see this company completely lost its way to innovate.
Well, all this of course, doesn’t mean that Microsoft cannot improve, and that consumers won’t buy the phone anyways. People most often don’t even know, what is the operating system on their phone and Microsoft has good distribution and marketing channels, but I don’t believe they can do it with such a product.
Let’s see, what will be the consumers choice!
Anyways I am waiting for the big Web OS re-launch next year. I think, that HP is doing really good in waiting the whole buzz this year, and then coming up with something mind-blowing for the beginning of next year. I still believe that WebOS is going to be the real competitor of the iPhone!